💡 划重点
- 以 ESP32‑C3 为核心,通过 SCD41 实时检测书桌周围 CO₂ 浓度
- 根据浓度驱动 WS2812 灯环变色,提醒通风或专注状态
- 支持蓝牙数据上报与无感记录,所有物料严格控制在 120 元以内
- 全文提供可编译的 Arduino / PlatformIO 骨架代码与接线细节
需求洞察
目标用户:长期在家或在宿舍书桌前学习、编程、阅读的学生及知识工作者。
真实痛点:密闭房间内,人呼吸产生的 CO₂ 浓度会快速上升至 1500–2500 ppm,导致头晕、注意力下降、犯困,而用户通常察觉不到。现有空气检测仪缺乏即时、直观的桌面提醒,也难以与学习专注状态联动。
为什么值得做:将 CO₂ 监测与桌面台灯融合,不增加额外设备;用灯环颜色无声告警,既能保护专注力,又能提醒开窗通风,成本低廉、功能聚焦,真实改善学习环境。
方案设计
感知层
- SCD41 传感器通过 I2C 连接 ESP32‑C3。该模块基于光声检测原理,出厂已校准,精度 ±(40 ppm + 5%),可同时输出 CO₂、温度、湿度。
- 一颗轻触按键用于切换工作模式(普通监测 / 专注计时)。
控制层
- 主控选用 ESP32‑C3(RISC‑V 内核,内置 Wi‑Fi 与 BLE 5.0)。本项目仅使用其 GPIO、硬件 I2C 和低功耗蓝牙。
- 读取 SCD41 数据后,依据预设阈值判断空气质量等级,并控制灯环动画。同时实现蓝牙广播与 GATT 服务,便于手机读取实时数据与历史记录。
执行层
- WS2812 灯环(12 灯珠):在书桌上提供直接视觉反馈。
- CO₂ < 600 ppm:柔和绿光呼吸,表示空气优良,可专注。
- 600–1000 ppm:黄光呼吸,提醒即将超标。
- > 1000 ppm:红光快闪,强烈提醒开窗通风。
- 按键短按切换专注模式,此时灯环亮度降低并转为暖白照明;长按 3 秒关闭所有灯效。
日志 / 联网层
- 使用 BLE 广播与 GATT 服务上报 CO₂、温度、湿度与当前模式,供手机 App 解析。无需持续连接,降低功耗。
- 未来可扩展 Wi‑Fi 将数据同步至 MQTT 或本地服务器。
物料清单
| 名称 | 数量 | 用途 | 估算单价(元) | 小计(元) |
|---|---|---|---|---|
| ESP32‑C3 开发板 (合宙或同等) | 1 | 主控与蓝牙通信 | 18 | 18 |
| SCD41 传感器模块 | 1 | CO₂、温湿度检测 | 78 | 78 |
| WS2812 灯环 (12灯) | 1 | 空气质量视觉反馈 | 9 | 9 |
| 轻触按键 (6×6mm) | 1 | 模式切换 | 0.5 | 0.5 |
| 10kΩ 电阻、电容、排针 | 若干 | 按键上拉、去耦、连接 | 2 | 2 |
| 亚克力外壳 + 3D 打印底座 | 1 | 结构支撑与光线柔化 | 10 | 10 |
| 杜邦线与焊锡 | 少量 | 接线 | 2 | 2 |
| 合计 | 119.5 |
接线与结构
- SCD41 → ESP32‑C3
VCC → 3.3V,GND → GND,SDA → GPIO 8,SCL → GPIO 9。
模块自身含上拉电阻,I2C 总线无需外接。
- WS2812 灯环 → ESP32‑C3
VCC → 5V(可由 USB 供电),GND → GND,DIN → GPIO 10。
使用 5 V 供电时需确保所有 GND 共地。
- 按键 → ESP32‑C3
一端接 GND,另一端接 GPIO 3,同时通过 10kΩ 电阻上拉至 3.3V,实现低电平触发。
全部使用指定引脚,未做改动,因为这些 IO 可直接映射为硬件 I2C 与普通输出,且无复用冲突。
核心代码
以下为 PlatformIO / Arduino 骨架,使用 SparkFun_SCD4x_Arduino_Library 与 Adafruit_NeoPixel,BLE 基于 ESP32 NimBLE 库。
#include <Wire.h>
#include <SparkFun_SCD4x_Arduino_Library.h>
#include <Adafruit_NeoPixel.h>
#include <NimBLEDevice.h>
#define LED_PIN 10
#define NUM_LEDS 12
#define BUTTON_PIN 3
SCD4x scd4x;
Adafruit_NeoPixel ring(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
NimBLEServer *pServer;
NimBLECharacteristic *pChar;
byte currentMode = 0; // 0: normal, 1: focus
uint16_t co2 = 0;
void updateLEDs() {
uint32_t color = ring.Color(0, 255, 0); // green
uint8_t brightness = 50;
if (co2 > 1000) {
color = ring.Color(255, 0, 0); // red
} else if (co2 > 600) {
color = ring.Color(255, 255, 0); // yellow
}
if (currentMode == 1) {
color = ring.Color(255, 140, 0); // warm white focus
brightness = 20;
}
for (int i = 0; i < NUM_LEDS; i++) {
ring.setPixelColor(i, color);
}
ring.show();
}
void setup() {
Serial.begin(115200);
Wire.begin(8, 9); // SDA=8, SCL=9
if (scd4x.begin(false, true, false)) { // auto calibrate off
Serial.println("SCD41 ready");
}
ring.begin();
ring.clear();
ring.setBrightness(50);
ring.show();
pServer = NimBLEDevice::createServer();
NimBLEService *pService = pServer->createService("181A"); // Environmental Sensing
pChar = pService->createCharacteristic("2A6E", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
pChar->setValue((uint16_t)0);
pService->start();
NimBLEAdvertising *pAdv = NimBLEDevice::getAdvertising();
pAdv->addServiceUUID(pService->getUUID());
pAdv->start();
}
void loop() {
static uint32_t lastRead = 0;
if (millis() - lastRead > 5000) {
if (scd4x.readMeasurement()) {
co2 = scd4x.getCO2();
Serial.printf("CO2: %d ppm\n", co2);
pChar->setValue(co2);
pChar->notify();
updateLEDs();
}
lastRead = millis();
}
// 按键短按切换模式
static uint32_t btnPressTime = 0;
if (digitalRead(BUTTON_PIN) == LOW) {
if (btnPressTime == 0) btnPressTime = millis();
} else {
if (btnPressTime != 0) {
uint32_t duration = millis() - btnPressTime;
if (duration > 3000) { // 长按关闭灯环
ring.clear();
ring.show();
} else if (duration > 50) {
currentMode = !currentMode;
updateLEDs();
}
btnPressTime = 0;
}
}
delay(10);
}
调试步骤
- 硬件检查:按接线表连接,万用表确认 3.3 V、5 V 与 GND 无短路,USB 供电后 ESP32‑C3 电源灯亮起。
- 传感器测试:烧录前期仅含串口输出的代码,观察串口监视器是否每 5 秒输出 CO₂、温度、湿度数值,确认 I2C 通信正常。
- 灯环调试:单独驱动灯环显示彩虹色,验证数据线连接,调整电源电流。
- 按键响应:短按切换模式,长按 3 秒关灯,通过串口打印当前模式确认按键消抖与逻辑。
- 蓝牙验证:手机安装 nRF Connect,扫描设备
CO2_LAMP,连接后读取 Environmental Sensing 服务下的 CO₂ 特征值,检查数值更新。 - 整机联调:在不同浓度环境下观察灯环颜色变化,确认阈值合理,必要时修改代码中的 ppm 界限。
设计图
CO₂ 学习专注监测台灯结构flow
1
SCD41 采集 CO₂/T/RH
→
2
ESP32‑C3 I2C 读取
→
3
按键切换模式
→
4
灯环颜色反馈
→
5
BLE 数据上报手机