基于BLE与ESP32的智能门窗雨水检测系统DIY指南 1. 项目概述与核心价值你有没有经历过这样的场景出门在外突然变天心里咯噔一下——“卧室的窗户好像没关” 或者半夜被雨声惊醒迷迷糊糊爬起来检查各个房间。这种不确定性带来的焦虑正是我动手打造这个智能门窗与雨水检测系统的初衷。它不是什么复杂的商业产品而是一个基于BLE低功耗蓝牙和ESP32的DIY解决方案核心目标就一个用极低的成本和功耗实现全天候的窗户状态与雨水监测并在下雨且窗户未关时第一时间发出警报。这个系统的巧妙之处在于其“分工协作”的架构。窗户传感器端极致追求低功耗选用了nRF52832这类专为BLE设计的芯片配合微动开关和一颗CR2032纽扣电池理论续航可达5年你几乎可以忘了它的存在。而作为“大脑”的接收与报警端则交给了功能更强的ESP32C3它负责扫描所有传感器信号、读取雨水检测板的模拟值、驱动本地声光报警并提供一个Web页面用于状态查看。整个系统不依赖云端数据在本地处理响应迅速且隐私性好。对于刚接触物联网DIY的朋友这个项目是一个绝佳的练手机会。它涵盖了无线传感、嵌入式编程、电路搭建和简单的人机交互设计。而对于有经验的开发者其低功耗设计思路和任务调度方式也很有参考价值。接下来我会带你从原理到实操一步步拆解这个系统分享我在搭建过程中踩过的坑和总结的技巧让你不仅能复现更能理解背后的“为什么”。2. 系统架构与核心组件选型解析2.1 整体系统工作流程在动手焊接任何元件之前理解整个系统如何协同工作是关键。整个系统的数据流和控制逻辑可以概括为下图所示的流程flowchart TD A[雨水检测PCB] --|模拟电压信号| B(ESP32C3 网关) C[nRF52832 门窗传感器] --|BLE广播“开/关”状态| B B -- D{核心逻辑判断} D -- E[状态显示与报警] subgraph E [状态显示与报警] E1[本地LED指示灯] E2[本地蜂鸣器] E3[Web服务器状态页] E4[pfodApp图形界面] end F[用户] --|静音/查看| B这个流程的核心在于ESP32C3网关的决策逻辑它持续监听雨水传感器的电压判断是否下雨和所有BLE传感器的广播判断窗户开关状态。当且仅当“下雨”和“至少一扇窗开”两个条件同时满足时才会触发声光报警。用户可以通过物理按键或手机App临时静音。2.2 传感器端追求极致的低功耗设计传感器端的设计哲学是“简约与休眠”。其核心部件是nRF52832模块这是一颗集成了ARM Cortex-M4内核和BLE射频的芯片在低功耗方面表现卓越。2.2.1 功耗控制的核心策略nRF52832实现超长续航的秘诀在于其工作模式调度深度睡眠System OFF模式这是功耗最低的模式芯片仅保留RAM中部分数据电流消耗可低至0.6μA。在此模式下CPU和大部分外设均关闭。事件驱动唤醒通过配置GPIO的外部中断本例中连接微动开关芯片可以从深度睡眠中被瞬间唤醒。窗户状态变化开/关就是一个典型的事件。短促广播被唤醒后芯片立即启动BLE射频以特定的广播间隔如100ms向外发送包含自身状态如“Front_Bedroom_Win_Rhs,O”的数据包持续一个短暂的窗口期如10秒。快速返回睡眠广播窗口结束后芯片立即切断射频重新进入深度睡眠模式等待下一个唤醒事件。关键参数解析广播间隔与功耗的权衡广播间隔越短被接收器扫描到的概率越高响应越及时但功耗也越高。原设计采用“每100秒广播10秒”的策略这是一个非常保守且高效的设置。我们来算一笔账假设广播时平均电流为10mA睡眠时电流为2μA。在一个100秒的周期内工作10秒睡眠90秒。 平均电流 ≈ (10mA * 10s 0.002mA * 90s) / 100s ≈ 1.018mA CR2032电池典型容量为220mAh理论续航 ≈ 220mAh / 0.001018A ≈ 216小时约9天——等等这显然不对。这是因为上述计算忽略了睡眠模式的超低电流。在深度睡眠System OFF下电流是微安级的。假设睡眠电流为2μA则 周期内电荷消耗 ≈ (10mA * 10s) (0.002mA * 90s) ≈ 100mAs 0.18mAs ≈ 100.18mAs 平均电流 ≈ 100.18mAs / 100s ≈ 1.0018mA 这个计算仍然不准因为它把10秒广播期的平均电流简单化了。实际上在广播间隔内如100ms芯片也是在工作与睡眠间快速切换。一个更接近实际的模型是芯片在100秒内只有10秒处于“周期性广播”的活跃状态这10秒内的平均电流可能在5-8mA其余90秒完全深度睡眠电流约0.6μA。这样算下来整体平均电流可能在几十微安级别从而实现数年的续航。核心要点是尽可能延长深度睡眠时间是省电的王道。2.2.2 微动开关的选择与安装技巧微动开关是这个传感器的“感知器官”。原项目提到了几种开关选择依据主要是行程和安装方式。TLZWLA微动开关体积小价格便宜但行程短需要非常精确的安装位置才能被窗户有效触发。带长杠杆的微动开关杠杆可以放大窗户的微小位移对安装精度的要求降低容错性更好是更推荐的选择。实操心得开关安装的“预压力”安装微动开关时最容易出错的地方是让开关处于“临界”状态。理想情况是窗户关闭时开关被完全压下常闭触点断开窗户打开时开关被完全释放常闭触点闭合。要避免窗户关不严或风力导致开关轻微颤动从而产生误报。我的经验是在固定开关底座时先让窗户处于关闭状态然后将开关按压到刚好触发的位置再稍微往回拧一点让开关有一个微小的“预压行程”确保接触可靠。可以用万用表的通断档在安装时实时监测。2.3 网关端ESP32C3的多任务中枢网关选择了Seeed Studio的XIAO ESP32C3模块。它尺寸小巧接口丰富足以胜任本项目的多任务需求。2.3.1 为何选择ESP32C3双核处理与FreeRTOSESP32系列支持FreeRTOS实时操作系统可以方便地创建独立任务。在本项目中BLE扫描、Web服务器、ADC采样、报警逻辑判断都可以运行在独立的任务中互不阻塞保证了系统的实时性和稳定性。丰富的无线连接除了负责BLE扫描ESP32C3还自带Wi-Fi用于提供Web访问界面方便在家庭局域网内通过浏览器查看状态。足够的ADC精度用于读取雨水检测板的模拟电压其12位ADC分辨率为0-4095对于区分“干”和“湿”的状态绰绰有余。成本与生态XIAO ESP32C3价格亲民Arduino社区支持完善降低了开发门槛。2.3.2 雨水检测原理与电路设计雨水检测部分采用了一个简单的电阻分压电路。其核心是一个特制的PCB或可用覆铜板自制其上的平行走线在干燥时电阻极大1MΩ被水淋湿后水桥接通走线电阻急剧下降可至20KΩ以下。电路连接如下一个5V电源通过两个180Ω电阻分压得到约2.5V的参考电压。这个2.5V连接到一个10KΩ的上拉电阻再连接到雨水检测PCB的一端PCB的另一端接地。ESP32C3的ADC引脚则连接在10KΩ电阻和雨水检测PCB的节点上。干燥时PCB电阻极大相当于开路。ADC引脚通过10KΩ电阻上拉到2.5VADC读数接近最大值例如4095对应3.3V2.5V对应约3100。湿润时PCB电阻变小如20KΩ与10KΩ电阻形成并联节点电压被拉低。根据并联分压公式电压会降至约1.8V左右ADC读数相应降低约2200。注意事项ADC采样的抗干扰处理直接读取单次ADC值极易受到电源噪声、电磁干扰的影响导致数值跳动可能产生误报。原代码采用了滑动平均滤波算法每3毫秒采样一次持续3秒约1000个样本然后取平均值作为最终结果。这是一种简单有效的软件滤波方法。在实际部署中还可以在ADC输入引脚与地之间并联一个0.1μF的陶瓷电容以滤除高频噪声。3. 硬件搭建与软件烧录实操指南3.1 门窗传感器制作与编程3.1.1 物料清单与焊接你需要准备nRF52832模块如Holyiot YJ-16048CR2032电池座微动开关根据窗户类型选择一小块PCB或万用板用于固定和连接导线、焊锡等焊接非常简单只需要将微动开关的两端分别连接到nRF52832模块的两个GPIO引脚一个配置为上拉输入另一个接GND。电池的正负极连接到模块的VCC和GND。如果使用原项目的PCB则按丝印焊接即可。对于金属窗框务必使用尼龙螺丝螺母进行绝缘固定或将PCB与窗框用塑料片隔开防止金属屏蔽BLE信号。3.1.2 软件环境配置与烧录安装Arduino IDE从Arduino官网下载并安装最新版IDE。添加nRF52832支持按照原项目指引在Arduino IDE的“开发板管理器”中添加pfod_lp_nrf52_2024这个第三方开发板支持包。这通常需要在“文件”-“首选项”的“附加开发板管理器网址”中添加特定的索引URL。安装必要库文件将项目提供的WinOpenDetect_libraries.zip解压到Arduino的草图文件夹下的libraries子目录中。注意不要使用IDE的“添加.ZIP库”功能因为该ZIP包内含多个库需要手动解压合并。修改并烧录代码打开lp_BLE_micro_switch.ino文件。找到LOCAL_NAME定义处为每个传感器设置一个唯一且易识别的名字例如“Master_Bedroom_Window_North”。这个名字就是它在BLE广播中的标识符。连接编程器nRF52832通常通过SWD接口SWDIO, SWCLK进行编程。你需要一个兼容的调试器如J-Link、ST-Link需配置或专用的nRF编程器。连接VCC、GND、SWDIO、SWCLK四根线到模块对应引脚。烧录与测试在Arduino IDE中选择正确的开发板如“Generic nRF52832”和端口点击上传。烧录成功后使用手机上的“nRF Connect”App进行测试。按下微动开关你应该能看到名为[你的LOCAL_NAME],C的设备出现松开开关名字会变为[你的LOCAL_NAME],O。避坑指南编程接口的稳定连接nRF52832的调试接口引脚间距很小使用杜邦线容易接触不良。我的经验是要么使用专用的夹子要么在编程时直接用焊锡暂时将导线焊在引脚上烧录完成后再拆除。烧录完成后务必记得将SWCLK引脚与GND短接或者通过软件将其设置为普通I/O口并拉低防止噪声意外将其拉高使芯片进入编程模式导致功耗剧增。3.2 网关接收器/雨水检测器搭建3.2.1 电路组装核心模块将XIAO ESP32C3插入万用板或焊接在定制PCB上。雨水检测接口使用屏蔽线连接一个RCA母座到万用板。线的一端接ESP32C3的某个ADC引脚如A0和GND另一端接RCA公头用于连接户外的雨水检测PCB。屏蔽层单端接地接ESP32的GND以减少干扰。声光报警将一个有源蜂鸣器注意是“有源”给电就响连接到一个GPIO引脚如D1和VCC/GND。将一个LED通过一个220Ω的限流电阻连接到另一个GPIO引脚如D0。静音按钮将一个常开型轻触开关一端接另一个GPIO引脚如D2另一端接地。并在该GPIO上启用内部上拉电阻。电源为整个系统提供一个稳定的5V/1A电源适配器供电。3.2.2 网关端软件烧录与配置安装ESP32开发板支持在Arduino IDE的开发板管理器中搜索“esp32”安装Espressif Systems提供的版本。特别注意原项目基于V2.0.11测试新版本可能存在库兼容性问题。建议在开发板管理器界面点击“esp32”旁的版本号选择“2.0.11”进行安装。选择开发板与分区方案开发板选择“Seeed Studio XIAO ESP32C3”。分区方案选择“Huge APP (3MB No OTA/1MB SPIFFS)”为代码留出足够空间。安装库与载入代码同样将WinOpenDetect_libraries.zip解压到Arduino的库目录。然后打开RD_ESP32C3_BLE_Scanner_Server.ino主程序。关键配置修改在代码开头的expectedDevices数组中填入你为所有门窗传感器设置的LOCAL_NAME必须完全一致。char expectedDevices[][MAX_BLE_ADVERTISED_NAME] { Master_Bedroom_Window_North, Master_Bedroom_Window_South, Living_Room_Balcony_Door, // ... 添加所有你的传感器名字 };校准雨水检测阈值找到rainDetector.cpp文件中的wetcount变量。上传代码后通过串口监视器或后续的Web页面查看雨水检测PCB在“完全干燥”和“淋湿后”的ADC原始读数。取一个中间值作为wetcount。例如干燥时读数为3000淋湿后读数为2000那么可以设置wetcount 2500。代码中会加入迟滞如±20来防抖。网络配置代码集成了ESPAutoWiFiConfig库。首次上电后ESP32会创建一个名为“ESP32_Config”的Wi-Fi热点。用手机或电脑连接这个热点浏览器会自动弹出或手动访问192.168.4.1在此页面配置你的家庭Wi-Fi名称、密码并为ESP32设置一个固定的局域网IP地址如192.168.1.200。配置完成后设备将重启并连接到你指定的网络。4. 系统调试、界面定制与深度优化4.1 功能调试与状态验证系统上电并联网后可以通过多种方式验证其工作状态Web页面监控在浏览器中输入你为ESP32设置的静态IP地址如http://192.168.1.200。页面会显示雨水传感器状态WET/DRY及当前ADC原始值。所有已配置门窗传感器的状态OPEN/CLOSED/BAD及最后被看到的时间戳。BAD状态如果某个传感器超过220秒未被扫描到其状态会显示为BAD黑色表示可能电池耗尽、损坏或距离太远。物理指示灯解读LED常灭所有窗户关闭无故障。LED常亮未下雨但有至少一扇窗打开。LED快速闪烁正在下雨且有至少一扇窗打开此时蜂鸣器应报警。LED慢速闪烁未下雨但有传感器被标记为BAD失联。报警逻辑测试手动洒水模拟下雨观察ADC值是否低于wetcount阈值Web状态是否变为WET。打开一扇已配置的窗户观察其状态是否变为OPEN。同时满足“下雨”和“开窗”蜂鸣器应响起LED快速闪烁。按下网关上的物理按钮报警应停止。直到雨水传感器变干后报警功能才会重新启用。4.2 使用pfodApp定制专属图形界面Web页面虽然直观但pfodApp提供的图形化界面更美观。定制过程是本项目的一个亮点它无需编写Android代码。安装与准备在手机安装pfodApp付费应用。在电脑或安卓设备上安装免费的pfodGUIdesigner应用。设计布局打开pfodGUIdesigner新建一个绘图。用线条工具勾勒出你家的房间平面图轮廓并留出窗户的位置。为每个窗户画一条短线段代表其“关闭”状态并务必将其标记为“Update”可更新元素并设置一个唯一的索引号如_update_idx_1。生成基础代码设计好“关闭”状态的布局后点击生成代码。你会得到一个文本文件其中包含Windows.h和Windows.cpp的代码段。用它们替换项目中原有的这两个文件。设计“打开”和“故障”状态重新打开pfodGUIdesigner在刚才的图纸上移动代表窗户的线段位置比如从窗框中间移到窗框边缘并改变其颜色如红色代表打开。再次生成代码。这次不要替换整个文件只复制新生成的void Windows::updateDwg()函数内容。合并状态逻辑在你的Windows.cpp文件中你会现在有两个updateDwg()函数。你需要手动将它们合并成一个并根据从BLE扫描器获取的每个窗户的实际状态来决定发送哪一组绘图指令位置和颜色。这需要你仔细对照代码中的索引号和你为每个传感器设置的LOCAL_NAME。合并后的函数结构如原项目所示是一系列if-else判断为每个窗户索引发送对应的图形指令。实操心得图形界面调试技巧在合并代码时最容易出错的是索引号与传感器名称的对应关系。一个清晰的调试方法是先在Web页面上确认所有传感器都能被正确识别。然后在Windows.cpp的updateDwg()函数里临时将所有窗户的绘图指令都固定为“打开”状态的红色上传代码。在pfodApp中查看所有窗户线都应该变红。然后再逐一修改将每个索引号与正确的传感器状态绑定。pfodApp有缓存如果界面没更新记得在连接页面清除缓存。4.3 常见问题排查与进阶优化4.3.1 BLE传感器失联显示BAD原因1距离过远或障碍物过多。BLE在室内穿墙能力有限特别是2.4GHz信号容易被混凝土墙、金属物体削弱。尝试调整网关位置或考虑增加中继器。原因2电池电量不足。虽然理论续航长但劣质电池或焊接时高温损伤可能导致实际容量下降。用万用表测量电池电压低于2.8V时应考虑更换。原因3广播冲突或环境干扰。如果家里有大量BLE设备可能存在信道拥堵。可以尝试在代码中修改传感器的广播间隔ADVERTISING_INTERVAL和广播持续时间ADVERTISING_DURATION略微增加间隔以减少冲突概率。4.3.2 雨水检测误报原因1阈值设置不当。在潮湿天气非下雨PCB表面可能凝结水汽导致电阻下降。适当提高wetcount阈值或增加迟滞范围。原因2PCB污染或腐蚀。雨水中的杂质长期积累会导致PCB走线腐蚀基线电阻发生变化。定期清洁PCB或考虑使用镀金工艺的PCB。这也是原项目作者建议探索光学雨量传感器的原因。原因3电气干扰。确保连接雨水传感器的屏蔽线接地良好且远离电源线等干扰源。可以在ADC输入引脚增加一个简单的RC低通滤波电路如1K电阻串联0.1uF电容对地。4.3.3 系统稳定性优化建议看门狗定时器在ESP32的loop()函数和关键任务中加入软件看门狗或使用硬件看门狗防止程序跑飞导致系统死机。错误日志利用ESP32的SPIFFS文件系统将重要的状态变化、传感器失联事件、重启记录等写入本地文件便于后期排查问题。OTA升级将分区方案改为支持OTA的版本这样以后修复bug或增加功能时可以直接通过网络远程更新固件无需拆机。功耗再优化传感器端如果对续航有极致要求可以进一步研究nRF52832的PPKPower Profiler Kit工具精确测量每一阶段的电流优化广播参数和睡眠模式配置。例如在窗户长时间处于静止状态时是否可以进一步延长广播周期这个项目从构思到实现最深的体会是“简单可靠”远比“功能繁多”重要。一个靠纽扣电池运行数年的传感器其价值在于你安装后就可以彻底忘记它直到它真正需要提醒你的时候。在调试过程中耐心和细致的测量如电压、ADC值、信号强度是成功的关键。希望这份详细的拆解能帮助你打造出属于自己的、稳定可靠的智能门窗雨感卫士。