Using a GPS module(neo-7m) with Raspberry Pi 3
Recently, I got an opportunity to work on an awesome project which included hardware and software development. The project was about Tractor Telematics. For starters, we needed to track the location of a tractor in real time. So, we the one and only way for it was to use Raspberry Pi and a GPS module. While trying to make things work, I faced a lot of problems in the configuration and there was no one-stop guide for it. Hence, I decided that I will write a blog about how I did it and what problems I faced along with their solutions.
NOTE: All of these steps were done on a Raspberry Pi 3 model B and ublox neo-7m GPS module but it should work on other models too.
Configuring UART
sudo raspi-config
Select -> Interfacing Options
After selecting Interfacing option, select Serial option to enable UART
Then it will ask for login shell to be accessible over Serial, select No shown as follows.
At the end, it will ask for enabling Hardware Serial port, select Yes,
Finally, our UART is enabled for Serial Communication on RX and TX pin of Raspberry Pi 3.
Then, reboot the Raspberry Pi.
Hardware connections
In the GPS module I have there were total 4 connections to be made as follows:
- VCC — 5v(pin 2)
- GND — Pi’s ground(pin 6)
- RX — Pi’s TX
- TX — Pi’s RX
Note that Pin 1 is the one facing the memory card slot and Pin2 is just adjacent to it. Refer to following images for better understanding.
Installing GPS Applications
sudo apt-get install gpsd gpsd-clients
Now, run the GPSD client
sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
Here, ttyS0 is my serial port where GPS data is received, for other Raspberry Pi models this might be different. So, just replace ‘XXX’ in ttyXXX with appropriate name.
Now, type the following code to check the connections.
cat /dev/ttyS0
You should see a continuous stream of data. It is raw GPS data in NMEA format. If you see something like $GPTXT,01,01,01,NMEA unknown msg*58 a lot then check your serial port configuration. If the ‘echo’ option is enabled that will cause this problem. Just do stty -F /dev/ttyS0 -echo
to disable echo then cat the gps serial device and those messages should stop.
Now, after this type cgps
and you should see something like below.
After some time the data will be shown here.
If the cat command shows data but you get nothing in cgps at all do the following :
- Check if port 2947 is open in firewall.
- Open the file
/etc/default/gps
in sudo with any text editor and change DEVICES=”” to DEVICES=”/dev/ttyS0" and then typesudo systemctl restart gpsd
Note : It may take sometime for GPS module to receive data. So it time or anything else is shown in cgps
that means configurations are all ok but module is not receiving GPS signals. So, just wait for sometime.
Some troubleshooting steps if cgps does not get a fix
1. Check GPS data stream
cat /dev/ttyS0
You should see the NMEA stream
2. Check GPS data with gpsmon
gpsmon /dev/ttyS0
It should run properly with the data stream
Note : It first two steps didn’t work, check you connections and configurations properly.
3. Run gpsd in debug mode
sudo gpsd /dev/ttyS0 -N -D3 -F /var/run/gpsd.sock
It should say that it is already running
4. Now type the following lines.
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket
5. Now, launch gpsd again
sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
Now, cgps should get a fix and no timeout.
After all the proper configurations, you need to run sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
every time the pi is rebooted. If you are using it as an IOT project you might want to automate everything.
Automating
Create a file at /etc/rc.local
sudo nano /etc/rc.local
Add following contents to the file
#!/bin/sh -e
sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
exit 0
This will run our sudo command on every boot.
Using python to get Latitude and Longitude
I used a simple python script to get latitude and longitude from the gps module.
Here, I print the Latitude and Longitude but you can actually do whatever you like with them and later on make this script to run every time on boot using cron job.
To make a cron job first type crontab -e
and in the window that appears write the following command.
@reboot cd /home/pi/ && python sendCoordinate.py
Change the path and file name accordingly.
Small Issue
Now, after everything was setup the system was working pretty nice. But after 2–3 trial runs I found that something was crashing and I was not able to get the coordinates on my web server.
Now, there could be only two problems, either the GPS module is not configuring properly on every startup or my internet connection had some issues on boot. After hours of hit-and-try, and trying several permutations and combinations of different things on the internet I did the following to make it work.
I made a shell script startup.sh
and added the following lines of code to it.
sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
stty -F /dev/ttyS0 -echo
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket
sudo killall gpsd
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket
sudo gpsd /dev/ttyS0 -F /var/run/gpsd.sock
sleep 10s
nohup python /home/pi/sendCoordinate.py > pylog.test &
Then I made it an executable.
sudo chmod 755 ./startup.sh
After added it as cronjob to be executed on every startup and everything ran without any problems. My crontab file looked like this.
@reboot cd /home/pi/ && sh startup.sh
Note : I know some of the lines in startup.sh are redundant and may not be necessary but due to time crunch I was not able to further test it and make it more simpler. If you are reading this and have a more optimal foolproof solution kindly let me know in the comments or at ayushgoyal.iitkgp@gmail.com .