跳到主要内容

人体感应灯

重要提示:关于开发板的兼容性

本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。

项目介绍

本项目通过 PIR(被动红外)传感器检测人体存在,自动控制 WS2812 LED 灯带的开关,实现智能感应照明功能。当传感器检测到人体活动时,灯带自动点亮;当持续一段时间未检测到活动后,灯带自动熄灭。

硬件连接

需要使用的器件有:

  • PIR 运动传感器 * 1
  • WS2812 灯条 * 1
  • 面包板 * 1
  • 导线
  • ESP32 开发板

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

ESP32-S3-Zero-Pinout

接线图
硬件连接注意事项
  • 电源连接:PIR 传感器和 WS2812 灯带都需要连接到 5V 电源。
  • 跳线帽设置:PIR 模块的跳线帽需要设置为 H 模式(高电平触发模式)。
  • 调试建议:为方便初次调试,建议先将 PIR 模块的检测距离调节到最低,避免误触发,待功能验证正常后再根据实际需求调整。

代码实现

提示

此代码示例依赖 FastLED 库。请在 Arduino IDE 的库管理器中搜索并安装 “FastLED” 库。

安装方法请参考:Arduino 库管理教程

/*
人体感应灯

当 PIR 传感器检测到人体运动时,点亮 WS2812 LED 灯带。
如果在设定时间内没有再次检测到运动,灯光将自动熄灭。

电路连接:
* PIR 传感器信号脚 -> 引脚 7
* WS2812 LED 数据脚 -> 引脚 8

Wulu (Waveshare Team)
*/

#include <FastLED.h>

// --- 配置参数 ---
const int pirPin = 7; // PIR 传感器连接的引脚
const int ledPin = 8; // LED 灯带连接的引脚
const int numLeds = 8; // 灯珠的数量
const unsigned long lightDuration = 5000; // 亮灯持续时间 (毫秒)

// 定义 LED 数组
CRGB leds[numLeds];

// --- 状态变量 ---
boolean isLightOn = false; // 记录当前灯是否亮着
unsigned long lastMotionTime = 0; // 记录最后一次检测到运动的时间

void setup() {
Serial.begin(115200);

// 设置 PIR 引脚为下拉输入模式 (未触发时保持低电平)
pinMode(pirPin, INPUT_PULLDOWN);

// 初始化 LED 灯带
FastLED.addLeds<WS2812, ledPin, GRB>(leds, numLeds);
FastLED.setBrightness(50);
FastLED.clear();
FastLED.show();

Serial.println("系统已启动...");
turnLightOff(); // 确保启动时灯是灭的
}

void loop() {
unsigned long currentTime = millis();
int motionState = digitalRead(pirPin);

// 1. 如果检测到运动,重置计时器
if (motionState == HIGH) {
lastMotionTime = currentTime;

// 如果灯没亮,把它打开
if (!isLightOn) {
Serial.println("检测到运动 -> 开灯");
turnLightOn();
isLightOn = true;
}
}
// 2. 如果没有运动,检查是否超时
else {
if (isLightOn) {
unsigned long duration = currentTime - lastMotionTime;

// 如果当前时间减去最后运动时间超过了设定时长
if (duration > lightDuration) {
Serial.println("超时无人 -> 关灯");
turnLightOff();
isLightOn = false;
delay(1000); //稍微延时,防止临界状态闪烁
}
}
}

delay(100); // 简单的循环延时
}

// 开灯函数
void turnLightOn() {
fill_solid(leds, numLeds, CRGB::Purple);
FastLED.show();
}

// 关灯函数
void turnLightOff() {
fill_solid(leds, numLeds, CRGB::Black);
FastLED.show();
}

代码解释

  • 引入库:引入 FastLED.h 库,这是一个功能强大且易于使用的 LED 控制库。

    提示

    此代码示例依赖 FastLED 库。请在 Arduino IDE 的库管理器中搜索并安装 “FastLED” 库。

    安装方法请参考:Arduino 库管理教程

  • 配置参数与全局变量

    • 使用 const 关键字定义常量,包括引脚号、LED 数量和持续时间。
    • 创建 CRGB 数组 leds,用于存储每个 LED 的颜色数据。
    • 定义全局变量 isLightOnlastMotionTime 用于状态管理。
    const int pirPin = 7;
    const int ledPin = 8;
    const int numLeds = 8;
    const unsigned long lightDuration = 5000;

    CRGB leds[numLeds];
  • 初始化 (setup)

    • 初始化串口和 PIR 引脚。
    • 使用 FastLED.addLeds 初始化灯带配置。这里指定了 LED 类型 (WS2812)、引脚 (ledPin) 和色彩顺序 (GRB)。
    • FastLED.setBrightness(50) 设置全局亮度,避免太刺眼或电流过大。
    void setup() {
    // ...
    FastLED.addLeds<WS2812, ledPin, GRB>(leds, numLeds);
    FastLED.setBrightness(50);
    // ...
    }
  • 功能函数 (turnLightOn / turnLightOff)

    • 将开灯和关灯的逻辑拆分为两个独立的函数,避免使用布尔参数,使代码意图更清晰。
    • 使用 fill_solid 函数快速填充整个灯带的颜色。
    • CRGB::Purple 是库中预定义的紫色,也可以使用 CRGB(128, 0, 128) 自定义。
    • FastLED.show() 发送数据更新灯带显示。
    void turnLightOn() {
    fill_solid(leds, numLeds, CRGB::Purple);
    FastLED.show();
    }
  • 主循环 (loop)

    • 逻辑与之前相同:检测 PIR 状态,有人则开灯并刷新时间,无人且超时则关灯。
    • 使用 millis() 进行非阻塞的时间计算。

参考链接