1. 项目概述与核心思路最近在捣鼓家里的智能家居发现一个挺有意思的隐私痛点卫生间。家里来客人或者自己家人共用时最怕的就是门锁坏了或者干脆没锁一推门进去的尴尬场面。传统的“有人/无人”挂牌或者机械锁要么不够直观要么不够“智能”。于是我就琢磨着能不能做一个低成本、高可靠性、且极具辨识度的“智能卫生间门状态指示器”。这个项目的核心目标非常明确当卫生间门关上时门外自动亮起一个醒目的红色闪烁LED灯明确告知“里面有人请勿打扰”。这比任何文字标识都更直观、更符合现代人的认知习惯。更重要的是我希望这个装置能“隐身”——所有电路、电池都藏在门体内部门外只露出一个极小的磁铁和LED灯珠保持门的美观。同时作为需要长期运行的设备极致的低功耗是设计的重中之重我可不想隔三差五就搬梯子拆门换电池。最终我选择使用一颗常见的ATtiny85单片机作为大脑。它的优势太明显了体积小只有8个引脚、功耗极低、价格便宜而且Arduino IDE支持它开发调试非常方便。整个系统的工作原理很简单一个安装在门框上的干簧管磁控开关作为传感器当门关上时安装在门板上的磁铁靠近开关闭合单片机检测到信号便驱动一颗高亮红色LED以特定频率闪烁。当门打开磁铁远离开关断开整个系统进入深度休眠功耗几乎为零。这个方案听起来简单但里面有不少门道比如如何将平均电流降到微安级别以保证电池能用上好几个月甚至一年如何将电路板做得足够薄以塞进标准的木门或复合门里以及如何确保安装牢固且不影响门的正常开合。接下来我就把从构思、设计、制作到调试的完整过程以及踩过的坑和总结的经验毫无保留地分享出来。2. 核心硬件选型与设计解析硬件是整个项目的骨架选型直接决定了项目的成败尤其是在功耗、体积和可靠性这三个维度上。2.1 微控制器为什么是ATtiny85市面上低功耗单片机不少比如STM32系列的低功耗型号、ESP8266的深度睡眠模式等。但我最终锁定ATtiny85是基于以下几个核心考量功耗与睡眠模式ATtiny85支持多种睡眠模式其中“掉电模式”Power-down最为彻底。在此模式下内核时钟、ADC、看门狗等全部关闭仅保留外部中断和两线接口如果需要典型电流可以低至0.1 µA在1.8V 25°C条件下。这对于我们这种99%时间门都处于打开状态系统休眠的应用场景来说是决定电池寿命的关键。体积与引脚它的SOP-8或DIP-8封装尺寸极小非常适合塞进狭窄的门缝或门板内部空间。我们只需要用到3个IO口一个输入检测磁开关一个输出驱动LED一个可选用于编程引脚资源绰绰有余。开发便利性可以通过Arduino IDE配合USBasp或Arduino as ISP编程器进行开发库生态丰富比如用于低功耗的avr/sleep.h库大大降低了开发门槛。成本单价仅几块钱即使做坏了或者想升级成本也几乎可以忽略不计。注意购买ATtiny85时要确认其支持的工作电压。我们计划使用3V供电两节AA电池所以要选择支持3V工作的型号。通常标称工作电压为2.7V - 5.5V的都没问题。2.2 传感器磁控开关的抉择检测门开关状态最常见的有微动开关、红外对管和磁控开关干簧管。微动开关需要机械接触安装精度要求高容易因门变形导致失灵红外对管功耗大。干簧管成了不二之选。工作原理干簧管是两个重叠的磁性簧片密封在玻璃管中。当有足够强的磁场我们用的钕铁硼磁铁靠近时簧片被磁化相互吸引而接触电路导通磁场消失后簧片依靠自身弹性复位电路断开。优点零功耗本身是无源器件不消耗电流。高可靠性密封结构不怕灰尘、水汽对于卫生间环境很重要。安装灵活磁铁和干簧管可以非接触式安装允许有几毫米的错位公差对门铰链磨损造成的轻微位移不敏感。选型要点类型选“常开型”Normally Open。尺寸选小型的如Φ3mm或Φ2mm便于隐藏。灵敏度注意其“吸合安匝”AT值值越小越灵敏。选择中等灵敏度的即可太灵敏可能受远处其他磁场干扰。我选择了一款Φ3x15mm的玻璃管干簧管吸合距离大约在10-15mm左右这意味着即使门关得不是特别严实也能可靠触发。2.3 电源方案电池与稳压功耗计算是低功耗设计的灵魂。我们来算一笔账活跃状态门关闭LED闪烁。假设LED工作电流20mA每秒钟闪烁一次亮50ms灭950ms。那么平均电流 20mA * (50ms / 1000ms) 1 mA。加上单片机运行电流约几mA我们按3 mA估算持续30ms的峰值。这个阶段的平均电流约为 3mA * (30ms / 1000ms) 0.09 mA。休眠状态门打开干簧管断开单片机进入掉电模式。此时电流主要由ATtiny85的休眠电流和电路漏电流构成可以控制在5 µA以下。零电流状态这是一个关键优化当门打开时干簧管物理断开。我们可以在硬件设计上将干簧管串联在电池和整个电路的电源正极之间。这样当门打开、干簧管断开时电池与电路完全物理隔离理论功耗为零。这是实现“数百小时”续航的核心技巧。基于以上分析电源选择两节串联的AA5号碱性电池。标称电压3V容量约2000-3000mAh。续航估算理想情况假设一天门关闭有人使用总时长为2小时7200秒其中LED闪烁占10%时间720秒其余时间单片机仅检测但LED不亮。那么每日耗电量 ≈ (0.09mA * 720s 0.005mA * 6480s) / 3600s/h ≈ 0.02 mAh。电池容量按2500mAh算理论续航可达125000小时超过14年当然这是理想值实际要考虑电池自放电碱性电池年自放电约2-5%、电路静态功耗等但用上一两年绝对没问题。实操心得不需要线性稳压器LDO。ATtiny85在3V电压下工作稳定直接电池供电即可省去LDO自身的功耗通常几个µA和压降最大化电池利用率。2.4 LED与驱动电路为了在白天光线充足时也能清晰可见需要一颗高亮度的红色LED。我选择了一款直径3mm、散射角、亮度高达8000-10000 mcd的红色LED。驱动电路不能直接用单片机IO口驱动。ATtiny85的IO口拉电流能力有限通常20mA左右直接驱动高亮LED可能导致端口过载发热甚至损坏芯片。所以需要增加一个简单的三极管开关电路。NPN三极管如2N3904基极通过一个限流电阻如1kΩ连接到单片机IO口。集电极接LED和限流电阻到电源正极发射极接地。当IO口输出高电平时三极管饱和导通LED点亮。这种接法下单片机只提供很小的基极电流约3V/1kΩ3mALED的工作电流由电池通过三极管提供保护了单片机。3. 电路设计与PCB布局要点有了核心器件接下来就是把他们连接起来并设计成可以塞进门里的形态。3.1 完整电路原理图解析整个系统的电路图非常简单但每一处都体现了低功耗的设计思想电源路径电池正极 → 干簧管一端 → 干簧管另一端 → 整个电路板的VCC。这是实现“零功耗”的关键开关。单片机最小系统ATtiny85的VCC接电路VCCGND接电池负极。在VCC和GND之间紧贴芯片放置一个0.1µF的陶瓷去耦电容用于滤除电源噪声。传感器输入干簧管另一端接电路VCC的那端同时连接一个下拉电阻如10kΩ到GND然后连接到ATtiny85的一个IO口如PB3。这样当干簧管闭合门关该IO口读到高电平VCC当干簧管断开门开下拉电阻确保IO口为稳定的低电平防止悬空引脚产生随机功耗和误触发。LED驱动选择一个IO口如PB4通过一个1kΩ电阻连接到NPN三极管2N3904的基极。三极管的发射极接地集电极连接LED的阳极长脚LED的阴极通过一个限流电阻连接到电路VCC。注意LED是接在VCC和集电极之间。限流电阻计算红色LED正向压降约1.8V-2.2V我们按2.0V算。电源电压3V。期望LED电流为20mA。那么电阻值 R (Vcc - Vled - Vce_sat) / Iled。三极管饱和压降Vce_sat很小约0.2V。所以 R ≈ (3V - 2.0V - 0.2V) / 0.02A 40Ω。可以选择一个47Ω或51Ω的标准电阻。实际亮度足够电流约18mA在安全范围内。编程接口预留一个6针的ISP接口连接SCK MISO MOSI RESET VCC GND用于烧录程序。烧录时需要临时将干簧管短接或者用外部电源供电。3.2 PCB设计与安装考量为了把电路板藏进门里PCB设计必须非常紧凑且薄。形状与尺寸我将PCB设计成细长条形宽度约15mm以适应门板厚度长度约60-80mm。所有元件采用0805或0603封装的贴片元件进一步降低厚度。电池安装采用一个贴片的AA电池座或者直接焊接带引线的电池扣。将电池平行于PCB放置整体包裹起来。传感器与LED引出干簧管和LED无法安装在主板上需要用细导线如AWG30的硅胶线引出。在PCB上预留焊盘。固定方式在PCB两端设计两个直径3mm的固定孔可以使用短小的自攻螺丝固定在门内部的木质结构上。确保不会打到门表面的饰面板。绝缘与防护电路板组装完成后整体用热缩管或者绝缘胶带包裹防止金属部件短路。如果卫生间湿度特别大可以考虑涂覆一层三防漆保形涂层。注意事项在门上钻孔穿线用于LED和干簧管时一定要小心。先用电钻打一个小导引孔确认门板内部没有金属加强筋或电线特别是如果是入户门改的卫生间门后再进行。孔位尽量选择在门的上方边缘或合页侧比较隐蔽。4. 固件开发与低功耗编程实战硬件是身体固件Firmware就是灵魂。我们的固件核心任务就两个检测门状态以及用最低功耗的方式驱动LED闪烁。4.1 开发环境搭建安装Arduino IDE。在“文件”-“首选项”的“附加开发板管理器网址”中添加ATtiny板的支持网址https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json打开“工具”-“开发板”-“开发板管理器”搜索“attiny”安装“attiny by David A. Mellis”。选择开发板“ATtiny25/45/85”。选择处理器“ATtiny85”。选择时钟“内部8MHz”为了低功耗我们不需要外部晶振。选择编程器“USBasp”或“Arduino as ISP”。4.2 核心代码逻辑与详解以下是完整的Arduino Sketch并附上逐段解析。#include avr/sleep.h #include avr/power.h #include avr/wdt.h // 引脚定义 const int reedPin 3; // PB3 干簧管输入带下拉电阻 const int ledPin 4; // PB4 LED控制输出通过三极管 // 变量定义 volatile bool doorClosed false; // 门状态标志 volatile确保在中断中修改能被主循环识别 void setup() { // 配置引脚 pinMode(reedPin, INPUT); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); // 初始确保LED熄灭 // 配置看门狗定时器WDT中断 // 看门狗在这里不是用于防跑飞而是作为一个低功耗的定时器来唤醒MCU // 设置WDT为1秒中断 MCUSR ~(1 WDRF); // 清除WDT复位标志 WDTCSR | (1 WDCE) | (1 WDE); // 允许配置更改 WDTCSR (1 WDIE) | (1 WDP2) | (1 WDP1); // 使能中断模式预分频设置为1秒 // WDP2和WDP1的组合对应1秒超时。具体对应关系需查数据手册。 // 使能全局中断 sei(); } void loop() { // 主循环唯一任务检查门状态标志并控制LED if (doorClosed) { // 门关着执行闪烁模式 blinkLED(); // 闪烁一次后重置标志等待下一次WDT中断检查 doorClosed false; } else { // 门开着什么都不做直接进入睡眠 // 实际上如果门一直开着loop()只会执行一次就进入睡眠直到门关上触发中断唤醒 } // 进入深度睡眠掉电模式 goToSleep(); } // 看门狗中断服务程序ISR ISR (WDT_vect) { // WDT每1秒触发一次中断唤醒MCU // 在这里检查门的状态 if (digitalRead(reedPin) HIGH) { doorClosed true; // 干簧管闭合磁铁靠近门关着 } else { doorClosed false; // 干簧管断开门开着 } // 注意这里只是设置标志不进行任何耗时操作。具体动作在主循环中处理。 } // LED闪烁函数 void blinkLED() { // 闪烁模式快速闪烁3次暂停循环。更醒目。 for (int i 0; i 3; i) { digitalWrite(ledPin, HIGH); delay(50); // LED亮50毫秒 digitalWrite(ledPin, LOW); delay(150); // LED灭150毫秒 } delay(500); // 三次闪烁后暂停500毫秒 } // 进入睡眠函数 void goToSleep() { // 设置睡眠模式为掉电模式最省电 set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); // 关闭未使用的模块以省电ADC 定时器等 power_all_disable(); // 注意这会使能看门狗但WDT在睡眠时是关闭的靠自身振荡器工作 // 进入睡眠程序在此暂停直到被中断唤醒 sleep_cpu(); // 唤醒后继续执行从这里开始 sleep_disable(); power_all_enable(); // 重新开启所有模块 }代码关键点解析中断驱动与状态标志我们没有在loop()里用digitalRead不断查询干簧管状态那太耗电了。而是利用看门狗定时器WDT每秒产生一次中断。在中断服务程序ISR里快速读取引脚状态并更新一个全局标志doorClosed。主循环根据这个标志决定是否闪烁LED。这样MCU99%以上的时间都在深度睡眠。看门狗作为低功耗定时器ATtiny85的看门狗定时器有一个独立的128kHz振荡器即使在最深度的睡眠模式下也能运行。我们将它配置为中断模式WDIE而不是复位模式WDE让它每隔1秒产生一次中断来唤醒MCU检查门状态。这是低功耗周期性任务的经典做法。volatile关键字因为doorClosed变量在中断ISR中被修改在主循环中被读取编译器优化可能会出问题。volatile告诉编译器这个变量可能随时被意外改变不要对它进行优化每次都要从内存中读取它的值。睡眠模式SLEEP_MODE_PWR_DOWN是AVR最省电的模式几乎关闭所有内部模块。调用sleep_cpu()后MCU停止执行指令直到有中断发生这里是WDT中断。LED闪烁模式简单的亮灭可能不够醒目。我采用了“快闪3次-暂停”的模式更容易吸引注意力也更具辨识度。4.3 程序烧录与熔丝位配置使用USBasp编程器连接PCB上的ISP接口。在Arduino IDE中点击“烧录引导程序”这会设置正确的熔丝位主要是设置时钟源为内部8MHz并禁用时钟分频器即让芯片运行在8MHz。重要提示熔丝位配置错误可能导致芯片锁死或无法编程。对于ATtiny85使用Arduino IDE的“烧录引导程序”功能是最安全简单的方式。它会自动配置好适合我们低功耗应用的熔丝位例如使能BOD掉电检测在1.8V这样当电池电压过低时MCU会复位而不是不可预测地运行避免电池过放。5. 组装、安装与调试全流程5.1 焊接与组装焊接顺序先焊接最小的元件电阻、电容然后是单片机插座如果用了插座最后是接线端子、电池座等大件。使用细尖头的烙铁和焊锡膏。功能测试焊接完成后先不要装进电池。用万用表蜂鸣档检查电源是否有短路。然后用外部可调电源调到3V或临时接上电池测试用磁铁靠近/远离干簧管观察LED是否按预期闪烁/熄灭。测量休眠电流在电源回路串联万用表电流档门打开状态下电流应小于10µA。绝缘处理测试无误后用热缩管将整个电路板除电池外包裹起来或者用绝缘胶带严密缠绕。电池正负极触点也要做好绝缘防止在门内移动时短路。5.2 门体安装步骤这是最需要耐心和细心的环节。定位LED位置选择在门外侧视线平齐或稍高的位置通常在门把手上方。用铅笔做标记。干簧管位置在门框上与门板上的磁铁位置对应。确保门关紧时磁铁中心正对干簧管中心距离在5mm以内。钻孔在门板LED标记处钻一个直径略大于LED灯珠如4mm的孔深度刚好让LED帽露出来。在门板侧面或顶部边缘选择内部有空间的位置钻一个更大的孔如10mm作为线路进入门内部的通道。在门框干簧管标记处钻一个小孔如3mm用于放置干簧管并在旁边钻一个细孔将导线引入门框内部或沿着门框走线。布线将LED的两根引线从门板正面小孔穿入从侧面大孔穿出。将干簧管的两根引线从门框小孔穿入。使用细长的穿线器或铁丝辅助。在门板和门框内部走线时尽量将线缆用扎带或胶布固定避免开关门时拉扯。固定传感器与LEDLED在门板内部用热熔胶或AB胶将LED牢固地固定在钻孔处确保其不会晃动且灯珠正面朝向门外。干簧管将干簧管塞入门框的孔中用热熔胶或环氧树脂胶固定。务必确保胶水不要渗入干簧管的玻璃管封接处以免影响簧片动作。磁铁在门板上与干簧管对应的位置开一个浅槽或直接使用强力双面胶/热熔胶将小磁铁固定。固定前关上门测试磁铁与干簧管的相对位置是否最佳即门关紧时干簧管可靠闭合门打开一点就断开。安装主板与电池在门板内部选择一个空旷、干燥、不易被挤压的位置通常靠近门顶部用螺丝或强力双面胶固定电路板。将所有引线LED、干簧管焊接到PCB对应焊盘上。连接电池并用扎带或胶带固定好电池。5.3 系统调试与优化安装好后进行最终测试功能测试反复开关门观察LED指示是否准确、即时。测试不同关门力度下的可靠性。功耗复测安装好后再次测量系统总功耗。门打开时电流应为微安级门关闭LED闪烁时平均电流在毫安级。外观修饰对于门外的LED孔和门框上的干簧管孔如果觉得不美观可以使用一小块透明亚克力板覆盖LED或者用颜色接近门框的补土/蜡笔填补干簧管小孔。灵敏度调整如果发现干簧管有时不触发或过于灵敏可以微调磁铁的位置或者尝试更换不同磁极方向磁铁翻转180度。6. 常见问题排查与进阶优化在实际制作和安装过程中你可能会遇到以下问题6.1 问题排查速查表问题现象可能原因排查步骤与解决方案LED完全不亮1. 电池没电或装反。2. 干簧管常开电路未通电。3. LED或三极管焊反、损坏。4. 程序未烧录或芯片损坏。1. 用万用表测电池电压检查极性。2. 用磁铁靠近干簧管或用导线短接干簧管两焊盘看是否通电。3. 检查LED极性长正短负检查三极管引脚EBC。4. 重新烧录程序检查ISP连接。LED常亮不闪1. 干簧管一直闭合磁铁太近或干簧管粘连。2. 程序逻辑错误doorClosed标志一直为真。3. 三极管击穿C-E短路。1. 移开磁铁看LED是否熄灭。检查干簧管。2. 调试程序在blinkLED()后加doorClosed false。3. 更换三极管。门关后LED不亮1. 干簧管未闭合距离太远或磁铁磁性弱。2. 干簧管引线断路。3. 程序中断未触发或状态检测错误。1. 调整磁铁位置确保门关紧时两者对齐且距离近。用万用表测干簧管通断。2. 检查焊接和导线。3. 用串口调试如果支持或通过一个额外的LED来指示doorClosed标志状态。电池消耗极快1. 休眠电流过大50µA。2. 门常关系统长期处于活跃状态。3. 存在短路或漏电。1. 断开干簧管测静态电流。检查单片机是否成功进入睡眠sleep_cpu()。检查所有IO口状态未用的应设置为输出低或输入上拉。2. 这是正常使用耗电检查LED电流是否过大。3. 检查PCB是否有焊锡桥接、元件是否损坏。LED闪烁不稳定1. 电源电压不稳电池电量不足。2. 程序中断冲突极少见。3. 接触不良。1. 更换新电池。2. 确保中断服务程序ISR尽可能短不调用delay()等阻塞函数。3. 检查所有焊点和接插件。6.2 进阶优化与扩展思路基础版本已经非常实用但如果你还想玩点花样这里有几个扩展方向双色LED或RGB LED使用一颗共阳RGB LED。门开时显示绿色常亮表示可用门关时显示红色闪烁。这需要增加两个三极管驱动并修改程序。无线状态上报增加一个蓝牙低功耗BLE模块如HM-10或nRF51822。当门状态变化时通过蓝牙通知手机App实现远程查看卫生间占用状态。但这会显著增加功耗和复杂度可能需要考虑更大的电池或可充电方案。光敏控制增加一个光敏电阻或光电二极管在环境光足够亮时白天降低LED亮度或关闭LED进一步省电环境暗时夜晚提高亮度。注意光敏元件本身也有微小的功耗。超时关闭防止有人忘记开门导致LED长亮。在程序中加入计时器如果门关闭状态持续超过一定时间如2小时则强制让LED停止闪烁或进入极低频率的提示模式并在门打开时复位。更优雅的安装设计3D打印的外壳将LED灯做成一个柔光的“有人”标识牌直接贴在门外内部隐藏磁铁和干簧管。这样无需在门上钻孔更适合租房或不想破坏装修的用户。这个项目从构思到实现最大的成就感来自于用极低的成本和简单的技术切实地解决了一个生活中的小痛点。它不依赖于网络不依赖云服务稳定可靠。整个制作过程也是对硬件设计、低功耗编程和动手能力的一次很好的锻炼。最关键的是当看到那个红色的小灯随着门的关闭而安心地闪烁起来时你知道那份小小的隐私得到了一个聪明而沉默的守护。