Raspberry Pi Pico
Weather Over WiFi

This experiment had me using Pimoroni's Pico Wireless Pack. The Wireless pack is an add-on board for the Pico which includes a ESP32-WROOM-32E module that you can connect to over SPI. Also on the board is an SD card reader for Micro SD cards and an RGB LED. It costs £12, which is a decent price considering how much you're going to be able to do with it.

The pack is intended to be connected directly to the Pico pins. I am testing mine out on the Pico to HAT board, which happens to have an extra set of pins for GPIO connectors.

Pico Circuit

Once connected to the Internet, you can download data using the APIs that various sites provide. I am using a free account on https://openweathermap.org/ to get weather data for my location. To replicate this project, you will need to sign up for a free account and generate an API key.

You need the following libraries for this project. Download the mpy library for these and copy to your lib folder.

Secrets

To make it easy to share your project with other folk, make a secrets.py file in your lib folder. You put your passwords and tokens in there. The file should look like this,

secrets = {
    'ssid' : 'YOUR SSID',
    'password' : 'YOUR WIFI PASSWORD',
    'timezone' : "Europe/London", # http://worldtimeapi.org/timezones
    'owm_token' : 'OPEN WEATHER MAP TOKEN',
    'lat' : "YOUR LATITUDE",
    'long' : "YOUR LONGITUDE"
    }

Clearly, you need to replace the capitalised sections with your personal details. You can also, by the way, use a hotspot on your mobile phone.

I adapted an Adafruit sample file to give a quick test of the connections.

import board
import busio
from digitalio import DigitalInOut
import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

print("ESP32 SPI webclient test")

TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"


# If you have an externally connected ESP32:
# NOTE: You may need to change the pins to reflect your wiring
esp32_cs = DigitalInOut(board.GP7)
esp32_ready = DigitalInOut(board.GP10)
esp32_reset = DigitalInOut(board.GP11)

spi = busio.SPI(board.GP18, board.GP19, board.GP16)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

requests.set_socket(socket, esp)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", [hex(i) for i in esp.MAC_address])

for ap in esp.scan_networks():
    print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"]))

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(secrets["ssid"], secrets["password"])
    except RuntimeError as e:
        print("could not connect to AP, retrying: ", e)
        continue
print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))
print(
    "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))
)
print("Ping google.com: %d ms" % esp.ping("google.com"))

# esp._debug = True
print("Fetching text from", TEXT_URL)
r = requests.get(TEXT_URL)
print("-" * 40)
print(r.text)
print("-" * 40)
r.close()

print("Done!")

With the WiFi and Internet connection working, I then got some data from Open Weather Map.

import board
import busio
from digitalio import DigitalInOut
import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

owm_url = "https://api.openweathermap.org/data/2.5/weather?lat=" + secrets["lat"]
owm_url += "&lon=" + secrets["long"] + "&appid=" + secrets["owm_token"]

esp32_cs = DigitalInOut(board.GP7)
esp32_ready = DigitalInOut(board.GP10)
esp32_reset = DigitalInOut(board.GP11)

spi = busio.SPI(board.GP18, board.GP19, board.GP16)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

requests.set_socket(socket, esp)

for ap in esp.scan_networks():
    print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"]))

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(secrets["ssid"], secrets["password"])
    except RuntimeError as e:
        print("could not connect to AP, retrying: ", e)
        continue
print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)

# Get the weather data
print()
print("Fetching data from https://api.openweathermap.com")
r = requests.get(owm_url)
print("-" * 40)
temp = r.json()["main"]["temp"] - 273.15
humidity = r.json()["main"]["humidity"]
pressure = r.json()["main"]["pressure"]
weather_main = r.json()["weather"][0]["main"]
weather_desc = r.json()["weather"][0]["description"]
print("Weather Data")
print("------------")
print()
print("Temperature:", round(temp,2), "Celsius")
print(weather_main, weather_desc, sep=", ")
print("Humidity: ", humidity, "%", sep="")
print("Pressure: ", pressure, "hPa", sep="")
print()
print("-" * 40)
r.close()

So far, this is just printing some basic weather data to the REPL. Tweaking the API call itself can return different units and different data fields for you. Obviously, it would be nice to output this information on a suitable display.

This was just a quick tester for the Wireless Pack and there is going to be a lot more that can be done with it. For now, though, getting some data in json format from a site with a free API is a nice start.