多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于Arduino的智能感应灯:人体感应+光线感应+蓝牙三合一控制

基于Arduino的智能感应灯:人体感应+光线感应+蓝牙三合一控制 先说结论这盏 Arduino 智能小灯把人体感应、光线感应和蓝牙控制三套逻辑集成在了一起天黑有人经过就自动亮光线充足时再多人走也不亮手机连上蓝牙还能随时手动开关。做这个项目的起因很实在——我家玄关开关离门口太远每天拎着东西进门都要先摸黑找墙冬天晚上起夜更是憋着一口气走到客厅才能开灯。市面上的成品感应灯要么没有环境光判断白天晃晃悠悠乱亮要么设置死板不能手动干预我就动了手搓一套的心思。现在这盏灯放在玄关实测了两周自动模式几乎没出过错蓝牙手动控制也稳定所以我把整个项目的选型思路、接线方式、完整代码和踩坑记录都整理了出来。这篇攻略适合刚接触 Arduino 的朋友照着做也适合有基础的人直接拿走逻辑改到自己场景里。1. 三种控制的需求拆解为什么人体感应、光线感应、蓝牙一个都不能少1.1 单一传感器的局限很多人最开始想的只是我买个人体感应模块不就完了实际用起来就会发现单靠人体感应做灯非常难受。HC-SR501 这类 PIR 传感器只要检测到移动的人体就会输出高电平完全不区分白天黑夜结果就是大白天阳光晒着你从旁边经过它照样亮。灯倒是亮了但纯属浪费电白天亮着还显得很蠢。只加光线感应也不行。光敏电阻只能告诉你环境亮不亮没法知道有没有人来了它压根就是个被动测量元件永远无法主动触发开灯动作。至于蓝牙控制它连自动化都算不上本质是把手机当成一个遥控器人还是得掏手机比传统开关先进不了多少。所以这三样东西其实是互补关系不是堆砌功能。1.2 三层逻辑怎么协同我的实际决策逻辑是这样的人体感应负责触发光线感应负责条件蓝牙负责覆盖。触发层HC-SR501 检测到人体移动产生一个高电平脉冲这是开灯的请求信号。条件层光敏电阻持续读取环境光强只有光线暗到设定阈值以下自动开灯这个动作才被允许执行。覆盖层特殊情况需要跳出自动化逻辑比如白天我想看柜子下面的暗角或者晚上坐在沙发上看书不想让玄关灯自动亮直接用 App 发指令强制开灯或强制关灯把自动模式临时切掉。最终在代码里体现为自动模式 环境光暗且人体信号有效两者用 AND 逻辑串起来蓝牙手动模式拥更高优先级A 开、B 关、C 重新回到自动。1.3 适合谁做、需要什么基础这个项目不需要你有电路设计经验认电路板上的字母方向、按图示插线就够了。软件方面只要能在 Arduino IDE 里复制粘贴代码、会选对开发板和串口号剩下的逻辑我会一行一行拆开讲。整个项目预算我压在五十块钱以内Arduino Uno 兼容板二十几块HC-SR501 三四块HC-06 蓝牙模块十块出头光敏电阻和电阻电容这些加起来不到五块。如果你的手机是 iPhone直接看完全文再做决定——HC-06 这类经典蓝牙模块在 iOS 上兼容性很差我会在蓝牙章节单独讲这个问题以及更省事的替代方案。2. 关键元器件选型与原理PIR、光敏电阻、HC-06 各自怎么工作2.1 人体感应核心HC-SR501 PIR 传感器HC-SR501 是目前最普及的热释电红外传感器模块这块板子的核心是一个热释电传感元件外面罩着半球形的菲涅尔透镜。人体体温大约 37℃辐射的红外线波长集中在 9.4 微米左右透镜把环境中的红外辐射汇聚到传感器表面传感器本身只对红外辐射的变化敏感——换言之它检测的是移动的热源一个静止坐在沙发上的人反而触发不了它。模块上有两个电位器和一个跳线帽很多人买了直接用根本不知道它们是干嘛的。灵敏度电位器调节检测距离顺时针拧到底大概能覆盖 7 米范围逆时针拧回来最小大概 3 米左右。家用小灯建议调到 3 到 4 米太远容易把门外路过的人、对面楼的人照进来。延时电位器调节输出高电平的持续时间可调范围约 5 秒到 300 秒。这里有个关键建议把延时调到最短逆时针到底附近让硬件只负责产生一个短脉冲真正的亮灯维持时长完全交给 Arduino 代码来控制。原因是代码改一个变量就能调整时长而每次蹲下去拧电位器非常难受。跳线帽旁边标着 H 和 L。H 是可重复触发模式检测到人持续输出高电平L 是不可重复触发人一直在也不会重新触发。本次项目要跳在 H 上配合代码实现人只要没走远灯就不会灭的效果。HC-SR501 工作电压 5V输出 TTL 电平Arduino 的数字引脚可以直接识别。上电初期有约 30 到 60 秒的预热时间这个阶段它会随机乱触发不是故障测试时等 1 分钟再开始。2.2 光线感应光敏电阻与分压电路光线感应方案我选的是最简单的光敏电阻LDR加固定电阻分压。你可能在网上看到过 BH1750 数字光照传感器精度更高、直接输出勒克斯数值但对于判断环境暗不暗这种二元决策光敏电阻的精度完全够用价格还便宜一大截。电路原理是个初中物理就讲过的串联分压。我用的是这个接法光敏电阻一端接 5V另一端引到模拟输入 A0同时 A0 通过一只 10KΩ 电阻接地。光敏电阻的阻值会随光照变化——光线越强阻值越小光线越暗阻值越大。于是 A0 点的电压就跟着光强变化Arduino 的analogRead会把 0 到 5V 的电压映射成 0 到 1023 的整数。具体数值可以算一下感受量级假设强光时光敏电阻降到 5KΩA0 点分压是 5 × 10 / (5 10) ≈ 3.33V模拟读数接近 682暗处光敏电阻升到 100KΩA0 点分压是 5 × 10 / (100 10) ≈ 0.45V模拟读数只有 92 左右。中间的分界线我建议起始阈值设 300然后在实测里根据你的房间环境微调。有一点必须提醒网上另一个常见接法是固定电阻接 5V、光敏电阻接地那个接法下模拟值和光照的关系正好反过来光越强数值越小。两种接法都能用但代码判断方向的写法完全不同后文会给出对应的改进说明别照抄接完发现逻辑反了。2.3 蓝牙通信HC-06 从机模块与 AT 指令蓝牙模块我选了 HC-06。HC-05 和 HC-06 外观几乎一样但 HC-05 支持主从一体、可以配对其他主机设备而 HC-06 是纯从机只等手机来连接。这个项目里只需要手机主动连模块HC-06 够用价格又低配置还简单。HC-06 默认串口波特率 9600默认名称通常是HC-06配对密码 1234 或者 0000。模块通过串口和 Arduino 通信协议上没有任何额外封装手机 App 发送一个字符模块就把这个字符原样吐给 Arduino 的串口引脚。我最终用字符指令实现控制A 开灯B 关灯C 回自动模式。给 HC-06 改名或者改波特率需要进 AT 指令模式——HC-06 的 AT 指令直接通过串口发就行不要求像 HC-05 那样上电前按住按键这块很多教程混着写容易把人绕晕。需要用 AT 指令时把模块的 TX、RX 先接到 USB 转 TTL 上在电脑串口助手发送AT能收到OK表示通信正常。但我必须说一句大实话这个项目用默认配置就能跑AT 指令属于锦上添花不改名也能连新手不必一开始就折腾它。2.4 为什么用 Arduino Uno 打底为什么不直接用 ESP32很多做智能硬件的人会问ESP32 自带蓝牙和 WiFi价格和 Uno 差不多为什么绕一圈用 Uno 再加蓝牙模块我的回答是Uno 有最庞大的教程资源和最成熟的排错路径。PIR 不触发、光敏数值不对、串口乱码这些问题在任何平台都会遇到但用 Uno 时你能在网上找到一万篇解法对新手来说是巨大的隐形优势。另一个原因涉及电平兼容性。HC-06 的 IO 耐压是 3.3V 级别虽然很多教程直接把它接到 5V 的 Arduino 串口上也能用这属于没出事的幸存者偏差我见过不止一个模块因此烧毁。Uno 配 HC-06 需要在数据线上做分压而 ESP32 本身就是 3.3V 电平接这类模块反而省心。所以这篇文章主流程用 Uno但我会在最后一个章节专门讲如果换成 ESP32代码迁移只要改蓝牙初始化部分其余逻辑几乎不动。3. 硬件搭建全记录接线表、供电方式和安装细节3.1 元器件清单元件规格/型号数量参考价格主控板Arduino Uno R3 兼容板1约 25 元人体感应HC-SR501 PIR 模块1约 4 元光线感应光敏电阻 GL5528 或同类1约 1 元固定电阻10KΩ1/4W 即可1几毛钱蓝牙模块HC-061约 12 元输出负载LED 220Ω 限流电阻1 组几毛钱面包板400 孔以上1约 8 元跳线公对公若干-约 5 元供电USB 线 5V 充电头1家里现成的如果最终想控制 220V 灯具把 LED 部分替换成 5V 继电器模块再接灯这个后文单说原型阶段用 LED 验证逻辑最安全。3.2 接线对照表这是整个项目最重要的接线表按照 1:1 对照着插就能用。我建议最后再接蓝牙模块先把 PIR 和光敏电阻调通减少排查范围。模块模块引脚Arduino 引脚说明HC-SR501VCC5V模块供电HC-SR501GNDGND共地HC-SR501OUTD2人体信号输出光敏电阻一端5V直接接电源光敏电阻另一端A0分压点10KΩ 电阻A0 同点GND上拉到地LED正极D9经 220Ω 电阻串联LED负极GND直接接地HC-06VCC5V模块供电注意别接反HC-06GNDGND共地HC-06RXDD10经 2KΩ 3.3KΩ 分压后接入HC-06TXDD113.3V 输出Arduino 能直接识别D10 到 HC-06 RXD 之间的分压是个易错点。Arduino 数字引脚输出 5V 高电平HC-06 的 RX 引脚期望的是 3.3V 逻辑电平直接对接长期使用有烧引脚的风险。正确做法是在 D10 和 HC-06 RXD 之间串一个 2KΩ 电阻然后在 HC-06 RXD 对地接一个 3.3KΩ 电阻两个电阻分压把 5V 降到约 3.1V正好落在安全范围。HC-06 的 TXD 输出 3.3V 是它的原生电平接到 Arduino D11 完全没问题不需要任何处理。3.3 供电与模块安装的注意点整块面包板由 USB 口 5V 供电总电流大概在 100mA 左右充电头输出 500mA 以上的都能吃饱。要特别注意不同模块要共地这点很多人嘴上知道但接线时容易漏只要某个模块和 Arduino 不共地信号电平就没有参考基准表现就是传感器读取结果完全随机。真实项目里我不会把传感器像实验室一样全堆在面包板上。HC-SR501 需要装在有一定高度、朝向人活动路径的位置比如玄关鞋柜顶面光敏电阻要放在能感受到整体环境光线但又不会被灯光直接照到的地方否则会出现灯一开光敏电阻读数立刻变小判为已是黑暗的死循环——严格说这个项目的灯是开环控制不会因为灯亮自动关灯但如果光敏电阻正对着灯头自动判断会明显失真。我的做法是把光敏电阻焊两根延长线甩到灯侧的阴影位置让传感器测的是房间整体亮度而不是灯本体亮度。HC-06 模块天线区域最好悬空不要贴合面包板金属接触片也别贴在金属外壳上信号会被屏蔽导致连接距离缩到一米内。4. 完整代码逐段解读状态判断、串口指令与防抖逻辑4.1 引脚定义与全局状态程序开头定义了所有引脚的用途集中管理最大的好处是后续改硬件接线只要改这里不用满代码翻。#include SoftwareSerial.h #define PIR_PIN 2 // HC-SR501 输出 - D2 #define LDR_PIN A0 // 光敏电阻分压点 - A0 #define LED_PIN 9 // LED - D9支持 PWM #define BT_RX_PIN 10 // HC-06 RXD - D10经分压 #define BT_TX_PIN 11 // HC-06 TXD - D11 SoftwareSerial myBT(BT_RX_PIN, BT_TX_PIN); int lightThreshold 300; // 环境光阈值低于它判定为暗 const long keepOnMillis 30000; // 自动模式下检测到人后保持亮灯 30 秒 const long triggerCooldown 5000; // 连续触发最小间隔防抖动 long lastTriggerTime 0; // 上一次有效触发的毫秒时间戳 boolean autoMode true; // 是否处于自动模式 boolean manualOn false; // 蓝牙手动强制开灯状态 boolean lastPirState false; // PIR 上一轮状态用于边沿检测autoMode和manualOn是两个独立的状态变量手动开灯时autoMode变 false、manualOn变 true回到自动模式时autoMode变 true、manualOn清 false。这种设计比用一个布尔变量表达三种状态清晰得多后续扩展定时模式时也不用重构逻辑。4.2 传感器读取与边沿防抖HC-SR501 的可重复触发模式下只要人还在移动输出就持续为高。但人在感应区边缘徘徊时输出会有比较快的抖动直接判断电平会导致灯一亮一灭闪个不停。我的处理方式是检测信号的上升沿而不是电平本身并且记录一个冷却窗口。void setup() { pinMode(PIR_PIN, INPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Serial.begin(9600); myBT.begin(9600); Serial.println(F(Smart Light initialized. PIR warming up...)); } void loop() { boolean pirNow digitalRead(PIR_PIN); int lightValue analogRead(LDR_PIN); boolean darkEnough (lightValue lightThreshold); // 只在 PIR 从低跳变到高时记录一次触发冷却期内忽略 if (pirNow !lastPirState (millis() - lastTriggerTime triggerCooldown)) { lastTriggerTime millis(); Serial.println(F(Motion detected)); } lastPirState pirNow; // 人体仍在感应区内移动时不断刷新最后触发时间 if (pirNow (millis() - lastTriggerTime triggerCooldown)) { lastTriggerTime millis(); } // 串口打印调试信息 static unsigned long lastPrintTime 0; if (millis() - lastPrintTime 500) { lastPrintTime millis(); Serial.print(F(LDR)); Serial.print(lightValue); Serial.print(F( darkEnough)); Serial.print(darkEnough); Serial.print(F( autoMode)); Serial.println(autoMode); } // ... 蓝牙指令解析与亮灯逻辑放在下一节 }注意这里我用了两种更新lastTriggerTime的方式第一个是边沿触发记录一次刚刚有人进入第二个是持续刷新当 PIR 一直输出高时让计时器一直延后表现为人体不离开感应区灯就不会进入倒计时熄灭。这两行配合起来就实现了人来了亮人走 30 秒后灭的效果。triggerCooldown的设置很关键。第一次上电或者 PIR 预热期间输出会有多次抖动冷却窗口保证抖动不会在短时间内反复更新触发计时。如果你发现灯总是亮一小会儿就灭先看是不是冷却时间设太长抢占了保持时间其次是确认 PIR 的跳线帽确实在 H 位置。4.3 蓝牙串口指令解析HC-06 把手机发来的字符原样送到 Arduino 串口我解析的指令只有三个A 强制开灯、B 强制关灯、C 恢复自动模式。为了容错代码同时支持大小写。void loop() { // ... 延续上一节的传感器读取代码 // 蓝牙指令处理 while (myBT.available()) { char cmd myBT.read(); Serial.print(F(BT CMD: )); Serial.println(cmd); switch (cmd) { case A: case a: autoMode false; manualOn true; Serial.println(F(Manual ON)); break; case B: case b: autoMode false; manualOn false; Serial.println(F(Manual OFF)); break; case C: case c: autoMode true; manualOn false; Serial.println(F(Auto Mode)); break; default: // 忽略其他字符 break; } } // 亮灯逻辑 boolean shouldLight false; if (autoMode) { // 自动模式光线暗且检测到过人体保持亮灯 keepOnMillis 毫秒 if (darkEnough (millis() - lastTriggerTime keepOnMillis)) { shouldLight true; } } else { shouldLight manualOn; } digitalWrite(LED_PIN, shouldLight ? HIGH : LOW); }自动模式的亮灯条件我刻意没有把当前 PIR 为高作为必要条件而是看最后触发时间距离现在是否小于 30 秒。这样 PIR 输出短脉冲后即使模块自身的延时旋钮调得很短Arduino 也能控制保持时间这正好回应了前面选型时把 PIR 延时调到最小的建议硬件负责薄薄的看一眼软件负责决定亮多久。蓝牙解析放在主循环里每轮都执行响应基本是即时的。while (myBT.available())会把缓冲区里的所有字符读完避免上一次指令残留在缓冲区里影响下一次判断。4.4 完整可运行代码把上面几段拼起来就是完整版可以直接复制到 Arduino IDE。接线按照第 3 章的表格烧录后打开串口监视器波特率 9600能看到实时的光敏读数和模式状态方便后期调参。#include SoftwareSerial.h #define PIR_PIN 2 #define LDR_PIN A0 #define LED_PIN 9 #define BT_RX_PIN 10 #define BT_TX_PIN 11 SoftwareSerial myBT(BT_RX_PIN, BT_TX_PIN); int lightThreshold 300; const long keepOnMillis 30000; const long triggerCooldown 5000; long lastTriggerTime 0; boolean autoMode true; boolean manualOn false; boolean lastPirState false; void setup() { pinMode(PIR_PIN, INPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Serial.begin(9600); myBT.begin(9600); Serial.println(F(Smart Light initialized. PIR warming up...)); } void loop() { boolean pirNow digitalRead(PIR_PIN); int lightValue analogRead(LDR_PIN); boolean darkEnough (lightValue lightThreshold); // 边沿检测低到高跳变且冷却时间已过记录一次触发 if (pirNow !lastPirState (millis() - lastTriggerTime triggerCooldown)) { lastTriggerTime millis(); Serial.println(F(Motion detected)); } lastPirState pirNow; // 持续刷新感应区内一直有人时间戳不断更新 if (pirNow (millis() - lastTriggerTime triggerCooldown)) { lastTriggerTime millis(); } // 每 500ms 打印一次调试信息 static unsigned long lastPrintTime 0; if (millis() - lastPrintTime 500) { lastPrintTime millis(); Serial.print(F(LDR)); Serial.print(lightValue); Serial.print(F( darkEnough)); Serial.print(darkEnough); Serial.print(F( autoMode)); Serial.println(autoMode); } // 蓝牙指令处理 while (myBT.available()) { char cmd myBT.read(); Serial.print(F(BT CMD: )); Serial.println(cmd); switch (cmd) { case A: case a: autoMode false; manualOn true; Serial.println(F(Manual ON)); break; case B: case b: autoMode false; manualOn false; Serial.println(F(Manual OFF)); break; case C: case c: autoMode true; manualOn false; Serial.println(F(Auto Mode)); break; default: break; } } // 亮灯逻辑 boolean shouldLight false; if (autoMode) { if (darkEnough (millis() - lastTriggerTime keepOnMillis)) { shouldLight true; } } else { shouldLight manualOn; } digitalWrite(LED_PIN, shouldLight ? HIGH : LOW); }如果你按照固定电阻接 5V、光敏电阻接地的另一种接法搭的电路只需要把darkEnough的条件从改成也就是模拟值高于阈值判定为暗其余代码完全不用动。5. 手机蓝牙配对与控制App 选型、调试命令和常见坑5.1 一个让 iPhone 用户省心的结论先说一个我在测试中踩得最深的坑iPhone 对 HC-06 这类经典蓝牙 SPP 模块的支持非常糟糕。iOS 系统从底层就不允许普通 App 访问经典蓝牙的串口服务市面上大多数号称兼容的 App 要么只能连接特定厂商模块要么是历史遗留的残废版本。如果你手里只有 iPhone我的第一条建议不是硬刚而是把 HC-06 换成 ESP32 或者 Arduino Nano 33 BLE 这类自带 BLE 的板子用 BLE 的 UART Service 通信App 选择面一下就宽了。安卓手机则没有这个限制HC-06 配合安卓 App 体验很顺这也是这套方案对新手最友好的组合。5.2 推荐 App 与配对步骤安卓端我用过比较顺手的两个一个是 Serial Bluetooth Terminal老牌串口终端界面朴素但功能极全可以自定义快捷发送按钮另一个是国产的蓝牙调试助手中文界面适合第一次玩蓝牙模块的人。两者都能自定义发送内容我把三个指令 A、B、C 各自绑了一个大按钮实际使用时根本不用敲键盘。配对流程按这个顺序来HC-06 接好线Arduino 上电此时模块上的 LED 快速闪烁表示等待配对。打开手机蓝牙设置搜索新设备看到 HC-06可能是默认名也可能显示为 linvor点击配对。输入 PIN 码HC-06 一般默认 1234旧批次有些默认 0000两个都试试。打开 App连接模块如果 App 里有设备列表选择选中 HC-06如果没有列表就在设置里手动选 SPP 服务。波特率选 9600和代码里myBT.begin(9600)一致。连接成功后模块 LED 会变成慢闪或者常亮不同批次表现不同但至少不再是快速闪烁。5.3 常见调试问题和排查路径配对不上是最常见的问题。先确认 Arduino 正在供电模块指示灯在闪再确认手机蓝牙能搜到设备——搜不到就检查 HC-06 的 VCC 和 GND 是否接反接反模块发热眼神不好的还能闻到糊味。能搜到但配对失败多半是 PIN 码不对把 1234 和 0000 都试一遍再不行查模块批次有些山寨模块出厂 PIN 被改成 8888。连上了但 App 发送指令没反应打开 Arduino IDE 的串口监视器看看是否打印BT CMD: A。如果根本没打印说明数据没到 Arduino检查 D10 到 HC-06 RXD 的连接和分压电路如果打印了但灯不亮问题在逻辑代码或者 LED 接线打印BT CMD: A之后应该连着打印Manual ON看到这两行就说明代码分支进去了。还有一个很多人会搞混的点HC-06 的 RXD 要和 Arduino 的发引脚交叉连接也就是 Arduino 的 D10 接模块的 RXDArduino 的 D11 接模块的 TXD。方向接反的现象是 App 发送没反应但模块 TXD 到 Arduino D11 这个方向如果断了则是连名字都收不到打印。6. 实测表现、可靠性问题与值得尝试的进阶方向6.1 放在玄关两周的真实表现灯做好之后在玄关运行了两周我把代码里keepOnMillis设成了 30 秒光敏阈值调到 280。实测效果非常符合预期傍晚天暗下来之后我从门口走动灯基本在 0.5 到 1 秒内亮起人走出感应范围后大约 30 秒熄灭误差很小。蓝牙控制的响应几乎感觉不到延迟App 按钮按下去灯基本同步亮灭。最让我意外的是白天表现。大晴天下午从门口来回走灯完全没反应说明光敏阈值卡的位置很对。连续阴雨天问题就出现了下午两三点室内已经很暗灯在四点左右就自动亮起来因为阈值是固定的。这不算 bug但说明了一个设计原则单阈值硬判断的天暗永远是相对值想要更符合人的感受要么分季节手动调要么做成双阈值迟滞判断或者换 BH1750 读具体勒克斯值再定上下限。6.2 PIR 误触发处理的几条经验PIR 误触发的头疼指数远超其他问题。实测中早上一楼阳光照进玄关地砖反光被透镜捕捉偶尔会有一次误触发冬天家里有取暖器暖风一吹也有概率触发。最有趣的一次是阳台的猫跳上鞋柜蹲了一会灯一晚上亮了好几次。我的处理经验按优先级排序先把灵敏度电位器逆时针调低这是最直接的手段然后把模块安装位置抬高并调整角度让透镜视场避开窗户和散热设备。PIR 先天只能感知移动的热源这是物理原理决定的无法靠软件完美消除。如果误触发仍然不可接受就该考虑换 RCWL-0516 微波雷达模块了它用多普勒雷达检测移动目标对温度不敏感宠物误触率更低代码和 HC-SR501 完全兼容还是三根线。6.3 代码层面的可靠性和功耗优化当前代码每 500ms 串口打印一次调试信息长时间运行会一直占用串口但不影响功能。正式部署时可以删掉打印或者用宏开关包起来。另外delay()我一处没用整个主循环是跑满的蓝牙指令响应不会被延时阻塞这在将来扩展功能时很重要——如果代码里出现delay(1000)蓝牙响应就会最多延迟 1 秒体验很差。低功耗方面Uno 本身不是低功耗平台待机电流就有 40mA 以上靠电池供电不太现实。如果要做成内置锂电池的桌面小夜灯两个方向一是用 ESP32 的 deep sleep没人时进入休眠、PIR 通过 RTC 引脚唤醒整体功耗能压到 10mA 左右二是直接用 PIR 模块的输出作为三极管开关控制 LEDArduino 只在需要时启动这是另一套思路代码要整个重构。6.4 往真灯升级继电器模块与安全提醒原型 LED 验证通过后很多人下一步就是控制真实灯具。我强烈不建议把 220V 交流电直接和 Arduino 接在一起正规做法是中间加一个带光耦隔离的 5V 继电器模块Arduino 的 D9 接继电器 IN 引脚模块 VCC 接 5V再用继电器触点控制灯具火线。这里有三条必须遵守的安全底线改造 220V 电路前断开总闸确认断电再操作。Arduino、HC-06、光敏电阻这些低压部分和 220V 部分在物理上保持距离绝缘胶带缠好裸露触点。继电器模块务必买带光耦隔离的版本不要用那种直接用三极管驱动的裸板隔离成本就差几块钱安全感天差地别。6.5 迁移到 ESP32 的思路与 wokwi 在线仿真如果你打算让灯接入 WiFi、加上 BLE 控制、以后还能对接语音助手ESP32 是最划算的下一步。硬件上把 HC-06 完全去掉ESP32 自带蓝牙D2、A0、D9 这些引脚映射关系基本不变代码里唯一大改的部分是串口初始化——ESP32 用Serial1.begin(9600)接传感器BLE 部分则要引入BluetoothSerial.h库调用SerialBT.begin(SmartLight)就能获得一个虚拟串口手机用 BLE 调试助手连接后收发逻辑和 HC-06 一模一样。还有一件我认为特别值得推荐的事如果你手头暂时没有硬件或者只是想在收到货之前把逻辑跑通可以去 Wokwi 网站在线仿真选一个 Arduino Uno画一个 PIR、一个光敏电阻、一个 LED把本文代码粘进去就能直接看运行效果。我踩过的很多引脚定义错误、逻辑判断错误其实在仿真里一分钟就能暴露出来比接线后拿万用表量半天快得多。这个项目做完之后我最大的体会是传感器 控制器 执行器这个铁三角组合能覆盖绝大多数入门智能硬件需求。光线感应给了系统判断环境的能力人体感应给了系统感知人的能力蓝牙通信则让系统接受人的干预三者结合才是一盏不招人烦的智能灯。你在自己的应用场景里把这三种传感器任意替换成温湿度、声音、土壤湿度控制对象换成风扇、水泵、舵机整套代码框架依然成立。这也是为什么我说别小看这个小灯它其实是智能家居里最典型的迷你样板间。
返回列表