Raspberry PI Pico W Weather Monitor with e-Paper

5
(3)

Last Updated on 27th July 2024 by peppe8o

This tutorial will show you how to create a cool Raspberry PI Pico Weather Display with an e-Paper (e-Ink) monitor showing the weather status and forecasts.

Please note that I’ve already covered, with a detailed tutorial, how to use an e-paper display with Raspberry PI Pico. You can refer to that post if you want to know more about customizing your e-paper display layout.

For this project, our Raspberry PI Pico isn’t going to measure the sun/rain status, but we’ll use a free online weather service to get both current values and forecasts for the following days.

IMPORTANT UPDATE: from the 3.0 API (2.5 has been deprecated in July 2024), OpenWeather requires a subscription to their One Call 3.0 API service with a credit card, to use it even for free. I will try to find a different solution for this project, without the use of a credit card, even if this solution is still free.

The Weather Service: OpenWeather

Open Weather is an online weather provider that enables you to get information about the current weather and the forecasts for any world position. The data exchange can be achieved by their API, authenticated by an API Key. So, you need to register on their website in order to get the API key.

openweathermap-logo

The registration is free, and it allows you to get up to 1,000 queries per day, which is more than enough for a simple Weather Display: with a few calculations, we can call for weather updates around 40 times per hour (1000/24), that is one call every 90 seconds. To tell the truth, in my opinion, a call every 15 minutes already gives a reliable update rate and is enough to avoid an e-ink display from wasting (please remember that e-ink displays have a limited refresh number, even if big).

Open Weather also gives paid plans with more detailed results and higher frequency. It isn’t required for this project’s goals, but you can check their pricing plans if required.

With the 3.0 API, you also need to subscribe to the One Call 3.0 API service plan.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

raspberry-pi-pico-w-front

This tutorial will show you the project without a case. Of course, you can customize your own case and display layout.

If you wish to send me pictures of your results, I will be really happy to publish them in this post. Please send them to giuseppe@peppe8o.com, with the pictures at least 1000 pixels in width.

Step-by-Step Procedure

Get OpenWeather API Key

Getting a valid API Key from OpenWeather is really simple. Just register to their website and confirm their registration email. Then, you can go to your personal API Keys page with the following link:

https://home.openweathermap.org/api_keys

Here you generate a new API key by filling in the “API key name” in the text box shown below with your favourite label, and then clicking the “Generate” button:

openweather-generate-api-key-2

This will give you an alphanumeric string that we’ll use later in our MicroPython code.

Prepare the Wiring

Please arrange the wiring according to the Raspberry PI Pico Pinout, as in the following picture:

raspberry-pi-pico-epaper-wiring-diagram

The wiring matches that used in my Raspberry PI Pico and e-paper (e-ink) Display tutorial, where you can find also pictures.

Install MicroPython on Raspberry PI Pico

Connect RPI Pico to Thonny. For the very first steps of installing MicroPython, you can refer to my tutorial about the first steps with Raspberry PI Pico.

Prepare the Weather Icons

The OpenWeather API can return us a limited number of weather conditions according to their Weather-Condition-Codes-2. In the “Main” column of their tables, you can find all the answers that we can grab with the API requests. We’ll use these names for our weather icons so that getting an answer like “Rain” will be directly addressed to our icon that will be named “Rain.pbm”.

So, we must create and save in our Raspberry PI Pico all the required icons for the following possible answers:

  • Thunderstorm
  • Drizzle
  • Rain
  • Snow
  • Mist
  • Smoke
  • Haze
  • Dust
  • Fog
  • Sand
  • Ash
  • Squall
  • Tornado
  • Clear
  • Clouds

It is important to note that we must create the icons as “pbm” files and the procedure to create them with the open-source GIMP is available in my Raspberry PI Pico and e-paper (e-ink) Display tutorial.

Also, note that you should create all of them with the same sizes, in order to fit your display layout and keep the same display space even when weather conditions change.

I’ve prepared a set of icons to make it possible for you to directly implement the code in your Raspberry PI Pico Weather Monitor. You can get the zip file including all the icons with the following download:

weather-icons-peppe8o.zip

Once downloaded, please extract from the zip and upload the pbm files in your Raspberry PI Pico storage, in the root folder.

Get MicroPython Libraries and Code

Please, also download the following libraries and upload them into your Raspberry PI Pico root folder:

  • pico_epaper-2.13.py (can vary if you have a different e-paper display, please refer WaveShare GitHub page for their products). Please note that you must rename it to “pico_epaper.py” before uploading it to your Raspberry PI Pico.

We also need the main code that will run our Raspberry PI Pico Weather Monitor:

Upload these files to your Raspberry PI Pico storage. Please also remember to rename the “pico-weather.py” to “main.py” if you want it to run automatically when plugging the power supply into the Raspberry PI Pico without a computer. You must also set this script with some custom variables as explained in the following section.

At the end, your Raspberry PI Pico W storage will include the following files:

raspberry-pi-pico-weather-monitor-storage

The pico-weather.py code

Let’s analyze the main code that performs the Weather Monitor job.

In the beginning, we include the libraries to get network connection and the weather information:

import netman
import urequests, json

The following lines must be edited with your home WiFi. The first identifies the 2-letter country code, while the SSID and password depends on your home WiFi settings:

country = 'IT'
ssid = 'your_WiFi_Name'
password = 'your_WiFi_Password'

After this, the Raspberry PI Pico will try to connect:

wifi_connection = netman.connectWiFi(ssid,password,country)

Now, the OpenWeather configuration comes. You should change here your API Key and your localization latitude and longitude (lat and long are available also from https://www.latlong.net):

api_key="your_OpenWeather_API_Key"
lat="41.9661" #change it with your Home latitude
lon="12.66" #change it with your Home longitude
exclude="current,minutely,hourly,alerts"
units="metric"

Then the code sets the OpenWeather API string according to what is configured with the variables. You don’t need to change anything here

url_call="https://api.openweathermap.org/data/2.5/onecall?lat="+lat+\
          "&lon="+lon+\
          "&exclude="+exclude+\
          "&units="+units+\
          "&appid="+api_key

Now, we send the request to OpenWeather service converting the response into a JSON string, named “forecast”, and then closing the request session:

w=urequests.get(url_call)
forecast=json.loads(w.content)
w.close() 

We have now the weather data, so we can proceed with the e-paper display setup and update. The following rows will include the required libraries for the e-paper display:

from pico_epaper import EPD_2in13
import framebuf, time

Then, we’ll define 2 custom functions that will help us to make the code simpler. The first custom function, pbm_draw(), has been already explained in my tutorial on the e-paper display usage:

def pbm_draw(x_pos,y_pos,file):
    with open(file, 'rb') as f:
        f.readline() # The first 2 lines of PBM files are info not related to the image
        f.readline() # the 2 readlines remove these lines
        size = f.readline().decode('utf-8') # The 3rd row includes a byte with picture sizes that is decoded
        (x,y)=size.split("\n")[0].split(" ") # X variable gets the width, y variable gets the height
        data = bytearray(f.read())
    fbuf = framebuf.FrameBuffer(data, int(x), int(y), framebuf.MONO_HLSB)
    epd.blit(fbuf, x_pos, y_pos, white)

The upd_time() custom function deals with getting an updated datetime value to show in our Raspberry PI Pico Weather Monitor in order to check if data have been updated recently. It uses the free WorldTimeAPI service (that doesn’t require an API Key) and converts the returning datetime string into substrings including month, day, hour, and minute:

def upd_time():
    url_call="http://worldtimeapi.org/api/timezone/Europe/Rome"
    clock=urequests.get(url_call)
    clock_string=json.loads(clock.content)
    datetime_str=clock_string["datetime"]

    month = datetime_str[5:7]
    day = datetime_str[8:10]
    hour = datetime_str[11:13]
    minute = datetime_str[14:16]

    return "Upd."+day+"/"+month+" "+hour+":"+minute

In the following lines, we initialize the e-paper display. Please note again that the epd definition could change according to your e-paper display:

epd = EPD_2in13()
black=0x00
white=0xff

epd.fill(white)
epd.display(epd.buffer)

The following lines will scrape the OpenWeather responsa to get the current (today) values for minimal and max temperature, rain quantity, weather icon and description. We associate these values to the related variables for usage in the next lines:

temp_min=str(forecast["daily"][0]["temp"]["min"])
temp_max=str(forecast["daily"][0]["temp"]["max"])
rain_qty=str(forecast["daily"][0]["rain"])
weather_main=forecast["daily"][0]["weather"][0]["main"]
weather_descr=forecast["daily"][0]["weather"][0]["description"]

The first display block will show the forecasts for today and the related icon:

epd.text("Today's Weather", 2, 1, black)
pbm_draw(0, 15,weather_main+'.pbm')
epd.text("TM:"+temp_max+"C", 65, 15, black)
epd.text("Tm:"+temp_min+"C", 65, 25, black)
epd.text("Rn:"+rain_qty, 65, 35, black)
epd.text(weather_descr, 0, 78, black)

The second block will show the time at which the update has been performed, by using our custom function previously described. This block is visually separated from the previous and the following with 2 horizontal lines:

epd.hline(0, 90, 125, black)
epd.text(upd_time(), 0, 92, black)
epd.hline(0, 101, 125, black)

The next code block will get the forecasts for the next 6 days. It uses a for loop, where the same values are extracted from the OpenWeater response and printed into 2 lines (as we’ll see in the following chapter):

start_line=105

for day in range(0,6):
    d=day+1
    temp_min=int(forecast["daily"][d]["temp"]["min"])
    temp_max=int(forecast["daily"][d]["temp"]["max"])
    if "rain" in forecast["daily"][d]:
        rain_qty=int(forecast["daily"][d]["rain"])
    else:
        rain_qty=0
    weather_main=forecast["daily"][d]["weather"][0]["main"]
    weather_descr=forecast["daily"][d]["weather"][0]["description"]
    line = start_line + 2 * day * 11
    epd.text("+"+str(d)+" day> "+weather_main, 0, line, black)
    epd.text("T:{}/{}".format(temp_max,temp_min), 4, line+10, black)
    epd.text("r:{:02d}".format(rain_qty), 90, line+10, black)

A final text line shows a very small banner with a reference to this blog (peppe8o.com). You can customize it too, according to your preferences (or leave it to remember where the project comes 🙂 ):

epd.text("by peppe8o.com", 0, 242, black)
epd.display(epd.buffer)

The display imagination is finished. We can send it to sleep, as e-paper technology can keep the shown information even in sleep mode and even without a power supply:

epd.sleep()

A 10 seconds time sleep is kept here, in order to make it possible for you to send an interrupt (if required, for debugging) before sending also the Raspberry PI Pico to sleep:

time.sleep(10)

Finally, we use the machine.deepsleep() function to send the Pico on standby for a defined “sleep_time” (in milliseconds). This will allow us to reduce the required current, as proved in my Raspberry PI Pico W Power Consumption (mA) and How to Reduce It tutorial. You can just set the number of minutes to your preferred:

sleep_minutes=15
sleep_time=sleep_minutes * 60 * 1000
machine.deepsleep(sleep_time)

Testing the Raspberry PI Pico Weather Monitor

The following picture shows the final result:

raspberry-pi-pico-weather-monitor-result

The following shows the “today section:

weather-monitor-today

Below this, the “Upd” (update) will show you when the last update has been performed:

weather-monitor-update-time

And, finally, the forecasts for the following days, where each day has temperatures (max/min) and rain quantity:

weather-monitor-forecasts

What’s Next

Interested in doing more with your Raspberry PI Pico? Try to look at my Raspberry PI Pico tutorials for useful and funny projects!

Enjoy!

How useful was this post?

Click on a star to rate it anonymously!

Average rating 5 / 5. Vote count: 3

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?