How to setup GPS module with Raspberry Pi?

At first, I simply wanted to connect the NEO-6M GPS module to my Raspberry Pi 4, but obtaining coordinates without their further use seemed uninteresting. Therefore, below is the process of connecting the module, as well as Python scripts for querying the openweathermap weather service API, receiving weather forecasts from it, and sending them via a Telegram bot.

Connecting the GPS module

For this we have a scheme:

gps module

We install the necessary packages:

sudo pip install pynmea2
sudo apt-get install gpsd gpsd-clients gpsd-tools minicom

Then we modify the configuration after saving the current one:

sudo cp /boot/cmdline.txt /boot/cmdline.txt.bak
sudo nano /boot/cmdline.txt

Replace the settings with the following ones:

sudo nano /boot/config.txt

Add to the end of the file:

dtparam=spi=on
dtoverlay=pi3-disable-bt
core_freq=250
enable_uart=1
force_turbo=1
init_uart_baud=9600

Reboot the mini-computer:

sudo reboot now

Configure the GPS module to a baud rate of 9600:

stty -F /dev/ttyAMA0 9600

Kill all gpsd processes and add the device to the configuration:

sudo killall gpsd
sudo nano /etc/default/gpsd

We are interested in the DEVICES parameter.

DEVICES="/dev/ttyAMA0"

Restart the software:

sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket 
sudo cgps -s

We should get something like this:

gpsd

Note that for the first time, the GPS module may take up to 20 minutes to acquire coordinates from satellites; subsequent acquisition times will be faster.

Script for obtaining coordinates from the GPS module

Now we need to write a Python script that will read latitude and longitude from the GPS module. We will expand it further later. Initially, it will look something like this:

#! /usr/bin/python
from gps import *
import time
import subprocess
import sys

gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)

while True:
    report = gpsd.next()
    if report['class'] == 'TPV':
      print(str(getattr(report,'lat',0.0)))
      print(str(getattr(report,'lon',0.0)))
    time.sleep(3)

Result:

python script

Script for obtaining weather forecast through the openweathermap.org API

To begin with, register on openweathermap.org, go to the API keys section of your account, and generate a new key. Alternatively, you can use the default key.

openweather api key

First, let’s learn how to simply retrieve weather data from the API using our key:

import requests
api_url = 'https://api.openweathermap.org/data/2.5/onecall?'

params = dict(
    lat=YOUR_LATITUDE,
    lon=YOUR_LONGITUDE,
    appid='YOUR_API_KEY',
    units='metric',
    exclude='minutely,daily',
    lang='ua'
)

resp = requests.get(url=api_url, params=params)
print(resp.json())

Creating a chatbot in Telegram

As I have detailed this step in the previous project ‘Raspberry Pi + OpenCV: object recognition and notifications via Telegram bot‘ I won’t repeat it here. You can simply refer to the relevant section on Setting up a Telegram bot for Raspberry Pi. The main thing at this step is to create a chatbot and obtain the token and chat ID.

Let’s put everything together

Well, we have some simplified versions of scripts that query the GPS module to obtain coordinates. Additionally, we have a separate script for fetching weather information based on coordinates from the weather service API, and we also have a chatbot. Now it’s time to expand the functionality of these scripts and integrate everything into a cohesive whole.

The workflow algorithm will be as follows:

  1. Run the main script:
    1.1. Obtain coordinates from the GPS module.
    1.2. Launch the next script and pass the coordinates to it.
  2. The next script receives coordinates from the previous one and:
    2.1. Makes an API request to the weather service with the coordinates.
    2.2. Parses the received response.
    2.3. Sends the parsed response to Telegram.

Taking into account the described algorithm above, the main script might look like this:

from gps import *
import time
import sys

gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)

while True:
    report = gpsd.next()
    if report['class'] == 'TPV':
      latitude = str(getattr(report,'lat',0.0))
      longitude = str(getattr(report,'lon',0.0))
      os.system("python api_forecast.py " + latitude + " " + longitude)
      sys.exit()
    time.sleep(3)

As evident from the code, the script stores coordinates in variables and passes them as arguments when launching the next script. The sys module is used to execute the next script. After the successful execution of the subsequent script, the main script terminates its operation using the sys.exit() method.

Now let’s consider the next script:

import requests
import datetime
import sys

TOKEN = "TELEGRAM_BOT_TOKEN"
chat_id = "CHAT_ID"
api_url = 'https://api.openweathermap.org/data/2.5/onecall?'

params = dict(
    lat=sys.argv[1],
    lon=sys.argv[2],
    appid='YOUR_API_KEY',
    units='metric',
    exclude='minutely,daily',
    lang='uk'
)

resp = requests.get(url=api_url, params=params)
data = resp.json()
forecast = ''
limit = 12
index = 0
for dt in data["hourly"]:
  forecast += "Час: " + datetime.datetime.fromtimestamp(dt["dt"]).strftime('%d-%m %H:%M') + "\nTemperature: " + str(dt["temp"]) + "\N{DEGREE SIGN}C." + " Description: " + dt["weather"][0]["description"] + "\n\n"
  if index == limit:
    break
  index+=1
message = "Current weather:\n" + "Time: " + datetime.datetime.fromtimestamp(data["current"]["dt"]).strftime('%d-%m %H:%M') + "\nTemperature: " + str(data["current"]["temp"]) + "\N{DEGREE SIGN}C." + " Description: " + data["current"]["weather"][0]["description"] + "\n\n" + "Today's wheather forcast:\n" + forecast
url = f"https://api.telegram.org/bot{TOKEN}/sendMessage?chat_id={chat_id}&text={message}"
requests.get(url).json()

The described script fetches the current weather from the weather service and provides an hourly forecast for the next 12 hours. It compiles this information into a message and sends it to Telegram. To read the arguments from the main script, the sys.argv method is utilized. The Telegram message looks like this:

telegram bot

You can further enhance this script to run regularly, for example, every day at 9 AM. This way, you’ll receive the current weather and the day’s forecast directly to your Telegram regularly 🙂

raspberry pi gps

I found the folloving materials very helpful:
1. https://github.com/FranzTscharf/Python-NEO-6M-GPS-Raspberry-Pi
2. https://openweathermap.org/api/one-call-api
3. https://ozzmaker.com/using-python-with-a-gps-receiver-on-a-raspberry-pi/

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *