Introduction: Raspberry PI LED Weather Station

We created a Raspberry PI Weather LED Station. It tells the user how hot and cold a city is by lighting up, and dimming, leds. It also has a led to tell them whether or not its raining in the city they typed in.

Created by Michael Andrews and Tio Marello.

Supplies

Tools

  1. Soldering Iron
  2. Dremel
  3. Saw

Materials

  1. Raspberry Pi 3 B+ ~40 Dollars ~ 30 Dollars
  2. Female to Male Jumper wires ~7 Dollars
  3. 3 Blue and 2 Red LED Diodes ~ 11 Dollars
  4. 100 Ohm Resistors ~ 13 Dollars
  5. 4 x 4 x 1/4 Wood Plank ~ 5 Dollars
  6. Solder ~ 10 Dollars
  7. Copper Wire ~ 5 Dollars

Step 1: Coding As Problem Solving

Coding is problem solving

So, in our project, what's our problem? Our problem is getting weather data and then using that data to tell our LEDS whether they're off or on. So this splits up our problem into three areas.

1. Getting Weather Data

2. Using That Data

3. Using LEDS

However, the language we used for this project, Python, and the hardware it's running on, Python, give us an easy way to accomplish these goals.

So, we'll let's start with the first problem, getting weather data.

Step 2: Coding: Getting Weather Data

Python by itself can not get weather data. We have to import two tools, as well as an external service, to get weather data. To do this, we use three tools.

1. Requests, a python module which allows webscraping

2. Json, a python module which allows us to use the JSON file format

3. OpenWeather, a website that can give us weather data

So, we bring the two modules by writing this code at the top of our python script.

import requests
import json

Before we use these tools, however, we need to use Openweather. For that, we have to create an account on their site and get an API key. Follow the instructions on their website and you will get a string of letters and numbers which will let us use their service. How?

openweather_api_key = "260a23f27f5324ef2ae763c779c32d7e" #Our API Key (Not Real)
base_call = "http://api.openweathermap.org/data/2.5/weather?q=" #OpenWeather Call 


#Here we get the user's city in the form of text
print("Type in a city!")
city_name = input()

#Here we assembled the address we'll plug into requests.get to receive weather data
full_call = base_call+city_name+"&appid="+openweather_api_key



#Finally we call requests.get with our address, then we convert it into a json file
Response = requests.get(full_call)
WeatherData = Response.json()


#JSON files contain different variables which we can access using this syntax
#Here we get the weather ID and the temperature in Kelvin of the city the user typed in

WeatherID = WeatherData["weather"][0]["id"]
City_TemperatureK = WeatherData["main"]["temp"]

Here we have the code that gets us our weather data. Requests, in the form of requests.get, takes in a website address and gives us a file from that website back. OpenWeather gives us an address to call to give us weather data in the form of a json. We assemble an address which we plug into requests and get a json file back. Then we create two variables and assign them to the temperature and weatherid of the user's city.

So now, with this code, we have two variables. We have a weatherID and a temperature in Kelvin.

Step 3: Coding: Using That Data

Now that we have these two variables, we have to prep them for use for our LEDS. For this aspect, we don't have to import any modules for this.

First, we convert the kelvin to Fahrenheit.

We do this by creating a variable with this syntax

<p>City_TemperatureF = (City_TemperatureK - 273)*1.8 + 32</p>

which converts from Kelvin to Fahrenheit (which is really converting from K -> C -> F)

Next is our weatherID. The weatherID is an ID that Openweather provides which tells us about the weather conditions of a city.

https://openweathermap.org/weather-conditions Here is a list of them.

We noticed that everything below 700 number was some sort of precipitation, so we just checked if the code was below 700 to see if it was raining.

<p>def CheckRain(IdCode):<br>    if IdCode < 700:
        return True
    else:
        return False</p>

With that, we have our two variables prepped for use with our Raspberry PI pins and LED Diodes.

Step 4: Coding: Using RPi.GPIO and LED Diodes

The RaspberryPi comes with a set of male pins that we can use to communicate with a host of electrical components, which in this case, is LED Diodes; it's akin to Arduino and its system. However, the Raspberry PI is a general purpose computer, as opposed to a microcontroller like the Arduino. So, we have to do a little bit more work to use them. This consists of setting up the pins on the Raspberry Pi. We do this by using this code.

<p>import RPi.GPIO as GPIO #We import the module so we can use it</p><p>#Set up the pins<br>GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)</p><p>#The pins the LEDs are plugged into. These may be different if you build it, so make sure to compare and change when necessary
Extreme_Hot_LED_PIN = 26
Hot_LED_PIN = 16</p><p>Extreme_Cold_LED_PIN = 5
Cold_LED_PIN = 6</p><p>Rain_LED_PIN = 23</p><p>#We go through every pin, using the .setup command, putting in its number and setting it as an output pin</p><p>GPIO.setup(Rain_LED_PIN, GPIO.OUT)<br>GPIO.setup(Extreme_Cold_LED_PIN, GPIO.OUT)
GPIO.setup(Cold_LED_PIN, GPIO.OUT)
GPIO.setup(Hot_LED_PIN, GPIO.OUT)
GPIO.setup(Extreme_Hot_LED_PIN, GPIO.OUT)</p>

However, this code would only let us use two states with the led, that is, on and off. However, we need it to to be able to dim the lights. To do this, we use Pulse Width Modulation.

Using Pulse Width Modulation

Pulse Width Modulation lets us output an analog signal using a digital pin. Essentially, it turns on and off the signal source at a high rate, which averages out to certain voltage. The RPi.GPIO allows us to use this, albeit with some extra code.

<p>#We create four pin objects using the GPIO.PWM command, which takes in a channel number</p><p>#The second number is the number of times it updates per second</p><p>ExtremeHotLED = GPIO.PWM(Extreme_Hot_LED_PIN, 100)<br>HotLED = GPIO.PWM(Hot_LED_PIN, 100)</p><p>ExtremeColdLED = GPIO.PWM(Extreme_Cold_LED_PIN, 100)
ColdLED = GPIO.PWM(Cold_LED_PIN, 100)</p>

For the next step, you'll have to know the way we update these pins.

We update the pins using the command

<p>ExtremeColdLED.start(x)<br>ColdLED.start(x)</p><p>ExtremeHotLED.start(x)
HotLED.start(x)</p>

x in this case would be the duty cycle, which determines how much it pulses off. It ranges from 0-100, so we have to base our next code off that fact.

Step 5: Coding: Getting LED Brightness

Because we have four different leds, we want to light them up depending on how. cold or hot it is at the user's city. We decided to have four stages for the led.

<p>#Functions </p><p>def getmiddleleftledintensity(TemperatureinF):<br>    #Left Equation: y=-(50/20)x + 175
    #Right Equation: y = (50/20)x - 75
    return -(50/20)*TemperatureinF + 175</p><p>def getmiddlerightledintensity(TemperatureinF):
    #Left Equation: y=-(50/20)x + 175
    #Right Equation: y = (50/20)x - 75
    return (50/20)*TemperatureinF - 75</p><p>def getextremeleftledintensity(TemperatureinF):
    #LeftEquation: y = -(100/30)x + 200
    #RightEquation: y = (100/30)x - (400/3)</p><p>    return -(100/30)*TemperatureinF + 200</p><p>def getextremerightledintensity(TemperatureinF):
    # LeftEquation: y = -(100/30)x + 200
    # RightEquation: y = (100/30)x - (400/3)</p><p>    return (100/30)*TemperatureinF - (400/3)</p><p>#Setting the LED Lights</p><p>def GetLEDBrightness(temp):</p><p>    if temp <= 0:
        extremecoldled = 100
        coldled = 100
        hotled = 0
        extremehotled = 0</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif temp >= 100:
        extremecoldled = 0
        coldled = 0
        hotled = 100
        extremehotled = 100</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif 0 < temp <= 30:
        extremecoldled = getextremeleftledintensity(temp) - 100
        coldled = 100
        hotled = 0
        extremehotled = 0</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif 100 > temp >= 70:
        extremecoldled = 0
        coldled = 0
        hotled = 100
        extremehotled = getextremerightledintensity(temp) - 100</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif  30 < temp < 50:
        extremecoldled = 0
        coldled = getmiddleleftledintensity(temp)
        hotled = 100 - coldled
        extremehotled = 0</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif  50 < temp < 70:
        hotled = getmiddlerightledintensity(temp)
        extremehotled = 0</p><p>        coldled = 100 - hotled
        extremecoldled = 0</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)
    elif temp == 50:
        extremecoldled = 0
        coldled = 50
        hotled = 50
        extremehotled = 0</p><p>        print("Extreme cold led:" + str(extremecoldled))
        print("Cold led:" + str(coldled))
        print("Extreme hot led" + str(extremehotled))
        print("Hot led:" + str(hotled))</p><p>        ExtremeColdLED.start(extremecoldled)
        ColdLED.start(coldled)</p><p>        ExtremeHotLED.start(extremehotled)
        HotLED.start(hotled)</p>

Alright, this section of code is really long. It's also pretty hard to explain. Essentially, the code up above looks at the temperature in Fahrenheit, and determines if it's in a set of ranges. Depending on the ranges, it gives a number for each led and its brightness and then sets the brightness by calling the start() command. That's the quick explanation. If it suffices, I recommend you move onto the next step, but if you want to see the long and tedious explanation, keep reading.

When we programmed, we decided the easiest way to get a value from a temperature was in the form of a mathematical function. So, we created a graph in GeoGebra to represent what the relationship between our temperature and our led brightness; the reason it goes above 100 is that the extra would be going into the second led. However, we ran into the issue of getting a single function to map all these points to a single function. We thought we could use a parabola, but we decided to just settle for using a series of if statements. In essence, this entire code is a piecewise function.

The functions at the top are the respective equation of lines. Once we determine where the temperature is on the graph, we run it through that function, get the brightness, and pass it onto the leds.

Step 6: Coding: Final Steps!

Finally, we add this statement at the end.

<p>try:
    while(True):
        GetLEDBrightness(City_TemperatureF)
        GetRainLED(WeatherID)
        time.sleep(10)
except KeyboardInterrupt:
    quit()</p>

The try and except statements allow us to exit code by using a keyboard short cut; eitherwise, we would have to shut down the Raspberry Pi to restart the code. Then we have a while loop which runs forever. We update the leds, as well as update the rain LED. We pause for ten seconds; OpenWeather allows only 60 calls for data per minute, and 10 seconds is plenty of updates.

And with that, our code is finished. Below is the finished code.

RaspberryPIWeatherStation.py

importrequests
importRPi.GPIOasGPIO
importjson
importtime
#Openweather idCodes less than 700 are all precipitation
defCheckRain(IdCode):
ifIdCode<700:
returnTrue
else:
returnFalse
defgetmiddleleftledintensity(TemperatureinF):
#Left Equation: y=-(50/20)x + 175
#Right Equation: y = (50/20)x - 75
return-(50/20)*TemperatureinF+175
defgetmiddlerightledintensity(TemperatureinF):
#Left Equation: y=-(50/20)x + 175
#Right Equation: y = (50/20)x - 75
return (50/20)*TemperatureinF-75
defgetextremeleftledintensity(TemperatureinF):
#LeftEquation: y = -(100/30)x + 200
#RightEquation: y = (100/30)x - (400/3)
return-(100/30)*TemperatureinF+200
defgetextremerightledintensity(TemperatureinF):
# LeftEquation: y = -(100/30)x + 200
# RightEquation: y = (100/30)x - (400/3)
return (100/30)*TemperatureinF- (400/3)
#GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#Pins
Extreme_Hot_LED_PIN=26
Hot_LED_PIN=16
Extreme_Cold_LED_PIN=5
Cold_LED_PIN=6
Rain_LED_PIN=23
#Pin Setup
GPIO.setup(Rain_LED_PIN, GPIO.OUT)
GPIO.setup(Extreme_Cold_LED_PIN, GPIO.OUT)
GPIO.setup(Cold_LED_PIN, GPIO.OUT)
GPIO.setup(Hot_LED_PIN, GPIO.OUT)
GPIO.setup(Extreme_Hot_LED_PIN, GPIO.OUT)
ExtremeHotLED=GPIO.PWM(Extreme_Hot_LED_PIN, 100)
HotLED=GPIO.PWM(Hot_LED_PIN, 100)
ExtremeColdLED=GPIO.PWM(Extreme_Cold_LED_PIN, 100)
ColdLED=GPIO.PWM(Cold_LED_PIN, 100)
defGetLEDBrightness(temp):
iftemp<=0:
extremecoldled=100
coldled=100
hotled=0
extremehotled=0
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
eliftemp>=100:
extremecoldled=0
coldled=0
hotled=100
extremehotled=100
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
elif0<temp<=30:
extremecoldled=getextremeleftledintensity(temp) -100
coldled=100
hotled=0
extremehotled=0
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
elif100>temp>=70:
extremecoldled=0
coldled=0
hotled=100
extremehotled=getextremerightledintensity(temp) -100
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
elif30<temp<50:
extremecoldled=0
coldled=getmiddleleftledintensity(temp)
hotled=100-coldled
extremehotled=0
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
elif50<temp<70:
hotled=getmiddlerightledintensity(temp)
extremehotled=0
coldled=100-hotled
extremecoldled=0
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
eliftemp==50:
extremecoldled=0
coldled=50
hotled=50
extremehotled=0
print("Extreme cold led:"+str(extremecoldled))
print("Cold led:"+str(coldled))
print("Extreme hot led"+str(extremehotled))
print("Hot led:"+str(hotled))
ExtremeColdLED.start(extremecoldled)
ColdLED.start(coldled)
ExtremeHotLED.start(extremehotled)
HotLED.start(hotled)
defGetRainLED(idCode):
ifCheckRain(idCode):
GPIO.output(Rain_LED_PIN, GPIO.HIGH)
else:
GPIO.output(Rain_LED_PIN, GPIO.LOW)
#Api information: Repalce API key with your oepnweather api key
openweather_api_key="460a23f27ff324ef9ae743c7e9c32d7e"
base_call="http://api.openweathermap.org/data/2.5/weather?q="
print("Type in a city!")
city_name=input()
full_call=base_call+city_name+"&appid="+openweather_api_key
#Getting Weather Data
Response=requests.get(full_call)
WeatherData=Response.json()
WeatherID=WeatherData["weather"][0]["id"]
City_TemperatureK=WeatherData["main"]["temp"]
City_TemperatureF= (City_TemperatureK-273)*1.8+32#Convert to Fahrenheit
#LED/GPIO Stuff
print("K:"+str(City_TemperatureK))
print("F:"+str(City_TemperatureF))
print(WeatherID)
try:
while(True):
GetLEDBrightness(City_TemperatureF)
GetRainLED(WeatherID)
time.sleep(10)
exceptKeyboardInterrupt:
quit()

Step 7: Building and Wiring Up

Whew! After all that coding, we get to the building, which is significantly easier. Due to the corona stay at home orders, we couldn't get to many of the tools we expected to have at school. So, this part is a bit simpler than what we intended. The specifics themselves are also flexible. First we drew a rectangle on a plank of wood. The specific size doesn't really matter too much, as it simply serves as a platform to put leds and electronics on.

Then we drilled five 1/8th in holes in our piece of wood.

We then cut out the rectangle from the plank to use as our platform for our electronics.

(This was when we started; we found a bigger saw!)

We then push the anode and cathode pins of the led into the holes; the leds should be laying ontop, their bulbs sticking out; keep track of which leg is longer and shorter. We then got set to start soldering together wires. First we solder the resistors to the anode leg of the LED (the longer leg).

Then, we solder the cathode legs of the LEDs to a single copper wire which we'll use as ground. It should look like this.

After we do that, we solder the male ends of female-male jumper cables to the end ends of each resistor and the copper ground wire. Once we do that, we can start plugging the wires into the raspberry PI GPIO pins. Here's a diagram! However, do note, the pins are the ones in the previously touched upon code.

Once you have that all wired up, now all you gotta do is get the Python file onto the raspberry Pi and open the terminal. run "python3 RaspberryPIWeatherStation.py" and then do as it shows.

Step 8: Demonstration and Conclusion

Thanks for reading all the way through! I'll attach the python script below! If there were things we could add, it'd probably be...

1. Support for different input types (cities, geographic points, etc.)

2. Support for more weather information

3. Add a little screen to show information

Let us know your thoughts! This was a fun project to build. We learned a lot about requests and getting internet documents using python, and we also learned a lot about using soldering.