Display real-time estimate of commute time between two locations based on traffic and historic data on a Character LCD using Raspberry Pi, Python 3 and Google Maps Distance Matrix API. If you have a LCD and a Raspberry Pi lying around or want to purchase one or if you are often late for work like me and want to have a traffic monitor then this project might be for you.
WiringWe are going to use Python programming language to make an Google Maps API call and then display the results to LCD
Installing the dependenciesAdafruit Python CharLCD libraryGet the LCD library from following Github link.
https://github.com/adafruit/Adafruit_Python_CharLCD
CD to the downloaded folder and run the following command.
sudo python3 setup.py install
Requestssudo pip3 install requests
Google Maps Distance Matric APIsudo pip3 install -U googlemaps
Getting an API key to make API callsLogin to your google account by visiting the following link and get the API key for your project. If you don't have an existing project, then you might have a create a new one.
https://developers.google.com/maps/documentation/distance-matrix/
Python CodePython 3 code for getting the commute time and displaying it on LCD
Importing the dependenciesimport time
import Adafruit_CharLCD as LCD
import requests
Variables for making API callUpdate the api_key
variable with the key you got before.
api_key = 'YOUR_API_KEY'
base_url = 'https://maps.googleapis.com/maps/api/distancematrix/json?'
Origin and destination addressesorigin = 'Papakura,Auckland,New+Zealand'
destination = 'Penrose,Auckland,New+Zealand'
Variables for driving the LCDCorresponding Raspberry Pi GPIO pins for register select, instruction and data registers on LCD. We will use these variables later to initialize the LCD.
lcd_rs = 4
lcd_en = 17
lcd_d4 = 25
lcd_d5 = 24
lcd_d6 = 23
lcd_d7 = 18
Size of the LCD, If you have a character LCD of 16x2, then modify the lcd_columns
variable to 16 and lcd_rows
to 2. Since, I used 20x4 LCD, I will use the following values.
lcd_columns = 20
lcd_rows = 4
Initialize the LCDCreate a lcd object by calling the constructor method defined in the Adafruit LCD library and pass in the required parameters. If your LCD supports backlight, then you could pass in an additional parameter of backlight = 1
or backlight = 0
to turn it on or off.
lcd = LCD.Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows)
Making the API callWe are going to structure the URL and then use python library requests to make a get request to API endpoint. To get a valid response you will also need to include additional parameters namely origins
, destinations
, departure time
, traffic_model
and API key
in your request. Response message is then stored in variable and converted to JSON. In this example, I have passed in the result to display message. This method makes two requests - one to get best guessed commute time and other to get pessimistic time. Pessimistic time will be often more than the best guessed time.
def get_data():
try:
# Make request to get best guess duration between specified two points
r1 = requests.get(base_url+'origins={}&destinations={}&departure_time={}&traffic_model={}&key={}'.format(origin, destination, time_in_seconds_UTC(), 'best_guess', api_key))
r1= r1.json()['rows'][0]['elements'][0] # Convert the response to JSON
best_guess_duration = r1['duration_in_traffic']['text']
# Make request to get worst case duration between specified two points
r2 = requests.get(base_url+'origins={}&destinations={}&departure_time={}&traffic_model={}&key={}'.format(origin, destination, time_in_seconds_UTC(), 'pessimistic', api_key))
r2 = r2.json()['rows'][0]['elements'][0] # Convert the response to JSON
pessimistic_duration = r2['duration_in_traffic']['text']
display('Estimated Drive Time', 'BG: ' + best_guess_duration, 'PSMT: ' + pessimistic_duration, human_readable_time()) # Pass the results to display function
except requests.exceptions.RequestException as e:
# Print time when exception happened and exception meyyssage
print(time.strftime("%d-%m-%Y %H:%M:%S", time.localtime()))
print(e)
display('Error, check console', 'Trying again...') # Update LCD with error message
Also, I have wrapped the code in try and except block to catch if the request fails for whatever reason. If the exception happens, print function will print the time when it happened and reason in console and LCD will show Error, check console', 'Trying again...'
. LCD will update with commute data again if the next request is successful.
Display function takes advantage of the message function provided by Adafruit LCD library. You can pass in upto four strings while calling it and it will display each string on a new line. lcd.clear()
will clear any existing text on LCD and lcd.home()
will bring the cursor to row 1 and column 1. For best results, you might want to limit the string length to maximum characters your LCD can display on each line. If you want to display multi-line message, then its best to use lcd.message()
def display(line1 = '', line2 = '', line3 = '', line4 = ''):
lcd.clear() # Clear the display
lcd.home() # Bring cursor to row 1 and column 1
lcd.message(line1 + '\n' + line2 + '\n' + line3 + '\n' + line4) # Print message
Get real time traffic dataSo far, we have the code to get distance and duration but but we are not actually making a request. To get a response we have to call get_data()
function and keep calling it every minute to get the updated duration based on traffic. I have wrapped this code in main()
function
def main():
display('Loading...')
get_data() # Gets and displays data on LCD
time.sleep(60) # Wait for 1 minute
The following code will keep the program running once started and display Stopped on LCD when you stop it.
while True:
try:
main()
finally:
display('Stopped')
Other helper functionsHelper functions are called in get_data()
method.
# This piece of code returns the time in seconds in UTC which is passed to maps API as a value for departure_time
def time_in_seconds_UTC():
return int(round(time.time()))
#Following code returns a human readable date and time, this is printed on fourth line of LCD
def human_readable_time():
return time.strftime("%d %b %Y %I:%M %P", time.localtime())
Starting the appFinally, we are at a point to start the program and get the real time traffic duration and distance on the LCD. You can get the code from following Github link.
https://github.com/dsdilpreet/blog/blob/master/time-to-destination/ttd.py
Copy the code to file and name in app.py
Open up your command prompt or terminal and cd into the folder and run the following command.
python3 app.py
End Resulthttps://dilpreet.dev/blog/display-commute-times-raspberrypi-lcd/
Comments