HomeTutorials › Raspberry Pi Weather Station – Part 3

Raspberry Pi Weather Station – Part 3

In the past two Raspberry Pi Weather Station Tutorials we have build the hardware to monitor several weather parameters and written the code to collect the information. In the third part of our four part tutorial we are going to figure out how to log our weather station’s data and display it on live updating graphs using a free web-based data service called ThingSpeak. ThingSpeak stores any data you send it and logs the time it receives it. Their service also allows you to create visualizations and data analysis – a very powerful tool! We are just going to touch on a few of the capabilities, so don’t be afraid to play around with ThingSpeak!

Overview:
Before we get started, you should have completed the previous two sections of this tutorial. Going forwards there are a few different things we need to do to get our data over to ThingSpeak. As always, we will break it down into a bunch of easier steps. We will start by creating an account with ThingSpeak, next we will gather the account information required to send data to ThingSpeak, we will then modify the code we wrote in the last part of the tutorial to send the data, test the connection and ensure the sent data is being received by ThingSpeak, and finally, take a quick look at the graph configuration and other features available.

Requirements:

parts

This tutorial requires several items:

  • A completed assembly from Part 1 of this tutorial set
  • Completed code from Part 2 of this tutorial set
  • 1 x Pi 3 / 3+ capable power supply
  • A USB Keyboard & Mouse
  • A HDMI compatible monitor
  • Internet access

Step 1 – Create a ThingSpeak account

Step4

Before we modify any of our code, or send anything anywhere, we need to go and create a free account at ThingSpeak. Jump on over to their site and generate an account.

Once your account is verified, log in.

Step 2 – Create a Channel

Step4

Now that we have an account set up we need to create a new channel to host and display our data. A ThingSpeak channel can have up to 8 different parameters sent to it. Since we only have 6 data parameters we are sending out, we will only need one channel for this project. Go ahead and click the “New Channel” button.

Step 3 – Configure your Channel

Step4

We are going to fill out each of the fields as shown. It is important that each field is the correct parameter – so field 1 needs to be temperature, field 2 needs to be humidity, etc. Aside from that: feel free to give your channel and appropriate name and fill out whatever information you want to share about your project. Once you are done, click Save at the bottom and your channel will be created.

Step 4 – Blank Channel

Step4

You should now see your channel, there isn’t much to see as there is no data for the graphs to plot… But we will get there! For now we are going to click the API Key tab at the top and get the necessary information we need to start sending data.

Step 5 – Get Your API Key

Step4

The API key is a unique key – this is used to identify data being sent to ThingSpeak as yours – it can be thought of as a unique, somewhat secure address. Don’t share this key – bored people could use this to send false data to your channel. Copy this key down; we are going to need it in the next steps as we write the Python code to send our data to ThinkSpeak.

Step 6 – Back To Coding The Pi

Step4

Changing gears, we are now going to start modifying the code we wrote on the Raspberry Pi in the last tutorial. If you don’t already have your project open in the Python editor on the Raspberry Pi, start by opening the terminal again and loading the Python 2 editor using the command:

idle3

Open your project file using the “file” menu.

Step 7 – Update Our Code

Our program already reads the sensors and collects the data, but to get this to ThingSpeak we will need to do a little bit more coding. ThinkSpeak accepts data in a few different ways – the easiest of which is a simple HTTP POST. This is basically a web address with your data tagged on the end that we will send every time we want to update the channel with new data (so every 15 seconds). Assembling the HTTP POST in Python is quite easy. We will just have to include a couple more libraries and add a bit more code to take care of it. We will also disable our print function we used to display our data at the end of our original code as we don’t need it anymore.

Working from our original code we are going to add/modify any of the highlighted lines:

import time
from w1thermsensor import W1ThermSensor
 
import board
import busio
import adafruit_bme280
i2c = busio.I2C(board.SCL, board.SDA)
 
import adafruit_ads1x15.ads1015 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
 
import RPi.GPIO as GPIO
import urllib
import http.client
 
key = "1Z170TQ59OH6F6JS"

 
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c)
ads = ADS.ADS1015(i2c)
ads.gain = 1
 
 
ds18b20 = W1ThermSensor()
 
interval = 15  #How long we want to wait between loops (seconds)
windTick = 0   #Used to count the number of times the wind speed input is triggered
rainTick = 0   #Used to count the number of times the rain input is triggered
 
#Set GPIO pins to use BCM pin numbers
GPIO.setmode(GPIO.BCM)
 
#Set digital pin 17 to an input and enable the pullup 
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
 
#Set digital pin 23 to an input and enable the pullup 
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
 
#Event to detect wind (4 ticks per revolution)
GPIO.add_event_detect(17, GPIO.BOTH) 
def windtrig(self):
    global windTick
    windTick += 1
 
GPIO.add_event_callback(17, windtrig)
 
#Event to detect rainfall tick
GPIO.add_event_detect(23, GPIO.FALLING)
def raintrig(self):
    global rainTick
    rainTick += 1
 
GPIO.add_event_callback(23, raintrig)
 
 
while True:
 
    time.sleep(interval)
 
    #Pull Temperature from DS18B20
    temperature = ds18b20.get_temperature()
 
    #Pull temperature from BME280
    case_temp = bme.temperature
 
    #Pull pressure from BME280 Sensor & convert to kPa
    pressure_pa = bme.pressure
    pressure = pressure_pa / 10
 
    #Pull humidity from BME280
    humidity = bme.humidity
 
    #Calculate wind direction based on ADC reading
    chan = AnalogIn(ads, ADS.P0) 
    val = chan.value * 16
    windDir = "Not Connected"
    windDeg = 999
 
    if 20000 <= val <= 20500:
        windDir = "N"
        windDeg = 0
 
    if 10000 <= val <= 10500:
        windDir = "NNE"
        windDeg = 22.5
 
    if 11500 <= val <= 12000:
        windDir = "NE"
        windDeg = 45
 
    if 2000 <= val <= 2250:
        windDir = "ENE"
        windDeg = 67.5
         
    if 2300 <= val <= 2500:
        windDir = "E"
        windDeg = 90
 
    if 1500 <= val <= 1950:
        windDir = "ESE"
        windDeg = 112.5
 
    if 4500 <= val <= 4900:
        windDir = "SE"
        windDeg = 135
 
    if 3000 <= val <= 3500:
        windDir = "SSE"
        windDeg = 157.5
 
    if 7000 <= val <= 7500:
        windDir = "S"
        windDeg = 180
 
    if 6000 <= val <= 6500:
        windDir = "SSW"
        windDeg = 202.5
 
    if 16000 <= val <= 16500:
        windDir = "SW"
        windDeg = 225
 
    if 15000 <= val <= 15500:
        windDir = "WSW"
        windDeg = 247.5
 
    if 24000 <= val <= 24500:
        windDir = "W"
        windDeg = 270
 
    if 21000 <= val <= 21500:
        windDir = "WNW"
        windDeg = 292.5
 
    if 22500 <= val <= 23000:
        windDir = "NW"
        windDeg = 315
 
    if 17500 <= val <= 18500:
        windDir = "NNW"
        windDeg = 337.5
 
    #Calculate average windspeed over the last 15 seconds
    windSpeed = (windTick * 1.2) / interval
    windTick = 0
 
    #Calculate accumulated rainfall over the last 15 seconds
    rainFall = rainTick * 0.2794
    rainTick = 0
 
    #Print the results
    #print( 'Temperature: ' , temperature)
    #print( 'Humidity:    ' , humidity, '%')
    #print( 'Pressure:    ' , pressure, 'kPa')
    #print( 'Wind Dir:    ' , windDir, ' (', windDeg, ')')
    #print( 'Wind Speed:  ' , windSpeed, 'KPH')
    #print( 'Rainfall:    ' , rainFall, 'mm')
    #print( ' ')

    params = urllib.parse.urlencode({'field1' : temperature, 'field2' : humidity, 'field3' : pressure, 'field4' : windSpeed,
                               'field5' : windDeg, 'field6' : rainFall,'key':key})

    #Configure header / connection address
    headers = {"Content-typZZe": "application/x-www-form-urlencoded","Accept": "text/plain"}
    conn = http.client.HTTPConnection("api.thingspeak.com:80")
 
    #Try to connect to ThingSpeak and send Data
    try:
        conn.request("POST", "/update", params, headers)
        response = conn.getresponse()
        print( response.status, response.reason)
        data = response.read()
        conn.close()
 
    #Catch the exception if the connection fails
    except:
        print( "connection failed")


  • (13-14) Import urllib and http.client libraries for our HTTP connection to Thingspeak
  • (16) Assign our API key from ThingSpeak to the variable “key” – this is the thing we copied in step 5
  • (151-158) Comment out our existing print statements, these aren’t needed
  • (160-161) Assign each measured variable to the correct field for ThingSpeak
  • (163-165) Configure the header and connection address
  • (167-173) Attempt to connect to ThinkSpeak and send the data, prints the response
  • (175-177) Catch the exception – this would occur if your internet connection was down, ThingSpeak was down, and prevents the program from crashing. Instead it will just ignore this failure to send, and attempt again with new data at the next interval (15 seconds in this case)

 
Let’s try it out – press “F5” and it should prompt you to save it. After saving it should run, and in the Python Shell window you should see it print “200 OK” – this means data has been successfully sent to ThingSpeak. It will continue to post data every 15 seconds.

If you see “connection failed”: double check you have input your API key correctly and check your internet connection is up on the Raspberry Pi!

Step 8 – Channel Updating

Step4

Now that we have data streaming out to ThingSpeak, jump over to your channel. You should now see data starting to appear on the graphs! By default they will show the last ~ 60 data points (roughly the last 15 minutes when sent at a 15 second interval).

Step 9 – Configuring Graphs

Step4

Each of the graphs can be configured by clicking the “pencil” logo in the top right corner of the graph. Add the title, X & Y axis labels, change the colors as you see fit. We also recommend setting the minimum value to zero on the wind speed and rainfall graphs to improve the auto formatting of the graph.

There are quite a few other options available as well – you can graph over much longer periods of time, thin the data reporting on the graph out, and even change the type of graph.

Step 10 – Sharing

Step4

By default, ThingSpeak Channels are private, but if you wish to share this information with the world, simply jump over to the sharing tab in your Channel and change the setting. If set to public, people can browse your channel, see your data, and you can even host each graph on external webpages.

Step 11 – External Graphs

Step4

To host graphs (and other visualizations) on external sites, ThingSpeak provides code that can be pasted into the HTML of your website. The code can be found by clicking the “chat bubble” logo in the top right of any graph or display widget. You can even create a basic HTML file containing all of these code snippets and host it on your own computer (or the Raspberry Pi itself) to create a basic weather dashboard!

Step 12 – Going Forwards

We are barely scratching the surface of what is possible with ThingSpeak – there are a lot of opportunities to improve how data is displayed and analyzed. You can even go ahead and generate additional information from your data like windchill, humidity, high/low temperature maximums, and others within the MATLAB Analysis tools. The Gauge Widget allows you to create dynamic gauges that display your data. Be sure to have a look through the tutorials on the ThingSpeak website to see all of the possibilities!

We are getting close to the end of this four part tutorial; in the final part we will look at getting the weather station outside running 24/7. There is a lot to consider when placing sensors outdoors. We will also look at keeping your hardware safe, power and internet connectivity, locating the station to get the best readings, things you can do to improve the accuracy of your sensors, and how to get your weather program to run whenever the Pi boots up. Ready to take on the last step? Jump over to Part 4 now!

Have A Question?
If you have any questions, or need further clarification please post in the comments section below; this way future users of this tutorial can see the questions and answers!

Parts Used In This Tutorial:

3 comments

  1. mike87
  2. Adrian

Leave a Reply