DIY低成本智能传感器盒:集成温湿度、光照与可调焦PIR运动检测 1. 项目概述与核心价值在折腾智能家居的这些年里我越来越觉得最核心、最有趣的部分往往不是那些成品设备而是自己动手搭建的感知节点。一个能精准“感受”环境变化并能自主做出判断的小盒子才是智能系统的“眼睛”和“皮肤”。今天要分享的这个DIY项目就是一个集成了温湿度、光照和可调焦PIR运动检测的“全能型”传感器盒。它的核心目标很明确用极低的成本总价不到10美元打造一个可以嵌入天花板、通过网页远程查看数据、并能根据环境条件比如光线不足时触发外部设备如灯光、警报的智能感知单元。这个项目的独特之处在于它的“可调焦”PIR设计。市面上大多数运动传感器视角固定要么太广容易误报要么太窄容易漏报。我们通过一个3D打印的“眼球”结构让PIR传感器可以像摄像机镜头一样前后移动从而灵活调整监测区域的远近和大小。无论是想监控整个房间还是只想盯着门口那一小块区域都能轻松实现。结合温湿度和光照数据它就能做出更智能的决策例如“只有在晚上且检测到运动时才打开走廊灯”避免了白天无谓的触发。整个方案基于乐鑫ESP8266芯片的Wemos D1 mini开发板通过I2C总线优雅地连接了GY-21SI7021温湿度传感器和GY-302BH1750光照传感器代码则直接内嵌了Web服务器界面无需复杂的文件系统上传。无论你是刚接触物联网的爱好者还是想为特定场景定制传感器的开发者这个项目都能提供一个清晰、完整且极具性价比的实现路径。2. 硬件选型与设计思路解析2.1 核心控制器为什么是Wemos D1 mini在众多物联网开发板中选择Wemos D1 mini几乎是性价比和易用性的最优解。它基于ESP8266自带Wi-Fi功能这意味着我们的传感器盒无需额外模块就能联网。其丰富的GPIO口11个足以应对本项目需求而且价格极其低廉通常在2-3美元左右。更重要的是它拥有庞大的Arduino兼容库和社区支持开发门槛极低。对于这个需要运行一个轻量级Web服务器的应用来说ESP8266的处理能力和内存80MHz主频约80KB用户可用RAM完全够用。注意购买时建议选择正品或口碑较好的版本有些劣质板子的Wi-Fi天线性能或稳压电路不稳定可能导致设备频繁掉线或重启。2.2 传感器三剑客精度、成本与接口的平衡温湿度传感器GY-21 (SI7021)SI7021是一款工业级的数字温湿度传感器精度高湿度±3%RH温度±0.4°C响应快并且自带工厂校准。相比常见的DHT11/DHT22它的I2C接口通信更可靠抗干扰能力更强代码也更简洁。虽然单价稍高约1.5-2美元但对于需要稳定数据的家庭环境监测来说这笔投资非常值得。光照传感器GY-302 (BH1750)BH1750是一款专门用于环境光强度检测的数字传感器它直接输出光照度值单位勒克斯Lux无需我们进行复杂的模拟量计算和校准。其光谱响应接近人眼测量范围广1-65535 Lux且通过I2C通信。选择它可以让我们轻松判断是白天、夜晚还是阴天为自动化逻辑提供关键输入。运动传感器HC-SR505 / AS-312 微型PIRPIR被动式红外传感器通过检测人体发出的红外热辐射变化来感知运动。HC-SR505或AS-312这类“微型”版本体积小巧非常适合嵌入我们的迷你盒中。它们通常输出数字信号检测到运动时输出高电平并且自带延时调节和光敏电阻可设置白天不触发。但它们的视角是固定的约120度圆锥形。这就是我们设计“可调焦”机械结构的原因——通过物理方式改变传感器在“眼球”内的前后位置实质上是调整了红外菲涅尔透镜的有效探测距离和角度实现了“调焦”效果。接口统一策略I2C总线将GY-21和GY-302都挂载在I2C总线上SDA, SCL是简化布线、节省GPIO口的最佳实践。I2C只需要两根数据线就可以连接多个设备每个设备有唯一地址。这使得我们主控板与传感器之间的连接非常整洁只有4根线VCC, GND, SDA, SCL。2.3 机械结构设计嵌入式安装与可调焦实现整个外壳设计为圆柱形直径适配标准的天花板开孔40x65mm矩形孔实际是嵌入60mm圆形开孔更常见实现隐蔽式安装。结构分为几个核心部件主壳体与上盖容纳Wemos主板和接线。传感器管固定温湿度和光照传感器确保其感应面朝下暴露在环境中。“眼球”组件Ball这是可调焦的核心。包含球型外壳SensorBall、球座BallMount和球框BallFrame。PIR传感器被固定在这个“眼球”内部。调焦原理球框通过螺丝固定在主壳体上但螺丝不拧死让球座能在框内有一定阻尼地转动。PIR传感器则通过一个单独的M3螺丝锁定在球座内的滑轨上。松开这颗螺丝就可以将PIR传感器在球座内前后滑动。向前推靠近球面探测角度变窄距离变远适合监控远处小区域如门口向后拉远离球面探测角度变宽距离变近适合监控近处大范围如房间中央。这种纯机械的调焦方式比寻找不同视角的透镜或更换传感器要灵活和低成本得多。3. 电路连接与焊接实操要点3.1 准备万用板与规划布局取一块约25x35mm的洞洞板万用板这将成为我们的小型“母板”。布局规划是关键Wemos D1 mini应放置在板子中央或一侧方便引出引脚。I2C传感器可以放置在另一侧它们的VCC、GND、SDA、SCL可以并联。PIR传感器的线需要留得稍长一些因为它最终要连接到可活动的“眼球”部件上。预留外部触发接口例如连接继电器的GPIO口和5V电源输入接口。先在纸上画个简图确定各个元件的相对位置和走线方向能避免后续焊接时手忙脚乱。3.2 详细接线图与焊接步骤以下是各模块连接到Wemos D1 mini的引脚定义模块引脚连接到 Wemos D1 mini说明GY-21 (SI7021)VCC3.3V绝对不要接5V会烧毁传感器。GNDGND公共地线。SDAD2 (GPIO4)I2C数据线。SCLD1 (GPIO5)I2C时钟线。GY-302 (BH1750)VCC3.3V同上接3.3V。GNDGND与GY-21共地。SDAD2 (GPIO4)与GY-21的SDA并联。SCLD1 (GPIO5)与GY-21的SCL并联。HC-SR505 PIRVCC5VPIR模块工作电压通常是5V。GNDGND公共地线。OUTD5 (GPIO14)运动信号输出可自定义其他数字引脚。外部继电器 (可选)IND6 (GPIO12)用于控制灯光/警报的信号引脚。VCC/GND接继电器模块电源注意继电器模块与Wemos共地。焊接流程固定Wemos首先将排母焊接到洞洞板上然后将Wemos D1 mini插入。或者直接将Wemos的引脚焊死在板子上不推荐不利于更换。建立电源轨用焊锡走线或杜邦线在板子上建立一条稳定的3.3V电源线和一条GND地线。焊接I2C传感器将GY-21和GY-302的VCC、GND分别连接到电源轨。将它们的SDA和SCL分别并联然后引线到Wemos的D2和D1。建议使用4.7KΩ的上拉电阻分别接在SDA和SCL到3.3V的线上以确保I2C通信稳定尤其在导线较长时。焊接PIR将PIR传感器的三条线VCC, GND, OUT焊接好并通过较长的杜邦线引出以便后续连接到“眼球”部件。焊接外部接口焊接好电源输入端子如DC插座或接线端子和用于触发继电GPIO引脚如D6。检查与测试焊接完成后务必用万用表通断档检查是否有短路特别是VCC和GND之间。确认无误后先不要装入外壳通电进行初步测试。3.3 初次上电与基础测试将USB线连接到Wemos D1 mini打开Arduino IDE的串口监视器波特率115200。如果代码已上传见下一章你应该能看到Wi-Fi连接信息和传感器数据打印。如果没有代码可以上传一个简单的测试程序分别读取I2C设备地址使用Wire库的扫描示例程序确认GY-21地址0x40和GY-302地址0x23都被正确识别。同时用手在PIR传感器前晃动观察其信号输出引脚用万用表电压档或接个LED测试是否从低电平跳变为高电平。实操心得焊接I2C总线时最怕的就是虚焊或短路。一个很好的习惯是每焊接完一个连接点都用万用表测一下。先确保所有GND点之间电阻为0导通所有VCC点之间电压一致。I2C通信失败十有八九是上拉电阻没接或接错或者SDA/SCL线接反了。4. 固件开发与Web服务器实现4.1 开发环境搭建与库依赖首先确保你的Arduino IDE已安装ESP8266开发板支持。在“文件”-“首选项”的“附加开发板管理器网址”中添加http://arduino.esp8266.com/stable/package_esp8266com_index.json。然后在“工具”-“开发板”-“开发板管理器”中搜索安装“esp8266”。本项目需要以下库可通过“项目”-“加载库”-“管理库”搜索安装Wire用于I2C通信通常已内置。Adafruit_SI7021用于驱动GY-21温湿度传感器。BH1750用于驱动GY-302光照传感器。ESP8266WiFi和ESP8266WebServer用于Wi-Fi连接和创建Web服务器已包含在ESP8266板支持包中。4.2 代码结构深度解析与原作者将HTML嵌入代码的方式一致我们采用此方法以简化部署。整个.ino文件逻辑清晰头文件与定义包含必要的库定义传感器对象、网络凭证SSID和密码、Web服务器对象、以及各功能引脚。#include Wire.h #include Adafruit_SI7021.h #include BH1750.h #include ESP8266WiFi.h #include ESP8266WebServer.h const char* ssid 你的Wi-Fi名称; const char* password 你的Wi-Fi密码; Adafruit_SI7021 tempHumidSensor Adafruit_SI7021(); BH1750 lightMeter; ESP8266WebServer server(80); // 在80端口启动服务器 const int pirPin D5; // PIR运动信号输入 const int relayPin D6; // 控制继电器的输出可选 bool motionDetected false; unsigned long lastMotionTime 0; const long motionTimeout 10000; // 运动状态保持10秒 const long sensorUpdateInterval 10000; // 传感器数据更新及网页自动刷新间隔 unsigned long previousMillis 0;HTML界面内嵌在setup()函数之前用一个长字符串变量存储整个HTML页面代码。这里使用了Font Awesome图标库的CDN链接来美化界面。页面包含一个简单的表格用于显示传感器数据和一个显示运动状态的区域。关键是一段JavaScript代码setTimeout(function(){ location.reload(); }, 10000);它实现了每10秒自动刷新页面。const char INDEX_HTML[] PROGMEM Rrawliteral( !DOCTYPE htmlhtmlheadmeta name\viewport\ content\widthdevice-width, initial-scale1\ link rel\stylesheet\ href\https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css\ stylebody {font-family: Arial; text-align: center; margin: 40px;} .sensor {margin: 20px; padding: 20px; background: #f2f2f2; border-radius: 10px; display: inline-block;}/style title智能传感器盒/title/headbody h1i class\fas fa-home\/i 天花板传感器盒监控/h1 div class\sensor\h2i class\fas fa-thermometer-half\/i 环境数据/h2 p温度: %TEMPERATURE% °C/pp湿度: %HUMIDITY% %%/pp光照: %LIGHT% Lux/p/div div class\sensor\h2i class\fas fa-running\/i 运动状态/h2 p状态: %MOTION%/ppsmall%LASTTRIGGER%/small/p/div scriptsetTimeout(function(){ location.reload(); }, 10000);/script /body/html )rawliteral;setup()函数初始化串口、连接Wi-Fi、初始化传感器、配置引脚模式、启动Web服务器并绑定处理函数。void setup() { Serial.begin(115200); delay(100); Serial.println(\n启动中...); // 连接Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(\nWi-Fi连接成功!); Serial.print(IP地址: ); Serial.println(WiFi.localIP()); // 初始化传感器 if (!tempHumidSensor.begin()) { Serial.println(未找到SI7021传感器); while (1); } lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE); // 引脚模式 pinMode(pirPin, INPUT); pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); // 初始关闭继电器 // 设置Web服务器路由 server.on(/, handleRoot); // 当访问根目录时调用handleRoot函数 server.begin(); Serial.println(HTTP服务器已启动); }loop()函数持续处理客户端请求并周期性更新传感器数据和检查运动状态。void loop() { server.handleClient(); // 处理来自浏览器的请求 unsigned long currentMillis millis(); // 定期更新传感器读数 if (currentMillis - previousMillis sensorUpdateInterval) { previousMillis currentMillis; updateSensorData(); // 自定义函数读取传感器值并存入全局变量 } // 检查PIR状态 int pirState digitalRead(pirPin); if (pirState HIGH) { if (!motionDetected) { motionDetected true; lastMotionTime currentMillis; Serial.println(检测到运动); // 在这里添加触发动作例如digitalWrite(relayPin, HIGH); // 可以加入条件判断如 if (lightLevel 50) { ... } } } else { // 如果超过超时时间未检测到新运动则重置状态 if (motionDetected (currentMillis - lastMotionTime motionTimeout)) { motionDetected false; Serial.println(运动状态重置。); // 关闭触发例如digitalWrite(relayPin, LOW); } } }请求处理与页面生成handleRoot()函数在每次浏览器访问时被调用。它读取最新的传感器数据和运动状态然后用这些值替换HTML模板中的占位符如%TEMPERATURE%生成动态页面发送给浏览器。void handleRoot() { String html String(INDEX_HTML); html.replace(%TEMPERATURE%, String(lastTemperature, 1)); html.replace(%HUMIDITY%, String(lastHumidity, 1)); html.replace(%LIGHT%, String(lastLight)); html.replace(%MOTION%, motionDetected ? span stylecolor:red;i classfas fa-exclamation-circle/i 活动中/span : span stylecolor:green;i classfas fa-check-circle/i 静止/span); // 可以添加最后触发时间的格式化显示 server.send(200, text/html, html); }4.3 条件触发逻辑的定制化这是项目智能化的核心。代码中注释提到的“条件触发”逻辑可以在PIR检测到运动pirState HIGH后的处理块中实现。例如实现一个“仅在低光照时开灯”的功能if (pirState HIGH) { if (!motionDetected) { motionDetected true; lastMotionTime currentMillis; Serial.println(检测到运动); // 条件触发示例光照低于50 Lux时打开继电器灯 if (lastLight 50) { digitalWrite(relayPin, HIGH); Serial.println(光照不足已触发继电器。); } } }你可以扩展更多条件比如在特定时间段内、当温度高于某个阈值时触发警报等。所有逻辑都在loop()函数中完成无需复杂的云端规则引擎。注意事项嵌入式设备上的逻辑应尽量保持简单、健壮。避免使用delay()函数它会阻塞整个循环导致Web服务器无响应。所有定时和状态判断都应使用millis()进行非阻塞式处理如上例所示。5. 机械组装与调焦校准全流程5.1 3D打印件处理与准备使用提供的STL文件进行打印。参数建议如下层高0.2mm在打印速度和表面质量间取得平衡。填充15%-20%足够结构件不需要高密度填充。壁厚/外壳数至少2层保证强度。材料PLA即可它易于打印、无异味、强度足够。如果设备安装在可能受热的位置如阁楼可考虑使用耐热性更好的PETG。支撑根据模型设计所有部件应无需支撑即可打印这能节省材料和时间。打印完成后仔细清除所有部件的毛边和拉丝特别是螺丝孔和滑动轨道部分确保活动部件顺滑。5.2 分步组装指南组装“眼球”组件将SensorBall球体放入BallMount球座中。用BallFrame球框盖住球座对齐四个螺丝孔。使用四颗M3x12mm螺丝将球框固定到主壳体上。关键技巧不要一次性将四颗螺丝拧紧。先都带上然后交替、逐步拧紧同时不断转动球体直到球体能在球框内转动但带有明显的阻尼感不会自行滑动为止。这个阻尼力是保持调焦后位置的关键。安装固定传感器将GY-21温湿度和GY-302光照传感器放入SensorHousingTube传感器管的指定卡槽内。确保GY-21的透气孔朝外GY-302的光敏元件朝下。用少量热熔胶固定传感器底部。注意胶不要堵住GY-21的透气孔也不要覆盖GY-302的感光窗。将传感器管插入主壳体底部的对应孔位通常会有一个卡扣或螺丝固定位。安装与调焦PIR传感器将PIR传感器从球座后部开口塞入SensorBall内部。通常球体内部会设计有导轨或卡槽。暂时不要拧紧固定PIR的M3x6mm螺丝。此时将整个传感器盒通电。打开串口监视器或者让助手观察Web界面上的运动状态。你可以在PIR传感器前方移动同时缓慢地将传感器在球体内前后滑动。向前推透镜更靠近球面开口你会感觉到监测区域变远、变窄向后拉区域变近、变宽。找到一个能覆盖你期望监控区域的最佳位置。位置确定后小心地拧紧那颗M3x6mm螺丝将PIR传感器锁定。注意螺丝不要拧得过紧以免压坏传感器或导致球体变形。最终集成将焊接好的Wemos主板小心地滑入HousingCover上盖内侧的卡槽中。整理好所有线缆避免缠绕或过度弯折尤其是PIR的引线。将上盖与主壳体底座对齐使用四颗M3x4mm螺丝固定。最后连接5V电源可以是手机充电器Micro USB线或者接一个5V的直流电源适配器。5.3 安装部署与指向调整在预定安装位置如天花板开一个直径约60mm的圆孔。将传感器盒从下往上推入孔中通常外壳会设计有卡扣或凸缘使其能卡在天花板内部。接通电源。现在通过转动整个“眼球”组件球座球体可以将PIR的监测方向对准你需要监控的区域例如门口、走廊、工作台。由于我们已经调好了焦这个方向上的监测范围就是确定的。通过网页界面你可以实时确认安装效果。6. 常见问题排查与优化技巧6.1 上电与连接问题问题现象可能原因排查步骤与解决方案上电无反应电源问题主板损坏。1. 用万用表测量电源输入端电压是否为稳定的5V。2. 检查USB线或电源线是否完好。3. 观察Wemos板载LED是否微亮。串口无输出串口波特率不对TX/RX线接错如果外接芯片未启动。1. 确认Arduino IDE中串口监视器波特率为115200。2. 尝试按一下Wemos的RST复位键。3. 换一个USB口或电脑尝试。无法连接Wi-FiSSID/密码错误信号太弱路由器设置限制。1. 检查代码中ssid和password是否正确注意大小写。2. 将设备靠近路由器测试。3. 查看路由器是否开启了MAC地址过滤或仅允许特定设备连接。能连Wi-Fi但无法访问网页Web服务器未启动IP地址错误防火墙阻挡。1. 查看串口日志确认“HTTP服务器已启动”信息。2. 在串口日志中找到正确的IP地址在浏览器中用http://[IP地址]访问而非sensorbox该域名需要局域网DNS支持。3. 检查电脑防火墙或杀毒软件是否阻止了本地网络访问。6.2 传感器数据异常问题现象可能原因排查步骤与解决方案所有I2C传感器读取失败I2C总线接线错误电源问题上拉电阻缺失。1. 用万用表检查SDA、SCL对地电压正常应在3.3V左右波动。若无电压检查上拉电阻。2. 运行I2C扫描程序确认是否能扫描到设备地址SI7021: 0x40, BH1750: 0x23。3. 确保传感器VCC接的是3.3V不是5V。温湿度读数固定或离谱SI7021传感器损坏或接触不良代码库不匹配。1. 重新插拔传感器检查焊点是否虚焊。2. 尝试使用Adafruit SI7021库的示例代码单独测试传感器。3. 确保安装了正确版本的Adafruit_SI7021库。光照读数始终为0或65535BH1750模式设置错误感光窗被遮挡。1. 检查代码中初始化语句lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);。2. 确保传感器表面的透明保护膜已撕掉且没有胶水遮挡。3. 尝试更换为BH1750::CONTINUOUS_HIGH_RES_MODE_2或ONE_TIME模式测试。PIR一直触发或不触发调焦不当安装环境干扰传感器延时调节旋钮设置。1. 重新进行调焦校准避免对准热源暖气、窗户阳光直射、通风口或宠物常活动区域。2. 检查PIR模块上的两个旋钮一个调节灵敏度SEN一个调节触发后保持时间TIME。可适当调低灵敏度或缩短保持时间。3. 在代码中增加去抖动逻辑例如连续检测到高电平超过500ms才判定为有效触发。6.3 系统稳定性与功能优化电源稳定性如果使用劣质USB电源或长距离供电电压波动可能导致ESP8266重启。建议在电源输入端并联一个100-470μF的电解电容以平滑电压。看门狗与异常重启ESP8266内置软件看门狗WDT但复杂的逻辑或阻塞操作可能导致其复位。可以在loop()函数开头添加ESP.wdtFeed();来喂狗。对于更严重的故障可以考虑使用硬件看门狗芯片。Web界面优化当前的界面每10秒全页刷新虽然简单但不够优雅。可以学习使用AJAX技术仅让网页后台定时如每秒向设备请求JSON格式的传感器数据然后动态更新页面局部内容实现无刷新更新。这需要将HTML和JavaScript分离并编写额外的API处理函数如server.on(/api/data, handleApiData)。数据持久化与上报本地网页查看适合调试和局域网访问。若想远程查看或记录历史数据可以将数据通过MQTT协议发布到本地服务器如Home Assistant, Node-RED或云平台需注意安全与合规。这需要引入PubSubClient等MQTT库。降低功耗本项目为常供电设计。如果想用电池需要大幅修改使用深度睡眠模式Deep Sleep让ESP8266大部分时间休眠仅定时唤醒读取传感器或由PIR中断唤醒发送数据后再次休眠。同时需选择低功耗的传感器版本并关闭无关电路。这个DIY传感器盒项目从构思到实现贯穿了硬件选型、电路设计、嵌入式编程和机械结构几个方面。它最吸引我的地方在于用很低的成本和清晰的思路解决了一个实际需求——获得一个可定制、可精准调整的智能感知节点。在实际部署中你可能需要根据自家天花板厚度调整外壳尺寸或者为了美观给外壳喷上漆。调试阶段耐心是关键尤其是调焦和排除环境干扰。当你在手机浏览器里看到实时刷新的环境数据并且灯光能随着你的走动自动亮起时那种成就感是购买任何成品设备都无法替代的。