Control the GPIO of a Raspberry Pi using SMS from a mobile phone

In this guide we will show you how to control the GPIO pins of a Raspberry pi by send a SMS to the Raspberry Pi from a mobile phone.

 

For this guide, the GSM modem we are using to receive the SMS is the  BerryGPS-GSM.

On the software side, we will be using Gammu, which is specifically designed to control  phones and GSM modules. It also has a daemon which will monitor the GSM modem for incoming SMSs.

We will configure Gammu to trigger a python script when a new SMS is received. We will use the contents of the SMS to control what happens in Python

LEDs are used here as an example, but you can do anything you like Eg. Open a garage door, turn on some lights, etc..

 

Wiring

Raspberry PI GPIO SMS

 

We will be using the three bottom right GPIO pins on the Raspberry Pi header. These are GPIO 16, 20 and 21.
Each is connected to a different color LED as shown above. The
The resistors used are 330 Ohm  and the GND pin (shorter pin) of the LEDs is connected to the GND power rail.

 

Setup

Install Gammu and python bindings;

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get install gammu-smsd python-gammu

Edit the config file;

pi@raspberrypi ~ $ sudo nano /etc/gammu-smsdrc

Find the below lines and add port and speed.
For the BerryGPS-GSM, use /dev/ttyACM1 for port and at115200 for speed

port = /dev/ttyACM1
connection = at115200

At the bottom of the file, add the line below. This is the python script which will run when a new SMS is received.

RunOnReceive = sudo python /home/pi/smsReceived.py

We will do a quick test. Restart the gammu service so the new config takes effect;

pi@raspberrypi ~ $ sudo /etc/init.d/gammu-smsd restart

Send a test SMS to a mobile number. The mobile number below is an example, you will need to update this;

pi@raspberrypi ~ $ echo "This is a test from a Raspberry Pi" | /usr/bin/gammu --sendsms TEXT +614123456789

 

Python Script

This python script will run every time a new SMS is received.

pi@raspberrypi ~ $ nano ~/smsReceived.py

Copy in the below code

import RPi.GPIO as GPIO
import time
import sys
import re


RED_LED =  21
GREEN_LED =  20
BLUE_LED =  16

GPIO.setmode(GPIO.BCM)
filename=str(sys.argv[1])                               #Gammu will pass the filename of the new SMS as an argument
complete_filename="/var/spool/gammu/inbox/"+filename    #we create the full path to the file here

GPIO.setup(RED_LED , GPIO.OUT)
GPIO.setup(GREEN_LED , GPIO.OUT)
GPIO.setup(BLUE_LED , GPIO.OUT)

sms_file=open(complete_filename,"r")
#read the contents of the SMS file
message=sms_file.read(160) #note that a not-parted SMS can be maximum 160 characters

#search the contents and perform an action. Rather than use 'find',
# we will use regular expression (re) so we can ignore case.
#Most smartphones will have the first letter capitalised
if re.search('red', message, re.IGNORECASE):
        GPIO.output(RED_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(RED_LED , GPIO.LOW)
elif re.search('green', message, re.IGNORECASE):
        GPIO.output(GREEN_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(GREEN_LED , GPIO.LOW)
elif re.search('blue', message, re.IGNORECASE):
        GPIO.output(BLUE_LED , GPIO.HIGH)
        time.sleep(2)
        GPIO.output(BLUE_LED , GPIO.LOW)



GPIO.cleanup()

To troubleshoot you can view the syslog

pi@raspberrypi ~ $ tail -f /var/log/syslog

Using a button and the GPIO on a Raspberry Pi to send a SMS

In this guide we will show you how to send a SMS using a button connected to the GPIO pins of a Rasberry Pi Zero.

 

For this guide, the GSM modem we are using to send the SMS is the  BerryGPS-GSM.

On the software side, we will be using Gammu, which is specifically designed to control  phones and GSM modules.

Python will be used to monitor some buttons connected to GPIO pins and Gammu python bindings will be used to send a SMS.

Buttons are used here as an example, but you can use anything to trigger the SMS, E.g. Temperature sensor, water level sensor, light sensor, etc..

We have includes some LEDs so we can see when the buttons are pressed.

Wiring

Raspberry Pi LED button

We will be using the three bottom right GPIO pins on the Raspberry Pi header. These are GPIO 16, 20 and 21.
Each is connected to a button and different color LED as shown above. The internal pull-down resisters will be used on these GPIO.
3.3v and GND are connect to the power rails on the breadboard.
The resistors used are 330 Ohm  and the GND pin (shorter pin) of the LEDs is connected to the GND power rail.

Continue reading Using a button and the GPIO on a Raspberry Pi to send a SMS

Real-time GPS tracking with a Raspberry Pi

In this guide, we will show how to do real time tracking, use a BerryGPS-GSM and initialstate.com 

Initialstate has some great tools to easily stream data from a Raspberry Pi to Initialstate.com and show this data within a dashboard using tiles.  We will send longitude,  latitude and  speed. And use a BerryGPS-GSM to get these values and upload them via 3G.

 

You will need to create an account on Initialstate.com and then grab your access key which can be found under "My Settings"

BerryGPS-GSM setup

If you are using a BerryGPS-GSM, you can follow this guide to get the GPS working and get your Pi to connect to via 3G using PPP.

The above guide also shows how to make your Pi connect to the carrier network automatically when booted. You will need this if you plan to perform remote tracking(E.g. Asset tracking).

Install required libraries

pi@raspberrypi ~ $ sudo apt-get install python-pip
pi@raspberrypi ~ $ sudo pip install pynmea2
pi@raspberrypi ~ $ sudo pip install ISStreamer

 

Main Python Script

Here we will create the main script which will stream the GPS data to Initialstate.com.
The code below creates a separate thread which is used to monitor the serial port. This is needed because we have a pause in the main loop. The pause is there to limit how much data we upload over 3G.
If we did everything in the same thread during the pause, the serial buffer would fill up (it is FIFO) and when we get the next value from the buffer, it will be old by a few seconds. This happens every loop and eventually the data will be minutes or hours behind.

The access key below is not a valid key, it is just an example. You will need to replace it with your own key.

pi@raspberrypi ~ $ nano ~/GPStracker.py

#! /usr/bin/python

from gps import *
from time import *
import threading
import datetime
from ISStreamer.Streamer import Streamer

gpsd = None  #Setup global variable 

#Setup the Initialstate stream, give it a bucket name and the access key
streamer = Streamer(bucket_name="GPS_Tracker20190713", bucket_key="GPS_Tracker20190713", access_key="ist_W4aHj0eCkMjCD8JVpp3AMsKomys8NaD")


class GPSDcollector(threading.Thread):
   def __init__(self, threadID):
      threading.Thread.__init__(self)
      self.threadID = threadID
      global gpsd #bring it in scope
      gpsd = gps(mode=WATCH_ENABLE) #Start GPSD
      self.running = True #Start running this thread
   def run(self):
      global gpsd
      while gpsdThread.running:
        gpsd.next() 
        
if __name__ == '__main__':
  gpsdThread = GPSDcollector(1) # create a thread to collect data
  try:
    gpsdThread.start() # start it up
    while True:
        print 'GPS ' , gpsd.utc,'--> CPU time->',datetime.datetime.now().time() ,
        if (gpsd.fix.longitude<>0) and (gpsd.fix.longitude<>'nan'): #Only upload data if it is valid
          streamer.log("Location", "{lat},{lon}".format(lat=gpsd.fix.latitude,lon=gpsd.fix.longitude))
          streamer.log("speed",gpsd.fix.speed)
        print '  lat    ' , gpsd.fix.latitude,
        print '  lon   ' , gpsd.fix.longitude,
        print '  speed ', gpsd.fix.speed

        sleep(5)
  except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "\nKilling Thread..."
    gpsdThread.running = False
    gpsdThread.join() # wait for the thread to finish what it's doing
  print "Done.\nExiting."
  

 

Start the script automatically on boot

If you are doing remote monitoring, you would want the script to run on boot. To do this, we will create a small script which will start the main python program.

pi@raspberrypi ~ $ nano ~/GPStrackerStart.sh

copy in the below lines;

#!/bin/bash
sleep 15
python /home/pi/GPStracker.py &

The pause above is there to give the Pi time to boot and connect via PPP.

Make the script executable;

pi@raspberrypi ~ $ chmod +x ~/GPStrackerStart.sh

We will use cron to start the script every time the Pi boots;

pi@raspberrypi ~ $ crontab -e

Add the below line to the bottom

@reboot /home/pi/GPStrackerStart.sh &

Other Guides and Tutorials for BerryGPS-GSM

Get a GPS fix in seconds using assisted GPS on a Raspberry Pi with a BerryGPS-GSM

Typically, a GPS module can take a few minutes to get  Time To First Fix(TTFF), or even longer if you are in  built up areas(+20mins).  This is because the Almanac needs to be downloaded from  satellites before a GPS fix can be acquired and only a small portion of the Almanac is sent in each GPS update.

Assisted GPS speeds this up significantly by  downloading  ephemeris, almanac, accurate time and satellite status over the network, resulting in faster TTTF, in a few seconds. This is very similar how to GPS works on a smartphone.

The BerryGPS-GSM supports assisted GPS. The below video shows a comparison between assisted and normal GPS.

  • Assisted GPS takes 19secs to get a fix
  • Normal GPS takes 8min 22Sec to get a fix

 

How does the BerryGPS-GSM do this?

The two main components on the BerryGPS-GSM are;

The SARA-U201 can be configured to download GPS assist data and then pass this over the the GPS module. These two components speak to each other via i2c.

This assist data is downloaded by the SARA-U201 modem (not the Pi), therefore the modem needs to create an internal PDP (Packet Data Protocol) connection.

Once the PDP connection is made, the SARA-U201 will reach out to uBlox AssitNow servers and download the latest assist data. A valid token is needed to perform this, all BerryGPS-GSM have had this token pre-configured.

Continue reading Get a GPS fix in seconds using assisted GPS on a Raspberry Pi with a BerryGPS-GSM

New Product: BerryGPS-GSM - Global 3G/2G cellular modem with GPS + SIM

We have released a new product:

BerryGPS-GSM - Global 3G/2G cellular modem with GPS + SIM

This is an all in one module which can provide location tracking and GSM services such as data, text and SMS to your project. It comes in the same form factor as a Raspberry Pi Zero, which makes it nice and compact when used with a Raspberry Pi Zero.

 

 

The two main components that make this board great are;

  • uBlox CAM-M8 GPS module (Same GPS found on BerryGPS-IMU)
  • uBlox SARA-U201 GSM for GSM connectivity, which has global coverage.

Both of these modules working together results in obtaining a GPS fix in secs, using Assisted GPS.

 

BerryGPS-IMU used by Plastic Monkeys in CanSat competition

Along with other sponsors, we are happy to congratulate Plastic Monkeys team for placing 3rd  (out of over 70 teams taking part) in the CanSats in Europe Polish Competition.

A CanSat is a type of sounding rocket payload used to teach space technology. It is similar to the technology used in miniaturized satellites.

In CanSat competitions, the payload is required to fit inside the volume of a typical soda can (66mm diameter and 115mm height).

A BerryGPS-IMU was used to provide location tracking for this project.

 

 

How to save GPS data to a file using Python

Below is an example python script which will save GPS data (time, Lon, Lat, speed and sats in view) to a file.

The gpsd client libraries  will be used to get the data from GPSD. We will be using the TPV class to get time, latitude, longitude and speed.

We can get the number of satellites in view by getting the length of the satellites object.

This page shows how to get gpsd up an running on a Raspberry Pi

Every time the script is run, it will create a new file beginning with the current date and time.

In this example, I am writing in a csv format, where each GPS attribute is separated by a comma.

#! /usr/bin/python
from gps import *
import time, inspect


f = open(time.strftime("%Y%m%d-%H%M%S")+'_GSPData.csv','w')

gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)

print 'GPStime utc\t\t\tlatitude\tlongitude\tspeed\tsats in view' # '\t' = TAB to try and output the data in columns.

f.write("GPStime utc,latitude,longitude,speed,sats in view\n")

try:

    while True:
        report = gpsd.next() #
        if report['class'] == 'TPV':
            GPStime =  str(getattr(report,'time',''))
            lat = str(getattr(report,'lat',0.0))
            lon = str(getattr(report,'lon',0.0))
            speed =  str(getattr(report,'speed','nan'))
            sats = str(len(gpsd.satellites))

            print  GPStime,"\t",
            print  lat,"\t",
            print  lon,"\t",
            print  speed,"\t",
            print  sats,"\t"

            f.write(GPStime + ',' + lat +',' + lon + ',' + speed + ',' + sats + '\n')

            time.sleep(1)

except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
    print "Done.\nExiting."
    f.close()

Using python with a GPS receiver on a Raspberry Pi

Here are three examples of how to  use python to get GPS data from a GPS receiver attached to a Raspberry Pi.

  1. Using GPSD client libraries
  2. Manually parsing NMEA sentences
  3. Using  pynmea2 to parse NMEA sentences

GPSD client libraries

The gpsd client libraries are based on JSON. The JSON objects have a "class" attribute (E.g. TPV,  SKY, DEVICE.etc...)  which can be used to filter on different information.

This guide shows how to get gpsd up an running on a Raspberry Pi.

The example python  script below filters on the TPV class, which is the Time Position Velocity report and then prints out the relevant information.

#! /usr/bin/python

from gps import *
import time
   
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) 
print 'latitude\tlongitude\ttime utc\t\t\taltitude\tepv\tept\tspeed\tclimb' # '\t' = TAB to try and output the data in columns.
  
try:


	while True:
		report = gpsd.next() #
		if report['class'] == 'TPV':
			
			print  getattr(report,'lat',0.0),"\t",
			print  getattr(report,'lon',0.0),"\t",
			print getattr(report,'time',''),"\t",
			print  getattr(report,'alt','nan'),"\t\t",
			print  getattr(report,'epv','nan'),"\t",
			print  getattr(report,'ept','nan'),"\t",
			print  getattr(report,'speed','nan'),"\t",
			print getattr(report,'climb','nan'),"\t"

		time.sleep(1) 

except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
	print "Done.\nExiting."

 

 

This python script filters on the SKY class and prints out satellite information.




#! /usr/bin/python

from gps import *
import time
import os
   
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE) 
  
try:
	while True:
		
		report = gpsd.next() #
		if report['class'] == 'SKY':
			os.system('clear')
			print ' Satellites (total of', len(gpsd.satellites) , ' in view)'
			for i in gpsd.satellites:
				print 't', i

		
			print '\n\n'
			print 'PRN = PRN ID of the satellite. 1-63 are GNSS satellites, 64-96 are GLONASS satellites, 100-164 are SBAS satellites'
			print 'E = Elevation in degrees'
			print 'As = Azimuth, degrees from true north'
			print 'ss = Signal stength in dB'
			print 'used = Used in current solution?'

		time.sleep(1) 


except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
	print "Done.\nExiting."


BerryGPS Raspberry Pi GPS

Manually parsing NMEA sentences

The python script below shows how to access GPS data by connecting directly to the serial interface.
It filters on $GPRMC NMEA sentences and then splits the well know attributes into different variables.



import serial

port = "/dev/serial0"

def parseGPS(data):
#    print "raw:", data #prints raw data
    if data[0:6] == "$GPRMC":
        sdata = data.split(",")
        if sdata[2] == 'V':
            print "no satellite data available"
            return
        print "---Parsing GPRMC---",
        time = sdata[1][0:2] + ":" + sdata[1][2:4] + ":" + sdata[1][4:6]
        lat = decode(sdata[3]) #latitude
        dirLat = sdata[4]      #latitude direction N/S
        lon = decode(sdata[5]) #longitute
        dirLon = sdata[6]      #longitude direction E/W
        speed = sdata[7]       #Speed in knots
        trCourse = sdata[8]    #True course
        date = sdata[9][0:2] + "/" + sdata[9][2:4] + "/" + sdata[9][4:6]#date

        print "time : %s, latitude : %s(%s), longitude : %s(%s), speed : %s, True Course : %s, Date : %s" %  (time,lat,dirLat,lon,dirLon,speed,trCourse,date)

def decode(coord):
    #Converts DDDMM.MMMMM > DD deg MM.MMMMM min
    x = coord.split(".")
    head = x[0]
    tail = x[1]
    deg = head[0:-2]
    min = head[-2:]
    return deg + " deg " + min + "." + tail + " min"


print "Receiving GPS data"
ser = serial.Serial(port, baudrate = 9600, timeout = 0.5)
while True:
   data = ser.readline()
   parseGPS(data)


 

Using  pynmea2 to parse NMEA sentences

The python script below shows how to access GPS data by connecting directly to the serial interface.
It filters on $GPGGA NMEA sentences and then uses pynmea2 to parse the data.

Pynmea2 can be installed with;

pi@raspberrypi ~ $ pip install pynmea2

import serial
import pynmea2

port = "/dev/serial0"

def parseGPS(str):
    if str.find('GGA') > 0:
        msg = pynmea2.parse(str)
        print "Timestamp: %s -- Lat: %s %s -- Lon: %s %s -- Altitude: %s %s -- Satellites: %s" % (msg.timestamp,msg.lat,msg.lat_dir,msg.lon,msg.lon_dir,msg.altitude,msg.altitude_units,msg.num_sats)


serialPort = serial.Serial(port, baudrate = 9600, timeout = 0.5)
while True:
    str = serialPort.readline()
    parseGPS(str)

Why does it take so long to get a GPS fix?

Have you ever wondered why it sometimes takes your GPS module 10-20 minutes to get a GPS fix?   This post will explain why.

 

Each satellite sends a message every 30 seconds.  This message consists of two main components;

  • Ephemeris data, used to calculate the position of each satellite in orbit
  • Almanac , which is information about  the time and status of the entire satellite constellation.

Only a small portion of the Almanac is included in a GPS message. It takes 25 messages (12.5 minutes) to get the full Almanac. The full Almanac is needed before a GPS fix can be obtained.  This is Time To First Fix (TTFF).

TTFF is a measure of the time required for a GPS receiver to acquire satellite signals and navigation data, and calculate a position solution (called a fix).

The above happens during a cold start, this is when the GPS module has been off for some time and has no data in its memory. A full Almanac download is required to get TTFF. If the GPS module has clear line of sight to all satellites, the shortest time for TTFF is 12.5 minutes.

In a warm start scenario,  the GPS module has valid Almanac data,  is close to its last position (100km or so) and knows the time  within about 20 seconds. This approximate information helps the receiver estimate the range to satellites.  The TTFF for a warm start can be as short as 30 seconds, but is usually just a couple of minutes.

A receiver that has a current almanac, ephemeris data, time and position can have a hot start. A hot start can take from 0.5 to 20 seconds for TTFF.

 

Smarts phones use Assisted GPS (aGPS), this allows them to download the Ephemeris data and Almanac over the cell network which greatly reduces the TTFF.

BerryGPS Raspberry Pi GPS

 

 

 

Raspberry Pi Embedded Cap With GPS & 10DOF

In this post we will show you how to geotag and capture the "attitude"  of photos taken with the Raspberry Pi camera and record these values within the photo itself using EXIF metadata

We used a modified (hacked?) cap to take the images in this post. The cap took photos, geo-tagged and recorded attitude as we walked around Sydney Harbour.

Components used were;

  • Raspberry Pi Zero W
  • BerryGPS-IMU
  • Raspberry Camera V2
  • A cap

The BerryGPS-IMU was used to capture the GPS coordinates as well as "attitude".   No external antenna was needed as the BerryGPS-IMU includes an internal antenna.

The "attitude" would include values such as pitch, roll, direction. Some of this data you can see annotate in the image below.


raspberry pi camera gps

Other programs can use some of this data to plot the image on a map and even show the direction of the camera at the time the image was taken.  A good example of this is seen in  GeoSetter

Camera attitude

 

The Cap

The cap has the BerryGPS-IMU sitting on top of the visor, with the Raspberry Pi sitting under the viso.  Some holes where made in the visor to allow connectivity between the BerryGPS-IMU and Raspberry Pi.
We also created a basic camera mount out of 3mm laser cut acrylic. M2.5 Nylon screws were used to hold everything in place.
Raspberry Pi GPS

 

Continue reading Raspberry Pi Embedded Cap With GPS & 10DOF

Blip, blop, bloop...