/ pyportal_weather_station / code.py
code.py
1 # SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 """ 6 PyPortal Weather Station 7 ============================================== 8 Turn your PyPortal into a weatherstation with 9 Adafruit IO 10 11 Author: Brent Rubell for Adafruit Industries, 2019 12 """ 13 import time 14 import board 15 import neopixel 16 import busio 17 import analogio 18 from simpleio import map_range 19 from digitalio import DigitalInOut 20 21 from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager 22 from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError 23 24 # sensor libs 25 import adafruit_veml6075 26 import adafruit_sgp30 27 from adafruit_bme280 import basic as adafruit_bme280 28 29 # weatherstation graphics helper 30 import weatherstation_helper 31 32 # rate at which to refresh the pyportal and sensors, in seconds 33 PYPORTAL_REFRESH = 30 34 35 # anemometer defaults 36 anemometer_min_volts = 0.4 37 anemometer_max_volts = 2.0 38 min_wind_speed = 0.0 39 max_wind_speed = 32.4 40 41 # Get wifi details and more from a secrets.py file 42 try: 43 from secrets import secrets 44 except ImportError: 45 print("WiFi secrets are kept in secrets.py, please add them there!") 46 raise 47 48 # PyPortal ESP32 Setup 49 esp32_cs = DigitalInOut(board.ESP_CS) 50 esp32_ready = DigitalInOut(board.ESP_BUSY) 51 esp32_reset = DigitalInOut(board.ESP_RESET) 52 spi = busio.SPI(board.SCK, board.MOSI, board.MISO) 53 esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) 54 status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) 55 wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) 56 57 # Set your Adafruit IO Username and Key in secrets.py 58 # (visit io.adafruit.com if you need to create an account, 59 # or if you need your Adafruit IO key.) 60 ADAFRUIT_IO_USER = secrets['aio_username'] 61 ADAFRUIT_IO_KEY = secrets['aio_key'] 62 63 # Create an instance of the Adafruit IO HTTP client 64 io = IO_HTTP(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) 65 66 # create an i2c object 67 i2c = busio.I2C(board.SCL, board.SDA) 68 69 # instantiate the sensor objects 70 veml = adafruit_veml6075.VEML6075(i2c, integration_time=100) 71 sgp30 = adafruit_sgp30.Adafruit_SGP30(i2c) 72 bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) 73 # change this to match the location's pressure (hPa) at sea level 74 bme280.sea_level_pressure = 1013.25 75 76 # init. the graphics helper 77 gfx = weatherstation_helper.WeatherStation_GFX() 78 79 # init. the ADC 80 adc = analogio.AnalogIn(board.D4) 81 82 # Set up Adafruit IO Feeds 83 print('Getting Group data from Adafruit IO...') 84 station_group = io.get_group('weatherstation') 85 feed_list = station_group['feeds'] 86 altitude_feed = feed_list[0] 87 eco2_feed = feed_list[1] 88 humidity_feed = feed_list[2] 89 pressure_feed = feed_list[3] 90 temperature_feed = feed_list[4] 91 tvoc_feed = feed_list[5] 92 uv_index_feed = feed_list[6] 93 wind_speed_feed = feed_list[7] 94 95 def adc_to_wind_speed(val): 96 """Returns anemometer wind speed, in m/s. 97 :param int val: ADC value 98 """ 99 voltage_val = val / 65535 * 3.3 100 return map_range(voltage_val, 0.4, 2, 0, 32.4) 101 102 def send_to_io(): 103 # handle sending sensor data to Adafruit IO 104 io.send_data(uv_index_feed['key'], uv_index) 105 io.send_data(wind_speed_feed['key'], wind_speed) 106 io.send_data(temperature_feed['key'], bme280_data[0]) 107 io.send_data(humidity_feed['key'], bme280_data[1]) 108 io.send_data(pressure_feed['key'], bme280_data[2]) 109 io.send_data(altitude_feed['key'], bme280_data[3]) 110 io.send_data(eco2_feed['key'], sgp_data[0]) 111 io.send_data(tvoc_feed['key'], sgp_data[1]) 112 113 while True: 114 print('obtaining sensor data...') 115 # Get uv index from veml6075 116 uv_index = veml.uv_index 117 # Get eco2, tvoc from sgp30 118 eCO2, TVOC = sgp30.iaq_measure() 119 sgp_data = [eCO2, TVOC] 120 # Store bme280 data as a list 121 bme280_data = [bme280.temperature, bme280.humidity, 122 bme280.pressure, bme280.altitude] 123 # Get wind speed 124 wind_speed = adc_to_wind_speed(adc.value) 125 # Display sensor data on PyPortal using the gfx helper 126 print('displaying sensor data...') 127 gfx.display_data(uv_index, bme280_data, 128 sgp_data, wind_speed) 129 print('sensor data displayed!') 130 try: 131 try: 132 print('Sending data to Adafruit IO...') 133 gfx.display_io_status('Sending data to IO...') 134 send_to_io() 135 gfx.display_io_status('Data Sent!') 136 print('Data sent!') 137 except AdafruitIO_RequestError as e: 138 raise AdafruitIO_RequestError('IO Error: ', e) 139 except (ValueError, RuntimeError, ConnectionError, OSError) as e: 140 print("Failed to get data, retrying\n", e) 141 wifi.reset() 142 continue 143 time.sleep(PYPORTAL_REFRESH)