The Teseo-LIV3 GPS module (as used in shabaz ' GPS / Galileo / BeiDou / GLONASS receiver) talks UART and I2C. I developed an OO driver and parser for it.
The Raspberry Pico port is now ready for a stable release.
GitHub Release 1.0, with binaries.
Overview:
- driver library for Teseo GPS (device independent)
- parser library for NMEA messages (device independent)
- UART and I2C implementation for Raspberry Pico / RP2040
- Teseo driver example (device independent, compiled for Pico)
- NMEA parser and Teseo driver example (device independent, compiled for Pico)
- I2C and UART binaries for both examples, ready to drop-and-run on your RP2040
Pico resources used only if you use I2C:
- I2C0
- SDA: GP16 (Pico I2C0 SDA)
- SCL: GP17 (Pico I2C0 SCL)
- baud: 100 * 1000
for I2C, SDA connects to SDA and SCL to SCL. The PCB that I use has the pull-ups for I2C.
Pico resources used only if you use UART:
- UART1
- TX: GP4 (Pico UART1 RX)
- RX: GP5 (Pico UART1 Tx)
- baud: 9600
- UART1 RX interrupt
for UART, RX connects to TX and vice versa
Pico common resources:
- RESET: GP18 (optional)
- 5V: VBUS
- 0V: GND
image: how to hook up the Teseo PCB to a Pico.
Dependency between examples, libraries and Pico / RP2040 port:
Api changes since previous version:
- the NMEA parser api is new functionality
- Teseo lib: the command / validation pair changed.
pair.second is no longer representing the validation line (the NMEA command itself has enough info).
new use: nmea_rr teseo::gll("$PSTMNMEAREQUEST,100000,0\n\r", "GLL,");
The first string, the NMEA command, is unchanged.
The second "check" string now represents the signature of a NMEA reply (and is used for that).
Code now uses the first string a command, and as validator for the closing validation line.
Example changes:
- new example to showcase the Teseo GPS communication lib, together with the NMEA parser lib
Infrastructure changes
- default build generates binaries for each example, in I2C and UART variant
- Pico C/C++ SDK compatible
- GitHub action scripts to validate build and create nightly releases
- Teseo and NMEA lib are subprojects that can be used in isolation
- Pico dependent code moved out of examples, into port/pico directory
- Pico I2C reader is way better and resource-friendlier in this version
Other:
- requires a C++23 capable toolchain. Developed and tested on GCC 13.3.1
- tested with Pico C/C++ SDK 1.5.1 and 2.0.0
Development examples
For the full source code of the parser example I review here, check the documentation.
Typical query - response - parse code example - query that returns a single reply:
teseo::teseo gps; std::string reply; bool valid; // intentionally uninitialised // nmea::gll o; // NMEA GLL object valid = gps.ask_gll(reply); // ask Teseo GPS library for GLL data if (valid) { valid = nmea::gll::from_data(reply, o); // fill NMEA GLL object with the reply attributes }
debugger view after the GLL object is built up:
Using the object in your code (print example snippet):
printf("lat: %f, lon: %f.", o.lat, o.lon);
GLL source: gps. lat: 50.863354 lon: 4.376334, time: 11:00:32.000.
Typical query - response - parse code example - query that returns a multiple replies:
teseo::teseo gps;
std::vector<std::string> replies(NMEA_MAX_REPLIES);
// vector size is a suggestion. STL will allocate at least NMEA_MAX_REPLIES
uint count; // intentionally uninitialised
bool valid; // intentionally uninitialised
// ...
valid = gps.ask_gsv(replies, count);
if (!valid) { return; }
for(auto r : std::ranges::subrange(replies.begin(), replies.begin() + count)) {
nmea::gsv o;
valid = nmea::gsv::from_data(r, o);
// .. either use the object, or store it in a container for later use.
}
debugger view:
Using the object in your code (example where the retrieved objects are directly used for printing, not stored for later use):
for(auto r : std::ranges::subrange(replies.begin(), replies.begin() + count)) {
nmea::gsv o;
valid = nmea::gsv::from_data(r, o);
printf("GSV source: ");
print_talker(o.source);
printf(".\r\n");
for(const auto s : o.sats) {
printf("sat prn: %i, elev: %i, azim: %i, snr: %i.\r\n",
s.prn, s.elev, s.azim, s.snr);
}
}
GSV source: gps.
sat prn: 3, elev: 84, azim: 344, snr: 21.
sat prn: 2, elev: 48, azim: 135, snr: 27.
sat prn: 17, elev: 48, azim: 271, snr: 25.
sat prn: 4, elev: 43, azim: 182, snr: 43.
GSV source: gps.
sat prn: 19, elev: 36, azim: 303, snr: 14.
sat prn: 21, elev: 32, azim: 133, snr: 21.
sat prn: 28, elev: 20, azim: 56, snr: 0.
sat prn: 31, elev: 20, azim: 92, snr: 0.
GSV source: gps.
sat prn: 6, elev: 16, azim: 304, snr: 0.
sat prn: 9, elev: 13, azim: 204, snr: 37.
sat prn: 49, elev: 31, azim: 179, snr: 41.
sat prn: 0, elev: 0, azim: 0, snr: 0.
GSV source: glonass.
sat prn: 84, elev: 77, azim: 311, snr: 0.
sat prn: 69, elev: 67, azim: 220, snr: 25.
sat prn: 68, elev: 56, azim: 41, snr: 25.
sat prn: 83, elev: 34, azim: 145, snr: 22.
GSV source: glonass.
sat prn: 85, elev: 20, azim: 323, snr: 0.
sat prn: 85, elev: 20, azim: 323, snr: 0.
sat prn: 77, elev: 9, azim: 34, snr: 0.
sat prn: 76, elev: 10, azim: 352, snr: 23.
GSV source: glonass.
sat prn: 67, elev: 8, azim: 41, snr: 0.
sat prn: 0, elev: 0, azim: 0, snr: 0.
sat prn: 0, elev: 0, azim: 0, snr: 0.
sat prn: 0, elev: 0, azim: 0, snr: 0.
visit the github repository (git clone https://github.com/jancumps/pico_gps_teseo.git --recursive)
view the online documentation
Link to all posts.