Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
Bettesworth Construction
CO2 Sensor

How to Build a Mini Air-Quality Monitoring System Using an ESP32

Learn how to build an ESP32 monitor that measures true CO2, PM1.0, PM2.5, PM10, temperature, and humidity—without confusing VOC estimates or raw PM readings with AQI.

By Bettesworth Construction Team 10 min read
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build the main version with an ESP32, a Sensirion SCD40 true CO2 sensor, and a Plantower PMSA003I particulate sensor. This combination reports CO2, PM1.0, PM2.5, PM10, temperature, and relative humidity, while Wi-Fi can provide a local web dashboard or publish readings to MQTT or Home Assistant.

It is an indicative indoor air-quality monitor, not a medical, safety, occupational-exposure, or regulatory instrument. CO2 indicates ventilation conditions; particulate readings indicate airborne particles. Neither sensor measures every pollutant.

What this monitor measures

“Air quality” is not one physical quantity. This project combines several useful indicators:

Measurement What it tells you What it does not tell you
CO2 A useful indicator of ventilation and occupancy indoors It is not a complete pollution or safety measurement
PM2.5 Fine particles from smoke, cooking, combustion, dust, and outdoor pollution It does not identify the particle’s source or chemical composition
PM10 Larger inhalable particles, often associated with dust and some combustion sources It is not a substitute for a professional exposure assessment
PM1.0 Very small particulate matter It is not automatically an official air-quality index
Temperature and humidity Environmental context and comfort information They do not establish whether air is safe
VOC or TVOC A broad gas-sensor response or trend It is not a direct measurement of every volatile organic compound or CO2

The PMSA003I measures particles optically. The SCD40 measures CO2 using a dedicated sensor rather than estimating it from a gas-sensor response. That distinction matters: an SGP30-derived “eCO2” value should not be presented as measured CO2. See the SCD40 and SCD41 documentation for the difference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Amazon Smart Air Quality Monitor, Detects temperature, humidity, carbon monoxide, PM2.5 and VOCs, Get notifications when air quality drops, Works with Alexa
  • Know your air – An Alexa air quality monitor that makes it easy to understand what’s in your indoor air.
  • Track and measure – Our indoor air quality monitor keeps tabs on 5 key factors: particulate matter (PM 2.5), volatile organic compounds (VOCs), carbon monoxide (CO), humidity, and temperature.
  • Stay informed – Get an indication of current indoor air quality from the color-coded LED, and detailed information and an easy-to-understand air quality score in the Alexa app.
  • Real-time alerts - Get notifications on your phone or announcements on Echo devices when Alexa detects poor indoor air quality.
  • Automate climate control - Enable Routines to turn on or off your compatible Alexa devices, such as air purifiers, dehumidifiers, and fans, when the indoor air quality sensors detect changes.

Choose the build

Minimal monitor

  • ESP32 development board
  • SCD40 breakout
  • Small I2C OLED
  • USB power

This version measures CO2, temperature, and relative humidity. It suits ventilation experiments, offices, classrooms, bedrooms, and first-time ESP32 projects.

Full mini air-quality monitor

  • ESP32 development board
  • SCD40 breakout
  • PMSA003I particulate breakout
  • OLED, TFT, e-paper display, or local web page
  • Regulated 5 V USB supply
  • Ventilated enclosure

This is the recommended design because it combines ventilation-related CO2 data with particulate measurements.

Battery version

A battery monitor can use an ESP32-C3 or similar low-power board, but continuous particulate sensing and Wi-Fi are demanding. The PMSA003I includes an active fan and laser assembly; the listed module can draw up to approximately 100 mA. Use periodic sampling, intermittent Wi-Fi, or local storage with batched uploads rather than assuming deep sleep makes the whole system low-power.

Parts and electrical requirements

Part Purpose Important detail
ESP32 development board Processing and Wi-Fi Choose a reputable board with USB programming, exposed I2C pins, and a stable 3.3 V regulator
SCD40 breakout True CO2, temperature, and humidity I2C; check the breakout’s voltage regulation and level shifting
PMSA003I PM1.0, PM2.5, PM10, and particle-size counts 5 V power and 3.3 V logic; approximately one-second data update
OLED, TFT, or e-paper display Local readings An I2C OLED is the simplest option
USB power supply System power Allow for ESP32 Wi-Fi bursts and particulate-sensor startup current
Enclosure and vents Protection and controlled airflow Do not seal the particulate sensor in an airtight case
Capacitors and wiring Electrical stability Use short wiring, a 0.1 μF decoupler, and suitable bulk capacitance near load transients

The PMSA003I STEMMA QT/Qwiic breakout is more convenient for beginners and includes a 5 V boost circuit according to its product listing. Check the exact breakout schematic before connecting it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wire the sensors

Both sensors can share an I2C bus because they use different addresses. On a conventional classic ESP32 DevKit, a common starting point is:

Signal Example connection
SDA GPIO 21
SCL GPIO 22
Logic 3.3 V
Ground Common GND

GPIO 21 and GPIO 22 are common defaults, not universal ESP32 assignments. ESP32-C3, ESP32-S2, ESP32-S3, and individual development boards may expose different pins. Check your board pinout and schematic.

SCD40

  • VCC to the breakout’s specified supply
  • GND to GND
  • SDA and SCL to the ESP32 I2C bus

PMSA003I

  • VCC to regulated 5 V
  • GND to common GND
  • SDA and SCL to the ESP32 I2C bus using 3.3 V logic
  • Keep the air inlet and outlet unobstructed

The bare PMSA003I module requires 5 V power, 3.3 V logic, and external 10 kΩ I2C pull-ups. If your breakout has 5 V pull-ups, do not connect those directly to ESP32 GPIO. Instead, use a 3.3 V-compatible board, isolate the pull-ups, or add a bidirectional I2C level shifter. Confirm the actual breakout schematic.

Rank #2
16 in 1 Air Quality Monitor Indoor 7" High-Precision Real-Time CO2 Monitor
  • 【16-in-1 Air Quality Monitor Indoor】Experience the ultimate indoor air quality monitoring with our 16-in-1 Air Quality Monitor, offering real-time detection of 9 key parameters including CO2, PM2.5, PM1.0, PM10, HCHO, TVOC, Temperature, Humidity, AQI, and Time. With 7 distinct AQI alert buzzers, this air quality tester ensures your family breathes with ease.(*Note: "16-in-1" refers to the combination of 9 key detectable parameters and 7 types of AQI alert buzzers.)
  • 【Crystal Clear 7-inch Large Display】Enjoy a 7-inch LED display for sharp, clear air quality readings. Provides an instant, comprehensive view of your indoor air without navigating through menus, with three brightness settings for any lighting condition
  • 【External High-Precision Sensors with 0.001 Accuracy】Equipped with advanced external high-precision sensors, this device delivers unmatched accuracy (0.001 units) by directly sampling the air. Its innovative multi-sensor array and enhanced airflow design detect even the slightest environmental changes, allowing for instant response and optimal safety. (*Note: Avoid touching the sensors or exposing them to perfumes/strong odors to maintain accuracy.)
  • 【Real-Time AQI Alert Buzzers】Our air quality monitor provides real-time monitoring and alerts for pollutants like CO2, PM2.5, PM1.0, PM10, HCHO, TVOC, Temperature, Humidity, and AQI, with 7 distinct alert functions. Stay informed with clear alerts and rest easy with a mute button to silence alarms. Your health and comfort are our priority. Toggle between Fahrenheit and Celsius instantly with a double-press of the "Power" button on this air quality detector.
  • 【Up to 8 Hours of Runtime & Flexible USB-C Charging】 Enjoy up to 8 hours of continuous air quality monitoring on a full charge. The USB-C charging interface offers flexible power options and is compatible with widely available USB-C cables, while the included AC adapter provides convenient charging at home. Designed for effortless monitoring wherever you need it—from bedrooms and living spaces to your car and beyond.

Install the software

Use the Arduino IDE or PlatformIO with the Arduino-ESP32 core, the sensor libraries supplied or recommended by the breakout vendor, Wire for I2C, and the ESP32 Wi-Fi and networking libraries. The Arduino-ESP32 documentation retrieved for 2026 lists Core 3.3.10, based on ESP-IDF 5.5; pin or verify library versions for a reproducible build. Consult the Arduino-ESP32 library documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Develop in this order:

  1. Upload a serial “hello world” sketch.
  2. Run an I2C scanner.
  3. Confirm the SCD40.
  4. Confirm the PMSA003I.
  5. Read each sensor independently.
  6. Add the display.
  7. Add validation and stale-data handling.
  8. Add Wi-Fi.
  9. Add a web page or MQTT.
  10. Add storage and recovery behavior.

Run an I2C scanner first

#include <Wire.h>

constexpr int SDA_PIN = 21;  // Change for your board
constexpr int SCL_PIN = 22;  // Change for your board

void setup() {
  Serial.begin(115200);
  delay(1000);
  Wire.begin(SDA_PIN, SCL_PIN);
  Serial.println("I2C scan");

  for (uint8_t address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    uint8_t error = Wire.endTransmission();
    if (error == 0) {
      Serial.printf("Found device at 0x%02Xn", address);
    }
  }
  Serial.println("Scan complete");
}

void loop() {}

The addresses you see depend on the board and breakout. An address response only proves that something answered on the bus; initialize each sensor with its library and confirm valid, changing measurements.

Read the SCD40 correctly

The SCD40 is not an instantaneous analogue sensor. Start periodic measurement using the API supported by your chosen library, check whether a new sample is ready, then read and timestamp it. Do not replace an unavailable sample with zero or display an old value as current.

Allow warm-up after power-up. The SCD40’s commonly published range is 400–2,000 ppm with accuracy of ±(50 ppm + 5% of reading), as listed in the Adafruit guide. Treat those as manufacturer-listed specifications under stated conditions, not a guarantee for an assembled enclosure.

Automatic and forced calibration require appropriate environmental conditions. For a field calibration, place the device outdoors or in a reliably known fresh-air environment, let it stabilize, use the library’s supported forced-calibration procedure, and record the date and reference condition. Never calibrate in a crowded room and call that fresh air.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read and smooth the PMSA003I

The PMSA003I reports PM1.0, PM2.5, PM10, and particle counts in several size bins. Its listed effective PM2.5 range is 0–500 μg/m3, with a maximum range of at least 1,000 μg/m3. Confirm the startup delay, interface mode, frame format, and checksum handling for your particular breakout and library.

Keep both the raw and displayed values. A simple display filter is:

Rank #3
hiBCTR 2-Pack BME680 4-in-1 Environmental Sensor Module, 5V
  • 4-in-1 Environmental Monitoring​​: Simultaneously measures temperature (-40°C to +85°C), humidity (±3% RH), barometric pressure, and VOC gases (IAQ index output).
  • ​​Multi-Protocol Interface​​: 5V compatible with I2C (3.4MHz max) and SPI (10MHz 3/4-wire) for Arduino/Raspberry Pi/ESP32 integration.
  • Ultra-Low Power Operation​​: Current as low as 2.1μA (1Hz temp/humidity) to 3.7μA (triple-sensor mode) with selectable sensor activation.
  • ​​Industrial-Grade Precision​​: VOC response time <1s (new sensor), ±1.5% RH humidity hysteresis, and IAQ air quality indexing capability.
  • ​​Ready-to-Use Module​​: Includes pre-soldered BME680 chip with labeled VCC/GND/SCL/SDA/SDO/CS pins (2x module per order).
filteredPM25 = 0.8f * filteredPM25 + 0.2f * newPM25;

Label this as a smoothed display value. It is not an official averaging period and must not be relabeled as AQI.

Display useful information

A compact screen or web page should show units, freshness, and errors:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
CO2:   742 ppm
PM2.5: 6.8 ug/m3
PM10:  11.2 ug/m3
Temp:  22.4 C
RH:    43 %
Updated: 2 s ago

Include a visible notice: For indication and trend monitoring only. This device is not a certified safety, medical, or regulatory instrument.

A robust reading loop should:

  1. Read CO2 only when a new sample is ready.
  2. Read and validate particulate data.
  3. Read optional environmental data.
  4. Reject impossible or stale values.
  5. Render the display.
  6. Publish or store the record.
  7. Log sensor and network errors.

Add a local ESP32 web dashboard

In Wi-Fi station mode, the ESP32 can join the local network and host a basic HTTP server. Espressif documents station and access-point modes and the current networking APIs in its Wi-Fi documentation and network documentation.

Use a connection timeout, retry failed connections, display the local IP address, and keep the monitor useful when Wi-Fi is unavailable. The page should include:

  • CO2 in ppm
  • PM2.5 and PM10 in μg/m3
  • Temperature and relative humidity
  • Last successful sensor update
  • Wi-Fi status
  • Sensor error state
  • Firmware version

A local page normally works only inside the home or building network. Do not expose an unauthenticated ESP32 web server directly to the public internet; use a VPN, secure gateway, or an appropriate cloud service instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Logging and integrations

  • LittleFS: Store CSV or JSON locally for privacy and offline use. Buffer records rather than writing every second because flash has finite write endurance.
  • MQTT: Publish to Home Assistant, Node-RED, InfluxDB, or Grafana through an authenticated broker. Do not expose the broker publicly.
  • Home Assistant: MQTT discovery, ESPHome, or a local HTTP integration can provide history and automations.
  • Cloud dashboards: Adafruit’s air-quality example demonstrates ESP32 publishing and PM-based AQI calculation, but account requirements, limits, credentials, and service availability should be checked before deployment.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Handle AQI carefully

Display measured PM2.5 first. AQI is a calculated index, not a sensor output. If you calculate U.S. EPA AQI, identify the pollutant, units, averaging period, concentration handling, jurisdiction, and breakpoint revision. Verify the current official table before implementing it.

Rank #4
Sale
GoveeLife Smart Air Quality Monitor with PM2.5 H5106, LED Display Wired
  • High Accuracy & Fast Refresh Data: With this smart sensor, the PM2.5 accuracy is ±15 µg/m³ while temperature and humidity accuracies are ±0.54°F and ±3%RH.The two-second correction data feature shows the latest changes in PM2.5, temperature, and humidity.Keep sensor clear for accurate detection.
  • Multifunctional Air Quality Detector: The GoveeLife Air Quality Monitor conveniently measures 3 important indexes for indoor air quality, including PM2.5, temperature, and humidity.
  • Switchable Display: Press the top button for the clock & PM2.5 display. Long press for 2 seconds to switch to bright screen mode & night mode. The LED indicator displays 4 levels of ambient air quality. 2.4G Wi-Fi is required to display the time.
  • Connect with GoveeHome Appliances: Set your target air quality and link with your other GoveeHome smart appliances. GoveeLife air purifiers, humidifiers, and space heaters will turn on and off automatically when the indoor air quality changes.
  • H5106 needs to be connected to a power source and supports GoveeLife devices: Smart Air Purifiers - H7126, H7120, H7124, H712C, H7122, H7123; Humidifiers - H7140; Fans - H7100, H7102

The generic interpolation is:

AQI = ((I_high - I_low) / (C_high - C_low)) * (C - C_low) + I_low

C is the pollutant concentration after the required truncation or rounding; C_low and C_high are concentration bounds; and I_low and I_high are the corresponding index bounds. Do not calculate a “CO2 AQI.” CO2 thresholds are ventilation guidance, not an EPA outdoor AQI category. A DIY monitor is not a regulatory monitor.

Build the enclosure around airflow

The enclosure is part of the measurement system. Provide separate, unobstructed inlet and outlet openings for the particulate sensor, and avoid putting its exhaust beside the CO2 inlet if the exhaust warms the air.

Room air
   ↓
[Inlet vents] → [PM sensor] → [Outlet vents]
       └──────→ [CO2 / temperature / humidity sensor]
  • Keep the SCD40 away from the ESP32 regulator and display backlight.
  • Do not let the user’s breath enter the inlet directly.
  • Avoid direct sunlight, heaters, humidifiers, cooking steam, and air-conditioner outlets.
  • For wall mounting, use breathing-zone height but avoid direct exhalation.
  • For a desk monitor, keep it several feet from a person’s face and computer exhaust.
  • Investigate condensation and high humidity before trusting unusual PM readings.

Validate trends, not laboratory accuracy

CO2

Compare ventilation changes: observe the reading with the room occupied, then ventilated, while allowing the sensor to respond. For calibration, use a known fresh-air condition and the sensor’s supported procedure. A fixed software offset is not the same as calibration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Particles

Check stable operation in clean indoor air and compare trends during controlled events such as cooking or outdoor-smoke episodes. Avoid placing incense or smoke directly beside the inlet; heavy contamination can foul the optical chamber. Agreement in trends with another monitor is more realistic than expecting identical absolute values.

Humidity

High relative humidity can cause particles to absorb water and appear optically larger, biasing or reducing comparability of PM readings. Record humidity alongside PM data rather than interpreting every change as a change in dry particle mass.

A BME680 can add environmental data, but its gas output is not a laboratory VOC analysis or direct CO2 measurement. Its documentation explains that additional Bosch software is needed for derived VOC or equivalent-CO2 values; it does not provide a built-in air-quality calculation.

Battery and deep-sleep design

For the simplest and most reliable monitor, use USB power continuously. For a battery design:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Wake the ESP32.
  2. Power and warm up the sensors.
  3. Take several readings.
  4. Store or publish the result.
  5. Power down the particulate sensor and enter deep sleep.

Alternatively, keep sensors active and wake Wi-Fi periodically to upload batches. This can preserve better sensor continuity but requires more storage and control logic. ESP32 deep sleep powers down the CPU and most digital peripherals; Wi-Fi and Bluetooth must be disabled before sleeping. See Espressif’s deep-sleep documentation. Measure the current of the entire system: sensor, regulator, USB interface, LEDs, display, charger, and Wi-Fi—not just the ESP32 chip.

Troubleshooting

Symptom Likely causes Fix
I2C scanner finds nothing Wrong pins, missing ground, no power, missing pull-ups, wrong connector order, or a bus held low Test one sensor at a time, verify the schematic, and check SDA/SCL voltage
SCD40 is stale or invalid Periodic measurement has not started, no new sample is ready, insufficient warm-up, reset, or unstable power Check the new-data status, wait for warm-up, and log initialization failures
PMSA003I reads zero or implausibly Missing 5 V, startup delay, wrong interface mode, blocked airflow, stopped fan, or invalid frame Verify supply, mode, fan, inlet/outlet, and checksum validation
ESP32 resets when Wi-Fi starts Weak USB supply, voltage drop, poor cable, PM startup current, brownout, or short Use a stable supply, improve wiring and bulk capacitance, and log the reset reason
Case changes the readings Restricted airflow or heat from the regulator, display, or ESP32 Compare open and enclosed operation, measure internal temperature, and redesign vents
Dashboard disappears Wi-Fi loss or blocked server loop Add timeouts, reconnect logic, a local display fallback, and a last-update timestamp

Useful alternatives

  • SCD41: Consider it when a higher CO2 range or more demanding application justifies the extra cost.
  • SCD30: A larger established option when compatibility matters more than size.
  • SGP30 or SGP40: Suitable for VOC trends when clearly labeled as VOC/eCO2 indicators, not replacements for true CO2 sensing.
  • PMS5003: A UART option with a large hobby ecosystem.
  • SPS30: Consider it when documentation and long-term stability are higher priorities.
  • HM3301 and similar sensors: Choose only after verifying voltage, interface, library support, and ESP32 compatibility for the exact module.

If the project later adds an analogue gas sensor or battery divider, do not treat raw ADC values as calibrated concentrations. Arduino-ESP32 documents analogRead() as raw and non-calibrated, while analogReadMilliVolts() provides calibrated millivolts; ADC behavior and pins vary among ESP32 families. See the ADC documentation.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Site Office

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.