DIY 智能夜灯教程:用 ESP8266 实现光敏+人体感应自动灯控(含常开/节能/自动模式)

本文详细介绍如何基于 ESP8266 搭建一套低成本、高实用性的智能灯控系统。系统融合 人体红外感应(PIR) 与 光敏电阻(LDR) 双重环境感知,实现“仅在黑暗且有人活动时自动亮灯”的节能逻辑。通过 Arduino 编程,设备支持 四种工作模式:常开、常闭、节能(微光夜灯)和自动(智能感应),满足不同场景需求。
2
安装串口驱动

首先需要安装CK341SER驱动程序,以支持后续的硬件连接与调试。
3
设置ESP8266下载地址




12
在Arduino IDE的开发板管理器中,添加ESP8266的下载源地址:http://arduino.esp8266.com/stable/package_esp8266com_index.json。
4
下载RGB依赖

在Arduino IDE中的"库管理"中下载Adafruit NeoPixel依赖,点击安装。
5
接线图

- 人体红外感应模块:
- OUT 引脚连接至 ESP8266 的 D1(GPIO5);
- VCC 接 3.3V 电源;
- GND 接 ESP8266 的 GND。
- 光敏电阻模块:
- DO(数字输出)引脚连接至 ESP8266 的 A0(模拟输入);
- VCC 接 3.3V 电源;
- GND 接 ESP8266 的 GND。
- RGB LED 灯带:
- 数据输入端(DIN 或标为 D0)连接至 ESP8266 的 D4(GPIO2);
- VCC 接 5V 电源(注意:灯带需独立供电或确保 ESP8266 开发板可承受负载);
- GND 与 ESP8266 共地。
6
代码

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_NeoPixel.h>
// === WiFi & MQTT 配置 ===
#define WIFI_SSID "vivoX200" // ← 改为你自己的 WiFi 名称
#define WIFI_PASSWORD "12345678" // ← 改为你自己的密码
#define MQTT_SERVER "broker.emqx.io"
#define MQTT_PORT 1883
#define DEVICE_ID "smart_nightlight_final_2025"
#define BASE_TOPIC "home/bedroom/nightlight"
// === 硬件引脚 ===
#define LED_PIN 2 // D4 (GPIO2) → WS2812B
#define PIR_PIN 5 // D1 (GPIO5) → HC-SR501 OUT
#define LDR_PIN A0 // 光敏电阻
// === 灯带参数 ===
#define NUM_LEDS 30
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
// === 工作模式 ===
enum Mode { MODE_AUTO, MODE_ON, MODE_ECO, MODE_OFF };
Mode currentMode = MODE_AUTO;
bool lightOn = false;
unsigned long lastMotionTime = 0;
const unsigned long LIGHT_OFF_DELAY = 6000; // 60秒
const int DARK_THRESHOLD = 600; // 根据实际环境调整!
// === MQTT 主题 ===
String topicSet = String(BASE_TOPIC) + "/set";
String topicStatus = String(BASE_TOPIC) + "/status";
String topicLdrValue = String(BASE_TOPIC) + "/ldr";
// ==================================================
void setup() {
Serial.begin(115200);
Serial.println("\n>>> 智能夜灯启动:天黑+有人则亮,人走后延时60秒关 <<<");
Serial.println("等待 PIR 初始化...(约60秒内避免测试)\n");
pinMode(PIR_PIN, INPUT);
strip.begin();
strip.show();
turnOffAll();
// 连接 WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n✅ WiFi 已连接");
// MQTT 初始化
mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
mqttClient.setCallback(handleMQTT);
}
// ==================================================
void loop() {
// MQTT 自动重连
if (!mqttClient.connected()) {
static unsigned long lastReconnectAttempt = 0;
if (millis() - lastReconnectAttempt > 5000) {
lastReconnectAttempt = millis();
if (mqttClient.connect(DEVICE_ID)) {
mqttClient.subscribe(topicSet.c_str());
mqttClient.publish(topicStatus.c_str(), "online", true);
Serial.println("🔗 MQTT 已连接");
}
}
} else {
mqttClient.loop();
}
// 读取传感器
int ldrValue = analogRead(LDR_PIN);
bool isDark = (ldrValue > DARK_THRESHOLD); // 若实际相反,请改为 <
bool motionNow = (digitalRead(PIR_PIN) == HIGH);
// 🔍 实时串口调试(每500ms)
static unsigned long lastDebug = 0;
if (millis() - lastDebug > 500) {
Serial.printf("[DEBUG] LDR=%d | Dark=%s | Motion=%s | Light=%s | Mode=",
ldrValue,
isDark ? "YES" : "NO",
motionNow ? "YES 🚶" : "NO",
lightOn ? "ON 💡" : "OFF 🌙");
switch (currentMode) {
case MODE_AUTO: Serial.println("AUTO"); break;
case MODE_ON: Serial.println("ON"); break;
case MODE_ECO: Serial.println("ECO"); break;
case MODE_OFF: Serial.println("OFF"); break;
}
lastDebug = millis();
}
// 上报 LDR 值(每5秒)
static unsigned long lastReport = 0;
if (millis() - lastReport > 5000) {
mqttClient.publish(topicLdrValue.c_str(), String(ldrValue).c_str());
lastReport = millis();
}
// === 核心逻辑:自动模式 ===
if (currentMode == MODE_AUTO) {
if (isDark) {
if (motionNow) {
// 有人:开灯 + 刷新最后活动时间
if (!lightOn) {
setFullWarmLight();
}
lastMotionTime = millis(); // 👈 关键:只要人在,就重置倒计时
} else {
// 无人:检查是否超时
if (lightOn && (millis() - lastMotionTime > LIGHT_OFF_DELAY)) {
turnOffAll();
}
}
} else {
// 天亮了,强制关灯
if (lightOn) {
turnOffAll();
}
}
}
// 其他模式处理
else if (currentMode == MODE_ON) {
setFullWarmLight();
}
else if (currentMode == MODE_ECO) {
setEcoLight();
}
else if (currentMode == MODE_OFF) {
turnOffAll();
}
delay(100);
}
// ====== LED 控制函数 ======
void setFullWarmLight() {
if (lightOn) return;
for (int b = 0; b <= 30; b++) {
uint32_t color = strip.Color(b, (int)(b * 0.6), (int)(b * 0.3));
for (int i = 0; i < NUM_LEDS; i++) strip.setPixelColor(i, color);
strip.show();
delay(20);
}
lightOn = true;
publishStatus();
}
void setEcoLight() {
for (int i = 3; i < NUM_LEDS; i++) strip.setPixelColor(i, 0);
uint32_t ecoColor = strip.Color(10, 6, 3);
for (int i = 0; i < 3; i++) strip.setPixelColor(i, ecoColor);
strip.show();
lightOn = true;
publishStatus();
}
void turnOffAll() {
if (!lightOn) return;
if (currentMode == MODE_AUTO || currentMode == MODE_ON) {
for (int b = 30; b >= 0; b--) {
uint32_t color = strip.Color(b, (int)(b * 0.6), (int)(b * 0.3));
for (int i = 0; i < NUM_LEDS; i++) strip.setPixelColor(i, color);
strip.show();
delay(20);
}
}
strip.clear();
strip.show();
lightOn = false;
publishStatus();
}
void publishStatus() {
String stateStr = lightOn ? "on" : "off";
String modeStr;
switch (currentMode) {
case MODE_AUTO: modeStr = "auto"; break;
case MODE_ON: modeStr = "on"; break;
case MODE_ECO: modeStr = "eco"; break;
case MODE_OFF: modeStr = "off"; break;
}
String json = "{\"state\":\"" + stateStr + "\",\"mode\":\"" + modeStr + "\"}";
mqttClient.publish(topicStatus.c_str(), json.c_str(), true);
}
// ====== MQTT 回调 ======
void handleMQTT(char* topic, byte* payload, unsigned int length) {
String msg = "";
for (int i = 0; i < length; i++) msg += (char)payload[i];
msg.trim();
msg.toUpperCase();
if (String(topic) == topicSet) {
if (msg == "ON") {
currentMode = MODE_ON;
Serial.println("📱 MQTT: 切换到常亮模式");
} else if (msg == "ECO") {
currentMode = MODE_ECO;
Serial.println("🌿 MQTT: 切换到节能模式");
} else if (msg == "OFF") {
currentMode = MODE_OFF;
Serial.println("📴 MQTT: 切换到关闭模式");
} else if (msg == "AUTO") {
currentMode = MODE_AUTO;
Serial.println("🤖 MQTT: 切换到自动模式");
} else {
Serial.println("⚠️ MQTT: 未知指令: " + msg);
return;
}
// 应用新模式
switch (currentMode) {
case MODE_ON: setFullWarmLight(); break;
case MODE_ECO: setEcoLight(); break;
case MODE_OFF: turnOffAll(); break;
case MODE_AUTO:
// 不主动开灯,由传感器控制
if (!lightOn) turnOffAll();
break;
}
}
}
7
MQTT连接

打开MQTTX客户端新建连接,输入名称以及服务器ip地址,完成之后点击右上角的连接。
8
添加订阅

点击 “添加订阅” 按钮,订阅设备控制主题。
当前支持四种灯光控制模式:
- 常开模式:灯保持常亮,适用于需要持续照明的场景。
- 常闭模式:灯保持关闭,适用于完全禁用灯光的情况。
- 节能模式:仅点亮少量 LED(如前3颗),提供微弱夜灯效果,兼顾省电与安全。
- 自动模式:根据环境光线与人体/声音感应智能控制——天黑且检测到活动时自动开灯,60 秒无活动后自动关闭。
选择合适的模式,即可实现灵活、智能的照明控制。
9
运行效果
0
0
0
qq空间
微博
复制链接
分享 更多相关项目
猜你喜欢
评论/提问(已发布 0 条)
0