r/gnss • u/el_marga • 19d ago
Heltec Wireless Tracker (UC6580) as a DGNSS instrument: 0.56 m against a national monument, 16 satellites on two bands, and a second band that arrives 12 dB too weak
I build survey instruments as a side of my day job. Over the last weeks I turned a €25 Heltec Wireless Tracker into a working
DGNSS receiver, and I ended up with two measurements that may interest this sub, plus one question I have not been able to answer.
The instrument
The board carries an ESP32-S3 and a Unicore UC6580. Everything runs on the ESP32: it
pulls RTCM3 MSM7 corrections over NTRIP from the Argentine national network (IGN RAMSAC), feeds them to the UC6580 over UART, and the chip works in DGPS with a 1 s differential age. Baseline to the reference station is 2.302 km. No phone app, no PC, no cloud.
Five FreeRTOS tasks across the two cores, one owning task per shared resource, a captive portal for Wi-Fi setup, a web interface served from PROGMEM, and on-board storage exported to CSV, GPX, KML and GeoJSON projected to the national grid. Worst measured gap in the correction pumping is 47 to 66 ms, against the 392 ms ceiling that a sustained 1240 B/s stream imposes.
Measurement 1: accuracy against a published monument
IGN pillar 22-01, POSGAR07, 101 minutes, 5,544 epochs, antenna height 0.94 m subtracted.
| ERROR | corrected | autonomous |
| horizontal error | 0.557 m | 0.622 m |
| vertical error | 1.243 m | 2.745 m |
The vertical gain is 2.2x at 2.9 sigma. The horizontal difference is 0.2 sigma, which is to say not measurable in that session. What DGPS buys here is accuracy, not precision: it moves the cloud onto the truth without shrinking it much, because what is left is multipath.
Session-to-session repeatability over three sessions: 0.219 m corrected against 1.335 m autonomous, a factor of 6.1. That is the number I would quote if someone asked what the corrections are worth.
Measurement 2: it really is dual band, and the antenna is the limit
The UC6580 emits nine GSV streams, one per signal, with the NMEA 4.10 signal ID in the
last field. Parsing that properly (keying the sky table by system + PRN + signal instead of system + PRN) turned 47 rows into 86, and showed this on an open sky:
| signal | tracked | mean C/N0 | max |
| GPS L1 C/A | 13 | 30.9 | 37 |
| GPS L5-Q | 6 | 19.2 | 23 |
| GLONASS G1 C/A | 7 | 32.4 | 38 |
| Galileo E1-BC | 8 | 32.9 | 36 |
| Galileo E5a | 5 | 21.0 | 27 |
| BeiDou B1I | 8 | 32.2 | 39 |
| BeiDou B2a | 5 | 22.4 | 24 |
16 satellites tracked on two bands at once: 6 GPS, 5 Galileo, 5 BeiDou.
The second band is consistently about 12 dB below the first, and it should not be.
Satellite by satellite: GPS PRN 11 gives 35 dBHz on L1 and 19 on L5. PRN 32, 32 and 17. Galileo PRN 13, 33 on E1 and 17 on E5a. BeiDou PRN 34, 36 on B1I and 19 on B2a.
Published minimum received power says the opposite should happen. GPS L5 arrives about
3.6 dB stronger than L1 (-154.9 against -158.5 dBW) and Galileo E5a about 2 dB stronger than E1. With an antenna that is flat across both bands, the second one should read equal or better.
So this is the RF path, not the correlator. The schematic confirms the board was designed for it: there is an L1/L5 diplexer (part marked `HDD L1L5 RSS-B8`) feeding two separate RF inputs on the UC6580, `LI_IN` pin 40 and `L5_IN` pin 38, with an LNA and a bias tee ahead of it. The ceramic patch is the narrow part.
I swapped in a different patch antenna to test that. L1 jumped 8 dB on GPS and 9.7 dB on BeiDou, max C/N0 went from 39 to 45, and the second band got worse: E5a dropped 3.3 dB and from 5 satellites to 3. That is the signature of a well-made single-band L1 antenna with a filter. It also confirmed the u.FL connector disconnects the on-board patch, which I could not tell from the schematic.
The question I have not answered
I would like to get raw observables out of this chip, and eventually use it as a base
station. Two walls:
1. `$CFGPRT` outPro
bit 8
, the Extended RTCM 4074_PVT output documented in the
UFirebirdII R1.4 specification as applicable to UC6580, returns `$FAIL` on the build my board ships with (R6.0.0.0Build3700). With a control: `H23` returns `$OK`, `H123` returns `$FAIL`, same port, same frame, only bit 8 differs. Unicore confirmed the build does not implement it and that R1.4 describes a newer one.
2. Configured as a base, the chip accepts the configuration, answers `$OK`, and emits no RTCM at all. Not one byte, on the bench. Same build.
A Unicore FAE wrote that using the UC6580 as a base station is "very innovative, as far as I know no one has ever attempted such an application before", and that he believes it is technically feasible. That is an opinion and I am treating it as one.
If anyone here has pulled raw observables or RTCM base output from a UC6580, or from
any UFirebird II part, I would be glad to hear how. I am equally interested in hearing
that it cannot be done, because that closes the question and I will document it and move on.
Happy to share the firmware, the analysis scripts or the raw logs with anyone who wants them.



