Fetching real-time weather data and controlling the speed of a motor fan with Raspberry Pi
userhead
42 2020-08-20 11:59:51
projectImage

P.S: This tutorial is aimed at users with some basic experience in using Raspberry Pi or other microcontrollers. However, people with no experience with Raspberry Pi or microcontrollers should still be able to follow along. 


What you will make 

This tutorial guides you on how to fetch the real-time weather data with Raspberry Pi using Open Weather Map API and how to control the speed of the fan depending on the current weather. 


What you will learn 

By creating a script to fetch the data from a weather database, you will learn: 

• How to access the OpenWeatherMap API with pyowm library in Python. 

• How to use different functions like PWM with GPIO library for accessing the GPIO pins on Raspberry Pi. 

• How to control/ adjust the speed of the fan depending on the real-time weather data in your local area.


Things you will need to complete this project: 

• Raspberry Pi with Raspberry Pi OS (Ubuntu/NOOBS should also work fine). 

  If you don’t have any OS installed on your Raspberry pi, head over to https://www.raspberrypi.org/downloads/ and follow the steps to get an OS installed on your Raspberry Pi.

• 3 (M-F) Jumper Cables 

• A digital motor module with plastic fan blades 


Configuring OpenWeatherMap 

You will need to register on Open Weather Map website to receive an API key. OpenWeatherMap.org has an amazing API for individuals that is both free and simple. Just select a service, generate an API key, and send requests! Then, use that data to create displays, change the state of a machine, or even control other devices. 

 Upon entering the site, first create a new account.

projectImage
projectImage

After signing in, navigate to the API page at the top to view their wide variety of weather APIs. Click the “Subscribe” button under the “Current Weather Data” section.

projectImage

This is the API that is available for free. At this tier, users are limited to 1 request per second, which should be plenty for a single project. The free tier also has a 5-day/3-hour forecast option and weather alerts. Select the “Get API key” button to go to the next page. 

projectImage

When you register, an email is sent to your e-mail address that contains a key. Make sure to allow a few hours for it to become active before using it. Once you have your key, keep it safe and don't share it online as it is used to identify you when using the service. 


Download the Pyowm and GPIO library 

With our API key in hand we now need to download the Python library for Open Weather Map, and that is called pyowm. We will download and install the version for Python 3. 

On your Raspberry Pi, you will need to be connected to the Internet and do the following. 

• Open the terminal 

• Type in sudo pip3 install pyowm. The library will be installed momentarily. 

• The rpio.gpio library should be already installed in your Raspberry Pi you are using Raspberry Pi OS or NOOBS OS. 


Code for getting the weather and controlling the fan speed: 

Fetching the weather: 

Head over to your favorite editor, open a new file and save it before moving on. We start the code by importing time, the pyowm and GPIO library that will give us the time, weather information and let us access the GPIO pins, respectively.

CODE
					import time
import RPi.GPIO as GPIO
from pyowm import OWM
				

Next we create a variable called owm, which will be used to contain your API key. This makes it easier to work with.

CODE
					owm = OWM('PASTE YOUR API KEY IN HERE') # valid API key
				

Then we use the city_id-registry() function from pyowm library to get the id of our location. We provide the place and the country’s name and the API gives us the city ID. This way we can confirm the location.

CODE
					reg = owm.city_id_registry()      # lots of results
list_of_tuples = SH = reg.ids_for('Shanghai', country='CN')  # only one: [ (1796236,, 'Shanghai, CN  ') ]
id_of_sh_city = list_of_tuples[0][0]
print(id_of_sh_city)
				

Now we create two more variables called mgr and observation that will set the location that we wish to use for our weather query, this works for any location around the world. It even works with postal and ZIP codes. You can play around with it if you are interested.

CODE
					# Search for current weather in Shanghai,Pudong (China)
mgr = owm.weather_manager()
observation = mgr.weather_at_place('SHanghai,CN')
				

Our next variable is simply called w and we use this variable to shorten the function that will gather the weather data for your location and print out the information.

CODE
					w = observation.weather )# <Weather - reference_time=2020-07-06 12:06:51+00, 
print(w) #status=rain, detailed_status=light intensity shower rain>
				

We define w_2, w_3, w_4 for wind, humidity and temperature respectively, to capture the wind speed, its direction, humidity and other various information related to the weather.

CODE
					# Weather details
w_2 = w.wind()                  # {'speed': 4, 'deg': 300}
w_3 = w.humidity                # 100
w_4 = w.temperature('celsius')  # {'temp': 23.4, 'temp_max': 23.89, 'temp_min': 22.78, #'feels_like': 26.07, 'temp_kf': None} #w_4 = int(w_4)      
				

Then, next three lines of the code are simple print functions that will print out the contents of the variables w_2, w_3 and w_4.

CODE
					print("The wind speed is", w_2) 
print("The humidity is", w_3) 
print("The temperature is", w_4) 
				

Your code should now look like this.

CODE
					import time
import RPi.GPIO as GPIO
from pyowm import OWM

owm = OWM('PASTE YOUR API KEY IN HERE') # valid API key

reg = owm.city_id_registry()# lots of results
list_of_tuples = SH = reg.ids_for('Shanghai', country='CN') # only one: [ (1796236,, 'Shanghai, CN  ') ]
id_of_sh_city = list_of_tuples[0][0]
print(id_of_sh_city)
# Search for current weather in Shanghai,Pudong (China)
mgr = owm.weather_manager()
observation = mgr.weather_at_place('SHanghai,CN')
w = observation.weather # <Weather - reference_time=2020-07-06 12:06:51+00, 
print(w) #status=rain, detailed_status=light intensity shower rain>
# Weather details
w_2 = w.wind()                  # {'speed': 4, 'deg': 300}
w_3 = w.humidity                # 100
w_4 = w.temperature('celsius')  # {'temp': 23.4, 'temp_max': 23.89, 'temp_min': 22.78, #'feels_like': 26.07, 'temp_kf': None} #w_4 = int
print("The wind speed is", w_2) 
print("The humidity is", w_3) 
print("The temperature is", w_4) 
				

Save your work, and run the python script from terminal. Open the terminal on your Raspberry pi and type python3 your_file_name.py

CODE
					pi@raspberrypi:~Downloads $ python3 raspberrypi_weather_ctrl_fan.py
				

You should see something like this.

CODE
					pi@raspberrypi: -/Downloads $ python3 raspberrypi_weather_ctrl_fan.py 
1796236
<pyowm.weatherapi25.weather.Weather - reference_time=2020-07-O7 06:57:35+00, status=clouds, detailed_status=scattered clouds> 
The wind speed is {'speed': 3, 'deg': 280}
The humidity is 66
The temperature is {'temp': 34.47, 'temp_max': 38.33, 'temp_min': 32.0, 'feels_like': 40.22, 'temp_kf': None}
				

This shows us in this case, the weather in Shanghai, China is cloudy now, and there is a 3Mph wind coming from 280 degrees, the humidity is 66, the current temperature is 34.47 degree Celsius, while the max temp for today is 38.33 degree Celsius and min temp is 32.0 degree Celsius, the real feel of the temperature is 40.22 degree Celsius.

Controlling the fan: 

Now that we have fetched the weather info, we can use this data to control the speed of the fan depending on the temperature. 

We only need some jumper cables and a motor module with plastic fan blades that we will directly connect to the Raspberry Pi.


Setup 

In most cases, the colors of the wires in the servo are as follows and follow the diagram to connect your servo to the Raspberry Pi: 

Black – comes to GND (pin 6) from the Pi 

Red – comes to 3V3 (pin 1) from the Pi 

Yellow/Orange/Green – to a free GPIO pin (e.g., GPIO17, pin 11)

projectImage

First, we define the GPIO pin number where our motor is connected, then we use setmode function which is BCM (GPIO board numbering method) and setup mode function which means the GPIO pin 17 is set as our output.   

CODE
					#Control the fan speed based on the weather data
motorPIN = 17
GPIO.setmode(GPIO.BCM) #for GPIO numbering, choose BCM
GPIO.setup(motorPIN, GPIO.OUT) #set GPIO as output
				

Motor module doesn’t occupy many GPIO pins to command a movement. For this, the rotation of the motor is controlled by the length of the pulse. 

The angle of the motor is set along the length of the pulse, so PWM is particularly useful, which sends repetitive signals at even intervals. To create PWM instance, p using GPIO library, we set the channel (the pin number in this case) and the frequency at which the motor should rotate. To start the PWM, we simply call the start function where the value of the parameter is duty cycle (0.0

CODE
					p = GPIO.PWM(motorPIN, 100) # GPIO 17 for PWM with 100Hz
p.start(2.5) # Initialization
				

Note that, PWM will also stop if the instance variable 'p' goes out of scope. Now, as we have our fan set, we define some simple if-else logic to control the speed of the fan. 

CODE
					try:
    if (w_4['temp'] >= 30):
        print('Fanspeed is set to 100')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(100) # GPIO 17 for PWM with 100Hz
        time.sleep(5000)
        
    if (w_4['temp'] >= 25):
        print('Fanspeed is set to 75')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(85) # GPIO 17 for PWM with 85Hz
        time.sleep(5000)
        
    if (w_4['temp'] >= 20):
        print('Fanspeed is set to 75')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(75) # GPIO 17 for PWM with 75Hz
        time.sleep(5000)    
        
    else:
        print('Fanspeed is set to 50, will stop soon')
        print('It is cold outside') 
        p.ChangeDutyCycle(50) # GPIO 17 for PWM with 50Hz
        time.sleep(20)
				

We can check whether the temperature is over a defined threshold and thus the PWM should change its values. The first line of the code here, compares the first entry ‘temp’ of the dictionary w_4 with the threshold value. Next two lines, print the fan speed and adds delay in the execution of our program. Here, ChangeDutyCycle is the duty cycle function. Notice import time at the beginning of our code, now we use this python module to set the time for how long the PWM should keep rotating the motor of the fan.

CODE
					except KeyboardInterrupt:
  p.stop()
  GPIO.cleanup()
				

Finally, upon any keyboard interruption. The PWM will stop as we used p.stop(). By using GPIO.cleanup(), we make sure that our program exits normally, all the ports we’ve used will be cleaned up and ready for use straight away. 

Your whole code should look like this now, 

CODE
					import time
import RPi.GPIO as GPIO
from pyowm import OWM

owm = OWM('PASTE YOUR API KEY IN HERE') # valid API key

reg = owm.city_id_registry()# lots of results
list_of_tuples = SH = reg.ids_for('Shanghai', country='CN') # only one: [ (1796236,, 'Shanghai, CN  ') ]
id_of_sh_city = list_of_tuples[0][0]
print(id_of_sh_city)
# Search for current weather in Shanghai,Pudong (China)
mgr = owm.weather_manager()
observation = mgr.weather_at_place('SHanghai,CN')
w = observation.weather # <Weather - reference_time=2020-07-06 12:06:51+00, 
print(w) #status=rain, detailed_status=light intensity shower rain>
# Weather details
w_2 = w.wind()                  # {'speed': 4, 'deg': 300}
w_3 = w.humidity                # 100
w_4 = w.temperature('celsius')  # {'temp': 23.4, 'temp_max': 23.89, 'temp_min': 22.78, #'feels_like': 26.07, 'temp_kf': None} #w_4 = int
print("The wind speed is", w_2) 
print("The humidity is", w_3) 
print("The temperature is", w_4) 
#Control the fan speed based on the weather data
motorPIN = 17
GPIO.setmode(GPIO.BCM) #for GPIO numbering, choose BCM
GPIO.setup(motorPIN, GPIO.OUT) #set GPIO as output

p = GPIO.PWM(motorPIN, 100) # GPIO 17 for PWM with 100Hz
p.start(2.5) # Initialization

try:
    if (w_4['temp'] >= 30):
        print('Fanspeed is set to 100')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(100) # GPIO 17 for PWM with 100Hz
        time.sleep(5000)
        
    if (w_4['temp'] >= 25):
        print('Fanspeed is set to 75')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(85) # GPIO 17 for PWM with 85Hz
        time.sleep(5000)
        
    if (w_4['temp'] >= 20):
        print('Fanspeed is set to 75')
        print('Press ctrl+c to stop')
        p.ChangeDutyCycle(75) # GPIO 17 for PWM with 75Hz
        time.sleep(5000)    
        
    else:
        print('Fanspeed is set to 50, will stop soon')
        print('It is cold outside') 
        p.ChangeDutyCycle(50) # GPIO 17 for PWM with 50Hz
        time.sleep(20)
    
except KeyboardInterrupt:
  p.stop()
  GPIO.cleanup()
				

Save your program and run the python file again from your command line and you should see the final output in the terminal. 

CODE
					pi@raspberrypi:~/Downloads $ python3 raspberrypi_weather_ctrl_fan.py 
1796236
<pyowm.weatherapi25.weather.Weather - reference_time=2020-07-07 06:57:35+00, status=clouds, detailed_status=scattered clouds> 
The wind speed is {'speed': 3, 'deg': 280}
The humidity is 66
The temperature is {'temp': 34.47, 'temp_max': 38.33, 'temp_min': 32.0, 'feels_like': 40.22, 'temp_kf': None}
Fanspeed is set to 100
Press ctrl+c to stop 
□
				

The fan speed is initialized to 100 since the temperature is over 30 degree Celsius, it runs for 5000 seconds before it stops automatically, it can also be stopped manually by pressing ctrl + c. 

Feel free to play around with other existing library functions on your own. 

projectImage

This project is based on the example project provided on https://projects.raspberrypi.org/en/projects/fetching-the-weather 


You can find the code for this project in the zip file attached at the end of the post. 

FILE
code_weather_Data_ctrl_fan_RASPBERRYPI.rar 1KB Download
License
1
All Rights
Reserved
[[i.text]]
licensBg
0
0
COMMENTS ([[commentTotla]])
[[c.user_name]] [[c.create_time]]
[[c.parent_comment.count]]
[[c.comment_content]]