CircuitPython firmware for the Unexpected Maker FeatherS3 (ESP32S3). Reads CO2, temperature, and humidity from an Adafruit SCD41 and publishes to MQTT every 60 seconds.
- Unexpected Maker FeatherS3
- Adafruit SCD41 CO2 sensor (connected via STEMMA QT / I2C)
- LiPo battery
Download the Adafruit CircuitPython bundle matching CircuitPython 9.x and copy these to CIRCUITPY/lib/:
adafruit_minimqtt/adafruit_scd4x.mpyneopixel.mpy
Copy to CIRCUITPY/settings.toml — never committed, device-specific:
SENSOR_NAME = "office"
WIFI_SSID = ""
WIFI_PASSWORD = ""
MQTT_BROKER = ""
MQTT_PORT = 1883
MQTT_USERNAME = ""
MQTT_PASSWORD = ""
PUSH_INTERVAL = 60
ALTITUDE = 0 # meters above sea levelcp code.py /Volumes/CIRCUITPY/code.py
cp feathers3.py /Volumes/CIRCUITPY/feathers3.pyThe device resets and starts running immediately.
Connect a serial console to see debug output:
screen /dev/cu.usbmodem* 115200Ctrl+C interrupts the script; Ctrl+D soft-reboots.
| Color | Meaning |
|---|---|
| Green | WiFi + MQTT connected |
| Red | Any failure |
| Blue (2s) | Factory reset armed — power cycle to apply |
| Off | Sleeping between readings |
The SCD41's Automatic Self-Calibration (ASC) assumes weekly exposure to outdoor air (~400 ppm). This firmware disables ASC, which is the correct setting for a permanently-indoor sensor. Without ASC, the factory calibration holds for years.
On first boot (or after a button-triggered reset), the firmware runs factory_reset() to clear any accumulated calibration drift from a prior ASC-enabled deployment. Subsequent boots skip the reset.
If the sensor begins reporting obviously wrong values, press the BOOT button during the sleep window (LED is off). The LED flashes blue to confirm. Power cycle the device — the factory reset runs on next boot, restoring the original calibration baseline.
The button only works during the sleep window between readings. If the LED is green or red, wait for it to turn off, then press.