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.