M5Stack Core2 based CO2 sensor using a SenseAir S8 with MQTT support.
This project implements a CO2 monitoring system using an M5Stack Core2 and a SenseAir S8 CO2 sensor. The device continuously measures CO2 levels, displays them on the built-in screen with color-coded warnings, and publishes readings to an MQTT broker for remote monitoring.
- M5Stack Core2: ESP32-based device with 320x240 touchscreen display
- SenseAir S8 CO2 Sensor: NDIR CO2 sensor (0-10,000 ppm range)
- Wiring:
- S8 RX → M5Stack GPIO 13
- S8 TX → M5Stack GPIO 14
- S8 VCC → 5V
- S8 GND → GND
Install these libraries via Arduino Library Manager:
- M5Core2 (by M5Stack)
- Adafruit MQTT Library (by Adafruit)
- SoftwareSerial (built-in to Arduino/ESP32)
Before uploading, modify these values in s8_m5.ino:
const char* mqtt_server = "192.168.1.100"; // Your MQTT broker IP
const int mqtt_port = 1883; // Your MQTT broker port
const char* ssid = "YourWiFiName"; // Your WiFi SSID
const char* password = "YourWiFiPassword"; // Your WiFi passwordOptional configuration:
int valMultiplier = 1; // Set to different value for alternate S8 models
#define FEED "esp32/co2" // MQTT topic to publish to- Install Arduino IDE 2.0 or later
- Add M5Stack board support:
- Go to File → Preferences
- Add to "Additional Board Manager URLs":
https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
- Install board: Tools → Board Manager → Search "M5Stack" → Install
- Install required libraries (see Software Dependencies)
- Select board: Tools → Board → M5Stack Arduino → M5Stack-Core2
- Select port: Tools → Port → (your device port)
- Upload the sketch
# Configure board support
arduino-cli config init
arduino-cli core update-index
arduino-cli core install m5stack:esp32
# Install libraries
arduino-cli lib install "M5Core2"
arduino-cli lib install "Adafruit MQTT Library"
# Compile
arduino-cli compile --fqbn m5stack:esp32:m5stack-core2 s8_m5.ino
# Upload (replace /dev/ttyUSB0 with your port)
arduino-cli upload -p /dev/ttyUSB0 --fqbn m5stack:esp32:m5stack-core2 s8_m5.ino
# Monitor serial output
arduino-cli monitor -p /dev/ttyUSB0 -c baudrate=9600- Device initializes M5Stack hardware and display
- Connects to WiFi (displays connection progress on serial)
- Begins main loop: reading CO2, updating display, publishing to MQTT
The CO2 reading is shown in large text with color coding:
- Green (< 500 ppm): Good air quality
- Yellow (500-700 ppm): Moderate air quality
- Red (≥ 700 ppm): Poor air quality, ventilation recommended
- Topic:
esp32/co2(configurable) - Format: Integer value (CO2 ppm)
- Frequency: Every 5 seconds
- Connection: Automatic reconnection with 3 retries
Connect at 9600 baud to see:
- WiFi connection status and IP address
- CO2 readings every 5 seconds
- MQTT connection status and publish results
The S8 uses a proprietary serial protocol:
0xFE 0x44 0x00 0x08 0x02 0x9F 0x25
Byte 0: 0xFE (Header)
Byte 1: 0x44 (Command)
Byte 2: 0x00
Byte 3: CO2 High Byte
Byte 4: CO2 Low Byte
Byte 5: Checksum High
Byte 6: Checksum Low
CO2 value calculation: (Byte3 × 256) + Byte4
- Verify SSID and password are correct
- Check WiFi signal strength
- Ensure WiFi is 2.4GHz (ESP32 doesn't support 5GHz)
- Check wiring connections
- Verify S8 has power (LED should be on)
- Check GPIO pins 13 and 14 are not used by other hardware
- Allow 30 seconds for sensor warm-up
- Verify MQTT broker is running and accessible
- Check broker IP address and port
- Ensure no firewall blocking port 1883
- Check broker logs for connection attempts
- If text size is wrong, check
setTextSize()value - Color thresholds can be adjusted in the display logic
The S8 sensor has automatic baseline calibration (ABC) enabled by default. For accurate readings:
- Expose sensor to fresh outdoor air (≈400 ppm) regularly
- ABC assumes sensor sees 400 ppm at least once every 7 days
- For manual calibration, refer to S8 datasheet
- Update rate: 5 seconds (adjustable via delay in loop)
- S8 measurement time: ~2 seconds per reading
- WiFi reconnection: Automatic if connection drops
- MQTT reconnection: Automatic with 3 retry attempts
Modify the delay at the end of loop():
delay(5000); // Change to desired millisecondsThe MQTT feed can be subscribed to by:
- Home Assistant
- Node-RED
- InfluxDB + Grafana
- Any MQTT-compatible system
To publish multiple sensors to MQTT, add additional feed definitions:
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, "esp32/temperature");See repository LICENSE file for details.