一个放在工位上的小装置,用来监控室内空气质量。最初的动机很简单——CO₂ 浓度高的时候人会感到困倦,我想知道什么时候该开窗。
硬件清单
| 组件 | 型号 | 用途 |
|---|---|---|
| 主控 | ESP32-S3 | Wi-Fi + 主要计算 |
| 温湿度 | SHT31 | I²C,精度 ±0.3°C |
| CO₂ | MH-Z19C | NDIR 光学传感器 |
| PM2.5 | PMS5003 | 激光散射颗粒物传感器 |
| 外壳 | 3D 打印 | PLA,白色 |
固件架构
固件用 Arduino framework + PlatformIO 开发,核心逻辑分为三个任务(FreeRTOS):
// 传感器采集任务(1000ms 间隔)
void sensorTask(void* pvParameters) {
for (;;) {
SensorData data;
data.temperature = sht31.readTemperature();
data.humidity = sht31.readHumidity();
data.co2 = mhz19.getCO2();
data.pm25 = pms.getPM25();
xQueueSend(sensorQueue, &data, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
// MQTT 发布任务(从队列消费)
void mqttTask(void* pvParameters) {
for (;;) {
SensorData data;
if (xQueueReceive(sensorQueue, &data, portMAX_DELAY)) {
publishToMQTT(data);
}
}
}数据流
ESP32 → MQTT Broker (Mosquitto) → Telegraf → InfluxDB → Grafana
所有服务运行在家里的 Mac mini 上,用 Docker Compose 管理:
services:
mosquitto:
image: eclipse-mosquitto:2
ports: ["1883:1883"]
telegraf:
image: telegraf:1.29
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf
influxdb:
image: influxdb:2
ports: ["8086:8086"]
grafana:
image: grafana/grafana:10
ports: ["3001:3000"]MQTT 主题设计
home/office/env/temperature
home/office/env/humidity
home/office/env/co2
home/office/env/pm25
采用 location/room/category/metric 的层级结构,便于后续扩展到多个房间。
当前状态与计划
目前已完成传感器采集和 MQTT 上报,Grafana 面板也基本搭好。待做:
- 低功耗模式(深睡眠 + 定时唤醒),尝试电池供电
- 屏幕显示(小 OLED 实时显示当前数值)
- 告警推送(CO₂ > 1000ppm 时发送通知)
- 外壳优化(目前开孔不够好,影响传感器精度)