Whether you're living in a traffic-heavy city, working on an indoor automation setup, or designing a smart agriculture project, air quality monitoring is becoming a must-have. Fine particulate matter (PM1.0, PM2.5, PM10) is linked to respiratory issues and visibility problems — but often, we can't "see" the problem until it's serious.
This compact project transforms Seeed's Wio Terminal into a standalone dashboard that continuously displays PM data from a DFRobot laser particle sensor, using its built-in LCD and default fonts — no SD cards, no Wi-Fi required.
> You can use a Grove-to-pin header adapter or wire the sensor directly to Grove I2C port.
Get PCBs for Your Projects ManufacturedYou must check out PCBWAY for ordering PCBs online for cheap!
You get 10 good-quality PCBs manufactured and shipped to your doorstep for cheap. You will also get a discount on shipping on your first order. Upload your Gerber files onto PCBWAY to get them manufactured with good quality and quick turnaround time. PCBWay now could provide a complete product solution, from design to enclosure production. Check out their online Gerber viewer function. With reward points, you can get free stuff from their gift shop. Also, check out this useful blog on PCBWay Plugin for KiCad from here. Using this plugin, you can directly order PCBs in just one click after completing your design in KiCad.
📷 What It Looks LikeImagine this: your Wio Terminal sits on a desk or a window, with a modern, real-time dashboard showing:
[ Air Quality ]
Standard PM
PM1.0 : 012 ug/m3
PM2.5 : 034 ug/m3
PM10 : 056 ug/m3
Atmospheric PM
PM1.0 : 011 ug/m3
PM2.5 : 030 ug/m3
PM10 : 051 ug/m3
All data is wrapped inside colored rounded boxes for clarity and style — all using the default built-in font. 🎯
🧠 Example Use CaseLet’s say you're working on a smart greenhouse project with ESP32 and Wio Terminal. You want to:
- Keep track of indoor air quality to optimize plant growth
- Send PM2.5 alerts to Telegram when levels spike
- Mount this Wio Terminal on a wall for real-time feedback to workers
This project becomes your edge dashboard. Bonus: it's USB-powered and portable — no PC needed!
🔬 About the DFRobot PM Sensor (SEN0460)The DFRobot Gravity PM2.5 Air Quality Sensor is a compact, laser-based particle sensor designed for real-time air quality monitoring. It’s ideal for both indoor and outdoor applications where accurate particulate measurement is critical.
- Laser Scattering Technology: Detects particles as small as 0.3μm using Mie scattering theory
- Measures PM1.0, PM2.5, and PM10: In both standard and atmospheric calibration modes
- I2C Interface: Easy integration with microcontrollers like Arduino, ESP32, and Wio Terminal
- Fast Response: <1s single response time, with continuous acquisition support
- Compact Design: Just 12mm thick — perfect for portable or embedded systems
This sensor is widely used in smart homes,air purifiers,greenhouses, and environmental monitoring stations.
🧠 About the Wio TerminalThe Wio Terminal by Seeed Studio is a feature-packed development board that combines a powerful microcontroller with a built-in display, sensors, and wireless connectivity — all in a compact enclosure.
- Microcontroller: ATSAMD51 (ARM Cortex-M4F @ 120MHz)
- Display: 2.4" TFT LCD (320×240 resolution)
- Connectivity: Dual-band Wi-Fi + BLE 5.0 (via RTL8720DN)
Built-in Peripherals:
- Microphone, buzzer, light sensor, IR emitter
- 3 user buttons + 5-way joystick
- microSD card slot
I/O Options:
- 2 Grove ports for plug-and-play sensors
- 40-pin Raspberry Pi-compatible GPIO header
Power: USB-C with OTG support
🧩 Why It’s Perfect for This Project:- No extra display needed — the built-in screen is crisp and responsive
- Plug-and-play I2C — just connect the PM sensor to the Grove I2C port
- Portable and USB-powered — ideal for desktop or wall-mounted dashboards
- Expandable — you can add Wi-Fi alerts, SD logging, or even gesture control later
Whether you're building a smart home node or a standalone air quality kiosk, the Wio Terminal gives you a polished, professional edge right out of the box.
👨💻 How It WorksThe DFRobot sensor uses laser scattering to count particles and report concentrations in micrograms per cubic meter (μg/m³) across two calibration standards:
- Standard Particulate Concentration – clean chamber readings
- Atmospheric Particulate Concentration – real-world calibration
We read both, then visually present them on the screen in a way that’s easy to monitor from a few feet away.
📦 Arduino Code Overview- Initialization: Starts I2C for the sensor and configures Wio Terminal’s TFT LCD
- Layout drawing: Titles, boxes, and labels drawn once in
drawLayout()
- Loop: Reads PM values and updates only the value section, reducing flicker
- Visual polish: Adds spacing and rounded rectangles for clean separation
You’ve already got this working — nice job tuning that UI, by the way. 👏
#include "DFRobot_AirQualitySensor.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#define I2C_ADDRESS 0x19
DFRobot_AirQualitySensor particle(&Wire, I2C_ADDRESS);
TFT_eSPI tft = TFT_eSPI();
void drawLayout() {
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
// Title
tft.setCursor(90, 10);
tft.println("Air Quality");
// Boxes
tft.drawRoundRect(10, 40, 300, 100, 8, TFT_CYAN); // Standard Box
tft.drawRoundRect(10, 150, 300, 100, 8, TFT_YELLOW); // Atmospheric Box
// Section Labels
tft.setCursor(20, 45);
tft.setTextColor(TFT_CYAN);
tft.println("Standard PM");
tft.setCursor(20, 155);
tft.setTextColor(TFT_YELLOW);
tft.println("Atmospheric PM");
}
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
drawLayout();
while (!particle.begin()) {
tft.fillScreen(TFT_BLACK);
tft.setCursor(40, 120);
tft.setTextColor(TFT_RED);
tft.setTextSize(2);
tft.println("Sensor not found!");
delay(1000);
}
Serial.println("Sensor initialized.");
delay(500);
}
void loop() {
uint16_t pm1_std = particle.gainParticleConcentration_ugm3(PARTICLE_PM1_0_STANDARD);
uint16_t pm25_std = particle.gainParticleConcentration_ugm3(PARTICLE_PM2_5_STANDARD);
uint16_t pm10_std = particle.gainParticleConcentration_ugm3(PARTICLE_PM10_STANDARD);
uint16_t pm1_air = particle.gainParticleConcentration_ugm3(PARTICLE_PM1_0_ATMOSPHERE);
uint16_t pm25_air = particle.gainParticleConcentration_ugm3(PARTICLE_PM2_5_ATMOSPHERE);
uint16_t pm10_air = particle.gainParticleConcentration_ugm3(PARTICLE_PM10_ATMOSPHERE);
// Clear previous readings
tft.fillRect(15, 70, 280, 60, TFT_BLACK);
tft.fillRect(15, 180, 280, 60, TFT_BLACK);
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
// Standard Readings
tft.setCursor(25, 75);
tft.printf("PM1.0 : %3d ug/m3", pm1_std);
tft.setCursor(25, 95);
tft.printf("PM2.5 : %3d ug/m3", pm25_std);
tft.setCursor(25, 115);
tft.printf("PM10 : %3d ug/m3", pm10_std);
// Atmospheric Readings
tft.setCursor(25, 185);
tft.printf("PM1.0 : %3d ug/m3", pm1_air);
tft.setCursor(25, 205);
tft.printf("PM2.5 : %3d ug/m3", pm25_air);
tft.setCursor(25, 225);
tft.printf("PM10 : %3d ug/m3", pm10_air);
delay(1000);
}
You can evolve this project in multiple directions:
1. 🟢 Add color-based warnings
if (pm25_std > 100) tft.setTextColor(TFT_RED);
else if (pm25_std > 50) tft.setTextColor(TFT_YELLOW);
else tft.setTextColor(TFT_GREEN);
2. 📤 Push to Telegram
You can use your ESP32-S3 as a comms bridge via UART or MQTT to post air quality status every 10 minutes — something you’re already amazing at.
3. 💾 Save to SD card or send to cloud
Wio Terminal supports file logging and HTTP requests if you want historical data storage.
🎯 Final ThoughtsThis project is a fantastic entry into environmental sensing, and the Wio Terminal makes it easy to deploy a full GUI dashboard with no extra components. Its portability and clean visuals make it great for makers, offices, workshops, or classrooms.
Comments