How’s the weather? With this DIY project, you’ll always have a very precise answer. Sure, you could check websites or smartphone apps, but why pass up the chance to build a Raspberry Pi weather station? This project is a great way to get used to dealing with the Sense HAT, Python scripts, and even web hosting apps. We’ll lay it all out below.

This is a simple project, but you will need more than just a Raspberry Pi device in order to build a Raspberry Pi weather station. No Raspberry Pi model comes out of the box with the sensors we’ll need in order to tell the temperature or humidity. Happily, adding those sensors is very easy to do. We’ll just need to grab a Sense HAT.

The Sense HAT is a Raspberry Pi peripheral that was originally designed for the Astro Pi mission, which saw some educational Raspberry Pi projects end up running on the International Space Station. The Sense HAT’s LED grid and various sensors have more terrestrial applications, too, and we’ll be exploring some of those today.

With the Sense HAT, we can sense the temperature and humidity. We can call that information up on our monitor with a script, and we can even display it on the Sense HAT’s LED grid. If we’re really feeling adventurous, we could even connect our Raspberry Pi to our network and this weather-related information in a web browser.

Below, we’ll show you how to do all three. First, though, here’s what you’ll need for this project:

If you’ve got all that, you’re ready to get started! Let’s dive in.

Building a Raspberry Pi weather station in Python

There are a few ways to display the weather information we want, but all of them start with using the Sense HAT to get the measurements in the first place. Our first serving of step-by-step instructions focuses on setting up the Sense HAT, sensing the information, and checking our work by displaying everything to our terminal in Raspbian.

Step 1: Attach your Sense HAT to your Raspberry Pi

The Sense HAT uses the Raspberry Pi’s GPIO pins to send and receive information (for more on the Raspberry Pi’s GPIO pins, check out our complete Raspberry Pi GPIO pin tutorial). To attach your Sense HAT to your Raspberry Pi, start with everything turned off and unplugged. Then, carefully slide the Sense HAT’s GPIO slots over the GPIO pins on your Raspberry Pi. It’s a good idea to also install the little supports that come with the Sense HAT.

If you have a GPIO breakout kit, you might want to use that to keep your Sense HAT a little further away from your Raspberry Pi’s CPU, which can get warm and mess up our readings. Using a heat sink on your Pi’s chip can help, too.

With everything attached properly, you can turn your Raspberry Pi back on. You should a rainbow displayed in the Sense HAT’s LED array if you’ve done it right.

Step 2: Let’s get some updates

Experienced Raspbery Pi DIYers know that running an update check is a smart way to start just about any project. Let’s do that. Open Terminal in Raspbian and enter this command:

sudo apt-get update
sudo apt-get upgrade

Once you’re up to date, double-check that you have the Sense HAT package:

sudo apt-get install sense-hat

Raspbian comes with the Sense HAT package already on board, but it never hurts to double-check.

Step 3: Write a script that sense temperature and humidity with your Sense HAT

Our first Raspberry Pi weather station code

Using terminal, open a new file with a text editor. We recommend using nano, a great text editor that’s built into Raspbian. You can do this by entering a command like this into the Terminal:

nano weatherstation.py

This tells nano to open the file (or create it, if it’s new) and that we’re working on a Python script.

Here’s what our script is going to look like. (There are a couple of ways to make this script neater, which we’ll discuss in just a moment.)

from sense_hat import SenseHat
sense = SenseHat()
sense.clear()
temp = sense.get_temperature()
cTemp = round(temp, 1)
fTemp = round(temp * 1.8 + 32, 1)
print("It is {} degrees Celsius".format(cTemp))
print("It is {} degrees Fahrenheit".format(fTemp))
humidity = round(sense.get_humidity(), 1)
print("The relative humidity is {}%".format(humidity))

Exit nano and save your progress by hitting Ctrl+X, then Y, and then Enter.

Now you can run your script by typing this into the Terminal:

sudo python weatherstation.py

You should see something like this:

A look at our Terminal window. Our Raspberry Pi weather station worked!

Why so warm? Our Raspberry Pi is generating some heat itself. A heat sink on the Raspberry Pi CPU or a GPIO breakout kit will help you dodge this issue.

Very cool! But that doesn’t totally explain how we got here, so let’s take a quick step back.

Step 4: Breaking down our code

Here’s a line-by-line breakdown of our code — along with some tips for making it better.

from sense_hat import SenseHAT

Here, we’re importing the Sense HAT library so that our Python interpreter knows what to do with certain commands when we run our program. Python can do a lot of stuff right out of the box, but it can do even more when we add “libraries,” which are chunks of extra commands and functionality. It wouldn’t really make sense for a bunch of Sense HAT-specific commands to be in Python by default, so it’s no surprise that we find these in a library.

sense = SenseHat()

Python fans will recognize this as “object instantiation.” We’re taking a class of commands — the SenseHat() class — and naming them with a variable. Now we’ll be able to call commands from this class by appending “sense” and a dot operator (aka a period) before the command.

sense.clear()

…and that’s just what we do here. This calls the clear() command in the SenseHat() class, clearing whatever junk our Sense HAT was doing out of the way so that we can start sensin’ some temps.

temp = sense.get_temperature()

Here, we declare our first variable: temp, which we identify as the temperature the Sense HAT senses.

cTemp = round(temp, 1)

The variable tempC will be our temperature in Celsius. The Sense HAT measures the temperature in Celsius by default, but the number it stores is full of decimal points. Let’s simplify things by using the round() command and specifying the number of decimal places we want as 1.

fTemp = round(temp * 1.8 + 32, 1)

Now for Fahrenheit. Since our initial measurement is in Celsius, we have to use a conversion formula.

print("It is {} degrees Celsius".format(cTemp))

We could assume that everything has gone well so far, but there’s no use in sensing the temperature if we don’t get to see the results. Here, we print the temperature to our Terminal screen. We’ve use the format() command to stick our number into the middle of our text, all pretty-like.

print("It is {} degrees Fahrenheit".format(fTemp))

Same thing here.

humidity = round(sense.get_humidity(), 1)

We’re all set on temperature, but what about humidity? Here, we set a variable named humidity. We use sense.get_humidity() to find our figure, and then we place that within the round() command and specify that we want 1 decimal place.

With this line, we’ve revealed something inefficient about our code. Since we can sense things and round them in the same line of code, we never actually needed to define the variable temp. We could simply delete the line defining temp and redefine cTemp and fTemp as round(sense.get_temperature(), 1) and round(sense.get_temperature() * 1.8 + 32, 1) respectively. And, in fact, that’s just what you should do — if you want to be abiding by best coding practices, anyway.

print("The relative humidity is {}%".format(humidity))

This line prints our humidity figure.

Printing weather information to the Sense HAT LED array

The Sense HAT has more than just sensors. It also has a cool grid of LEDs that we can program to display information. Let’s make our weather station work without a monitor!

Step 1: Our new code

This version of our Raspberry Pi weather station Python code will print our results to the Sense HAT's LED matrix

You can edit your old code if you’d like, but we’re going to make a new file just to keep ourselves organized:

nano LEDweather.py

Here’s the code we’re using this time around:

from sense_hat import SenseHat
sense = SenseHat()
sense.clear()
cTemp = round(sense.get_temperature(), 1)
fTemp = round(sense.get_temperature() * 1.8 + 32, 1)
humidity = round(sense.get_humidity(), 1)
sense.show_message("It is {} degrees Celsius".format(cTemp))
sense.show_message("It is {} degrees Fahrenheit".format(fTemp))
sense.show_message("The relative humidity is {}%".format(humidity))

You can run this code using this command in Terminal:

sudo python LEDweather.py

You should see the weather information scroll gloriously across your Sense HAT’s LED screen.

Step 2: How does this work?

For the most part, this code works just like the last script we wrote. We’ve cleaned up our variables (we no longer define a variable temp, because we can use the sense.get_temperature() command in its place), but the only big change here is the addition of these lines:

sense.show_message("It is {} degrees Celsius".format(cTemp))
sense.show_message("It is {} degrees Fahrenheit".format(fTemp))
sense.show_message("The relative humidity is {}%".format(humidity))

You can probably figure out how these work. The command sense.show_message() prints messages to the Sense HAT’s LED screen. It works pretty much exactly like print() did in our last script.

Creating an online Raspberry Pi weather station

We’ve used our sense HAT to check the temperature and humidity, and we’ve been able to take in that information in two ways so far: within our Terminal window and via the sense HAT’s LED matrix. Let’s try a third way. Here’s how to get your weather information on the web.

Step 1: Another Python script

Code for the web version of our Raspberry Pi weather station

You don’t need to invest in a domain name and hosting to do this project. We can just host our own little site using a Flask, a web app framework in Python. Flask should already be on board thanks to Raspbian, but let’s double-check:

sudo apt-get install python3-flask

Once you’re sure you’re all set on that front, open a new Python file in nano:

nano weatherapp.py

…and fill it up with some nice new code. Here’s what we’re entering in our new Python file:

from flask import Flask, render_template
from sense_hat import SenseHat
app = Flask(__name__)
@app.route("/")
def index():
sense = SenseHat()
cTemp = round(sense.get_temperature(), 1)
fTemp = round(sense.get_temperature() * 1.8 + 32, 1)
humidity = round(sense.get_humidity(), 1)
return render_template("weathersite.html", cTemp=cTemp, fTemp=fTemp, humidity=humidity)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")

Step 2: What did we just do?

Some parts of this code should be familiar. Once again, we import libraries, do a little object instantiation, and use our Sense HAT to define the variables cTemp, fTemp, and humidity. There are some new lines, too, however.

app = Flask(__name__)

At this point in our code, we’ve already imported Flask. Now, we’ll call a single instance of Flask. We use __name__ here because the name of our module may change depending on whether or not it’s the main program running — more on that in a moment.

@app.route("/")

This tells Flask which URL will trigger our function. We just need “/” here, but you could write things for “/home” or “/index” if you wanted to.

def index():

Now we’re defining our function.

After defining our variables, we close our our function with:

return render_template("weathersite.html", cTemp=cTemp, fTemp=fTemp, humidity=humidity)

Here’s a key part of our code. We’re choosing our template (weathersite.html, which we haven’t created yet) and we’re making sure that variables in our template have values coming from our function.

if __name__ == "__main__":

This is a Python staple that essentially determines if our Python script is running as the main program. When we run this script directly (by typing “sudo python weatherapp.py” into the Terminal, for example), our Python interpreter will set __name__ to be “__main__” — so this should be true, and our last line should execute.

app.run(debug=True, host='0.0.0.0')

This runs Flask and gets our little web-hosting operation going.

Step 3: Make a web page

HTML code for our Raspberry Pi weather station

You could run weatherapp.py now, but it wouldn’t do much for you. It uses the template weathersite.html, which doesn’t exist — yet.

Let’s make a templates directory:

mkdir templates

…and now let’s stick a new HTML file in it and open that bad boy up in nano.

nano templates/weathersite.html

Now we have a new HTML document open. Here’s what we’ll type up in that document:

<!doctype html>

<html>
   <head>
      <title>Weather Station</title>
   </head>

   <body>
      <h1>How's the weather?</h1>

      <h2>Temperature</h2>
         <p><strong>{{ cTemp }}</strong> degrees Celsius</p>
         <p><strong>{{ fTemp }}</strong> degrees Fahrenheit</p>

      <h2>Humidity</h2>
         <p><strong>{{ humidity }}%</strong> relative humidity</p>
      </body>
</html>

Now, when we run our Python script, it should host this HTML page and provide the variables that we’ve mentioned in the HTML.

We won’t bother with the breakdown, since HTML is pretty easy to read. Just note the use of variables in {{ brackets }} — those are the same ones that we defined back in our weatherapp.py script and sent to the template with the ninth line of that script.

Step 4: Fire up your server and pay your site a visit

Our Python script and HTML template are both done. Let’s see how they are working! In Terminal on our Raspberry Pi, we’ll enter this command:

sudo python weatherapp.py

You’ll see something like this:

Running a server for our Raspberry Pi weather station

Open up your Pi’s web browser and navigate to the address indicated by the code above: 0.0.0.0:5000 (or 127.0.0.1:5000 — same thing).

You should see something like this:

Raspberry Pi weather station web page

You can access this same screen from other devices on your network by using a web browser and navigating to your Raspberry Pi’s local IP address followed by :5000. But you won’t be able to access your site from outside of your home network unless you set up port forwarding.

Step 5: Set up port forwarding

If you want to be able to check your Raspberry Pi weather station from anywhere, you’ll need to take one more step.

Setting up port forwarding means accessing your router. Type in your router’s IP address (it should be printed on a sticker somewhere on the router) and log in with your administrator credentials (again, they should be on the sticker — unless you’ve changed them, which is a smart move). Your router may also let you mess with settings using an app or some other sort of access/login setup.

Find your router’s port forwarding options and set them up like this:

Service port: 80

Internal port: 5000

IP address: [set this to your Raspberry Pi’s IP address]

Protocol: TCP

Now your Raspberry Pi weather station should be accessible from outside of your home network. Just run the weatherapp.py script on your Raspberry Pi and then enter your Raspberry Pi’s public IP address into a web browser address bar. (If you don’t know your Pi’s public IP address, you can ask Google.) You should see your weather station website!