CircuitPython Library Installation
First make sure you are running the latest version of Adafruit CircuitPython for your board.
COnnect the PyPortal to your computer via a known good data+power USB cable.
In Mu, you can connect to the board's serial REPL so you are at the CircuitPython >>> prompt.
Now to get the PyPortal connected to Adafruit IO and the internet. To do this, you'll create a secrets text file.
Secrets File Setup
If you have not yet set up a secrets.py file in your CIRCUITPY drive and connected to the internet using it, follow this guide and come back when you've successfully connected to the internet.
With a secrets.py file on your CIRCUITPY drive - add your Adafruit IO Username and Adafruit IO Key to the secrets.py file.
Your secrets.py file should look like this:
secrets = { 'ssid' : '_your_wifi_ssid', 'password': '_your_wifi_password', 'aio_username' : '_your_adafruit_io_username', 'aio_key' : '_your_big_huge_super_long_aio_key_' }
After you finish editing secrets.py, make sure to save the file (cmd/ctrl+s).
Add CircuitPython Code and Project Assets
In the embedded code element below, click on the Download Project Bundle button, and save the .zip archive file to your computer.
Then, uncompress the .zip file, it will unpack to a folder named pyportal_weatherstation.
Copy the entire contents of the pyportal_weatherstation directory to your PyPortal CIRCUITPY drive including subdirectories.
# SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries # # SPDX-License-Identifier: MIT """ PyPortal Weather Station ============================================== Turn your PyPortal into a weatherstation with Adafruit IO Author: Brent Rubell for Adafruit Industries, 2019 """ import time import board import neopixel import busio import analogio from simpleio import map_range from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError # sensor libs import adafruit_veml6075 import adafruit_sgp30 from adafruit_bme280 import basic as adafruit_bme280 # weatherstation graphics helper import weatherstation_helper # rate at which to refresh the pyportal and sensors, in seconds PYPORTAL_REFRESH = 30 # anemometer defaults anemometer_min_volts = 0.4 anemometer_max_volts = 2.0 min_wind_speed = 0.0 max_wind_speed = 32.4 # 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 # PyPortal ESP32 Setup esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) # Set your Adafruit IO Username and Key in secrets.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = secrets['aio_username'] ADAFRUIT_IO_KEY = secrets['aio_key'] # Create an instance of the Adafruit IO HTTP client io = IO_HTTP(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) # create an i2c object i2c = busio.I2C(board.SCL, board.SDA) # instantiate the sensor objects veml = adafruit_veml6075.VEML6075(i2c, integration_time=100) sgp30 = adafruit_sgp30.Adafruit_SGP30(i2c) bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) # change this to match the location's pressure (hPa) at sea level bme280.sea_level_pressure = 1013.25 # init. the graphics helper gfx = weatherstation_helper.WeatherStation_GFX() # init. the ADC adc = analogio.AnalogIn(board.D4) # Set up Adafruit IO Feeds print('Getting Group data from Adafruit IO...') station_group = io.get_group('weatherstation') feed_list = station_group['feeds'] altitude_feed = feed_list[0] eco2_feed = feed_list[1] humidity_feed = feed_list[2] pressure_feed = feed_list[3] temperature_feed = feed_list[4] tvoc_feed = feed_list[5] uv_index_feed = feed_list[6] wind_speed_feed = feed_list[7] def adc_to_wind_speed(val): """Returns anemometer wind speed, in m/s. :param int val: ADC value """ voltage_val = val / 65535 * 3.3 return map_range(voltage_val, 0.4, 2, 0, 32.4) def send_to_io(): # handle sending sensor data to Adafruit IO io.send_data(uv_index_feed['key'], uv_index) io.send_data(wind_speed_feed['key'], wind_speed) io.send_data(temperature_feed['key'], bme280_data[0]) io.send_data(humidity_feed['key'], bme280_data[1]) io.send_data(pressure_feed['key'], bme280_data[2]) io.send_data(altitude_feed['key'], bme280_data[3]) io.send_data(eco2_feed['key'], sgp_data[0]) io.send_data(tvoc_feed['key'], sgp_data[1]) while True: print('obtaining sensor data...') # Get uv index from veml6075 uv_index = veml.uv_index # Get eco2, tvoc from sgp30 eCO2, TVOC = sgp30.iaq_measure() sgp_data = [eCO2, TVOC] # Store bme280 data as a list bme280_data = [bme280.temperature, bme280.humidity, bme280.pressure, bme280.altitude] # Get wind speed wind_speed = adc_to_wind_speed(adc.value) # Display sensor data on PyPortal using the gfx helper print('displaying sensor data...') gfx.display_data(uv_index, bme280_data, sgp_data, wind_speed) print('sensor data displayed!') try: try: print('Sending data to Adafruit IO...') gfx.display_io_status('Sending data to IO...') send_to_io() gfx.display_io_status('Data Sent!') print('Data sent!') except AdafruitIO_RequestError as e: raise AdafruitIO_RequestError('IO Error: ', e) except (ValueError, RuntimeError, ConnectionError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue time.sleep(PYPORTAL_REFRESH)
Before running the code, verify CIRCUITPY looks like the following:
Before continuing make sure your board's lib folder has the following files and folders copied over.
- adafruit_bitmap_font
- adafruit_bme_280
- adafruit_bus_device
- adafruit_display_text
- adafruit_esp32spi
- adafruit_io
- adafruit_sgp30
- adafruit_veml6075
- neopixel
- simpleio
From the Mu Editor, click the Serial button to open the REPL. The output should look like the following:
code.py output: Set icon to /icons/pyportal_splash.bmp loading fonts... setting up textareas... Getting Group data from Adafruit IO... obtaining sensor data... displaying sensor data... UV Index: 0.0110945 Temperature: 24.7 C Humidity: 10.2% Wind Speed: 0.090100 m/s Altitude: -98.900 meters, Pressure: 1025.18 hPa eCO2 = 400 ppm TVOC = 0 ppb
The code will first attempt to initialize all of the sensors, libraries, and get the Adafruit IO weatherstation group.
If everything worked properly, you should see the PyPortal and Adafruit IO+ Logo appear on your PyPortal.
Shortly after the splash screen disappears, you should see the sensor text fields appear.
The code will first attempt to initialize all of the sensors, libraries, and get the Adafruit IO weatherstation group.
If everything worked properly, you should see the PyPortal and Adafruit IO+ Logo appear on your PyPortal.
Shortly after the splash screen disappears, you should see the sensor text fields appear.
Every 30 seconds, the PyPortal will obtain new data from the sensors and send it to Adafruit IO.
- To change the rate at which the PyPortal samples and sends data (in seconds), modify the
PYPORTAL_REFRESH
variable.
When the data is sent from the weather station to Adafruit IO, the status text area will change to Data Sent!
But how do we know the data was actually sent to Adafruit IO?
Adafruit IO Usage
While your PyPortal displays Data Sent!, how do you know the data reached the Adafruit IO service?
The monitor page on Adafruit IO displays a live view off incoming data (and errors!).
Navigate to the Adafruit IO Monitor page. Only data received while the tab is open will be displayed on the page.
Wait for the PyPortal to send data to Adafruit IO. You should see incoming data appear underneath the Live Data heading.
Text editor powered by tinymce.