Closed TakiKroSmaN closed 2 years ago
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
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);
}
}
}
//=======================================================================
`
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
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?
OK, I will check your tips and let you know. Thank you :)
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?
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,A23 $GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598, ,10 $GPZDA,181813,14,10,2003,00,004F
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:
I hope this helps! Best wishes, Paul
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
Thank you very much! everything works perfect :)
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.