Raspberry Pi Live Weather Forecast With TFT LCD Display

Overview

Accurate weather predictions are important for planning our day-to-day activities. For example, farmers need information to help them plan for the planting and harvesting of their crops. For us, it can help us prepare the things we bring when we go out, such as an umbrella if we know it’s going to rain. Weather forecasting helps us to make more informed daily decisions, and may even help keep us out of danger.

This project aims to grab information from an online weather forecast website and display the necessary information on a TFT LCD screen for users to view easily.

The application is not limited to just a weather forecast display. It can grab information from any website, such as stock market prices or even your YouTube video’s view count. Following this guide should give you a general idea on how to make it work.


Hardware Used

  • Raspberry Pi Zero W – 1
  • 
    2.2-inch TFT LCD Display ILI9341 (240×320) – 1
  • 
    Breadboard – 1
  • 
     47Ω or 220Ω Resistor – 1

  • Jumper Wires
  • 
    
    

    Software Used

    Libraries Used


    Application Description

    Raspberry Pi Zero W

    The Raspberry Pi (RPi) is a series of small single-board computers developed by the Raspberry Pi Foundation to promote teaching of basic computer science in schools and in developing countries. The RPi has been widely used to make things like cameras, gaming machines, robots, web servers and media centers.

    Pin Mapping

    How does it work?

    The RPi works similar to an Arduino in terms of how it operates, but there are several differences between the two. All Raspberry Pi boards use Python as the main language, but also support Ruby and C, while the Arduino only supports C. Moreover, the RPi is more expensive and much more complex for beginners looking to get into electronics projects. However, it can handle multiple programs at a time due to its higher processing power.

    2.2-inch TFT LCD Display ILI9341 (240×320)

    TFT LCD is short for thin-film-transistor liquid-crystal display. It is a variant of a LCD that uses thin-film transistor technology to improve image qualities such as addressability and contrast. These are commonly used in appliances including computer monitors, mobile phones, handheld devices, video game systems, navigation systems, projectors, and television.

    How does it work?

    All the pixels on a TFT LCD screen are configured in a row-and-column format, and each pixel is attached to a very tiny silicon transistor that rests directly on the glass panel. This setup allows each pixel to be given a charge and for the charge to be kept even when the screen is refreshed to produce a new image.


    Hardware Setup

    • SDO/MISO connected to RPi MISO board pin 21
    • LED connected to RPi 5V with a 47Ω resistor in series
    • SCK connected to RPi SCLK board pin 23
    • SDI/MOSI connected to RPi MOSI board pin 19
    • DC/RS connected to RPi board pin 12
    • RESET connected to RPi board pin 16
    • CS connected to RPi CE0_N board pin 24
    • VCC and GND connected to RPi 5V and Ground respectively

    Raspberry Pi Setup

    Before proceeding, you need to be able to connect to your Raspberry Pi using the VNC Viewer. Click here for the official documentation on how to do it made by the company themselves.

    Enabling SPI

    To allow the TFT LCD to work, we have to enable SPI through the Raspberry Pi Configurations. Assuming you’ve already connected to your Raspberry Pi, click on the raspberry icon on the bottom left, hover over Preferences, and click on “Raspberry Pi Configuration.”

    When the window pops up, click on “Interfaces” and ensure that SPI is enabled. Once done, click “OK.”

    Installing Required Libraries

    Next, we have to install the requests and Adafruit_Python_ILI9341 library so make sure your Raspberry Pi is connected to the Internet. Open the Terminal by clicking its icon on the bottom left and simply enter the command pip install requests to install the requests library. Once that is done, enter the command sudo apt-get install build-essential python-dev python-smbus python-imaging python-numpy then the command sudo python setup.py install to install the Adafruit_Python_ILI9341 library.


    ThingHTTP Setup

    To fetch data, we must request an API. Assuming that you’ve already installed the requests library as instructed above, the next step is to make APIs for a particular data from a website. We’ll be using ThingSpeak’s ThingHTTP app so you have to Sign up on their website https://thingspeak.com. If you already have an account, login and click on “Apps” and then “ThingHTTP.”

    In doing so, you should be directed to your ThingHTTP page. Click on “New ThingHTTP” to create one.

    Once loaded, you will be presented with the its settings. Change the name for easier identification and put the URL of the website you’re trying to fetch data from. Keep the rest default.

    The next step requires you to go to the website you want to get the data from, hover over the specific data you want to fetch, and select “Inspect.”

    Right click the data from the window pop-up on the right side, hover over “Copy” and then select “Copy XPath.”

    Once you’ve copied the XPath, go back to the ThingHTTP settings and paste it on the Parse String box and hit save.

    Once saved, you can get the API link on the right side of the page. You will need that later in the code.

    Repeat the process for the other data you need, such as the temperature, precipitation, humidity, etc.


    Code

    For the code, you can do it on your computer via Python IDLE, Notepad++, or any text editing software or IDE that supports Python then transfer it to the Raspberry Pi through the VNC Viewer. You can also code inside the RPi itself, but I find this to be easier.

    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont
    from time import sleep
    import requests
    import datetime
    
    import Adafruit_ILI9341 as TFT
    import Adafruit_GPIO as GPIO
    import Adafruit_GPIO.SPI as SPI
    
    DC = 18
    RST = 23
    SPI_PORT = 0
    SPI_DEVICE = 0
    
    # Create TFT LCD display class.
    disp = TFT.ILI9341(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000))
    
    # Initialize display.
    disp.begin()
    
    #font = ImageFont.load_default()
    font = ImageFont.truetype('Highest.ttf', 28)
    bigfont = ImageFont.truetype('Highest.ttf', 38)
    
    # Define a function to create rotated text.  Unfortunately PIL doesn't have good
    # native support for rotated fonts, but this function can be used to make a
    # text image and rotate it so it's easy to paste in the buffer.
    def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)):
        # Get rendered font width and height.
        draw = ImageDraw.Draw(image)
        width, height = draw.textsize(text, font=font)
        # Create a new image with transparent background to store the text.
        textimage = Image.new('RGBA', (width, height), (0,0,0,0))
        # Render the text.
        textdraw = ImageDraw.Draw(textimage)
        textdraw.text((0,0), text, font=font, fill=fill)
        # Rotate the text image.
        rotated = textimage.rotate(angle, expand=1)
        # Paste the text into the image, using it as a mask for transparency.
        image.paste(rotated, position, rotated)
    
    while True:
    	weather = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=DFARJB5K7NRMH723')
    	temp = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=DTDBUJV92LCDRR9E')
    	tempC = str(round((int(temp.text)-32)*(5.0/9), 1))
    	precip = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=RONUZA8J3E57XC75')
    	hum = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=7HTFKFGFBDBPNPYW')
    	wind = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=7SF4TOGRXQ8VPKQT')
    	time = datetime.datetime.now()	
    	disp.clear((0,0,0))
    	draw_rotated_text(disp.buffer, "Davao City Weather ", (200, 0), 270, bigfont, fill=(135,206,250))
    	print ("Last Updated " + time.strftime("%b %d %H:%M:%S"))
    	draw_rotated_text(disp.buffer, "Last Updated " + time.strftime("%b %d %H:%M:%S"), (170, 0), 270, font, fill=(66,244,182))
    	print (weather.text)
    	draw_rotated_text(disp.buffer, weather.text, (140, 0), 270, font, fill=(235,244,66))
    	print ("Temperature: " + tempC + " degrees C")
    	draw_rotated_text(disp.buffer, "Temperature: " + tempC + " degrees C", (100, 0), 270, font, fill=(255,255,255))
    	print ("Precipitation: " + precip.text + "%")
    	draw_rotated_text(disp.buffer, "Precipitation: " + precip.text + "%", (70, 0), 270, font, fill=(255,255,255))
    	print ("Humidity: " + hum.text + "%")
    	draw_rotated_text(disp.buffer, "Humidity: " + hum.text + "%", (40, 0), 270, font, fill=(255,255,255))
    	print ("Wind: " + wind.text)
    	draw_rotated_text(disp.buffer, "Wind: " + wind.text, (10, 0), 270, font, fill=(255,255,255))
    
    	disp.display()
    	sleep(60)

    To run the code, open the terminal and change the directory to where the file is located using the command cd <directory> then run the command python <file name>.py.


    Code Breakdown

    Library Import

    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont
    from time import sleep
    import requests
    import datetime
    
    import Adafruit_ILI9341 as TFT
    import Adafruit_GPIO as GPIO
    import Adafruit_GPIO.SPI as SPI

    Before starting, we must include the libraries to be used in the project. The Adafruit_ILI9341 library will allow the TFT LCD to work and it is dependent on the PIL (Python Imaging Library) to function. The RPi.GPIO library provides a class to control the GPIO on the Raspberry Pi and the GPIO.SPI library allows the SPI protocol that the TFT LCD requires. The requests library allows us to fetch data from any website. The datetime library is for showing the current time and the time.sleep library is for the delay.

    Pre-Initialization

    DC = 18
    RST = 23
    SPI_PORT = 0
    SPI_DEVICE = 0
    
    disp = TFT.ILI9341(DC, rst=RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=64000000))
    
    disp.begin()
    
    #font = ImageFont.load_default()
    font = ImageFont.truetype('Highest.ttf', 28)
    bigfont = ImageFont.truetype('Highest.ttf', 38)

    We then assign the DC and RESET pins to the RPi board pin 18 and 23 respectively. The SPI port and device should be 0 by default. After that, we create the TFT LCD display and initialize the display. Two font settings have been created to be used later to display our text on the TFT LCD. Since the default font of the library is only 8 pixels which is very small, I downloaded the Highest font style from https://www.dafont.com/ and placed the .tff file in the same directory as the code. You can use the default font if you like by removing the comment from the code, or download a different font from the same website aforementioned. The font sizes can be specified in the second parameter of ImageFont.truetype().

    Draw Rotated Text Function

    def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)):
        # Get rendered font width and height.
        draw = ImageDraw.Draw(image)
        width, height = draw.textsize(text, font=font)
        # Create a new image with transparent background to store the text.
        textimage = Image.new('RGBA', (width, height), (0,0,0,0))
        # Render the text.
        textdraw = ImageDraw.Draw(textimage)
        textdraw.text((0,0), text, font=font, fill=fill)
        # Rotate the text image.
        rotated = textimage.rotate(angle, expand=1)
        # Paste the text into the image, using it as a mask for transparency.
        image.paste(rotated, position, rotated)

    This function is from the example of the Adafruit_Python_ILI9341 library. Since PIL doesn’t have good native support for rotated fonts, this function was created to cover that. The specific details of how each line contributes is commented on the code.

    Display Loop

    while True:
    	weather = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=DFARJB5K7NRMH723')
    	temp = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=DTDBUJV92LCDRR9E')
    	tempC = str(round((int(temp.text)-32)*(5.0/9), 1))
    	precip = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=RONUZA8J3E57XC75')
    	hum = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=7HTFKFGFBDBPNPYW')
    	wind = requests.get('https://api.thingspeak.com/apps/thinghttp/send_request?api_key=7SF4TOGRXQ8VPKQT')
    	time = datetime.datetime.now()

    This is where the data from the website is being fetched via API requests. Make sure the URL inside requests.get() is the data you want to fetch, and store that in a variable. To get the current date and time, we can use datetime.datetime.now().

    disp.clear((0,0,0))
    	draw_rotated_text(disp.buffer, "Davao City Weather ", (200, 0), 270, bigfont, fill=(135,206,250))
    	print ("Last Updated " + time.strftime("%b %d %H:%M:%S"))
    	draw_rotated_text(disp.buffer, "Last Updated " + time.strftime("%b %d %H:%M:%S"), (170, 0), 270, font, fill=(66,244,182))
    	print (weather.text)
    	draw_rotated_text(disp.buffer, weather.text, (140, 0), 270, font, fill=(235,244,66))
    	print ("Temperature: " + tempC + " degrees C")
    	draw_rotated_text(disp.buffer, "Temperature: " + tempC + " degrees C", (100, 0), 270, font, fill=(255,255,255))
    	print ("Precipitation: " + precip.text + "%")
    	draw_rotated_text(disp.buffer, "Precipitation: " + precip.text + "%", (70, 0), 270, font, fill=(255,255,255))
    	print ("Humidity: " + hum.text + "%")
    	draw_rotated_text(disp.buffer, "Humidity: " + hum.text + "%", (40, 0), 270, font, fill=(255,255,255))
    	print ("Wind: " + wind.text)
    	draw_rotated_text(disp.buffer, "Wind: " + wind.text, (10, 0), 270, font, fill=(255,255,255))
    
    	disp.display()
    	sleep(60)

    Before drawing the words, first we have to clear the display to refresh its content. The draw_rotated_text() function is called to draw the words and data onto the TFT LCD screen. Just follow the format given and change the coordinates or position relative to the TFT LCD screen. I have set it to be 30-40 pixels apart. You can even change the rotation, font, and color of the text. For the time display format, we have to use time.strftime to get the string representing date and time. %b is for the month, %d is for the day, %H is for the hour, %M is for the minute, and %S is for the seconds. After the words are drawn, we then display it with disp.display() and set a delay so it does not spam.


    Conclusion

    This project is really a great way to learn about fetching data from a given website. This can be used in a wide range of applications. Since it can grab information from any website, such as stock market prices or even your YouTube video’s view count, people can use this to create live information boards without having to give public access to the whole website.


    References

    The post Raspberry Pi Live Weather Forecast With TFT LCD Display appeared first on CreateLabz.

    Api requestDatetimeIli9341KnowledgebaseLcdLive weather forecastPilPythonRaspberry piRaspberry pi zeroRpiRpi zero wSpiTftThinghttpZero

    Leave a comment

    All comments are moderated before being published