The on-board BME280 sensor paired with the deep sleep capabilities of the ESP32-S2 make it easy to set up an IoT data feed with new data coming in between power saving naps.
This demo wakes up, takes readings from the BME280 sensor, then connects to WiFi and sends the data to Adafruit IO before going back into deep sleep. For accurate data it's best to take a reading from the sensor right away after waking up from deep sleep before connecting to WiFi because the device generates some heat while in operation. Getting a reading immediately will minimize the impact of that residual heat from the device itself on the data you collect.
Create Adafruit IO Feeds
The demo code assumes that 3 Adafruit IO feeds will exist: temperature
, humidity
, and pressure
. Create them using the Adafruit IO web interface.
Create Feeds
- Click the "Feeds" navigation link at top of the page
- Then click on the "New Feed" button.
Create a Dashboard
If you'd like a way to view the data values together at a glance, you can create a dashboard using gauges and/or line charts. Here is one example of a dashboard layout. Customization is a key feature of Adafruit IO dashboards, change it up to suite your own needs.
CircuitPython Code
Use the Download Project Bundle button to download the example code. Unzip and then copy the code.py and required libraries to your CIRCUITPY drive. In your settings.toml file, include these values for WiFi network credentials and AIO authentication.
This example works best with CircuitPython version 9.x. Deep sleep and sending data over the network have an open issue under 10.x that can cause the flash storage to get corrupted.
WIFI_SSID="your-network-name" WIFI_PASSWORD="your-network-password" AIO_USERNAME="your-aio-username" AIO_KEY="your-aio-token"
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries # # SPDX-License-Identifier: MIT """ CircuitPython example for deep sleep and BME280 sensor sending data to Adafruit IO. """ from os import getenv import time import alarm import board import digitalio import neopixel import wifi from adafruit_bme280 import advanced as adafruit_bme280 import adafruit_connection_manager import adafruit_requests from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError # enable power to NeoPixels. np_power = digitalio.DigitalInOut(board.NEOPIXEL_POWER) np_power.switch_to_output(value=True) # standard LED builtin_led = digitalio.DigitalInOut(board.LED) builtin_led.switch_to_output(value=True) # neopixel to use for status status_pixel = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.1, pixel_order=neopixel.GRB, auto_write=True ) status_pixel[0] = 0xFF0000 # Create sensor object, using the board's default I2C bus. i2c = board.I2C() # uses board.SCL and board.SDA bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) print("Found BME280") # change this to match the location's pressure (hPa) at sea level bme280.sea_level_pressure = 1013.25 # temperature converted to F temperature = bme280.temperature * 9 / 5 + 32 humidity = bme280.relative_humidity pressure = bme280.pressure print("\nTemperature: %0.1f F" % temperature) print("Humidity: %0.1f %%" % humidity) print("Pressure: %0.1f hPa" % pressure) bme280.mode = adafruit_bme280.MODE_SLEEP bme280.overscan_temperature = adafruit_bme280.OVERSCAN_X16 bme280.overscan_humidity = adafruit_bme280.OVERSCAN_X16 bme280.overscan_pressure = adafruit_bme280.OVERSCAN_X16 bme280.iir_filter = adafruit_bme280.IIR_FILTER_DISABLE bme280.standby_period = adafruit_bme280.STANDBY_TC_1000 # set status pixel to yellow status_pixel[0] = 0xFFFF00 print("Connecting to AdafruitIO") # Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml # (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.) ssid = getenv("WIFI_SSID") password = getenv("WIFI_PASSWORD") aio_username = getenv("ADAFRUIT_AIO_USERNAME") aio_key = getenv("ADAFRUIT_AIO_KEY") print("Connecting to %s" % ssid) wifi.radio.connect(ssid, password) print("Connected to %s!" % ssid) # setup socket pool and requests session pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio) requests = adafruit_requests.Session(pool, ssl_context) # Initialize an Adafruit IO HTTP API object io = IO_HTTP(aio_username, aio_key, requests) # set status pixel to green status_pixel[0] = 0x00FF00 try: # Get the feeds from Adafruit IO temperature_feed = io.get_feed("temperature") humidity_feed = io.get_feed("humidity") pressure_feed = io.get_feed("pressure") # send data to the feeds io.send_data(temperature_feed["key"], temperature) io.send_data(humidity_feed["key"], humidity) io.send_data(pressure_feed["key"], pressure) except AdafruitIO_RequestError as e: print(e) print( "You must create feeds on AdafruitIO for: temperature, humidity, and pressure" ) # turn off the neopixel and builtin LED np_power.value = False builtin_led.value = False # Create an alarm that will trigger 5 minutes from now. time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + (5 * 60)) # Exit the program, and then deep sleep until the alarm wakes us. alarm.exit_and_deep_sleep_until_alarms(time_alarm) # Does not return, so we never get here.
Arduino Code
Follow the instructions on the Adafruit IO page to install the required libraries. Modify the config.h file to include your network credentials and AIO authentication, instructions are on the Adafruit IO page.
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries // // SPDX-License-Identifier: MIT #define IO_USERNAME "your-aio-username" #define IO_KEY "your-aio-token" #define WIFI_SSID "your-wifi-ssid" #define WIFI_PASS "your-wifi-pass" #include "AdafruitIO_WiFi.h" AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries // // SPDX-License-Identifier: MIT #include "config.h" #include <Adafruit_BME280.h> #include <Adafruit_NeoPixel.h> Adafruit_BME280 bme; // I2C AdafruitIO_Feed *temperature = io.feed("temperature"); AdafruitIO_Feed *humidity = io.feed("humidity"); AdafruitIO_Feed *pressure = io.feed("pressure"); float temp, humid, pres; Adafruit_NeoPixel pixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800); void setup() { Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // wait for serial monitor to open //while(! Serial); // turn on neopixel pinMode(NEOPIXEL_POWER, OUTPUT); digitalWrite(NEOPIXEL_POWER, HIGH); pixel.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) pixel.setBrightness(10); // not so bright pixel.setPixelColor(0, 0xFF0000); // red pixel.show(); if (! bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); deepSleep(); } Serial.println("Found BME280"); float temp = bme.readTemperature(); float pres = bme.readPressure() / 100.0F; float hum = bme.readHumidity(); // shhh time to close your eyes bme.setSampling(Adafruit_BME280::MODE_SLEEP, Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::FILTER_OFF, Adafruit_BME280::STANDBY_MS_1000); Serial.print("Connecting to Adafruit IO"); pixel.setPixelColor(0, 0xFFFF00); // yellow pixel.show(); // connect to io.adafruit.com io.connect(); // wait for a connection while(io.status() < AIO_CONNECTED) { Serial.print("."); delay(100); } // we are connected pixel.setPixelColor(0, 0x00FF00); // green pixel.show(); Serial.println(); Serial.println(io.statusText()); io.run(); temp = temp * 9.0 / 5.0 + 32; Serial.print("Temperature = "); Serial.print(temp); Serial.println(" *F"); temperature->save(temp); Serial.print("Pressure = "); Serial.print(pres); Serial.println(" hPa"); pressure->save(pres); Serial.print("Humidity = "); Serial.print(hum); Serial.println(" %"); humidity->save(hum); Serial.println(); deepSleep(); } void loop() { // we never get here! } void deepSleep() { pinMode(NEOPIXEL_POWER, OUTPUT); digitalWrite(NEOPIXEL_POWER, LOW); // off pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); esp_sleep_enable_timer_wakeup(300000000); // 5 minutes esp_deep_sleep_start(); }
Page last edited June 25, 2025
Text editor powered by tinymce.