In this part of the lesson, you will add a GPS sensor to your Raspberry Pi, and read values from it.
The Raspberry Pi needs a GPS sensor.
The sensor you'll use is a Grove GPS Air530 sensor. This sensor can connect to multiple GPS systems for a fast, accurate fix. The sensor is made of 2 parts - the core electronics of the sensor, and an external antenna connected by a thin wire to pick up the radio waves from the satellites.
This is a UART sensor, so sends GPS data over UART.
The Grove GPS sensor can be connected to the Raspberry Pi.
Connect the GPS sensor.
-
Insert one end of a Grove cable into the socket on the GPS sensor. It will only go in one way round.
-
With the Raspberry Pi powered off, connect the other end of the Grove cable to the UART socket marked UART on the Grove Base hat attached to the Pi. This socket is on the middle row, on the side nearest the SD Card slot, the other end from the USB ports and ethernet socket.
-
Position the GPS sensor so that the attached antenna has visibility to the sky - ideally next to an open window or outside. It's easier to get a clearer signal with nothing in the way of the antenna.
The Raspberry Pi can now be programmed to use the attached GPS sensor.
Program the device.
-
Power up the Pi and wait for it to boot
-
The GPS sensor has 2 LEDs - a blue LED that flashes when data is transmitted, and a green LED that flashes every second when receiving data from satellites. Ensure the blue LED is flashing when you power up the Pi. After a few minutes the green LED will flash - if not, you may need to reposition the antenna.
-
Launch VS Code, either directly on the Pi, or connect via the Remote SSH extension.
⚠️ You can refer to the instructions for setting up and launching VS Code in lesson 1 if needed. -
With newer versions of the Raspberry Pi that support Bluetooth, there is a conflict between the serial port used for Bluetooth, and the one used by the Grove UART port. To fix this, do the following:
-
From the VS Code terminal, edit the
/boot/config.txt
file usingnano
, a built in terminal text editor with the following command:sudo nano /boot/config.txt
This file can't be edited by VS Code as you need to edit it with
sudo
permissions, an elevated permission. VS Code doesn't run this permission. -
Use your cursor keys to navigate to the end of the file. then copy the code below and paste it on the end of the file:
dtoverlay=pi3-miniuart-bt dtoverlay=pi3-disable-bt enable_uart=1
You can paste using the normal keyboard shortcuts for your device (
Ctrl+v
on Windows, Linux or Raspberry Pi OS,Cmd+v
on macOS). -
Save this file and exit nano by pressing
Ctrl+x
. Pressy
when asked if you want to save the modified buffer, then pressenter
to confirm you want to overwrite/boot/config.txt
.If you make a mistake, you can exit without saving, then repeat these steps.
-
Edit the
/boot/cmdline.txt
file in nano with the following command:sudo nano /boot/cmdline.txt
-
This file has a number of key/value pairs separated by spaces. Remove any key/value pairs for the key
console
. They will probably look something like this:console=serial0,115200 console=tty1
You can navigate to these entries using the cursor keys, then delete using the normal
del
orbackspace
keys.For example, if your original file looks like this:
console=serial0,115200 console=tty1 root=PARTUUID=058e2867-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
The new version will be:
root=PARTUUID=058e2867-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
-
Follow the steps above to save this file and exit nano
-
Reboot your Pi, then reconnect in VS Code once the Pi has rebooted.
-
-
From the terminal, create a new folder in the
pi
users home directory calledgps-sensor
. Create a file in this folder calledapp.py
. -
Open this folder in VS Code
-
The GPS module sends UART data over a serial port. Install the
pyserial
Pip package to communicate with the serial port from your Python code:pip3 install pyserial
-
Add the following code to your
app.py
file:import time import serial serial = serial.Serial('/dev/ttyAMA0', 9600, timeout=1) serial.reset_input_buffer() serial.flush() def print_gps_data(line): print(line.rstrip()) while True: line = serial.readline().decode('utf-8') while len(line) > 0: print_gps_data(line) line = serial.readline().decode('utf-8') time.sleep(1)
This code imports the
serial
module from thepyserial
Pip package. It then connects to the/dev/ttyAMA0
serial port - this is the address of the serial port that the Grove Pi Base Hat uses for its UART port. It then clears any existing data from this serial connection.Next a function called
print_gps_data
is defined that prints out the line passed to it to the console.Next the code loops forever, reading as many lines of text as it can from the serial port in each loop. It calls the
print_gps_data
function for each line.After all the data has been read, the loop sleeps for 1 second, then tries again.
-
Run this code. You will see the raw output from the GPS sensor, something like the following:
$GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 $GPGSA,A,1,,,,,,,,,,,,,,,*1E $BDGSA,A,1,,,,,,,,,,,,,,,*0F $GPGSV,1,1,00*79 $BDGSV,1,1,00*68
If you get one of the following errors when stopping and restarting your code, add a
try - except
block to your while loop.UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 0: invalid start byte UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte
while True: try: line = serial.readline().decode('utf-8') while len(line) > 0: print_gps_data() line = serial.readline().decode('utf-8') # There's a random chance the first byte being read is part way through a character. # Read another full line and continue. except UnicodeDecodeError: line = serial.readline().decode('utf-8') time.sleep(1)
💁 You can find this code in the code-gps/pi folder.
😀 Your GPS sensor program was a success!