GPS Data missing and miss formatted

HI,
I am moving my project from an ESP32 S3 to a RP2040 feather to save on battery power. The issue I have, has stumped me. The GPS stream is not been recieved correctly and hence i am unable to parse the data when calling the gps routines.

However, the gps data stream is recieved correctly if I access the gps data stream from the main loop? which points to issue with my gps routine, buts it looks ok and does work fine on the ESP32 S3.

The gps outputs at 9600 baud at 1hz. I Only need to transmit $GNRMC and $GNGGA so the gps is set up for this.

I have created a stripped out code out to replicate and try and see what going wrong but I am stuck.

#include <Arduino.h>
#include <MicroNMEA.h>
#include "gnssmodule.h"

GNSSModule gnss;

void setup() {

  Serial2.setRX(9); // setup UART1 RX
  Serial2.setTX(8); // setup UART1 TX
  Serial.begin(115200);
  gnss.initialize();

}

void loop() {
//  while(Serial2.available()) {
//            Serial.write(Serial2.read());    // check we are reading gps data stream
          
 // outputs the correct and expected gps sentences        
//$GNGGA,103503.000,,,,,0,00,3.9,,,,,,*46
//$GNRMC,103503.000,V,,,,,,,190125,,,N,V*23
//$GNGGA,103504.000,,,,,0,00,3.9,,,,,,*41
//$GNRMC,103504.000,V,,,,,,,190125,,,N,V*24
//}

gnss.readGNSS();
// calling gps parse from gnssmodule produces only the $GNGGA up to the 8th field??????
//$GNGGA,104217.000,,,,,0,00,25.5$GNGGA,104218.000,,,,,0,00,25.5$GNGGA,104219.000,,,,,0,00,25.5$GNGGA,104220.000,,,,,0,00,25.5$GNGGA,
}

gnssmodule.h

#ifndef _GNSSMODULE_H
#define _GNSSMODULE_H

#include "Arduino.h"
#include "MicroNMEA.h"

class GNSSModule  {

public:
    MicroNMEA nmea;

    GNSSModule();
    bool readGNSS();
    void initialize();
    bool step();
    uint8_t getHour();
    uint8_t getMinute();
    double getLatitude();
    double getLongitude();
    
private:
    long _lastUpdateTime;
};

#endif

gnssmodule.cpp

#include "gnssmodule.h"

GNSSModule::GNSSModule() {};

void GNSSModule::initialize() {     // initialise the gps module
    Serial2.begin(9600);       //map GPS on uart1 to pin 8 and 9
    while(!Serial2.available()) {   // if serial2 available do stuff
    // add uirenderer screen to here if gpas is availabe
         }
  
 //   set a flag here to indicate init has worked
}

// Returns true if new data was read.
bool GNSSModule::readGNSS() {
    if((millis() - _lastUpdateTime) > 1000) {  // 1 hz update so make sure we only read after 1000ms
        while(Serial2.available()) {           // is serial ready?  
            Serial.write(Serial2.read());      // check we are reading gps data stream
         //   nmea.process(Serial2.read());  precess gps into usable data
        }
        _lastUpdateTime = millis();            // set update conter back to curent millis
        return true;                           // set flag to true if we have success
    } else {
        return false;                          // else return false no data
    }
}

uint8_t GNSSModule::getHour() {
    return nmea.getHour();
}

uint8_t GNSSModule::getMinute() {
    return nmea.getMinute();
}

double GNSSModule::getLatitude() {
  Serial.print(nmea.getLatitude());
    return (double) nmea.getLatitude();
}

double GNSSModule::getLongitude() {
    return (double) nmea.getLongitude();
}

bool GNSSModule::step() {
    return readGNSS();
}

Any pointers/help will be most welcome
regards
jeremy

I quick google search seems to indicate that the ESP32 uses a 256 byte serial buffer, but the RP2040 only uses 32 bytes. You are only reading the GPS serial data once each second, so the buffer is overflowing, causing most of the data to be lost.

It is generally better to read data from the serial input at frequent intervals, storing it in your own buffer until a full line of data has been received, then processing that line of data.

1 Like

Many thanks
It must be something like that. But it does read the gps stream correctly direct from the main loop. It only drops data when I try to get data in through the gnssmodule.cpp. Method gnssmodule::Readgnss()

In the main loop, you are reading characters from the GPS and writing them to Serial as soon as they arrive, instead of letting them accumulate in the receive buffer for 1000mS. At 9600 baud, it takes a bit over 33mS to fill a 32-byte buffer, any longer than that between reads and you risk losing characters.

1 Like

thanks
So i need to write some additional code to implement my own buffer in the readgnss . Ok i will try to do that
Many thanks

HI,
First hurdle over, with a bit of reading the solution was rewriting with buffer array inserted in the bool GNSSModule::readGNSS().

// Returns true if new data was read. Also RP2040 only has 32byte uart recieve buffer so needs message buffer routine.

bool GNSSModule::readGNSS() {

while (Serial2.available()>0)  // is there anything in the UART recieve buffer
{
  char inByte = Serial2.read();  //if so read the byte into the char inByte
  if(inByte!= '\n')  //look for line feed at the end of the sentance ie if not found then read char to buffer array
  {
_messageBuffer[_messagepos] = inByte;  // now put the read character into the array 
_messagepos ++;        // inc the array pointer
  }

  else
  {
_messageBuffer[_messagepos] = '\0';  //add a null to the end off the message
Serial.println(_messageBuffer);     // debug see if it works
 _messagepos=0;   //reset array pointer to first 
  }
}
  return true; 
}

thanks david_2018
jeremy

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.