stevemarple / MicroNMEA

A compact Arduino library to parse NMEA sentences.
GNU Lesser General Public License v2.1
98 stars 43 forks source link

isValid is always False #19

Open Subtle1rony opened 1 year ago

Subtle1rony commented 1 year ago

I am using the Portenta H7 with Portenta Cat. M1/NB IoT GNSS Shield, tying to run MicroNMEA_integration.ino example in the Arduino IDE. My GPS device is returning valid strings with data for $GPGGA and $GNRMC but it never sees them as valid.

Also I think the code gets stuck in this loop as the stream of nmea strings is continuous:

    while (GPS.available()) {
        char c = GPS.read();

        // process is true when a valid NMEA string has been processed
        nmeaProcessStatus = nmea.process(c); // this does periodically become 1
    }

I changed it to:

    while (GPS.available()  && !nmeaProcessStatus) {
        char c = GPS.read();
        // process is true when a valid NMEA string has been processed
        nmeaProcessStatus = nmea.process(c);
    }

Then it does break from the loop but these lines always return no for nmea.isValid()

        // Output GPS information from previous second
        Serial.print("Valid fix: ");
        Serial.println(nmea.isValid() ? "yes" : "no"); //this returns no
stevemarple commented 1 year ago

Is that in the gpsHardwareReset() function? The loop is intended to wait until the first valid mesage is received, so it seems no valid messages are being read. That could be for various reasons (for example, wrong pins or serial port, wrong baud rate, or lines too long for the buffer passed to MicroNMEA). Can you change the loop from

while (GPS.available()) {
    char c = GPS.read();
    ... 
}

to

while (GPS.available()) {
    char c = GPS.read();
    console.print(c);
    ... 
}

so that the incoming characters are printed? That should help identify where the problem is.

Subtle1rony commented 1 year ago

Thanks for the response! I did add a print and the individual characters printed as expected. The issue was with the while loop in the example, it never met a condition to break from it. However, it may have been a typo in the example, as I just changed the while loop to encapsulate everything and it started producing valid data.

I also realized this example script was part of an Arduino provided Portenta H7 GSM package, not necessarily directly from the MicroNMEA package. This the full script for MicroNMEA_integration.ino that worked for me, maybe it can help if someone else runs into the same issue.

#include <GPS.h>
#include <GSM.h>
#include <MicroNMEA.h>

#include "arduino_secrets.h"
constexpr auto pin { SECRET_PIN };
constexpr auto apn { SECRET_APN };
constexpr auto username { SECRET_USERNAME };
constexpr auto pass { SECRET_PASSWORD };

char nmeaBuffer[100];
MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));

// Keep track of NMEA string processing
auto nmeaProcessStatus { false };

// Check for valid fix every checkValidInterval ms
constexpr unsigned long checkValidInterval { 5000 };
unsigned long checkValidNow {};

void setup()
{
    Serial.begin(115200);
    for (const auto timeout = millis() + 2500; !Serial && millis() < timeout; delay(250))
        ;

    // GSM.debug(Serial);
    delay(1000);

    Serial.println("Starting Carrier Network registration");
    if (!GSM.begin(pin, apn, username, pass, CATM1)) {
        Serial.println("The board was not able to register to the network...");
        // do nothing forevermore:
        while (1)
            ;
    }
    Serial.println("Enable GNSS Engine...");
    // GPS.begin() start and eanble the GNSS engine
    GPS.begin();
    Serial.println("GNSS Engine enabled...");
    Serial.println("Waiting for a valid fix.");

    checkValidNow = millis();
}

void loop()
{
    while (GPS.available()) {
        char c = GPS.read();
        // process is true when a valid NMEA string has been processed
        nmeaProcessStatus = nmea.process(c);
//  } this was where the original while loop ended

      if (nmeaProcessStatus && millis() > checkValidNow) {
          checkValidNow = millis() + checkValidInterval;

          // Output GPS information from previous second
          Serial.print("Valid fix: ");
          Serial.println(nmea.isValid() ? "yes" : "no");

          if (!nmea.isValid())
              return;

          String navSystem;
          switch (nmea.getNavSystem()) {
          case 'N':
              navSystem = "GNSS";
              break;
          case 'P':
              navSystem = "GPS";
              break;
          case 'L':
              navSystem = "GLONASS";
              break;
          case 'A':
              navSystem = "Galileo";
              break;
          default:
              break;
          }
          Serial.print("Nav. system: ");
          Serial.println(navSystem);

          Serial.print("Num. satellites: ");
          Serial.println(nmea.getNumSatellites());

          Serial.print("HDOP: ");
          Serial.println(nmea.getHDOP() / 10., 1);

          Serial.print("Date/time: ");
          Serial.print(nmea.getYear());
          Serial.print('-');
          Serial.print(int(nmea.getMonth()));
          Serial.print('-');
          Serial.print(int(nmea.getDay()));
          Serial.print('T');
          Serial.print(int(nmea.getHour()));
          Serial.print(':');
          Serial.print(int(nmea.getMinute()));
          Serial.print(':');
          Serial.println(int(nmea.getSecond()));

          long latitude_mdeg = nmea.getLatitude();
          long longitude_mdeg = nmea.getLongitude();
          Serial.print("Latitude (deg): ");
          Serial.println(latitude_mdeg / 1000000., 6);

          Serial.print("Longitude (deg): ");
          Serial.println(longitude_mdeg / 1000000., 6);

          long alt;
          Serial.print("Altitude (m): ");
          if (nmea.getAltitude(alt))
              Serial.println(alt / 1000., 3);
          else
              Serial.println("not available");

          Serial.print("Speed: ");
          Serial.println(nmea.getSpeed() / 1000., 3);
          Serial.print("Course: ");
          Serial.println(nmea.getCourse() / 1000., 3);
          nmea.clear();
      }
    } //  changed to end while loop here
}