Skip to content

Automatic NMEA - VTG, RMC, ZDA #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
TakiKroSmaN opened this issue Feb 28, 2022 · 9 comments · Fixed by #122
Closed

Automatic NMEA - VTG, RMC, ZDA #120

TakiKroSmaN opened this issue Feb 28, 2022 · 9 comments · Fixed by #122
Labels
enhancement New feature or request

Comments

@TakiKroSmaN
Copy link

TakiKroSmaN commented Feb 28, 2022

Hello,

Could you create the same function for VTG, RMC and ZDA data?
My data logger require that data in NMEA structure.
Data logger: RaceChrono.

Thank you :)
Regards Tomasz.

@PaulZC
Copy link
Collaborator

PaulZC commented Feb 28, 2022

Hi Tomasz (@TakiKroSmaN ),
There may be an easy way to do this using processNMEA or setOutputPort.
It sounds like you are only using the library as an I2C to serial interface?
Adding Auto support for all three messages is quite a lot of work. Please tell me more about your application first.
Best wishes,
Paul

@TakiKroSmaN
Copy link
Author

Hi Paul,

GNSS: NEO-M9N
Board: SparkFun Thing Plus - ESP32-S2 WROOM

I'm read over UART NMEA data (enabled only required VTG, RMC, GGA, ZDA) and send it to the TCP/IP client which is RaceChrono apllication on my phone.
It's working but with 2-5sec. delay.

`

#include <WiFiClient.h>
#include <WiFi.h>

#include <Wire.h> //Needed for I2C to GNSS

#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;

int port = 80;  //Port number
WiFiServer server(port);

#define Hz 20 // navigation rate
#define Serial1Baud 9600 // 460800  //9600

boolean ledState = LOW;
unsigned long previousMillis = 0;        // will store last time LED was updated
unsigned long currentMillis = millis();

//Server connect to WiFi Network
const char *ssid = "GNSS";  //Enter your wifi SSID
const char *password = "abcdefghijk";  //Enter your wifi Password

//=======================================================================
//                    Power on setup
//=======================================================================
void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);

  Wire.begin();
  // Wire.setClock(100000);

  while (myGNSS.begin() == false)
  {
    currentMillis = millis();
    if (currentMillis - previousMillis >= 100) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(LED_BUILTIN, ledState);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);

  Serial1.begin(Serial1Baud);
  myGNSS.setSerialRate(Serial1Baud);

  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password); //Connect to wifi

  IPAddress myIP = WiFi.softAPIP();
  server.begin();


  myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_UART1); //Several of these are on by default on ublox board so let's disable them
  myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_UART1);
  myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_UART1);
  myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_UART1); //Only leaving GGA & VTG enabled at current navigation rate
  myGNSS.enableNMEAMessage(UBX_NMEA_VTG, COM_PORT_UART1);
  myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_UART1);
  myGNSS.enableNMEAMessage(UBX_NMEA_ZDA, COM_PORT_UART1);
  myGNSS.setUART1Output(COM_TYPE_NMEA);
  
  myGNSS.disableDebugging();

  myGNSS.setNavigationFrequency(Hz); //Set output to x times a second
  myGNSS.setMeasurementRate(1000 / Hz);
  myGNSS.setHNRNavigationRate(Hz);
  // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
  // myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
  myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages
  myGNSS.setDynamicModel(DYN_MODEL_AUTOMOTIVE);
  // Tell the library we are expecting the module to send PVT messages by itself to our Rx pin.
  // You can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call checkUblox cyclically)
  myGNSS.assumeAutoPVT(true, true);

  //myGNSS.saveConfiguration();


  /*  Serial.print("Open Telnet and connect to IP:");
    Serial.print(myIP);
    Serial.print(" on port ");
    Serial.println(port);*/
}
//=======================================================================
//                    Loop
//=======================================================================



void loop()
{
  WiFiClient client = server.available();

  if (client) {
    digitalWrite(LED_BUILTIN, HIGH);
    //client.println("Connected");
    client.flush();
    Serial1.flush();
    previousMillis = currentMillis;

    while (client.connected())
    {
      currentMillis = millis();
      if (currentMillis - previousMillis >= 5) {
        previousMillis = currentMillis;
        if (myGNSS.getPVT() && (myGNSS.getInvalidLlh() == false))
        {
          while (Serial1.available()) {
            client.write(Serial1.read());
          }
        }
      }
      else {
        client.flush();
        Serial1.flush();
      }

    }
    digitalWrite(LED_BUILTIN, LOW);
    client.stop();
  }


  else {
    currentMillis = millis();
    if (currentMillis - previousMillis >= 1000) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(LED_BUILTIN, ledState);
    }
  }
}
//=======================================================================

`

@PaulZC
Copy link
Collaborator

PaulZC commented Feb 28, 2022

Hi Tomasz (@TakiKroSmaN ),

OK. I think I understand what you are trying to do.

Please check that 9600 baud is fast enough to handle all the NMEA messages at 20Hz. I suspect you are trying to send too much data for 9600 baud. I think you need to use a higher baud rate? You can use setSerialRate to do that.

Instead of using serial, you could enable the NMEA messages on I2C. Then 'process' them (push then to WiFi) with processNMEA. Please see Example2. Delete everything to do with MicroNMEA. Do your client.write from inside processNMEA.

I can see how full "auto" support would help this, but, as I said, it is a lot of work - and you are the only person to have asked for it. ;-)

I am happy to leave this request open, but it will be a long time before I can implement it. If you have time, please add the required code yourself and send me a Pull Request.

Best wishes,
Paul

@PaulZC PaulZC added the enhancement New feature or request label Feb 28, 2022
@PaulZC
Copy link
Collaborator

PaulZC commented Feb 28, 2022

Also, it is not clear if you have the PVT messages enabled?
Instead of myGNSS.assumeAutoPVT(true, true);, please try myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution.
Maybe that is what is causing your code to stall?

@TakiKroSmaN
Copy link
Author

TakiKroSmaN commented Feb 28, 2022

OK, I will check your tips and let you know.
Thank you :)

@TakiKroSmaN
Copy link
Author

So, if I use band higher than 9600 I get communication problem (char error or stall for 1 sec).
PVT change doesn't help.
When I tried with processNMEA and use serial monitor then it's works but output is around 6Hz.

void loop()
{
  myGNSS.checkUblox();
}
//=======================================================================

void SFE_UBLOX_GNSS::processNMEA(char incoming)
{
  Serial.print(incoming);
}

I have no idea how to put in client.print in to SFE_UBLOX_GNSS::processNMEA becouse if I use while (client.connected) incoming is not refreshing.
If I use some other option then client after sent char is disconnected.
Is there any other fuction which I can use to get data from I2C?

@PaulZC
Copy link
Collaborator

PaulZC commented Mar 1, 2022

If we think about how much data you are trying to transfer:

GGA + VTG + RMC + ZDA

$GPGGA,002153.000,3342.6618,N,11751.3858,W,1,10,1.2,27.0,M,-34.2,M,,00005E
$GPVTG,309.62,T, ,M,0.13,N,0.2,K,A
23
$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598, ,10
$GPZDA,181813,14,10,2003,00,00
4F

That is 223 characters. And that doesn't include the extra decimal places for the high resolution Lat and Lon.

At 20Hz, you are trying to transfer close to 4500 Bytes per second. For serial, that is 45000 bits per second.

So for serial, you need to use at least 57600 baud. Probably 115200 to be safe.

100kHz I2C should be OK.

But that does not include the PVT message. That adds another 100 Bytes per message.

At 20Hz, you're now trying to transfer 6500 Bytes per second. 65000 bits per second. 115200 baud serial is probably OK, but 100kHz I2C is not looking good - there are large overheads with the I2C bus data transfer.

Then you need to think about how large your buffers are. Is the serial receive buffer in the ESP32 large enough to hold the data while you transfer it to WiFi, or will it overflow?

Then there is the data rate the ESP32 to phone WiFi connection can actually support - with all the transfer and application overheads. I do not know what that figure is.

processNMEA is called each time a single character is processed. You may get better results if:

  • You create a buffer in ESP32 memory. Say a RingBufferN or a similar circular FIFO buffer.
  • In processNMEA, add the character to the buffer.
  • In the main loop, wait until the buffer contains a suitable 'packet' of data before sending it.
    • I do not know what size that packet should be, but maybe 500 to 1000 characters?
    • It will depend on how efficient the WiFi connection is when transferring small vs large packets.
  • Monitor how much data the buffer contains.
    • Check it does not overflow.

I hope this helps!
Best wishes,
Paul

@PaulZC PaulZC linked a pull request Mar 2, 2022 that will close this issue
@PaulZC
Copy link
Collaborator

PaulZC commented Mar 2, 2022

Hi Tomasz (@TakiKroSmaN ),

It is your lucky day!

I was doing more work on the library and decided to add the auto support you requested. Please see the new auto-NMEA examples 3 and 4 for more details. v2.2.3 will be released in a few minutes.

Good luck with your project,
Paul

@TakiKroSmaN
Copy link
Author

Thank you very much! everything works perfect :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants