1. 方案整体设计与选型思路
做智能家居这几年,我经手过不少方案,从最早的单片机+继电器、到用ESP8266做远程控制、再到现在这套ESP32双协议栈方案,中间踩过的坑比写的代码还多。先说结论:如果你的项目需要同时兼顾WiFi联网和BLE低功耗设备接入,用ESP32做一站式方案是目前性价比最高、开发效率最稳的路线,没有之一。
1.1 为什么是ESP32而不是“ESP8266+独立BLE芯片”
很多新手第一次接触智能家居,第一反应是用ESP8266,毕竟便宜,几块钱一块板子。但ESP8266只有WiFi,没有BLE。你做个灯泡开关、插座没问题,可一旦涉及温湿度传感器、门磁、人体红外这类电池供电的节点,ESP8266就尴尬了——WiFi协议的功耗摆在那,一块18650电池撑死跑几天,根本没法做低功耗节点。
有人会说,那我再外挂一颗BLE芯片不就行了?技术上确实可以,比如ESP8266加一颗nRF52832,但工程上你会立刻遇到三个麻烦:第一,板子面积翻倍,天线布局互相干扰,信号调试想哭;第二,双芯片之间串口通信要自己设计协议,主从握手、数据重传、异常恢复全得自己写;第三,成本翻倍,开发周期拉长,完全不划算。
ESP32最核心的价值就是一颗芯片同时集成了WiFi和BLE两套协议栈,硬件上共用一颗2.4G天线,软件上乐鑫已经帮你把协议栈调度和共存处理好了。你直接用Arduino库或者ESP-IDF就能调双模,不用操心底层射频切换的问题。而且ESP32的价格现在已经卷到十几块钱,比很多单独的BLE芯片还便宜。
我在实际项目里测试过,ESP32同时开启WiFi STA模式连接路由器、BLE广播扫描周围设备,CPU占用和内存都还有富余,跑MQTT加简单的传感器逻辑完全没问题。这个“一颗芯片搞定所有连接”的特性,才是“一站式”三个字的底气。
1.2 智能家居场景里的WiFi和BLE到底各自负责什么
我见过不少开发者的误区是把WiFi和BLE一视同仁,觉得两个协议都要能做所有事,结果代码写得臃肿不说,功耗和稳定性都崩了。实际在智能家居系统里,这两个角色分工非常明确。
WiFi负责的是“长连接、大数据量、云端交互”这条线:设备接入你家路由器,通过MQTT协议连接本地Home Assistant或者云平台,上报状态、接收控制指令、做OTA固件升级、同步日志时间校准等等。它的优势是传输距离远、穿墙能力强、带宽大,缺点是功耗高,所以只适合常供电的设备,比如智能插座、墙壁开关、网关主机、带电源的传感器。
BLE负责的是“短连接、低功耗、快速配对”这条线:门磁传感器、温湿度探头、人体存在传感器、智能门锁、遥控器这类电池供电的节点,平时深度睡眠,醒来广播一次数据,或者等手机靠近了建立GATT连接传数据。BLE的功耗比WiFi低一到两个数量级,一颗钮扣电池撑半年到一年是常态。
还有一个非常实用的职责分配:用BLE做配网。配网这个词对新手来说可能有点抽象,其实就是“让设备知道你家的WiFi账号密码”。传统做法是手机开热点让设备连接,再通过网页配置,过程繁琐。而ESP32可以在出厂时先开启BLE广播,手机App扫描到设备后,通过BLE直接把WiFi账号密码写进设备NVS存储区,设备再自动切到WiFi模式连网。整个配网过程10秒搞定,用户体验完全不同。
1.3 主流连接架构的横向对比
| 方案类型 | WiFi | BLE | 功耗 | 成本 | 适合场景 |
|---|---|---|---|---|---|
| ESP8266 单WiFi | 有 | 无 | 高 | 低 | 常供电插座、灯控 |
| STM32+外挂BLE | 无 | 有 | 低 | 高 | 纯低功耗传感器 |
| STM32+ESP8266+BLE | 有 | 有 | 中 | 高 | 网关类产品 |
| ESP32 双协议栈 | 有 | 有 | 中 | 低 | 一站式智能家居 |
我自己在做的这套方案用的就是ESP32双模,核心思路是:空气温湿度计、门窗传感器这些电池节点用BLE广播数据,客厅的网关用ESP32同时开WiFi和BLE,WiFi连路由器上报到MQTT,BLE负责收集周围节点数据并转发。这样网关既是WiFi终端,又是BLE中心。节点只跑BLE,功耗极低;网关常供电,功耗高点无所谓。这种架构下,整个系统只需要一种主控芯片,开发维护成本最省。
2. 开发环境与硬件准备
方案定了之后,第二步就是把手头的东西备齐。ESP32开发板型号多,不少新手在这里就绕晕了,什么ESP32、ESP32-S3、ESP32-C3,长得差不多,实际用起来差得挺远。
2.1 芯片型号怎么选,各有什么坑
ESP32原版(经典款)用的是双核Xtensa LX6,集成WiFi和BLE 4.2,性能和兼容性最均衡,Arduino库、ESP-IDF、各种开源项目基本都是优先适配它,新手入门买这个最稳。缺点是功耗相对高一点,而且2024年以来乐鑫一直在推新芯片,原版ESP32的库存和价格有波动,采购的话要留意。
ESP32-S3是后起之秀,加了向量指令、更大的SRAM、USB原生支持,BLE升级到5.0,WiFi性能也更好。S3最大的变化是取消了传统蓝牙BR/EDR,只保留BLE,但做智能家居完全够用,毕竟没人用ESP32连老式蓝牙耳机。S3的AI加速能力对小度、语音唤醒这类场景有优势,如果你要做带语音助手的智能家居终端,S3是首选。
ESP32-C3是RISC-V单核的低成本方案,主打性价比和低功耗,同样支持WiFi和BLE5.0。它只有单核160MHz,很多初学者担心性能不够,实际测试跑MQTT加传感器轮询、BLE广播这些常规活完全能够胜任,价格还比原版便宜不少。缺点是单核跑太多任务时容易被各种回调抢占,代码里别搞太多忙等循环。
我最近的项目里网关用ESP32-S3,传感器节点用ESP32-C3,整体成本和功耗表现都满意。如果是刚入门,直接买ESP32-AITHINKER的DevKit或者合宙ESP32-C3开发板,几十块钱,折腾坏了不心疼。
2.2 Arduino开发环境配置与国内源加速
开发环境我推荐Arduino IDE或Visual Studio Code加PlatformIO插件,看个人习惯。用Arduino IDE的话,有个关键步骤很多人卡住:在“首选项-附加开发板管理器网址”里添加乐鑫的JSON地址:
https://espressif.github.io/arduino-esp32/package_esp32_index.json添加后,在“开发板管理器”里搜索esp32,安装最新版。但这里有个国内用户绕不开的痛点——乐鑫的服务器在国外,直接下载经常十几KB/s,装到一半超时失败。解决办法有两个:一是用国内镜像源(比如一些高校或云厂商提供的esp32包镜像),把上面的URL替换成可用的镜像地址;二是在Gitee或网盘上找别人整理好的esp32 arduino完整离线包,Windows版解压后直接拷进Arduino的hardware目录,比在线安装省心得多。
装好之后别忘了装USB转串口驱动。ESP32开发板用的串口芯片有两种常见方案:CP2102和CH340。Win10以上系统一般能自动识别,如果设备管理器里看不到COM口,去官网下载对应驱动手动安装,问题立刻解决。
2.3 烧录方式的坑,第一次必踩
烧录失败是ESP32新手最容易崩溃的时刻。现象是Arduino IDE编译成功,但提示“Connecting.............”然后报错A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header。
这个问题的原因九成是开发板没有进入下载模式。ESP32不像STM32那样需要手动拉BOOT0,它通过串口工具在特定时序下拉低IO0引脚来进入下载模式。实际操作时,按住开发板上的BOOT键(有的板子标的是IO0),点Arduino的上传按钮,看到“Connecting”字样出现时松开BOOT键,基本就能烧进去。如果开发板没有BOOT键,可以用杜邦线把IO0引脚和GND短接,上电进入下载模式,烧完断电复位。
另一个常被忽略的点是波特率。ESP32开发板默认烧录波特率是921600,如果你的USB转串口芯片质量一般或者线太长,容易丢包。遇到反复失败,把Tools里的Upload Speed改成115200,成功率会明显提升。
3. WiFi功能实现:联网稳定才是硬道理
WiFi作为智能家居的主干网络,最核心的诉求是“稳定”。很多入门项目灯光控制都做通了,一上线就掉线,每隔几个小时断一次,根子都在WiFi这部分没处理好。
3.1 STA模式连接路由器的正确姿势
最基础的连接代码很简单:
#include <WiFi.h> const char* ssid = "YourSSID"; const char* password = "YourPassword"; void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Connected!"); }但这段代码直接用在生产环境会出问题:如果路由器重启、WiFi信号暂时丢失、或者路由器换了信道,WiFi.begin()内部的自动重连机制往往不能可靠地恢复连接。我建议自己做一层连接状态检测,放主循环里:
void WiFiKeepAlive() { if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi disconnected, reconnecting..."); WiFi.disconnect(); WiFi.reconnect(); int retries = 0; while (WiFi.status() != WL_CONNECTED && retries < 20) { delay(500); retries++; } } }实测下来,与其依赖SDK内部的重连线程,不如自己定时检测。一般每5秒检测一次就够了,检测太频繁反而会拖累BLE的任务调度。另外,如果开发板有天线,注意天线附近不要被金属外壳完全遮挡,有些人把ESP32塞进金属配电箱里,WiFi信号直接衰减到不可用,这不是代码能解决的问题。
3.2 配网机制:从AP配网到BLE配网
设备第一次上电没有WiFi凭据时,需要一个“告诉它你家WiFi密码”的过程。常见的方案有三种,我按推荐程度排一下。
SmartConfig(ESP-Touch)是乐鑫原生的配网方式:手机App通过UDP广播把WiFi广播包里的SSID和密码编码发出去,ESP32在混杂模式下监听并解码。优点是用户操作简单,不用切换热点;缺点是对路由器的AP隔离、广播隔离设置比较敏感,有些商用路由器环境会失败。
SoftAP配网是最传统的方式:设备自己开一个WiFi热点,手机连上这个热点,然后访问192.168.4.1网页,在网页表单里输入家里WiFi的账号密码。优点是兼容性极好,任何手机浏览器都能操作;缺点是流程略繁琐,而且设备开热点的时候发给它的数据不加密,如果在意安全就需要加一层鉴权。
BLE配网是这几年智能家居产品的主流方式:设备上电后开启BLE广播,手机App扫描到设备,建立BLE GATT连接,把WiFi账号密码通过一个自定义特征写入。流程快、体验好、支持加密,前提是手机端要做App开发。ESP32做BLE配网的核心代码涉及创建GATT服务,建议参考ESP32 BLE库中的GATT server示例,把配网用的服务和正常业务数据的服务分开定义,配网完成后通过标志位切换整个协议栈的工作模式。
我目前的主力方案是BLE配网优先,AP配网兜底。两条路都可以把WiFi凭据写入Preferences(NVS)存储区,下次上电直接读取,无需重复配网。
3.3 MQTT接入:智能家居的数据总线
WiFi通了,下一步就是让设备接入智能家居控制中枢。我强烈推荐MQTT协议,它专门为物联网设备设计,发布订阅模型天然适合多设备联动,而且已经成了智能家居事实上的标准协议,Home Assistant、Node-RED、各种云平台都原生支持。
ESP32端的Arduino库有PubSubClient,用法非常简洁:
#include <PubSubClient.h> #include <WiFi.h> WiFiClient espClient; PubSubClient mqttClient(espClient); void callback(char* topic, byte* payload, unsigned int length) { String message = ""; for (int i = 0; i < length; i++) { message += (char)payload[i]; } if (String(topic) == "home/livingroom/switch1/set") { // 控制逻辑 } } void setup() { mqttClient.setServer("192.168.1.100", 1883); mqttClient.setCallback(callback); mqttClient.connect("esp32_gateway_01"); mqttClient.subscribe("home/livingroom/switch1/set"); }主题规划是个容易被忽视但是极其重要的设计点。我的习惯是统一用“home/区域/设备类型/设备名/属性”的结构,比如温湿度上报主题是home/livingroom/sensor/temp_humi/state,控制灯的主题是home/livingroom/light/desk/set。这样在MQTT客户端里过滤主题时非常方便,Home Assistant自动发现功能也要求类似的层级规范。
MQTT客户端的连接稳定性同样不能马虎。最好每隔几秒检查一下mqttClient.connected()状态,掉线就自动重连。另外,发布频率不要无脑设成100ms一次,一是路由器受不了,二是没必要,温度和湿度这类数据10秒上报一次已经非常及时。
4. BLE功能实现:低功耗节点的数据入口
BLE在智能家居方案里承担的角色,我前面说了有两块:一是配网,二是低功耗节点的数据采集和广播。这里重点讲后者。
4.1 BLE广播与服务:让传感器“开口说话”
BLE的通信模式有两种:广播模式和连接模式。广播模式最简单,设备周期性向外发送一小段数据包,旁边任意扫描设备都能收到;连接模式需要建立GATT连接,适合双向控制和数据量更大一点的应用。
对电池供电的温湿度传感器来说,广播模式是最优解。一个温湿度数据就几个字节,根本不需要建立连接,广播包塞得下。代码层面可以用BLE库的Advertising功能:
#include <BLEDevice.h> #include <BLEServer.h> BLEAdvertising* pAdvertising; void setupBLE() { BLEDevice::init("TempHumi_Node_01"); pAdvertising = BLEDevice::getAdvertising(); // 自定义广播数据:把温湿度编码进manufacturer data pAdvertising->start(); } void loop() { float temp = readTemperature(); float humi = readHumidity(); // 更新广播数据并重启广播 pAdvertising->stop(); // 设置新的manufacturer data pAdvertising->start(); delay(10000); // 10秒广播一次 }BLE广播的最大好处是功耗极低。广播完了立刻让ESP32进入深度睡眠(esp_deep_sleep),定时5分钟醒一次采集数据、广播一次、再睡回去,平均电流能做到几十微安。这个级别用两节AA电池供电,跑一年完全可行。
如果需要双向通信,比如手机要远程读取传感器历史数据、或者给节点下发配置参数,就需要GATT服务了。GATT服务的核心概念是服务和特征:一个服务包含若干特征,每个特征有UUID、权限和值。通常的做法是创建一个自定义服务UUID(比如4fafc201-1fb5-459e-8fcc-c5c9c331914b),服务里放一个温度特征、一个湿度特征、一个配置特征。手机或者BLE调试助手通过读写这些特征来交互数据。我用过nRF Connect和LightBlue这两个工具检查ESP32的广播和服务信息,调试阶段帮了大忙。
4.2 WiFi和BLE共存的协处理
这是ESP32双协议栈方案里最有技术含量的一环。WiFi和BLE共用同一根2.4G天线和同一个射频前端,芯片内部通过时分复用机制来协调,但开发者如果乱用会导致串扰和卡顿。
我自己遇到过一个典型问题:WiFi连接状态下,BLE广播一启动,WiFi丢包率明显上升。排查原因是BLE广播的功率设得太高,而且广播间隔太短,射频频繁抢占信道。解决办法是把广播间隔拉大到100ms以上,降低广播发射功率,实测丢包率恢复正常。代码里用如下参数:
esp_ble_adv_params_t advParams = {}; advParams.adv_int_min = 0x100; // 约200ms advParams.adv_int_max = 0x100;另外一个容易被忽略的点是CPU频率。ESP32默认可能跑在240MHz,够用。但如果你把CPU频率调低到80MHz或者160MHz来省电,同时开WiFi和BLE的话,协议栈的处理时间会被拉长,可能出现蓝牙回调卡顿。建议这类双模应用直接锁定240MHz,或者至少160MHz。
还有内存分配问题。ESP32的BLE协议栈和WiFi协议栈各自都要占不少RAM,默认的Arduino环境里如果你同时启用,可能导致堆内存不足、设备随机重启。遇到这种情况,用esp_bt_mem_release(ESP_BT_MODE_BTDM)释放不用的传统蓝牙BR/EDR内存,或者调整BLE协议栈的日志等级和并发连接数上限,都能挤出不少空间。
4.3 低功耗设计:把电池寿命拉满
做电池供电节点,低功耗是绕不开的功课。ESP32本身不算低功耗芯片,但通过合理设计深度睡眠模式,还是能实现可用水平的续航。
核心思路是:平时深度睡眠,定时器唤醒来干活。代码大致这样:
esp_sleep_enable_timer_wakeup(5 * 60 * 1000000ULL); // 5分钟唤醒一次 esp_deep_sleep_start(); // 进入深度睡眠深度睡眠模式下,WiFi和BLE协议栈都停止工作,电流可以降到10uA左右。但注意GPIO引脚的状态,某些引脚在睡眠时如果有外部上拉或下拉电阻,会产生额外漏电流。此外,板载稳压芯片(比如AMS1117)本身的静态电流也要算进去,这类LDO的自耗电可能比芯片的深度睡眠电流还大,所以电池供电方案尽量选择不带LDO的开发板,或者自己搭一个低静态电流的供电方案。
传感器读取和BLE广播本身也要优化,尽量减少工作时间。一次完整的“唤醒-读传感器-发送数据-再睡觉”流程应该控制在200ms以内,剩下的4分59秒都在深度睡眠里度过。
5. 实战:搭一套可用的WiFi+BLE智能家居原型
前面讲了一堆理论和细节,这一节把整个方案串起来,做一个能跑的完整原型。以最常见的客厅环境为例:一个温湿度监测节点、一个智能灯控开关、一个网关主机,这三个设备拼出一套小规模的智能家居系统。
5.1 硬件连接与传感器选型
温湿度传感器我推荐SHT30或BME280,用I2C接口通信,比DHT11可靠太多。DHT11便宜但精度差、响应慢,而且协议是私有的单总线,时序要求苛刻,用ESP32跑还容易受到中断干扰。SHT30是I2C接口,接线就四根线:VCC、GND、SCL、SDA,加两个4.7K上拉电阻。
接线示意:
- ESP32的GPIO21做SDA,GPIO22做SCL(这是默认的I2C引脚,别接错)
- VCC接3.3V,GND接GND
- SDA和SCL分别通过4.7K电阻上拉到3.3V
智能灯控简单一点,用GPIO13控制一个5V继电器模块,继电器常开触点串到灯泡回路里。注意ESP32的GPIO输出电压是3.3V,而有些继电器模块的驱动需要更高电压,选模块时确认是低电平触发的3.3V兼容版本。
5.2 完整的物模型设计
为了让设备之间通信不混乱,我给每个设备定义一套物模型。所谓物模型就是数据和命令的抽象定义,它决定了MQTT主题和BLE特征的含义。
| 设备 | 数据/命令 | 传输方式 |
|---|---|---|
| 温湿度节点 | 温度、湿度、电量 | BLE广播 |
| 网关 | 收集节点数据、云端上报 | WiFi MQTT + BLE扫描 |
| 智能灯控 | 开关状态、开关控制 | WiFi MQTT |
网关的代码逻辑有点复杂,核心是双协议栈同时跑:BLE扫描周围节点广播包,解析出温湿度数据,然后通过MQTT发布到home/livingroom/sensor/temp_humi/state主题;同时订阅灯的开关主题,收到控制指令后翻转GPIO13。
5.3 关键代码片段:BLE扫描解析温湿度
在ESP32上做BLE扫描用BLEScan库。扫描回调里过滤出属于我们自定义温湿度节点的设备名,然后从manufacturer data字段解析数据:
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { if (advertisedDevice.getName() == "TempHumi_Node_01") { // 解析manufacturer data前4字节:前2字节温度,后2字节湿度 std::string data = advertisedDevice.getManufacturerData(); if (data.length() >= 4) { int16_t tempRaw = (data[1] << 8) | data[0]; int16_t humiRaw = (data[3] << 8) | data[2]; float temp = tempRaw / 100.0; float humi = humiRaw / 100.0; mqttClient.publish("home/livingroom/sensor/temp_humi/state", ("{\"temp\":" + String(temp) + ",\"humi\":" + String(humi) + "}").c_str()); } } } };数据格式是自己定义的,所以发送端和接收端必须保持一致。我这里传输的是整数形式,温度25.31度就编码为2531,接收端除以100还原,这样做的好处是占用字节少、不需要浮点传输,BLE广播数据一次最多31字节,能省就省。
5.4 接入Home Assistant
如果你已经在用Home Assistant,那这套方案接入非常顺。Home Assistant的MQTT Discovery功能可以自动发现设备,只需要在主题设计中遵循它的规范,比如配置主题用homeassistant/sensor/temp_humi/config,下发一个JSON格式的配置消息,HA就会自动创建一个温湿度传感器实体。这样整个智能家居系统就有了统一的管理界面和自动化联动能力。
我用这套原型跑了一个多月,稳定性还不错。温湿度节点两节AA电池用了大概7周才需要更换,网关和灯控一直供电,重启过两次,原因都是家里路由器固件更新导致重启,ESP32这边的自动重连机制都正常恢复,没有再人工干预过。
6. 常见问题与排查技巧实录
这一节是实打实的经验总结,我把这套方案从零搭建过程中遇到过的各种问题集中整理出来,你后面实操时直接对照排查。
6.1 烧录失败与串口异常
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| Timed out waiting for packet header | 没进入下载模式 | 按住BOOT键再上传,看到Connecting松手 |
| No serial data received | COM口选错或驱动没装 | 检查设备管理器,重新装CH340/CP2102驱动 |
| 烧录后板子反复重启 | 电源供电不足 | 换USB线,优先用带屏蔽的短线,避免用充电宝 |
| 编译时报找不到esp32开发板 | JSON源或者离线包没装好 | 重新安装开发板包,检查硬件目录结构 |
6.2 WiFi不稳定:频繁掉线重连
这个问题的排查优先级建议是:先看电源,再看天线和距离,最后怀疑代码。ESP32的WiFi模块在发射瞬间电流峰值能到300mA以上,如果用的是劣质USB供电或者面包板供电,电压跌落会导致射频失锁,表现出来就是连上了就断、断了又连。换一个至少500mA的稳定供电,问题通常立刻消失。
天线方面,PCB天线的ESP32开发板对周围环境很敏感,不要让它趴在金属桌面上工作,尽量垫高或者用带外置天线的型号。信道弯曲导致信号弱的情况也遇到过,用手机上的WiFi分析仪看看你所在环境哪个信道拥堵,然后在路由器里固定到相对空闲的信道,ESP32的重连稳定性会好很多。
6.3 BLE扫描不到设备或数据解析错误
BLE扫描不到设备最常见的原因是你开启了WiFi并且两者冲突。前面说过,双协议栈共存时建议把BLE扫描窗口调短一点,给WiFi留出射频时间。另外扫描回调里处理数据如果耗时太长,会拖累下一次扫描周期,所以回调里只做解析和缓存,把MQTT发布放到主循环里。
数据解析错误一般是字节序没对齐。很多人用结构体指针直接映射广播数据的buffer,结果因为结构体字节对齐问题,读到的int16_t顺序反了。我建议统一用单独的字节数组,然后显式拼接:
int16_t tempRaw = (data[1] << 8) | data[0];这样不管平台怎么裁剪对齐都不会出错。
6.4 ESP32重启与内存不足
设备莫名其妙重启是嵌入式开发最棘手的bug之一。ESP32重启时会在串口打印panic信息,直接翻日志定位。最常见的panic原因是malloc失败或者堆栈溢出,解决办法是把大块缓冲区从栈上挪到全局变量或堆上,减少递归调用层级。
如果同时开WiFi和BLE,建议在初始化顺序上做点讲究:先初始化WiFi和MQTT,等WiFi连接成功后再初始化BLE。实测这个顺序比反过来稳定,因为WiFi连接过程要处理DNS、DHCP等一堆任务,如果同时被BLE抢占CPU,容易在启动阶段卡死。
我自己还有个习惯:在关键节点打印短日志,用一套简单的日志级别宏,出问题时直接看串口输出就能定位到哪一步。这个习惯帮我省了大量debug时间,建议你也养成。
6.5 传感器数据异常跳动
传感器读出来的数据偶尔跳一下,比实际值高出一大截,这通常是电磁干扰导致的。继电器吸合瞬间会产生很大的电流突变,而这个突变会沿着供电线路倒灌进传感器。解决办法有三个:继电器单独供电、控制信号和传感器走线分开、在传感器VCC对地加一个10uF去耦电容。我试过全加上之后,数据曲线干净了很多。
另外一个容易被忽视的坑是I2C总线上有设备地址冲突。如果你同时挂了多个I2C传感器,确认它们的地址各不相同,否则通信会乱掉。可以用I2C扫描程序检查总线上的地址。
7. 写在最后的补充建议
这套方案做到现在,我个人最大的感受是把“一站式”做扎实,关键不在于某一个功能多炫,而在于每个环节之间不打架。WiFi和BLE共存,GPIO资源和供电分配,这些在项目初期就规划好,后面能少走很多弯路。
如果后续要继续扩展,我建议顺着两个方向走:一是往更多节点上扩,用BLE Mesh做大规模低功耗传感器网络,覆盖整屋;二是往智能化上做,把语音控制、人体存在检测联动进来,让这套系统从“能联网控制”升级成“真正的智能家居”。硬件基础已经打好了,ESP32剩下的就是软件生态的深度挖掘。