With the release of the drivers for UART I thought I'd put them through their paces so pulled out a GPS receiver module. This is a cheap module that connects to the ESP32 as a 9600 bps serial device. The new driver worked exactly as advertised and there were no issues. I hooked up the ability to read a line at a time from UART and echoed the result to the debug log. Next I thought I'd have a go at decoding the result. Most GPS devices emit line terminated ASCII strings called "sentences" that conform to the NMEA 183 protocol. Thankfully there is a pre-built library for working with this protocol that can be found here:
https://github.com/cloudyourcar/minmea
It compiled cleanly under ESP-IDF and worked first time without issue. I now read lines from UART which is connected to the GPS module. The lines are passed into the NMEA parser and the result is all the GPS data we could want including latitude, longitude, speed, track (heading), real world clock time, satellites in view and satellites being used. There is a world of other data available but I haven't seen a need to investigate that yet.
No obvious use for GPS attached to ESP32 yet but possibilities could include autonomous robots, tracking/recording (put one in your car to see where your car ends up) etc etc.
Later ... sample now available on GitHub: https://github.com/nkolban/esp32-snippe ... re/gps/gps
[Info] GPS decoding on the ESP32
[Info] GPS decoding on the ESP32
Last edited by kolban on Wed Jan 18, 2017 4:37 am, edited 1 time in total.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: GPS decoding on the ESP32
Thanks -- I want to put an ESP32 and a GPS in my car so it can sync when it comes to my home/office WiFi so I can use it to track mileage etc. I think this will definitely get used!
-
- Posts: 1
- Joined: Wed Feb 05, 2020 4:03 am
Re: [Info] GPS decoding on the ESP32
Hi @kolban,
I read quite a few of your posts and your ESP32 book.
There is a topic onto which there is not enough detailed explanation on in my view:
Time slicing and time scheduling on sensor polling.
Typically using an MCU like ESP32 to build a multi-sensor system : How would you go about reading the GPS data stream on serial in an efficient way. Efficient as in: Avoid looping on Serial.read() >0 all the time when the GPS receiver is producing updates at 1Hz (light years for a 240MHZ MCU).
This means that :
- Looping 100% of the time will eat up 1 of the 2 cpu cores of the ESP32
- However if not reacting fast when the 1st character of a new NMEA sentence update is produced, then we get a serial buffer overflow and miss data. what's the best strategy to achieve that ?
I thought of the following sequence
1) ESP32 startup + GPS initialisation
2) ESP32 thread A starts looping over serial.available()
3) the 1st character arrives on serial, thread A records the timestamp
4) thread A stops looping over serial.available() but instead Using the recorded timestamp, triggers a periodic timers interrupt exacly 1second later
so that we are polling the GPS at 1Hz and in sync with updates
5) Everytime the ISR handler is called, dispatch a task notification to a task that loops over the Serial port, reads the GPS update and then processes / logs it on SD card etc.False
Would that be a good strategy : an alternative I thought of is using the PPS interrupt, my question is : is the PPS interrupt in sync with position updates, or is it just
a quartz that is in sync with the GPS atomic clock time gotten from the GPS network ?
i.e. I know that the PPS depending on configuration sends 1 to many pulses interrupt signal per second on the the PPS pin.
Now if the pps rate in HZ is known it should be possible to correlate it to the GPS position update reception ? or maybe not if im wrong.
I never managed to get to the bottom of this question. not enough time to investigate with my day job working on software but other matters.
Last but not least I heard that become reading data from the serial port continuously + processing NMEA sentences is about the heaviest task an average MCU based system is gonna
do, it's a good idea to do the housekeeping work i.e. log data to SD card, in the gap of time when the GPS data has been received and processed, when the MCU does not have
anything to do until the next GPS update : empty GAP time slot below
time sequence:
t0 t = t0+1s t0 +2s
|GPS update | GPS data processing | empty GAP... | next GPS update | next GPS data processing | next GAP |
so so so so many simplistic GPS reading examples around without the how and why one needs to be careful about not wasting time looping for nothing.
I'd love having your view on that. I see so many codes which are sub-optimal in terms or Real time mcu time scheduling.
i.e either simplistic using a switch() case cycle == x : ... cycle++ state machine, or multiple tasks and way too many semaphore or mutexes.
An external interrupts, + timer interrupts + a handling tasks that gets to do the processing work commanded by triggered interrupts seems like a good compromise to me.
i.e .
GPS interrupt, sensor A,B,C ... interrupts, housekeeping interrupts, screen update interrupts...
core 0 :
maintask(){
//setup interrupts.
// create interruptHandlerTask()
}
core 1:
interruptHandlerTask() {
switch (ISR_FLAG) {
case sensor A,B,C, GPS, screen update:
do_the_dataprocessing_work()
}
}
I read quite a few of your posts and your ESP32 book.
There is a topic onto which there is not enough detailed explanation on in my view:
Time slicing and time scheduling on sensor polling.
Typically using an MCU like ESP32 to build a multi-sensor system : How would you go about reading the GPS data stream on serial in an efficient way. Efficient as in: Avoid looping on Serial.read() >0 all the time when the GPS receiver is producing updates at 1Hz (light years for a 240MHZ MCU).
This means that :
- Looping 100% of the time will eat up 1 of the 2 cpu cores of the ESP32
- However if not reacting fast when the 1st character of a new NMEA sentence update is produced, then we get a serial buffer overflow and miss data. what's the best strategy to achieve that ?
I thought of the following sequence
1) ESP32 startup + GPS initialisation
2) ESP32 thread A starts looping over serial.available()
3) the 1st character arrives on serial, thread A records the timestamp
4) thread A stops looping over serial.available() but instead Using the recorded timestamp, triggers a periodic timers interrupt exacly 1second later
so that we are polling the GPS at 1Hz and in sync with updates
5) Everytime the ISR handler is called, dispatch a task notification to a task that loops over the Serial port, reads the GPS update and then processes / logs it on SD card etc.False
Would that be a good strategy : an alternative I thought of is using the PPS interrupt, my question is : is the PPS interrupt in sync with position updates, or is it just
a quartz that is in sync with the GPS atomic clock time gotten from the GPS network ?
i.e. I know that the PPS depending on configuration sends 1 to many pulses interrupt signal per second on the the PPS pin.
Now if the pps rate in HZ is known it should be possible to correlate it to the GPS position update reception ? or maybe not if im wrong.
I never managed to get to the bottom of this question. not enough time to investigate with my day job working on software but other matters.
Last but not least I heard that become reading data from the serial port continuously + processing NMEA sentences is about the heaviest task an average MCU based system is gonna
do, it's a good idea to do the housekeeping work i.e. log data to SD card, in the gap of time when the GPS data has been received and processed, when the MCU does not have
anything to do until the next GPS update : empty GAP time slot below
time sequence:
t0 t = t0+1s t0 +2s
|GPS update | GPS data processing | empty GAP... | next GPS update | next GPS data processing | next GAP |
so so so so many simplistic GPS reading examples around without the how and why one needs to be careful about not wasting time looping for nothing.
I'd love having your view on that. I see so many codes which are sub-optimal in terms or Real time mcu time scheduling.
i.e either simplistic using a switch() case cycle == x : ... cycle++ state machine, or multiple tasks and way too many semaphore or mutexes.
An external interrupts, + timer interrupts + a handling tasks that gets to do the processing work commanded by triggered interrupts seems like a good compromise to me.
i.e .
GPS interrupt, sensor A,B,C ... interrupts, housekeeping interrupts, screen update interrupts...
core 0 :
maintask(){
//setup interrupts.
// create interruptHandlerTask()
}
core 1:
interruptHandlerTask() {
switch (ISR_FLAG) {
case sensor A,B,C, GPS, screen update:
do_the_dataprocessing_work()
}
}
Who is online
Users browsing this forum: No registered users and 41 guests