ESP32 with Ublox NEO-6M
ESP32 with Ublox NEO-6M
For the past days, I have been trying to make the ESP32 work with the Ublox NEO-6M GPS module.
I haven't found any libraries to work with micropython.
I have connected the gps module with the esp and it is blinking red every second which if i'm not wrong means that it has a gps lock.
I just need to get the gps latitude and longitude once in a while and not every second.
Is there any library or any code I can use?
I haven't found any libraries to work with micropython.
I have connected the gps module with the esp and it is blinking red every second which if i'm not wrong means that it has a gps lock.
I just need to get the gps latitude and longitude once in a while and not every second.
Is there any library or any code I can use?
Re: ESP32 with Ublox NEO-6M
Most GPS devices communicate with the host by sending NMEA data over a UART. You should be able to read this using machine.UART on the ESP32.
NMEA is text based so it's easy to see whether you're getting data...my memory from debugging NMEA systems on boats is that it's something like $GPRMC is the line that has the lat/long in it.
There was a thread on the forum recently discussing using https://github.com/peterhinch/micropyth ... master/gps -- that looks like a great way to work with this.
NMEA is text based so it's easy to see whether you're getting data...my memory from debugging NMEA systems on boats is that it's something like $GPRMC is the line that has the lat/long in it.
There was a thread on the forum recently discussing using https://github.com/peterhinch/micropyth ... master/gps -- that looks like a great way to work with this.
Re: ESP32 with Ublox NEO-6M
I saw the github link.jimmo wrote: ↑Sat Feb 15, 2020 11:41 pmMost GPS devices communicate with the host by sending NMEA data over a UART. You should be able to read this using machine.UART on the ESP32.
NMEA is text based so it's easy to see whether you're getting data...my memory from debugging NMEA systems on boats is that it's something like $GPRMC is the line that has the lat/long in it.
There was a thread on the forum recently discussing using https://github.com/peterhinch/micropyth ... master/gps -- that looks like a great way to work with this.
And yes it does work and very nicely indeed.
I am trying to get the NMEA data and then edit them myself.
This is my part of the code that has to do with gps
Code: Select all
from machine import UART
uart = UART(2, 9600)
uart.init(9600, bits=8, parity=None, stop=1)
test = uart.read()
print(test)
if(test == None):
print('No location found')
else:
#edit the NMEA data
And if i run the script many times in a row i'll freeze the esp board.
Both the gps board and the esp board are at the same spot where the github code gets coordinates normally.
So i'm definitely doing something wrong here and therefore i'm not being able to get the NMEA data.
EDIT
I just pressed the EN button of the ESP.
When i ran the script again i get NMEA data.
But only for the first time i run it.
Then i get 'None' again as data.
So every time i press the EN button i get data for the first run of the script only.
Re: ESP32 with Ublox NEO-6M
Maybe you can glean from the test code below, running just fine on a TTGO T-22-V1.7 with a NEO-6M. MicropyGPS still needs some work as it's not really coded to deal with erroneous NMEA strings. As you can see the T22 board has an additional cheap OLED display of the SSD1306 family connected to GPIO0 and GPIO4 working as I2C to make the module a standalone GPS receiver.
If you only want to see the acquired data on the console uncomment the #print lines.
Hint: I usually work with Thonny as a minimal IDE for my microPython work, giving me really good turn around times when programming.
Links:
MicropyGPS - https://github.com/inmcm/micropyGPS
Thonny - https://thonny.org/
If you only want to see the acquired data on the console uncomment the #print lines.
Hint: I usually work with Thonny as a minimal IDE for my microPython work, giving me really good turn around times when programming.
Links:
MicropyGPS - https://github.com/inmcm/micropyGPS
Thonny - https://thonny.org/
Code: Select all
import time
import machine
from micropyGPS import MicropyGPS
import ssd1306
import _thread
import time
WIDTH = 128
HEIGHT = 64
def main():
i2c = machine.I2C(scl=machine.Pin(0), sda=machine.Pin(4))
dsp = ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, 0x3c, False)
uart = machine.UART(1, rx=12, tx=15, baudrate=9600, bits=8, parity=None, stop=1, timeout=5000, rxbuf=1024)
gps = MicropyGPS()
while True:
buf = uart.readline()
for char in buf:
gps.update(chr(char)) # Note the conversion to to chr, UART outputs ints normally
#print('UTC Timestamp:', gps.timestamp)
#print('Date:', gps.date_string('long'))
#print('Latitude:', gps.latitude)
#print('Longitude:', gps.longitude_string())
#print('Horizontal Dilution of Precision:', gps.hdop)
#print('Altitude:', gps.altitude)
#print('Satellites:', gps.satellites_in_use)
#print()
dsp.fill(0)
y = 0
dy = 10
dsp.text("{}".format(gps.date_string('s_mdy')), 0, y)
dsp.text("Sat:{}".format(gps.satellites_in_use), 80, y)
y += dy
dsp.text("{:02d}:{:02d}:{:02.0f}".format(gps.timestamp[0], gps.timestamp[1], gps.timestamp[2]), 0, y)
y += dy
dsp.text("Lat:{}{:3d}'{:02.4f}".format(gps.latitude[2], gps.latitude[0], gps.latitude[1]), 0, y)
y += dy
dsp.text("Lon:{}{:3d}'{:02.4f}".format(gps.longitude[2], gps.longitude[0], gps.longitude[1]), 0, y)
y += dy
dsp.text("Alt:{:0.0f}ft".format(gps.altitude * 1000 / (12*25.4)), 0, y)
y += dy
dsp.text("HDP:{:0.2f}".format(gps.hdop), 0, y)
dsp.show()
def startGPSthread():
_thread.start_new_thread(main, ())
if __name__ == "__main__":
print('...running main, GPS testing')
main()
Re: ESP32 with Ublox NEO-6M
The GPS will only send data over the UART periodically, so not every call to read() will return data.
But you also need to do more work to buffer and re-assemble lines. I assume this is what micropygps and as_GPS do.
Re: ESP32 with Ublox NEO-6M
I tried with the code you mentioned.wthie wrote: ↑Sun Feb 16, 2020 10:23 pmMaybe you can glean from the test code below, running just fine on a TTGO T-22-V1.7 with a NEO-6M. MicropyGPS still needs some work as it's not really coded to deal with erroneous NMEA strings. As you can see the T22 board has an additional cheap OLED display of the SSD1306 family connected to GPIO0 and GPIO4 working as I2C to make the module a standalone GPS receiver.
If you only want to see the acquired data on the console uncomment the #print lines.
Hint: I usually work with Thonny as a minimal IDE for my microPython work, giving me really good turn around times when programming.
Links:
MicropyGPS - https://github.com/inmcm/micropyGPS
Thonny - https://thonny.org/
Code: Select all
import time import machine from micropyGPS import MicropyGPS import ssd1306 import _thread import time WIDTH = 128 HEIGHT = 64 def main(): i2c = machine.I2C(scl=machine.Pin(0), sda=machine.Pin(4)) dsp = ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, 0x3c, False) uart = machine.UART(1, rx=12, tx=15, baudrate=9600, bits=8, parity=None, stop=1, timeout=5000, rxbuf=1024) gps = MicropyGPS() while True: buf = uart.readline() for char in buf: gps.update(chr(char)) # Note the conversion to to chr, UART outputs ints normally #print('UTC Timestamp:', gps.timestamp) #print('Date:', gps.date_string('long')) #print('Latitude:', gps.latitude) #print('Longitude:', gps.longitude_string()) #print('Horizontal Dilution of Precision:', gps.hdop) #print('Altitude:', gps.altitude) #print('Satellites:', gps.satellites_in_use) #print() dsp.fill(0) y = 0 dy = 10 dsp.text("{}".format(gps.date_string('s_mdy')), 0, y) dsp.text("Sat:{}".format(gps.satellites_in_use), 80, y) y += dy dsp.text("{:02d}:{:02d}:{:02.0f}".format(gps.timestamp[0], gps.timestamp[1], gps.timestamp[2]), 0, y) y += dy dsp.text("Lat:{}{:3d}'{:02.4f}".format(gps.latitude[2], gps.latitude[0], gps.latitude[1]), 0, y) y += dy dsp.text("Lon:{}{:3d}'{:02.4f}".format(gps.longitude[2], gps.longitude[0], gps.longitude[1]), 0, y) y += dy dsp.text("Alt:{:0.0f}ft".format(gps.altitude * 1000 / (12*25.4)), 0, y) y += dy dsp.text("HDP:{:0.2f}".format(gps.hdop), 0, y) dsp.show() def startGPSthread(): _thread.start_new_thread(main, ()) if __name__ == "__main__": print('...running main, GPS testing') main()
I did make some changes to it to match my hardware/needs.
My code is below:
Code: Select all
from machine import UART
from micropyGPS import MicropyGPS
uart = UART(2, baudrate=9600, bits=8, parity=None, stop=1)
gps = MicropyGPS()
buf = uart.readline()
print("TEST PRINTING BUFFER:")
print(buf)
for char in buf:
gps.update(chr(char)) # Note the conversion to to chr, UART outputs ints normally
print('UTC Timestamp:', gps.timestamp)
print('Date:', gps.date_string('long'))
print('Latitude:', gps.latitude)
print('Longitude:', gps.longitude_string())
print('Horizontal Dilution of Precision:', gps.hdop)
print('Altitude:', gps.altitude)
print('Satellites:', gps.satellites_in_use)
print()
Which if i am understanding correctly means that the "buf" value is Null instead of having a value.
Could you explain how that part of the code works or suggest some solution?
Yes, that seems to be the case.
I was just hoping for a way to check if gps has data and receive them and then extract only the info i needed(GPRMC) using my code.
I already have made code to extract the info from the NMEA string.
Now i need a way to get the NMEA itself
Re: ESP32 with Ublox NEO-6M
Yeah. You need to do something like:
Code: Select all
line = uart.readline()
if line:
for c in line:
gps.update(c)
but what you probably actually want is:
Code: Select all
while True:
if uart.any():
gps.update(chr(uart.read()))
else:
# do other things?
- romeotango
- Posts: 29
- Joined: Tue Jun 16, 2015 10:52 am
- Location: Germany
Re: ESP32 with Ublox NEO-6M
Hello, good morning!
In principle it is quite simple:
Read and interpret the output.
Unfortunately the output of the GPS module is not always correct and above all not complete.
Cleaning up the values is an essential part of the work.
Peter Hinch has thought a lot about this. And even more important: he has documented it really well.
Before you start dealing with recurring problems with the data stream, read
https://github.com/peterhinch/micropython-async/gps.
The methods of data preparation are understandable without asyncio, especially because they are well documented in the program.
By the way: The data from the GPS module are read as bytecode with readline(), so they have to be converted first. This is also very well explained there.
Please always keep in mind that a GPS module needs a long time to provide correct position data, especially under 'non free sky' conditions.
RT
In principle it is quite simple:
Read and interpret the output.
Unfortunately the output of the GPS module is not always correct and above all not complete.
Cleaning up the values is an essential part of the work.
Peter Hinch has thought a lot about this. And even more important: he has documented it really well.
Before you start dealing with recurring problems with the data stream, read
https://github.com/peterhinch/micropython-async/gps.
The methods of data preparation are understandable without asyncio, especially because they are well documented in the program.
By the way: The data from the GPS module are read as bytecode with readline(), so they have to be converted first. This is also very well explained there.
Please always keep in mind that a GPS module needs a long time to provide correct position data, especially under 'non free sky' conditions.
RT
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: ESP32 with Ublox NEO-6M
Rather than starting from scratch can I suggest an alternative approach? Take the working solution and adapt its NMEA parsing to suit your requirements.
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: ESP32 with Ublox NEO-6M
So i ended up doing something like that:
With that code i get NMEA data nearly every time succesfully.
Maybe the module has gotten a better satelite fix as well compared to the previous days.
I also managed to transform to lat/lon data succesfully.
I get "ValueError: invalid syntax for number" some times at the latfinal and longfinal lines but that shouldn't be anything hard to fix.
Thanks everyone for your help and suggestions.
Code: Select all
uart = UART(2, baudrate=9600, bits=8, parity=None, stop=1)
line = uart.readline()
#tries to get value from uart around every second for 10 seconds or less
#if it gets data it checks if GPRMC is present and it breaks the for function if it is
for x in range(10):
line = uart.readline()
time.sleep(1)
if("GPRMC" in str(line)):
#print("FOUND GPRMC")
break
x = str(line).split("\r\n")
for i in range(len(x)):
if("$GPRMC" in x[i]):
counter = i
splitted = x[counter].split(",")
#if statements for calculating lat/long in case we get value 28 or 028
#lat
if(int(splitted[3][0:2])<10):
latfinal = float(splitted[3][0:3]) + float(splitted[3][3:])/60
else:
latfinal = float(splitted[3][0:2]) + float(splitted[3][2:])/60
print("Latitude is: " + str(latfinal))
#lon
if(int(splitted[5][0:2])<10):
longfinal = float(splitted[5][0:3]) + float(splitted[5][3:])/60
else:
longfinal = float(splitted[5][0:2]) + float(splitted[5][2:])/60
print("Longtitude is: " + str(longfinal))
Maybe the module has gotten a better satelite fix as well compared to the previous days.
I also managed to transform to lat/lon data succesfully.
I get "ValueError: invalid syntax for number" some times at the latfinal and longfinal lines but that shouldn't be anything hard to fix.
Thanks everyone for your help and suggestions.