From 739f2be25a8f7ab22acf803d8a10d0751a882911 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 21 Jul 2025 11:49:41 -0400 Subject: [PATCH] add parse --- examples/ublox_ddc_parse_nmea.ino | 192 ++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 examples/ublox_ddc_parse_nmea.ino diff --git a/examples/ublox_ddc_parse_nmea.ino b/examples/ublox_ddc_parse_nmea.ino new file mode 100644 index 0000000..0cf5458 --- /dev/null +++ b/examples/ublox_ddc_parse_nmea.ino @@ -0,0 +1,192 @@ +/*! + * @file ublox_ddc_parse_nmea.ino + * + * Example sketch demonstrating parsing NMEA sentences from a u-blox GPS/RTK module + * using the Adafruit_GPS and Adafruit_UBX libraries. + * + * Written by Brent Rubell for Adafruit Industries. + * + * MIT license, all text above must be included in any redistribution + */ + +#include +#include +#include + +// Adafruit_UBloxDDC object with default I2C address (0x42) +Adafruit_UBloxDDC gps; +// Create Adafruit_UBX parser using the DDC object as input stream +Adafruit_UBX ubx(gps); +// Create Adafruit_GPS object for use as a NMEA parser only +Adafruit_GPS NMEA; + +// Buffer to store NMEA sentences from the module (may be partial sentences) +const size_t SZ_NMEA_BUFFER = 128; +uint8_t buffer[SZ_NMEA_BUFFER]; +uint32_t timer = millis(); + +/*! + * @brief Sets the NMEA output to only RMC and GGA sentences and waits for an + * acknowledgment. All other common NMEA sentences are disabled to increase + * loop() performance by decreasing the amount of messages output by the UBlox + * module. + * @return Status indicating success, failure, or timeout + */ +UBXSendStatus SetNMEAOutputRMCGGAOnly() { + UBXSendStatus status; + // Disable all common NMEA messages + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_GLL_DISABLE, + sizeof(UBX_CFG_MSG_NMEA_GLL_DISABLE)); + if (status != UBX_SEND_SUCCESS) + return status; + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_GSA_DISABLE, + sizeof(UBX_CFG_MSG_NMEA_GSA_DISABLE)); + if (status != UBX_SEND_SUCCESS) + return status; + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_GSV_DISABLE, + sizeof(UBX_CFG_MSG_NMEA_GSV_DISABLE)); + if (status != UBX_SEND_SUCCESS) + return status; + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_VTG_DISABLE, + sizeof(UBX_CFG_MSG_NMEA_VTG_DISABLE)); + if (status != UBX_SEND_SUCCESS) + return status; + // Enable only GGA and RMC messages + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_GGA_ENABLE, + sizeof(UBX_CFG_MSG_NMEA_GGA_ENABLE)); + if (status != UBX_SEND_SUCCESS) + return status; + status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG, + UBX_CFG_MSG_NMEA_RMC_ENABLE, + sizeof(UBX_CFG_MSG_NMEA_RMC_ENABLE)); + return status; +} + +void setup() { + // Initialize serial port for debugging + Serial.begin(115200); + while (!Serial) { + ; // Wait for serial port to connect + } + + // Initialize GPS module + if (!gps.begin()) { + Serial.println("Failed to initialize GPS module!"); + while (1); // Halt if initialization fails + } + Serial.println("GPS module initialized successfully!"); + + // Initialize the u-blox parser + if (!ubx.begin()) { + Serial.println("Failed to initialize u-blox parser!"); + while (1); // Halt if initialization fails + } + Serial.println("u-blox parser initialized successfully!"); + ubx.verbose_debug = 3; // Set debug level to verbose + + // Set NMEA output on DDC to RMC and GGA sentences only + UBXSendStatus status = SetNMEAOutputRMCGGAOnly(); + if (status != UBX_SEND_SUCCESS) { + Serial.print("Failed to configure NMEA output [status code: "); + Serial.print(status); + Serial.println("]"); + while (1); // Halt if setting NMEA output fails + } +} + +void loop() { + static char nmeaSentenceBuf[SZ_NMEA_BUFFER]; + static int nmeaSentenceIdx = 0; + + // Check how many bytes are available + int bytesAvailable = gps.available(); + + if (bytesAvailable > 0) { + // Read up to SZ_NMEA_BUFFER bytes at a time + size_t bytesToRead = min(bytesAvailable, (int)SZ_NMEA_BUFFER); + size_t bytesRead = gps.readBytes(buffer, bytesToRead); + + // Build NMEA sentences and parse when complete + for (size_t i = 0; i < bytesRead; i++) { + char c = buffer[i]; + + // Add to buffer if space available + if (nmeaSentenceIdx < SZ_NMEA_BUFFER - 1) { + nmeaSentenceBuf[nmeaSentenceIdx++] = c; + } + + // Check for end of NMEA sentence + if (c == '\n') { + nmeaSentenceBuf[nmeaSentenceIdx] = '\0'; + + // Parse the NMEA sentence + if (NMEA.parse(nmeaSentenceBuf)) { + // Successfully parsed sentence! + Serial.println(nmeaSentenceBuf); + // approximately every 2 seconds or so, print out the current stats + if (millis() - timer > 2000) { + timer = millis(); // reset the timer + Serial.print("\nTime: "); + if (NMEA.hour < 10) { + Serial.print('0'); + } + Serial.print(NMEA.hour, DEC); + Serial.print(':'); + if (NMEA.minute < 10) { + Serial.print('0'); + } + Serial.print(NMEA.minute, DEC); + Serial.print(':'); + if (NMEA.seconds < 10) { + Serial.print('0'); + } + Serial.print(NMEA.seconds, DEC); + Serial.print('.'); + if (NMEA.milliseconds < 10) { + Serial.print("00"); + } else if (NMEA.milliseconds > 9 && NMEA.milliseconds < 100) { + Serial.print("0"); + } + Serial.println(NMEA.milliseconds); + Serial.print("Date: "); + Serial.print(NMEA.day, DEC); + Serial.print('/'); + Serial.print(NMEA.month, DEC); + Serial.print("/20"); + Serial.println(NMEA.year, DEC); + Serial.print("Fix: "); + Serial.print((int)NMEA.fix); + Serial.print(" quality: "); + Serial.println((int)NMEA.fixquality); + if (NMEA.fix) { + Serial.print("Location: "); + Serial.print(NMEA.latitude, 4); + Serial.print(NMEA.lat); + Serial.print(", "); + Serial.print(NMEA.longitude, 4); + Serial.println(NMEA.lon); + Serial.print("Speed (knots): "); + Serial.println(NMEA.speed); + Serial.print("Angle: "); + Serial.println(NMEA.angle); + Serial.print("Altitude: "); + Serial.println(NMEA.altitude); + Serial.print("Satellites: "); + Serial.println((int)NMEA.satellites); + } + } + } else { + Serial.println("Failed to parse sentence."); + } + nmeaSentenceIdx = 0; // Reset index for next sentence + } + } + } + // Short delay to prevent overwhelming the module + delay(10); +} \ No newline at end of file