sparkfun / SparkFun_u-blox_GNSS_v3

An Arduino library which allows you to communicate seamlessly with u-blox GNSS modules using the Configuration Interface
Other
54 stars 24 forks source link

Missing callbacks for NMEA messages #38

Closed Benik3 closed 11 months ago

Benik3 commented 11 months ago

Subject of the issue

Callbacks (which can be set for e.g. NMEA GGA messages) are called only once, even that buffer on serial line contained more messages.

Your workbench

Wemos D1 mini ESP32 (ESP-WROOM-32) GPS Beitian BK-280 (Ublox M9) Connected using ESP Serial2 port. Now powered by USB.

Steps to reproduce

uint32_t tstcounter = 0;

void callbackGPGGA(NMEA_GGA_data_t *nmeaData)
{
    tstcounter++;
}

void setup()
{
    Serial.begin(115200);
    delay(1000);

    Serial2.setRxBufferSize(4096);
    Serial2.begin(115200); // GPIO Rx 16, Tx 17

    while (myGNSS.begin(Serial2) == false) // Connect to the u-blox module
    {
        Serial.println(F("u-blox GNSS not detected"));

        Serial.println(F("Retrying..."));
        delay(1000);
    }

    myGNSS.setNMEAGPGGAcallbackPtr(&callbackGPGGA); // register callback for GGA NMEA message
}

void loop()
{
    if (Serial2.available() > 2000) 
    {
        tstcounter = 0;
        myGNSS.checkUblox();
        myGNSS.checkCallbacks();
        Serial.printf("Callback was called: %d times\n", tstcounter);
    }
}

Expected behavior

Callback should be called for each received NMEA message. Also I would expect that check for callback is made inside the library (when doing reading and parsing during e.g. checkUblox or getPVT)

Actual behavior

The code above will always report 1 time of callback call, even that Serial buffer contain around 20 GGA messages.

PaulZC commented 11 months ago

Hi,

This is simply how the library functions. It is not a good match for your use case.

checkUblox will process all data waiting in the receive buffer. But, internally, there is storage for only one GNGGA or GPGGA message. If the buffer contains more than one GGA message, the later ones are discarded. checkCallbacks will only call the GGA callback once, using the first message.

The solution is to structure your code differently. If the GGA messages are arriving every 1000ms, structure your code so checkUblox and checkCallbacks are called every ~500ms. There is very little overhead. They will return almost immediately if: there is no data in the receive buffer; or no callbacks are waiting.

Best wishes, Paul

Benik3 commented 11 months ago

It's not really problem to call the check faster, it's just not fail proof. Unfortunately naming this functionality "callback" is not the best, because compared to how most callbacks works, this is just " manually check now if there was some NMEA message and return only last" instead of event based "hey there is NMEA message, jump to callback and then return back". Also what I found e.g. function getPVT also do parsing like checkUblox, so it can break the callback functionality even more, if you forgot to checkCallback after each use of such function.

Benik3 commented 11 months ago

I solved it now by adding CheckCallback into DevUBLOXGNSS::processNMEA. It's not the best solution (it will probably add some overhead), but works.