1. 项目概述:当ESP32遇见人体感应
在智能家居和物联网应用中,人体感应联动灯光是最基础也最实用的场景之一。这个ESP32嵌入式开发案例,通过HC-SR501人体红外传感器检测移动信号,触发WS2812B RGB LED灯带点亮,完整实现了"人来灯亮"的自动化控制。相比市面上的成品方案,自主开发的优势在于可完全自定义触发逻辑、灯光效果和联动规则。
我曾在一个展厅项目中部署过类似的系统,需要根据人流动线实现不同分区的渐亮效果。商用传感器要么价格昂贵,要么无法满足定制化需求,最终选择ESP32方案节省了60%成本。这个案例虽然基础,但包含了嵌入式开发中最关键的几个技术点:GPIO输入输出控制、PWM调光协议、中断处理以及低功耗设计,是入门物联网开发的绝佳练手项目。
2. 硬件选型与电路设计
2.1 核心器件选型解析
ESP32开发板选用的是ESP32-WROOM-32D模组,主要看中其双核240MHz主频和超低功耗特性。实际测试中,在深度睡眠模式下整机电流仅0.15mA,非常适合需要长期待机的人体感应场景。注意要选择带CP2102或CH340串口芯片的版本,否则需要额外购买调试器。
HC-SR501人体传感器的探测距离在出厂时默认为3米,通过板载电位器可调节至7米。其输出信号为3.3V TTL电平,与ESP32完美兼容。需要特别注意的是传感器上有个跳线帽,选择"可重复触发"模式时,只要检测到持续移动就会保持高电平输出,而单次触发模式则固定输出3秒高脉冲。
WS2812B灯带选用的是每米60灯的密度版本,采用单线归零码通信协议。这种灯带的优势在于每个LED可独立寻址控制,且只需要一个GPIO引脚就能驱动整条灯带。购买时要注意电压匹配(常见有5V和12V两种),5V版本在长距离传输时需要每5米增加电源注入点。
2.2 电路连接要点
完整的接线示意图如下:
| ESP32引脚 | 连接目标 | 备注 |
|---|---|---|
| GPIO13 | HC-SR501 OUT | 输入模式需配置上拉电阻 |
| GPIO15 | WS2812B DI | 数据线需串联220Ω电阻 |
| 3V3 | HC-SR501 VCC | 注意不是5V供电 |
| GND | 共地连接 | 传感器与灯带共地很重要 |
关键提示:WS2812B的供电一定要单独走线,切勿通过开发板的3.3V引脚供电!我曾因这个错误导致整个系统不稳定。建议使用5V/2A以上的独立电源,灯带正负极直接接电源,仅将数据线接ESP32。
3. 软件环境搭建与核心代码解析
3.1 开发环境配置
推荐使用PlatformIO + VSCode的组合,比Arduino IDE更适合项目管理。新建工程时选择"Espressif 32"平台,在platformio.ini中需要添加以下依赖:
ini复制lib_deps =
adafruit/Adafruit NeoPixel @ ^1.10.2
espressif/ESP32Servo @ ^0.11.0
人体传感器的检测逻辑需要用到中断,为避免抖动影响,在setup()中需要配置滤波:
cpp复制#define PIR_PIN 13
#define LED_PIN 15
#define LED_COUNT 60
volatile bool motionDetected = false;
unsigned long lastTrigger = 0;
void IRAM_ATTR detectsMovement() {
if(digitalRead(PIR_PIN) && millis() - lastTrigger > 3000){
motionDetected = true;
lastTrigger = millis();
}
}
void setup() {
pinMode(PIR_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PIR_PIN), detectsMovement, RISING);
// 灯带初始化
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
strip.begin();
strip.show(); // 初始化为全灭
}
3.2 灯光控制算法实现
为实现平滑的灯光渐亮效果,采用HSV色彩空间转换比直接使用RGB更易控制亮度。下面代码实现了从暖黄到冷白的渐变:
cpp复制void setAllLeds(uint16_t hue, uint8_t sat, uint8_t val) {
for(int i=0; i<LED_COUNT; i++) {
strip.setPixelColor(i, strip.ColorHSV(hue, sat, val));
}
strip.show();
}
void breathingEffect() {
uint8_t brightness = 0;
bool ascending = true;
while(motionDetected) {
setAllLeds(6000, 255, brightness); // 6000对应暖白色
if(ascending) {
brightness += 5;
if(brightness >= 200) ascending = false;
} else {
brightness -= 2;
if(brightness <= 10) {
ascending = true;
if(millis() - lastTrigger > 30000) motionDetected = false;
}
}
delay(30);
}
setAllLeds(0,0,0); // 全部熄灭
}
4. 低功耗优化与生产部署
4.1 电源管理策略
在电池供电场景下,需要启用ESP32的深度睡眠模式。修改后的中断处理如下:
cpp复制void setup() {
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, HIGH);
if(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) {
handleMotion();
}
// 30秒无活动进入睡眠
delay(30000);
esp_deep_sleep_start();
}
void handleMotion() {
// 唤醒后初始化外设
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
strip.begin();
breathingEffect();
}
实测表明,采用深度睡眠后,2000mAh锂电池可维持系统工作约6个月(每天触发20次计算)。如需更长续航,可考虑以下优化:
- 缩短灯带点亮持续时间
- 降低WS2812B的亮度等级
- 选用灵敏度更高的PIR传感器减少误触发
4.2 安装调试经验
在展厅项目中总结的安装要点:
- 传感器高度建议1.2-1.5米,俯角15°安装
- 避免正对空调出风口或窗户,防止气流干扰
- 灯带安装位置与传感器探测区域要有重叠
- 长距离传输时,数据线要加屏蔽层
常见问题排查表:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 灯带部分不亮 | 电源功率不足 | 增加电源注入点 |
| 传感器频繁误触发 | 灵敏度调节过高 | 顺时针调整灵敏度电位器 |
| ESP32无法唤醒 | GPIO13未正确配置唤醒源 | 检查ext0_wakeup参数 |
| 灯带颜色异常 | GRB顺序设置错误 | 修改NEO_GRB为NEO_RGB等 |
5. 进阶扩展方向
基于这个基础框架,可以扩展更多实用功能:
- 亮度自适应:通过光敏电阻检测环境光,自动调节灯带亮度
- 多区域联动:多个ESP32通过WiFi组网,实现跨区域灯光接力
- 模式记忆:利用EEPROM存储用户偏好的灯光颜色和亮度
- 远程控制:接入MQTT协议,通过手机APP控制灯光模式
一个实际的升级案例是为咖啡厅开发的"迎宾灯光系统",当顾客进门时触发玄关灯带,随着移动路径依次点亮座位区灯光,最后在吧台区域形成聚光效果。这需要组合多个PIR传感器和灯带分段控制,核心逻辑仍然基于本文介绍的基础原理。
