In this tutorial, we will learn about a NEO-6M GPS module and how to interface it with ESP32 using MicroPython to obtain GPS parameters such as latitude, longitude, altitude, date, time, speed, satellites, etc. We will learn how GPS works and the overview of the NEO-6M GPS module with an introduction, pinout, and specifications. After that, we will learn to interface a NEO-6M GPS Module module with ESP32.
For demonstration purposes, we will display the GPS location parameters including latitude, longitude, number of satellites, and current time on the Thonny shell console as well as on an OLED.
We have a similar guide with Raspberry Pi Pico:
PrerequisitesBefore we start this lesson make sure you are familiar with and have the latest version of MicroPython firmware installed in your ESP32 board and have a running Integrated Development Environment (IDE) in which we will be doing the programming such as uPyCraft IDE or Thonny IDE.
If you want to use VS Code, you can follow this guide:
Recommended Reading: GPS ( Global Positioning System) – working
The Global Positioning System (GPS) is a satellite-based navigation system that consists of 24 orbiting satellites, each of which makes two circuits around the Earth every 24 hours. These satellites transmit three bits of information – the satellite’s number, its position in space, and the time the information is sent. These signals are picked up by the GPS receiver, which uses this information to calculate the distance between it and the GPS satellites. With signals from three or more satellites, a GPS receiver can triangulate its location on the ground (i.e., longitude and latitude) from the known position of the satellites. With four or more satellites, a GPS receiver can determine a 3D position (i.e., latitude, longitude, and elevation).
In addition, a GPS receiver can provide data on your speed and direction of travel. Anyone with a GPS receiver can access the system. Because GPS provides real-time, three-dimensional positioning, navigation, and timing 24 hours a day, 7 days a week, all over the world, it is used in numerous applications, including GIS data collection, surveying, and mapping.
Point to Remember: A GPS receiver locates any three or more of the satellites, calculates the distance to each, and uses this information to generate its own location. This operation is based on a simple mathematical principle called Trilateration.
NEO-6M GPS Module IntroductionThe NEO-6M GPS module is a GPS receiver that can locate all locations on Earth as it is able to track approximately 22 satellites. It consists of a high-performance u-blox 6 positioning engine. Measuring 16 x 12.2 x 2.4 mm, its compact architecture along with its low power consumption makes it a good choice for IoT projects. Overall it is a good cost-effective GPS receiver.
Hardware OverviewLet us learn a little bit about its hardware. To obtain GPS readings, we have to use the NEO-6M GPS module with an antenna. The antenna is firmly attached to the module via the U.FL connector. This connector is found on the GPS module.
NEO-6M GPS ChipIn the middle of the GPS module, you can find the NEO-6M chip. This is responsible for tracking up to 22 satellites and any location on the Earth on several channels. Due to its highly sensitive tracking nature, it makes the NEO-6M module a popular GPS tracker.
Some key features of NEO-6M chip include:
Moving ahead, the module comes with a position fix LED indicator. This LED indicates through its blinking effect whether the module is searching for satellites or has already found them. If the LED blinks after every second, then it indicates that the position fix is found. However, if the LED does not blink then the module is still searching for the satellites.
3.3V low-dropout RegulatorThe module also comes equipped with a 3.3V LDO regulator (MIC5205). This provides an efficient linear voltage regulation with ultralow-noise output and very low dropout voltage. Additionally, the module is can also tolerate 5V easily.
SpecificationsThe table below shows some specifications of the NEO-6M module.
Type GPS Supply 2.7 V-3.6 V Operating Current 45mA Operating Temperature -40°C ~ 85°C Horizontal Position Accuracy 2.5m Communication Protocol NMEA, UBX Binary, RTCM Features RTC Crystal and External Interrupt/Wake up Interface UART, SPI, USB and DDCFor more information regarding the NEO-6M module refer to its datasheet given here.
Pinout of NEO 6M ModuleThe diagram below shows the pinout of the NEO 6M module. It consists of 4 pins named GND, TX, RX, and VCC.
GND This is the ground pin that will be connected with the ground of the microcontroller. TX This is the transmission pin used for serial communication. RX This is the receiver pin used for serial communication. VCC This is the VCC pin used to power up the GPS module. Interfacing NEO-6M Module with ESP32 and OLEDWe will need the following components to connect our ESP32 development board with the OLED Display and NEO-6M GPS module.
The OLED display has 4 terminals which we will connect with the ESP32 board. As the OLED display requires an operating voltage in the range of 3.3-5V hence we will connect the VCC terminal with 3.3V which will be in common with the ESP32 board. SCL of the display will be connected with the SCL pin of the module and the SDA of the display will be connected with the SDA of the module. By default, the I2C pin in ESP32 for SDA is GPIO21, and for SCL is GPIO22. The connections between the two devices can be seen in the table below.
SSD1306 OLED Display ESP32 VCC 3.3V SDA GPIO21(I2C SDA) SCL GPIO22(I2C SCL) GND GNDSimilarly, the NEO-6M GPS module also has 4 terminals which we will connect with the ESP32 board. As the GPS module requires an operating voltage in the range of 2.7-3.6V hence we will connect the VCC terminal with 3.3V which will be in common with the ESP32 board. The TX (transmitter) terminal of the GPS module will be connected with the RX2 pin of the ESP32 for communication. Likewise, the RX (receiver) terminal of the GPS module will be connected with the TX2 pin of the ESP32.
ESP32 NEO-6M Module 3.3V VCC RX2 TX TX2 RX GND GNDAll three devices will be commonly grounded.
The diagram below shows the schematic diagram of ESP32 with OLED display and NEO 6M Module.
ESP32 with NEO-6M and OLED Understanding basic NMEA sentenceThe NEO-6M GPS module sends GPS data in NMEA format. It is of various kinds including $GPRMC, $GPGGA etc. Each NMEA data field is separated by a comma and starts with a ‘$’.
Below you can view the $GPXXX syntax that denotes the different types of NMEA messages:
$GPGGA Global Positioning System Fix Data. It provides 3D location and accuracy data $GPGSA It provides GPS DOP and active satellites $GPGSV It provides the detailed information of the GPS satellite $GPGLL It provides the geographic Latitude and Longitude $GPRMC It provides the position, velocity and time $GPVTG It provides the dual ground/water speedLet us understand how to read the basic NMEA sentence i.e. $GPGGA. Here is an example $GPGGA NMEA sentence:
$GPGGA, 103005, 3807.038, N, 07128.99030, E, 1, 07, 1.43, 134.5, M, 42.9, M, , *78
We will have to install the SSD1306 OLED library for MicroPython to continue with our project.
Install this library.
After a few moments this library will get successfully installed. Now we are ready to program our ESP32 with OLED display.
MicroPython Script Obtaining GPS Data from NEO-6M Modulefrom machine import Pin, UART, SoftI2C
from ssd1306 import SSD1306_I2C
import utime, time
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000) #initializing the I2C method for ESP32
oled = SSD1306_I2C(128, 64, i2c)
gpsModule = UART(2, baudrate=9600)
print(gpsModule)
buff = bytearray(255)
TIMEOUT = False
FIX_STATUS = False
latitude = ""
longitude = ""
satellites = ""
GPStime = ""
def getGPS(gpsModule):
global FIX_STATUS, TIMEOUT, latitude, longitude, satellites, GPStime
timeout = time.time() + 8
while True:
gpsModule.readline()
buff = str(gpsModule.readline())
parts = buff.split(',')
if (parts[0] == "b'$GPGGA" and len(parts) == 15):
if(parts[1] and parts[2] and parts[3] and parts[4] and parts[5] and parts[6] and parts[7]):
print(buff)
latitude = convertToDegree(parts[2])
if (parts[3] == 'S'):
latitude = -latitude
longitude = convertToDegree(parts[4])
if (parts[5] == 'W'):
longitude = -longitude
satellites = parts[7]
GPStime = parts[1][0:2] + ":" + parts[1][2:4] + ":" + parts[1][4:6]
FIX_STATUS = True
break
if (time.time() > timeout):
TIMEOUT = True
break
utime.sleep_ms(500)
def convertToDegree(RawDegrees):
RawAsFloat = float(RawDegrees)
firstdigits = int(RawAsFloat/100)
nexttwodigits = RawAsFloat - float(firstdigits*100)
Converted = float(firstdigits + nexttwodigits/60.0)
Converted = '{0:.6f}'.format(Converted)
return str(Converted)
while True:
getGPS(gpsModule)
if(FIX_STATUS == True):
print("Printing GPS data...")
print(" ")
print("Latitude: "+latitude)
print("Longitude: "+longitude)
print("Satellites: " +satellites)
print("Time: "+GPStime)
print("----------------------")
oled.fill(0)
oled.text("Lat: "+latitude, 0, 0)
oled.text("Lng: "+longitude, 0, 10)
oled.text("Satellites: "+satellites, 0, 20)
oled.text("Time: "+GPStime, 0, 30)
oled.show()
FIX_STATUS = False
if(TIMEOUT == True):
print("No GPS data is found.")
TIMEOUT = False
How the Code Works?
We will start by importing the UART, Pin and SoftI2C class from the machine module. Next we will also import utime and time module to incorporate delays. We will also import the ssd1306 which is the OLED display library that we installed earlier. This will help us in accessing all the functions defined inside it.
from machine import Pin, UART, SoftI2C
from ssd1306 import SSD1306_I2C
import utime, time
Initializing OLED
Next, we will initialize the I2C GPIO pins for SCL and SDA respectively.
We have created an I2C() method which takes in three parameters. The first parameter specifies the I2C GPIO pin of the board which is connected to the SCL line. The second parameter specifies the I2C GPIO pin of the board which is connected to the SDA line. The last parameter is the frequency connection of the OLED.
We are setting the SCL on GPIO22 and the SDA on GPIO21.
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000)
This SCL and SDA pin data gets saved in the object ‘i2c’ which will connect to the I2C bus and help in the communication between the two devices
Now, we will create an object ‘oled’ of SSD1306_I2C which uses the width, height, and the i2c object as parameters.
oled = SSD1306_I2C(128, 64, i2c)
Initialize UART Communication
Then we will define the NEO-6M UART connection by creating an object ‘gpsModule’. By using UART() we specified the UART channel as the first parameter and the baud rate as the second parameter. We are using UART2 in this case with baud rate 9600 for the uart communication.
Then we will print these NEO-6M module connection details in the Thonny shell console.
gpsModule = UART(2, baudrate=9600)
print(gpsModule)
Data Variables
Then we will create a byte array object called buff to store the NMEA sentences.
buff = bytearray(255)
The following variables will store the GPS parameters including Latitude, Longitude, Number of satellites and UTC time.
latitude = ""
longitude = ""
satellites = ""
GPStime = ""
The following function obtains the GPS coordinates. We are running a while loop to obtain the GPS data from the basic NMEA sentence $GPGGA. Latitude, Longitude, Satellites and time will be acquired from the NMEA sentence accordingly and saved in their respective variables.
def getGPS(gpsModule):
global FIX_STATUS, TIMEOUT, latitude, longitude, satellites, GPStime
timeout = time.time() + 8
while True:
gpsModule.readline()
buff = str(gpsModule.readline())
parts = buff.split(',')
if (parts[0] == "b'$GPGGA" and len(parts) == 15):
if(parts[1] and parts[2] and parts[3] and parts[4] and parts[5] and parts[6] and parts[7]):
print(buff)
latitude = convertToDegree(parts[2])
if (parts[3] == 'S'):
latitude = -latitude
longitude = convertToDegree(parts[4])
if (parts[5] == 'W'):
longitude = -longitude
satellites = parts[7]
GPStime = parts[1][0:2] + ":" + parts[1][2:4] + ":" + parts[1][4:6]
FIX_STATUS = True
break
if (time.time() > timeout):
TIMEOUT = True
break
utime.sleep_ms(500)
The following function is responsible to convert the raw longitude and latitude data to actual values.
def convertToDegree(RawDegrees):
RawAsFloat = float(RawDegrees)
firstdigits = int(RawAsFloat/100)
nexttwodigits = RawAsFloat - float(firstdigits*100)
Converted = float(firstdigits + nexttwodigits/60.0)
Converted = '{0:.6f}'.format(Converted)
return str(Converted)
Inside the infinite loop we will call the getGPS(gpsModule) function first. If the GPS data is available then print it both on the Thonny shell console and the OLED display. If the GPS data is not acquired within the time set within the program, then “No GPS data is found” message is printed on the shell console instead.
while True:
getGPS(gpsModule)
if(FIX_STATUS == True):
print("Printing GPS data...")
print(" ")
print("Latitude: "+latitude)
print("Longitude: "+longitude)
print("Satellites: " +satellites)
print("Time: "+GPStime)
print("----------------------")
oled.fill(0)
oled.text("Lat: "+latitude, 0, 0)
oled.text("Lng: "+longitude, 0, 10)
oled.text("Satellites: "+satellites, 0, 20)
oled.text("Time: "+GPStime, 0, 30)
oled.show()
FIX_STATUS = False
if(TIMEOUT == True):
print("No GPS data is found.")
TIMEOUT = False
Demo
After you have copied the following code onto a new file, click the ‘Save’ icon to save your program code on your PC.
After you have saved the code press the Run button to upload the code to your board. Before uploading code make sure the correct board is selected.
In the shell terminal of your IDE, you will be able to view the following GPS parameters:
Once the code is uploaded to ESP32, you will be able to view the GPS data on the OLED as well:
To read more GPS related articles, follow the links below:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4