SparkFun .lib TOPGNSS

Hello! I don’t know if the question makes sense since I’m a bit confused about the SparkFun library and its use with modules other than SparkFun’s. Recently, I started focusing on ESP32 (LoRa) development for GNSS. Here at the university, I have a TOPGNSS TOP906 module. I managed to make it work as a rover and display corrected coordinates on a screen. However, what I wanted to test is using the ESP32 with this module as a data source for a Caster server. Unfortunately, I recently discovered that SparkFun has a module based on u-blox, including an example to make it work as a base station.

My question is whether it is possible to use SparkFun’s example with the TOPGNSS TOP906 module. I believe it is not possible, but this is not entirely clear to me. I appreciate any assistance in clarifying my doubt. Below is the code I am using to test the module and the results.

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // SparkFun Library
SFE_UBLOX_GNSS myGNSS;
 
#define RXD2 16
#define TXD2 17
 
 
void setup()
{
  Serial.begin(115200); // Serial Monitor
  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2); // UART communication with the GNSS module
  delay(500); // Wait 500ms to stabilize communication
  Serial.println("Starting GNSS module via UART...");
 
  // Initialize the GNSS module on Serial2
  myGNSS.enableDebugging(Serial2);
 
  if (!myGNSS.begin(Serial2)) {
    Serial.println("Failed to initialize the GNSS module. Retrying...");
    delay(2000); // Wait before retrying
    ESP.restart(); // Restart ESP32
  }
 
  Serial.println(F("GNSS module initialized successfully."));
 
  // Configure NMEA and UBX output via UART
  myGNSS.setUART1Output(COM_TYPE_UBX); 
  myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); // Save output configuration
  // Check firmware version
 }
 
void loop()
{
  // Process GNSS data
  myGNSS.checkUblox();
 
 
   if (myGNSS.getFixType() == 0) {
    Serial.println("No fix: the module has not locked onto satellites yet.");
  } else {
    Serial.print("Operation mode ");
    Serial.println(myGNSS.getFixType());
    double latitude = myGNSS.getLatitude() / 10000000.0; // Convert to degrees
    double longitude = myGNSS.getLongitude() / 10000000.0; // Convert to degrees
    Serial.print("Latitude: ");
    Serial.print(latitude, 7);
    Serial.print(" | Longitude: ");
    Serial.println(longitude, 7);
 
    // Capture and display the number of visible satellites
    uint8_t numSatellites = myGNSS.getSIV(); // Number of satellites in use
    Serial.print("Satellites: ");
    Serial.println(numSatellites);
 
    // Capture and display the date (DD/MM/YYYY)
    uint16_t year = myGNSS.getYear();
    uint8_t month = myGNSS.getMonth();
    uint8_t day = myGNSS.getDay();
    Serial.print("Date: ");
    Serial.print(day);
    Serial.print("/");
    Serial.print(month);
    Serial.print("/");
    Serial.println(year);
 
    // Capture and display the time (HH:MM:SS)
    uint8_t hour = myGNSS.getHour();
    uint8_t minute = myGNSS.getMinute();
    uint8_t second = myGNSS.getSecond();
    Serial.print("Time: ");
    Serial.print(hour);
    Serial.print(":");
    Serial.print(minute);
    Serial.print(":");
    Serial.println(second);
  }
 
  delay(1000);
 
}

Answer:

Starting GNSS module via UART...
GNSS module initialized successfully.
Operation mode 96
Latitude: 107.3446932 | Longitude: 0.0000143
Satellites: 63
Date: 0/0/0
Time: 0:0:0
Operation mode 96

Hi @Mateus ,

It looks like the TOP906 has the u-blox ZED-F9P on it. So, yes, you should be able to use our library with that board.

But your code is confused. The ZED-F9P default baud rate is 38400, not 115200. And myGNSS.enableDebugging(Serial2); should be myGNSS.enableDebugging(Serial);. Maybe that explains why the Latitude is wrong?

I hope this helps,
Paul

Hello Paul, thank you for responding.
From what I understand, the TOP906 module has two UARTs. UART1 is used to configure the module’s parameters and output NMEA RTCM. UART2 is used for input and output for the NMEA and RTCM protocols.
I connected the USB port to the PC, and through u-center, I verified that it is receiving latitude and longitude.
Through u-center, I also verified that it has the following PRT (Ports): 0 - I2C, 1 - UART1, 2 - UART2, 3 - USB, and 4 - SPI.
So, I configured UART1 to 115200 with Protocol in set to (0+1 UBX+NMEA) and Protocol out set to (0 - UBX).
The reason I use the module on Serial2 is because Serial is being used to power the ESP and to display messages read from UART1 (connected to the module via an RS232 connection) in the serial monitor.
The connection is essentially as follows:

Module (GNSS) ----------------> UART1 ----RS232-------> ESP pins (16,17)
                          \__________> USB -----PC (running u-center)```

Hi Mateus,

OK, I understand.

Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2); is correct if you have changed the baud rate on UART1 to 115200.

myGNSS.begin(Serial2) is correct.

But myGNSS.enableDebugging(Serial2); is not correct. You should use myGNSS.enableDebugging(Serial);. You want the debug messages to go to Serial - the ESP32 USB console. At the moment, you are sending the debug messages back to the ZED-F9P on UART1.

Also, I think you mean “TTL”, not “RS232”? True RS232 has higher voltages and the polarity is inverted.

I hope this helps,
Paul

Hello Paul, great tip! I really wasn’t noticing the error in the module’s debug command.
I am using two TTL ↔ RS232 converters connected via a null serial cable.
If I configure the module to send NMEA data, using the TinyGPS++ library, I can retrieve latitude, longitude, and date/time.
However, since I am trying to use the ESP32 as a base to send data to a Caster server, I need to be able to read the data in UBX format.

Sending: CLS:NAV ID:PVT Len: 0x0 Payload:
sendCommand: Waiting for No ACK response
waitForNoACKResponse: TIMEOUT after 1100 msec. No packet received.

Sending: CLS:NAV ID:PVT Len: 0x0 Payload:
sendCommand: Waiting for No ACK response
waitForNoACKResponse: TIMEOUT after 1100 msec. No packet received.
Latitude: 107.3446932 | Longitude: 0.0000143

Sending: CLS:NAV ID:PVT Len: 0x0 Payload:
sendCommand: Waiting for No ACK response
waitForNoACKResponse: TIMEOUT after 1100 msec. No packet received.
Satellites: 63

Sending: CLS:NAV ID:PVT Len: 0x0 Payload:
sendCommand: Waiting for No ACK response
waitForNoACKResponse: TIMEOUT after 1100 msec. No packet received.

Unfortunately, I am unable to use the library to read the coordinates. With debugging enabled, I noticed that it indicates the module did not return any packets.

Thanks in advanced!

Hi Mateus,

I think you might have protocol problem. I am surprised the myGNSS.begin is successful. What debug messages do you see when the code starts after a reset?

Best,
Paul

Hi Paul!
I simplified the code to only show the debug.

Starting GNSS module via UART...
createFileBuffer: Warning. fileBufferSize is zero. Data logging is not possible.

Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
sendCommand: Waiting for ACK response
Incoming: Size: 1 Received: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
packetCfg now valid
packetCfg classAndIDmatch
waitForACKResponse: TIMEOUT with valid data after 1100 msec. 
GNSS module initialized successfully.

Hi Mateus,

This is very strange… The debug messages should look like this:

14:14:41.439 -> Starting GNSS module via UART...
14:14:41.439 -> createFileBuffer: Warning. fileBufferSize is zero. Data logging is not possible.
14:14:41.486 -> 
14:14:41.486 -> Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
14:14:41.486 -> sendCommand: Waiting for ACK response
14:14:41.486 -> Incoming: Size: 20 Received: CLS:CFG ID:0x0 Len: 0x14 Payload: 1 0 0 0 C0 8 0 0 0 96 0 0 63 0 1 0 0 0 0 0
14:14:41.486 -> packetCfg now valid
14:14:41.486 -> packetCfg classAndIDmatch
14:14:41.486 -> Incoming: Size: 2 Received: CLS:ACK ID:0x1 Len: 0x2 Payload: 6 0
14:14:41.486 -> packetCfg now valid
14:14:41.486 -> packetAck now valid
14:14:41.486 -> packetCfg classAndIDmatch
14:14:41.486 -> packetAck classAndIDmatch
14:14:41.486 -> waitForACKResponse: valid data and valid ACK received after 37 msec
14:14:41.532 -> GNSS module initialized successfully.
14:14:41.532 -> 
14:14:41.532 -> Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
14:14:41.532 -> sendCommand: Waiting for ACK response
14:14:41.532 -> Incoming: Size: 20 Received: CLS:CFG ID:0x0 Len: 0x14 Payload: 1 0 0 0 C0 8 0 0 0 96 0 0 63 0 1 0 0 0 0 0
14:14:41.532 -> packetCfg now valid
14:14:41.532 -> packetCfg classAndIDmatch
14:14:41.532 -> Incoming: Size: 2 Received: CLS:ACK ID:0x1 Len: 0x2 Payload: 6 0
14:14:41.532 -> packetCfg now valid
14:14:41.532 -> packetAck now valid
14:14:41.532 -> packetCfg classAndIDmatch
14:14:41.532 -> packetAck classAndIDmatch
14:14:41.532 -> waitForACKResponse: valid data and valid ACK received after 27 msec
14:14:41.579 -> 
14:14:41.579 -> Sending: CLS:CFG ID:0x0 Len: 0x14 Payload: 1 0 0 0 C0 8 0 0 0 96 0 0 63 0 1 0 0 0 0 0
14:14:41.579 -> sendCommand: Waiting for ACK response
14:14:41.579 -> Incoming: Size: 2 Received: CLS:ACK ID:0x1 Len: 0x2 Payload: 6 0
14:14:41.579 -> packetCfg now valid
14:14:41.579 -> packetAck now valid
14:14:41.579 -> packetCfg classAndIDmatch
14:14:41.579 -> packetAck classAndIDmatch
14:14:41.579 -> waitForACKResponse: no data and valid ACK after 27 msec
14:14:41.579 -> 
14:14:41.579 -> Sending: CLS:CFG ID:SAVE Len: 0xC Payload: 0 0 0 0 1 0 0 0 0 0 0 0
14:14:41.625 -> sendCommand: Waiting for ACK response
14:14:41.625 -> Incoming: Size: 2 Received: CLS:ACK ID:0x1 Len: 0x2 Payload: 6 9
14:14:41.671 -> packetCfg now valid
14:14:41.671 -> packetAck now valid
14:14:41.671 -> packetCfg classAndIDmatch
14:14:41.671 -> packetAck classAndIDmatch
14:14:41.671 -> waitForACKResponse: no data and valid ACK after 55 msec
14:14:41.671 -> 
14:14:41.671 -> Sending: CLS:NAV ID:PVT Len: 0x0 Payload:
14:14:41.671 -> sendCommand: Waiting for No ACK response
14:14:41.809 -> Incoming: Size: 92 Received: CLS:NAV ID:PVT Len: 0x5C Payload: 98 21 19 0 E6 7 5 1 0 1B 1B F0 FF FF FF FF 0 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 98 BD FF FF FF FF FF FF 0 AB 86 DF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 4E 0 0 80 A8 12 1 F 27 0 0 5C 41 4F 21 0 0 0 0 0 0 0 0
14:14:41.809 -> packetCfg now valid
14:14:41.809 -> packetCfg classAndIDmatch
14:14:41.809 -> waitForNoACKResponse: valid data with CLS/ID match after 148 msec
14:14:41.809 -> No fix: the module has not locked onto satellites yet.

I can not explain why the myGNSS.begin is successful when waitForACKResponse shows a TIMEOUT.

Perhaps you have periodic UBX messages already enabled on UART1?

Please try a “factory reset” of the module. Connect using USB. Open u-center. Connect. Open View \ Messages View. Navigate to UBX CFG CFG. Select “Revert to default configuration”, and Send. Select “Save current configuration”, and Send. Select UBX CFG PRT. Change the UART1 baud rate to 115200. Do not change the Protocol In or Out. Send. Return to CFG CFG and “Save current configuration” again. Then run your code again. Post the debug messages here.

Thank you,
Paul

After resetting the module to the default parameters, I noticed that it enabled all output protocols on both UARTs.
Running the code, here’s the output:

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // SparkFun Library
SFE_UBLOX_GNSS myGNSS;


#define RXD2 16
#define TXD2 17


void setup()
{
  Serial.begin(115200); // Serial Monitor
  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2); // UART communication with the GNSS module by module RS232
  delay(500); // Wait 500ms to stabilize communication
  Serial.println("Starting GNSS module via UART...");

  // Initialize the GNSS module on Serial2
  myGNSS.enableDebugging(Serial);
 
  if (!myGNSS.begin(Serial2)) {
    Serial.println("Failed to initialize the GNSS module. Retrying...");
    delay(2000); // Wait before retrying
    ESP.restart(); // Restart ESP32
  }

  Serial.println(F("GNSS module initialized successfully."));

 }

void loop()
{
  // Process GNSS data
  myGNSS.checkUblox();

  delay(1000);

  // You can add other library functions to extract specific data
}
//-------------------------------------------------------------------------

Output:

Starting GNSS module via UART...
createFileBuffer: Warning. fileBufferSize is zero. Data logging is not possible.

Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
sendCommand: Waiting for ACK response
waitForACKResponse: TIMEOUT after 1100 msec.
begin: isConnected - second attempt

Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
sendCommand: Waiting for ACK response
waitForACKResponse: TIMEOUT after 1100 msec.
begin: isConnected - third attempt

Sending: CLS:CFG ID:0x0 Len: 0x1 Payload: 1
sendCommand: Waiting for ACK response
Checksum failed: checksumA: 0 checksumB: 2 rollingChecksumA: 244 rollingChecksumB: 232
waitForACKResponse: TIMEOUT after 1100 msec.
Failed to initialize the GNSS module. Retrying...
Starting GNSS module via UART...
createFileBuffer: Warning. fileBufferSize is zero. Data logging is not possible.

And running a code to display NMEA on the same port, keeping all configurations the same, here’s the output:

#include <TinyGPS++.h> // Biblioteca TinyGPS++

TinyGPSPlus gps; // Objeto da biblioteca TinyGPS++

#define RXD2 16
#define TXD2 17
#define GNSS Serial2

void setup()
{
  Serial.begin(115200); // Comunicação com o Serial Monitor
  GNSS.begin(115200, SERIAL_8N1, RXD2, TXD2); // Comunicação UART com o módulo GNSS
  delay(500); // Aguarda estabilização da comunicação
  Serial.println("Iniciando módulo GNSS via UART...");
}

void loop()
{
  static String nmeaLine = ""; // Armazena a linha de dados NMEA recebida

  // Processa os dados recebidos do GNSS
  while (GNSS.available() > 0) {
    char c = GNSS.read();
    Serial.print(c); // Exibe o caractere recebido diretamente no console

    // Constrói a linha completa de mensagem NMEA
    if (c == '\n') { // Final de linha encontrado
      Serial.println("\nLinha NMEA completa: " + nmeaLine);
      nmeaLine = ""; // Limpa o buffer para a próxima linha
    } else if (c != '\r') { // Ignora o caractere '\r'
      nmeaLine += c; // Adiciona o caractere ao buffer
    }

    gps.encode(c); // Decodifica os dados NMEA

    // Se houver informações válidas de localização, exibe no Serial
    if (gps.location.isUpdated()) {
      Serial.print("Latitude: ");
      Serial.println(gps.location.lat(), 6); // Exibe a latitude com 6 casas decimais
      Serial.print("Longitude: ");
      Serial.println(gps.location.lng(), 6); // Exibe a longitude com 6 casas decimais
    }
  }

  delay(100); // Aguarda antes de processar novos dados
}
Iniciando módulo GNSS via UART...
/*a lot of binary code*/ .............................

UBX-MON-VER
Software Version: EXT CORE 1.00 (0fa0ae)
Hardware Version: 00190000
Extension(s):
ROM BASE 0X118B2060
FWVER=HPG 1.32
PROTVER=27.31
MOD=ZED-F9P
GPS;GLO;GAL;BDS;SBAS;QZSS

Hi @Mateus ,

There is something very strange going on… I can not explain it.

Are you sure you have set the baud rate correctly?

NMEA data is text, human-readable text. You say you see “a lot of binary code” with the TinyGPS++ example. You should see text containing “$GNGGA” and your latitude and longitude?

Please share a photo or wiring diagram of how you are connecting the ESP32 to the TOPGNSS board.

Best,
Paul

Hi Paul,
I checked the baud rate, and it’s set to 115200. When I mentioned that a lot of binary code appears, it’s because after the reset, the module released the UBX and RTCM3 protocols, so I could see the NMEA data in addition to the binary data on the port. This happens because the program takes the characters from the serial port and sends them to the Serial.
Attached are a diagram and a screenshot. In the screenshot, you can verify the 115200 connection and see the messages:
u-blox GNSS initialized successfully…
GNSS module initialized successfully.

UART2 is connected to an RS232 module, which, via a null modem cable, is connected to another RS232 module that connects to the ESP32.

https://drive.google.com/drive/folders/1Br_E_d0a11WMldozUif49NPxMOGJ7BIF?usp=share_link

I can modify the ESP32 firmware to display NMEA, for example, in this connection system, and it works well.

Yes, I am certain the baud rate is set to 115200 on the TOP906 ports and in the test program configurations. I tested other baud rates, and the behavior remains the same: it connects but apparently does not receive the ACK.

I can see the NMEA messages. When I mentioned seeing “a lot of binary code,” it was because, after a reset, the module activates RTCM3 and UBX on the UART output. However, if I disable these protocols on the UART, I can see the NMEA messages perfectly. Even if I use PUTTY on the serial port and set it to 115200, I see the same output as the test program shows.

I am sharing the files via Google Drive since the platform did not allow me to attach the images.
TU CONsegue entrar nesse link ?
https://drive.google.com/drive/folders/1Br_E_d0a11WMldozUif49NPxMOGJ7BIF?usp=share_link

Yes, I am certain the baud rate is set to 115200 on the TOP906 ports and in the test program configurations. I tested other baud rates, and the behavior remains the same: it connects but apparently does not receive the ACK.

I can see the NMEA messages. When I mentioned seeing “a lot of binary code,” it was because, after a reset, the module activates RTCM3 and UBX on the UART output. However, if I disable these protocols on the UART, I can see the NMEA messages perfectly. Even if I use PUTTY on the serial port and set it to 115200, I see the same output as the test program shows.

I am sharing the files via Google Drive since the platform did not allow me to attach the images.
TU CONsegue entrar nesse link ?
[Images wire and screen ](https:// SparkFun - Google Drive)

Yes, I am certain the baud rate is set to 115200 on the TOP906 ports and in the test program configurations. I tested other baud rates, and the behavior remains the same: it connects but apparently does not receive the ACK.

I can see the NMEA messages. When I mentioned seeing “a lot of binary code,” it was because, after a reset, the module activates RTCM3 and UBX on the UART output. However, if I disable these protocols on the UART, I can see the NMEA messages perfectly. Even if I use PUTTY on the serial port and set it to 115200, I see the same output as the test program shows.

I am sharing the files via Google Drive since the platform did not allow me to attach the images.

Shared files

Hi Mateus,

Thank you for the photos.

It is clear that data is getting from the ZED UART2 to the ESP32. The issue may be that data is not being transmitted by the ESP32, or not arriving at the ZED. It could be a GPIO pin or UART (Serial) conflict.

Looking at the pins_arduino.h file for the heltec wifi lora 32 V2, I see that pin 16 is labelled RST_OLED. Link. So long as you are not attempting to use the OLED, you should be OK. And we know that the ESP32 is able to receive data.

Do you have a logic analyzer or oscilloscope which you could use to monitor Pin 17 and UART2 RXD?

There are different ways of defining the ESP32 HardwareSerial UARTs:

// In globals
HardwareSerial mySerial(1); // Use ESP32 UART1
int8_t myTxPin = 17; // GPIO pin for UART TX
int8_t myRxPin = 16; // GPIO pin for UART RX

// In setup
mySerial.begin(115200, SERIAL_8N1, myRxPin, myTxPin);
while (myGNSS.begin(mySerial) == false) //Connect to the u-blox module using mySerial
{
  Serial.println(F("u-blox GNSS not detected"));
}

Maybe try different GPIO pins? It looks like pins 12 and 13 are not used for anything else.

I am going to be away for a few days. Hopefully someone else can help you in the meantime.

Best wishes,
Paul