Skip to the content
4 layers109.5 × 79 mmAirQuality, the printed circuit board in 3D

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

8

README

README.md

Air 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:

SignalGPIO
I2C SDA22
I2C SCL23
RTC interrupt2
E-paper MOSI18
E-paper SCK19
E-paper chip select17
E-paper data/command21
E-paper reset20
Top button0
Bottom button1

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:

  1. Hold the AQM's bottom button while booting it. Release the button when the AQM displays Pairing with PM.
  2. 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.
  3. 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

ButtonGPIOAt bootDuring operation
Top0Erase the complete NVS partition, including Matter commissioning, Wi-Fi credentials, and the saved PM peerNo action
Bottom1Enter PM-pairing mode and replace the previously saved PM peer after successful pairingChange 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:

sh
pio run -e esp32c6
pio run -e esp32c6 -t upload
pio device monitor -b 115200

The 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

text
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 table

The primary firmware files are:

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
QtyValueFootprintReferences
101uFCapacitor_SMD:C_0603_1608MetricC1, C3, C4, C5, C6, C7, C8, C10, C12, C16
31N5819Diode_SMD:D_SOD-123D1, D2, D3
2100KResistor_SMD:R_0603_1608MetricR6, R7
21µFCapacitor_SMD:C_0603_1608MetricC17, C18
2220nFCapacitor_SMD:C_0603_1608MetricC14, C15
24.7KResistor_SMD:R_0603_1608MetricR1, R2
24.7uFCapacitor_SMD:C_0603_1608MetricC2, C11
25.1KResistor_SMD:R_0603_1608MetricR10, R11
2TL3330AF260QGAirQualityFootprints:SW_TL3330AF260QGS1, S2
10Resistor_SMD:R_0603_1608MetricR3
10.47Resistor_SMD:R_0603_1608MetricR4
1100nFCapacitor_SMD:C_0603_1608MetricC9
110KResistor_SMD:R_0603_1608MetricR8
110K/0Resistor_SMD:R_0603_1608MetricR5
110uFCapacitor_SMD:C_0603_1608MetricC13
14.7ΩResistor_SMD:R_0603_1608MetricR9
168uHInductor_SMD:L_0805_2012MetricL1
1BAT-HLD-001AirQualityFootprints:BAT_BAT-HLD-001BAT1
1Conn_01x08_SocketConnector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_VerticalJ4
1DHT20Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalU3
1FH34SRJ-24S-0.5SH_50_AirQualityFootprints:HRS_FH34SRJ-24S-0.5SH_50_J1
1I2C TestConnector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ3
1LOGOAirQualityFootprints:AQ-QRG***
1MAX31328NELB+TAirQualityFootprints:21-0140AK_L1055M-1_MXMU4
1SCD41-D-R2AirQualityFootprints:QFN20_SCD41-D-R2_SENU1
1SGP41-D-R4AirQualityFootprints:XDCR_SGP41-D-R4U5
1Si1308EDLPackage_TO_SOT_SMD:SOT-323_SC-70Q1
1UJ20-C-V-C-1-SMT-TRAirQualityFootprints:CUI_UJ20-C-V-C-1-SMT-TRJ2
1XIAO-ESP32-C6AirQualityFootprints:XIAO-ESP32C6-DIPU2

Similar boards

  • 2 layers174.5 × 126.3 mmChoc, the printed circuit board in 3D

    Choc

    ARognes/Gravi

    An open source, split, wireless, smd, 42 key, keyboard family

    181 parts1AGPL-3.0
  • 4 layers140 × 100 mmRecline actuator controller, the printed circuit board in 3D

    Recline actuator controller

    Accessibilita/recline-controls

    Hardware project for open source wheel chair recline control electronics

    181 partsCERN-OHL-S-2.0
  • 2 layers65 × 56 mmAMS Dongle, the printed circuit board in 3D

    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 layers64.1 × 31.8 mmHEDC B002, the printed circuit board in 3D

    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 mmEsp32-c6-wroom1 board, the printed circuit board in 3D

    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 mmAir quality pcb, the printed circuit board in 3D

    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).