

AirQuality
AQM is an ESP32-C6-based, Matter compatible, indoor air-quality monitor. It measures carbon dioxide, temperature, humidity, VOC, and NOx, displays the latest readings on an e-paper display, and publishes its…
- Size
- 109.5 × 79 mm
- Copper layers
- 4
- Thickness
- 1.6 mm
- Parts
- 47
- Nets
- 56
- Pads
- 209
- Tracks, vias
- 399, 50
- Pours
- 1
- Routed
- Yes
- KiCad
- KiCad 9.0 (file 20241229)
- Created
- 3 Dec 2025
- Updated
- 29 Oct 2026
Overview
AirQuality is an open-source printed circuit board by Tsquash, from the Tsquash/AirQualityMonitor repository on GitHub, published under the Apache-2.0 licence. It is a 4-layer board of 109.5 × 79 mm with 47 parts on 56 nets, routed with 399 tracks and 50 vias.
It is built around the DHT20, SGP41-D-R4 and MAX31328NELB+T, with the SCD41-D-R2, TL3330AF260QG and BAT-HLD-001 among its other parts. Its parts include 18 capacitors, 11 resistors, 5 ICs, 4 connectors and 3 diodes. It belongs with the sensors and measurement and radio and wireless boards and the ESP32 and RISC-V boards of this library.
Main components
8DHT20
SIP-4-40℃~+80℃ 0%RH~100%RH 2.2V~5.5V 980uA Factory calibration I2C ±0.5℃ ±3%RH SIP-4 Temperature and Humidity Sensor ROHSAosong ElecTemperature And Humidity SensorSGP41-D-R4
DFN-6(2.4x2.4)DFN-6(2.4x2.4) VOC Sensors ROHSSensirionVOC SensorsMAX31328NELB+T
LGA10UncategorisedAnalog DevicesSCD41-D-R2
LGA-20UncategorisedSensirionTL3330AF260QG
SMD-30℃~+70℃ 12V 2.6N 3.4mm 50,000 cycles 50mA 6.9mm Black J-Lead Rectangular Button SPST Surface Mount, Right Angle SMD Tactile Switches ROHSE-SwitchTactile SwitchesBAT-HLD-001
SMDSMD Button And Strip Battery Connector ROHSTE ConnectivityButton And Strip Battery ConnectorSI1308EDL
SC-70-3-55℃~+150℃ 1 N-channel 1.4nC@10V 1.5A 1.5V 105pF 11pF 132mΩ@10V 23pF 30V 400mW N-Channel SOT-323 MOSFETs ROHSVishay IntertechnologyMOSFETsUJ20-C-V-C-1-SMT-TR
SMDSMD USB Connectors ROHSCUIUSB Connectors
README
README.mdAir Quality Monitor
AQM is an ESP32-C6-based, Matter compatible, indoor air-quality monitor. It measures carbon dioxide, temperature, humidity, VOC, and NOx, displays the latest readings on an e-paper display, and publishes its measurements through Matter over Wi-Fi. It can also pair with the companion PM sensor particle over Bluetooth Low Energy (BLE) to add PM2.5 and PM10 measurements to its existing Matter endpoint.
Hardware
- MCU: Seeed Studio XIAO ESP32-C6
- Carbon-dioxide sensor: Sensirion SCD41
- Temperature and humidity sensor: ASAIR DHT20
- Before assembly, pry open the DHT20 module's plastic case and desolder its two 10 kΩ I2C pull-up resistors. The AQM PCB already supplies the I2C pull-ups, so leaving the module's resistors may cause unexpected errors
- VOC and NOx sensor: Sensirion SGP41
- uses the Sensirion Gas Index Algorithm
- RTC: Analog Devices MAX31328
- Display: 3.7-inch, 416 x 240 pixel monochrome e-paper display
- GDEY037T03 panel/UC8253 driver, driven with GxEPD2 and Adafruit GFX libaries
- PM interconnect: BLE link to the companion Matter PM sensor
- Enclosure: acrylic sandwich-style enclosure
The primary pin assignments are defined in
main/sense.cpp, main/screen.cpp, and
main/buttons.h:
| Signal | GPIO |
|---|---|
| I2C SDA | 22 |
| I2C SCL | 23 |
| RTC interrupt | 2 |
| E-paper MOSI | 18 |
| E-paper SCK | 19 |
| E-paper chip select | 17 |
| E-paper data/command | 21 |
| E-paper reset | 20 |
| Top button | 0 |
| Bottom button | 1 |
Operating modes
Matter commissioning
The AQM is a Matter-over-Wi-Fi device and requires a 2.4 GHz Wi-Fi network and a Matter controller. On an uncommissioned device, the display shows the Matter QR code and manual pairing code. Scan the QR code with a Matter-compatible controller app and complete the app's setup flow for Matter devices. This project uses Matter development credentials and is not Matter-certified, so the controller may ask for confirmation before adding it. Although all devices have the same pairing code, multiple AQM devices on one network is tested working.
After commissioning, the AQM obtains local time over the network. It determines
the UTC offset from https://ipapi.co/utc_offset/, synchronizes system time with
pool.ntp.org, writes that time to the MAX31328 RTC, and attempts another RTC
sync once per hour. The hourly sync re-queries the current UTC offset, and supports DST.
If the RTC already contains valid time, the local display can continue operating
before Matter commissioning completes.
Normal operation
The SGP41 is sampled once per second to maintain the VOC and NOx gas-index algorithms. Ten seconds before each minute, the RTC wakes the firmware to take new DHT20 and SCD41 readings, finalize any PM reading received for that minute, update the Matter attributes, and append CO2, VOC, and NOx values to the 60-sample history. At the start of the next minute, the active display page is redrawn.
The main page shows the date, time, temperature, relative humidity, CO2, VOC,
NOx, and the overall air-quality level. The second page graphs the most recent
60 one-minute CO2, VOC, and NOx readings. The display performs a full refresh at
:00 and :30 each hour and uses partial refreshes between them.
Linked to a PM sensor
The AQM can pair with the companion Matter PM sensor over BLE.
Pairing protocol
Put both devices into pairing mode and keep them nearby:
- Hold the AQM's bottom button while booting it. Release the button when the
AQM displays
Pairing with PM. - Start or restart the PM sensor in pairing mode. A new PM sensor automatically enters pairing mode on its first boot. On later boots, hold its pair button or factory reset button to force another pairing attempt.
- Leave both devices powered and nearby until each displays
Pairing Successful. Both pairing windows last up to 120 seconds.
The devices discover and authenticate each other automatically. If either device displays Pairing Timed Out, put both devices back into pairing mode and retry with them nearby.
On success, the PM peer is saved in non-volatile storage and the AQM reconnects
to it automatically on later boots.
The AQM sends its RTC time and measurement schedule to the PM sensor. The PM sensor returns one-minute PM1.0, PM2.5, and PM10 averages, which the AQM exposes through Matter. If the BLE connection is interrupted, the AQM retains the last PM reading for up to three missed minutes and clears it after the fourth. All other AQM sensing and display functions continue without a linked PM sensor.
Buttons
| Button | GPIO | At boot | During operation |
|---|---|---|---|
| Top | 0 | Erase the complete NVS partition, including Matter commissioning, Wi-Fi credentials, and the saved PM peer | No action |
| Bottom | 1 | Enter PM-pairing mode and replace the previously saved PM peer after successful pairing | Change display page |
A boot action requires the button to be held continuously for at least one second during the two-second startup check. Factory reset takes priority if both buttons are held. After a factory reset, the device restarts and displays its Matter commissioning screen.
Readings
The AQM measures or receives the following values:
- ☁️ CO2: measured by the SCD41 and reported in ppm
- +/- (50 ppm + 2.5% of the reading) from 400 to 1,000 ppm
- +/- (50 ppm + 3% of the reading) from 1,001 to 2,000 ppm
- +/- (40 ppm + 5% of the reading) from 2,001 to 5,000 ppm
- 🌡️ Temperature and 💧relative humidity: measured by the DHT20
- Temperature accuracy: +/- 0.75 degrees C
- Relative-humidity accuracy: +/- 4% RH
- 🍃 VOC and 💨 NOx indices: measured by the SGP41 and calculated with the
Sensirion Gas Index Algorithm
as unitless index points from 1 to 500; they are relative air-quality signals,
not measured gas concentrations
- VOC's long-term average is 100, lower values indicate improving conditions and higher values indicate worsening conditions
- NOx's typical baseline is 1, values above 1 indicate NOx events
- Allow approximately one hour for reliable VOC detection and six hours for reliable NOx event detection after startup
- Matter has concentration-measurement clusters for these readings but no
unit for index points. For compatibility, the firmware
currently publishes each index through its corresponding concentration
cluster with the unit set to
µg/m³. That displayed unit is incorrect: the numeric values are still unitless VOC and NOx indices and must not be interpreted as physical concentrations.
- PM1.0, PM2.5, and PM10: received in micrograms per cubic meter from a linked Matter PM sensor
The overall air-quality value is the worst of the current CO2, VOC, NOx, PM1.0, PM2.5, and PM10 bands. It is reported as Good, Fair, Moderate, Poor, Very Poor, or Extremely Poor.
Build, upload, and serial output
Install PlatformIO and the Espressif platform dependencies, connect the XIAO ESP32-C6, then run these commands from the project directory:
pio run -e esp32c6
pio run -e esp32c6 -t upload
pio device monitor -b 115200The PlatformIO environment is defined in platformio.ini.
The project uses the Arduino and ESP-IDF frameworks and is configured for the
seeed_xiao_esp32c6 board. Serial diagnostics run at 115200 baud. Upload-port
selection may need to be configured for the host computer. A clean or first
compile can take 10 minutes or longer while PlatformIO builds the ESP-IDF and
Matter dependencies, but later incremental builds are faster since the build is cached.
Bundled MAX31328 library
lib/Max31328RTC is a local fork of Analog Devices'
MAX31328 Arduino Driver.
The upstream library did not work unchanged with the ESP32-C6, so this fork:
- leaves I2C initialization to the firmware instead of calling
Wire.begin()from the RTC constructor, which would initialize the bus before the AQM assigns its SDA and SCL pins; - casts the write buffer to the byte-pointer type required by the ESP32-C6
Arduino
Wire.write()overload, fixing the compile error; and - updates the time, calendar, and control/status output structures only after a successful I2C read, preventing failed reads from copying invalid data.
The upstream driver is licensed under Apache-2.0, which permits modification
and redistribution. The fork retains the upstream copyright and modification
notices and includes the complete license at
lib/Max31328RTC/LICENSE.txt.
License
The original firmware, PCB and schematic files, manufacturing files, enclosure files, UI assets, and documentation in this repository are available under the Apache License 2.0. You may use, modify, manufacture from, and share, the original or modified project, provided that you follow the license terms :)
Project layout
main/ Firmware source, embedded display assets, and component config
myBitmap/ Embedded monochrome display bitmaps
myFont/ Embedded Adafruit GFX fonts
lib/ Project-local libraries, including the altered MAX31328 driver
KICAD/ PCB schematic, layout, symbols, and footprints
Production/ Manufacturing BOMs and Gerber archive
2D/ Enclosure and PCB cutout drawings
3D/ Board, spacer, and enclosure models
UI/ Display mockups, fonts, and bitmaps
.vscode/ VS Code project configuration
platformio.ini PlatformIO build environment
LICENSE Apache License 2.0 project license
sdkconfig.defaults.* ESP-IDF default configurations
huge_app.csv ESP-IDF flash partition tableThe primary firmware files are:
main/main.cpp: boot flow, Matter startup, scheduling, and the main loopmain/sense.cpp: sensor initialization and sampling, gas indices, RTC alarms, network time, and overall air-quality calculationmain/screen.cpp: e-paper initialization, status screens, measurement pages, and history graphsmain/buttons.cpp: boot-hold detection and display-page button handlingmain/matter_air_quality_sensor.cpp: Matter endpoint, measurement clusters, and attribute updatesmain/pm_link.cpp: BLE PM pairing, reconnection, timing, and PM-reading receptionmain/pm_protocol.h: BLE data structures shared with the companion PM project
Troubleshooting
- Matter commissioning does not complete: Confirm that the Matter controller and 2.4 GHz Wi-Fi network are online and that the phone is close enough for BLE commissioning. Factory-reset the AQM before retrying it on a different Matter fabric or Wi-Fi network.
- Time or date is incorrect: The AQM needs network access to the timezone
API and NTP server. Check the Wi-Fi network's Internet connectivity and
inspect the serial log for
[Time]or[RTC]errors. - A sensor reports invalid or fixed readings: Check the shared I2C wiring, sensor power, and serial output. The firmware logs DHT20, SCD41, SGP41, and RTC communication errors.
- VOC or NOx readings seem unstable after startup: Leave the device powered while the gas-index algorithms learn their baseline. VOC needs about one hour and NOx about six hours for reliable event detection.
- For most other errors: Check the serial log! I tried to leave debugging print statements that were helpful to me during development.
Parts
47| Qty | Value | Footprint | References |
|---|---|---|---|
| 10 | 1uF | Capacitor_SMD:C_0603_1608Metric | C1, C3, C4, C5, C6, C7, C8, C10, C12, C16 |
| 3 | 1N5819 | Diode_SMD:D_SOD-123 | D1, D2, D3 |
| 2 | 100K | Resistor_SMD:R_0603_1608Metric | R6, R7 |
| 2 | 1µF | Capacitor_SMD:C_0603_1608Metric | C17, C18 |
| 2 | 220nF | Capacitor_SMD:C_0603_1608Metric | C14, C15 |
| 2 | 4.7K | Resistor_SMD:R_0603_1608Metric | R1, R2 |
| 2 | 4.7uF | Capacitor_SMD:C_0603_1608Metric | C2, C11 |
| 2 | 5.1K | Resistor_SMD:R_0603_1608Metric | R10, R11 |
| 2 | TL3330AF260QG | AirQualityFootprints:SW_TL3330AF260QG | S1, S2 |
| 1 | 0 | Resistor_SMD:R_0603_1608Metric | R3 |
| 1 | 0.47 | Resistor_SMD:R_0603_1608Metric | R4 |
| 1 | 100nF | Capacitor_SMD:C_0603_1608Metric | C9 |
| 1 | 10K | Resistor_SMD:R_0603_1608Metric | R8 |
| 1 | 10K/0 | Resistor_SMD:R_0603_1608Metric | R5 |
| 1 | 10uF | Capacitor_SMD:C_0603_1608Metric | C13 |
| 1 | 4.7Ω | Resistor_SMD:R_0603_1608Metric | R9 |
| 1 | 68uH | Inductor_SMD:L_0805_2012Metric | L1 |
| 1 | BAT-HLD-001 | AirQualityFootprints:BAT_BAT-HLD-001 | BAT1 |
| 1 | Conn_01x08_Socket | Connector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_Vertical | J4 |
| 1 | DHT20 | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | U3 |
| 1 | FH34SRJ-24S-0.5SH_50_ | AirQualityFootprints:HRS_FH34SRJ-24S-0.5SH_50_ | J1 |
| 1 | I2C Test | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J3 |
| 1 | LOGO | AirQualityFootprints:AQ-QR | G*** |
| 1 | MAX31328NELB+T | AirQualityFootprints:21-0140AK_L1055M-1_MXM | U4 |
| 1 | SCD41-D-R2 | AirQualityFootprints:QFN20_SCD41-D-R2_SEN | U1 |
| 1 | SGP41-D-R4 | AirQualityFootprints:XDCR_SGP41-D-R4 | U5 |
| 1 | Si1308EDL | Package_TO_SOT_SMD:SOT-323_SC-70 | Q1 |
| 1 | UJ20-C-V-C-1-SMT-TR | AirQualityFootprints:CUI_UJ20-C-V-C-1-SMT-TR | J2 |
| 1 | XIAO-ESP32-C6 | AirQualityFootprints:XIAO-ESP32C6-DIP | U2 |
Similar boards
- 2 layers174.5 × 126.3 mm

- 4 layers140 × 100 mm

Recline actuator controller
Accessibilita/recline-controls
Hardware project for open source wheel chair recline control electronics
181 partsCERN-OHL-S-2.0 - 2 layers42.5 × 18.5 mm

- 2 layers65 × 56 mm

AMS Dongle
EOSCogniton/ELIZ-2022
Le Git Artemiz de l'EPSA. Contient le Catia, ainsi que la documentation en cours et quelques modèles.
46 parts4 - 2 layers63.5 × 44.5 mm

Adafruit adafruit matrixportal m4 pcb adafruit matrixportal m4
oomlout/oomlout_oomp_project_bot_v_2
62 parts - 2 layers64.1 × 31.8 mm

HEDC B002
Thaddeus-Maximus/dotclock
An ESP32-based alarm clock with a dot matrix LED display, rotary encoder interface, MP3 audio playback, and a web configuration UI.
34 parts - 4 layers75 × 56.4 mm

Esp32-c6-wroom1 board
pushtiujeniya/esp32-c6-environmental-logger
This repository contains an Environmental Sensor Station and Data Logger powered by the ESP32-C6-WROOM-1 microcontroller.
59 parts4 - 2 layers75 × 75 mm

Air quality pcb
aleemacc/air_quality_sensor
PCB design for a custom air quality measuring device
30 parts
Questions
How big is the AirQuality PCB?
It measures 109.5 × 79 mm and has 4 copper layers, 1.6 mm thick.
What parts does the AirQuality use?
47 parts, built around the DHT20, SGP41-D-R4, MAX31328NELB+T and SCD41-D-R2. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
Where can I download the AirQuality KiCad files?
From the Tsquash/AirQualityMonitor repository on GitHub, at the commit this page was made from: the board is KICAD/AirQuality.kicad_pcb and its schematic KICAD/AirQuality.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the AirQuality design in my own project?
Its repository publishes it under the Apache-2.0 licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).