资讯动态

ESP32+MQTT改造除湿机:接入Home Assistant的IoT实战

发布时间:2026/8/27 5:08:48 来源:尧图企业网站定制
说实话把除湿机接入 IoT 网络这件事我一直觉得比折腾智能音箱、智能灯值得多。你就想这么一个问题南方回南天你人在公司家里湿度 85%木地板、衣柜、钢琴、相机全都在默默吸水而你完全不知道。等周末回去看到墙壁挂水珠、柜子发霉再开除湿机已经晚了。普通除湿机只能靠面板上的按键和旋钮出门在外就是个“睁眼瞎”它连“今天抽了多少杯水”都不会告诉你。给除湿机加一个 IoT 大脑成本不算高解决的全是刚需问题远程看温湿度、自动维持目标湿度、漏水报警、和新风系统联动。这篇文章我会完整记录我从拆机、接线、写固件到接入 Home Assistant 的全过程。适合有一定动手能力、想把普通家电变智能的朋友参考。项目整体思路是用 ESP32 做边缘控制节点用 SHT30 数字温湿度传感器做环境感知用继电器模拟按键控制除湿机启停再用 MQTT 接入本地智能家居平台。整个过程走下来你会发现所谓 IoT 改造并不神秘它其实就是“传感器采集 - 边缘决策 - 网络上报 - 平台联动”这条链路的实体化。1. 改造思路与方案选型为什么是 ESP32 MQTT1.1 这台除湿机到底缺什么先说我手头这台除湿机压缩机式标称每天 12L 除湿量面板上就三个东西一个电源键、一个湿度设定旋钮、一个水箱满指示灯。它的内部控制逻辑其实很简单旋钮设定目标湿度机器内部自带的湿度传感器检测到湿度高于设定值就启动压缩机低于设定值就停机。这就是一个典型的本地闭环系统。但问题恰恰出在这。第一它的传感器在机器内部检测的是机身周围局部湿度不是房间真实平均湿度第二它没有数据记录能力你根本不知道家里湿度是缓慢上升还是持续波动等发现问题时往往已经晚了第三它没有网络人不在家就无法主动开机除湿。所以我给这台机器定的改造目标很明确增加独立的数字温湿度传感器把它放到回风口或房间代表点位而不是只依赖机器内部那枚老式传感器。将温湿度数据实时上传到本地 IoT 平台并保存历史曲线。把原机的“旋钮设定”逻辑升级成可远程配置、可联动场景的逻辑。增加漏水检测、设备异常告警等保护功能。这套改造做完除湿机就从“被动响应机器”变成了“主动维护环境湿度”的 IoT 节点。1.2 硬件选型ESP32 几乎是唯一答案如果你在网上搜“智能除湿机改装”很多人会用 ESP8266 配 DHT22我也这么干过但后来全部升级成 ESP32 SHT30。为什么有四个很实际的理由ESP32 双核 足够的 GPIO除了跑传感器读取和 MQTT还能同时处理本地控制逻辑、OTA、看门狗不会出现资源不够导致卡顿。ESP8266 在同时开 WiFi、读传感器、处理控制逻辑时偶尔会出现云台阻塞或断流问题。ESP32 原生支持蓝牙和 WiFi虽然本项目只用 WiFi但如果后续想接蓝牙温湿度计、或做配网二维码底子就在这儿了。SHT30 是 I2C 数字接口精度高、长期稳定性好、出厂校准。DHT22 虽然便宜但靠单总线时序通信对线长和干扰敏感用半年后飘移明显。Arduino / ESPHome / PlatformIO 生态成熟社区资料多遇到问题一搜就能找到答案。传感器方面我最终选的是 SHT30。它的典型精度是 ±2% RH相对湿度温度精度 ±0.3°C这个级别对除湿控制已经绰绰有余。如果你手头已经有 DHT22 也能用但建议把它放在离主机稍远一点的地方用短线连接并且每隔一段时间用标准湿度计对比校准一下。继电器模块我也踩过几个坑。普通 5V 继电器模块便宜十几块钱但要注意两点一是上电瞬间 GPIO 默认电平是否会导致继电器误动作二是触点容量够不够。压缩机启动瞬间电流远大于稳态电流如果你改造的是大功率除湿机最好选 16A 触点容量的继电器模块或者再加一个交流接触器做中间级。我在这个项目里用的是一路 5V 继电器模块光耦隔离触点额定 10A/250VAC对 12L 的机器够用。如果你要控制 20L 以上的大机器强烈建议再加接触器别省这个钱。1.3 通讯方案MQTT 而不是私有云很多所谓“智能除湿机”出厂就带 Wi-Fi但 App 体验做得一言难尽第一个问题是数据走厂商私有云断网就全瞎第二个问题是 App 只给一个开关和定时功能没有数据曲线也不支持和 Home Assistant 这类本地平台联动第三个问题是厂商一旦停止维护设备就变成“电子垃圾”。所以我从一开始就决定通讯协议用 MQTT平台用 Home Assistant所有核心逻辑走本地优先。MQTT 的优势在于它是物联网行业的事实标准基于发布/订阅模型非常适合这种“传感器定时上报 控制命令下行”的场景。它的 QoS 机制可以保证消息不丢retain 标志可以让新订阅的设备立刻拿到当前状态遗嘱消息Last Will and Testament还能在设备掉线时通知平台。这些能力用 HTTP 轮询实现起来会很别扭。在这个项目里数据流是这样的SHT30 传感器 - ESP32 本地逻辑 - MQTT BrokerHome Assistant 自带 Mosquitto | - Home Assistant 仪表盘 - Node-RED 自动化 - 手机 App 推送控制流是反过来的手机/App - MQTT Broker - ESP32 - 继电器 - 除湿机电源键。2. 硬件改装从拆机到接线2.1 拆机与定位关键检测点动手前必须先断电这点没有任何商量余地。除湿机内部有压缩机、启动电容、控制板特别是启动电容在断电后可能还存着电需要等几分钟或者用放电电阻放电后再碰。我拆开外壳后第一件事是拍照记录内部结构特别是控制板上的线序方便后面复原。拆开后要找到控制面板上面板按钮对应的接线位置。大多数除湿机面板上是轻触开关一端接控制板的地/信号端另一端接按键扫描端口。你不需要理解它的扫描原理只要能找到“按下电源键时哪两个焊点会导通”就可以把继电器触点并联上去。用万用表二极管档或通断档在按下按键时听蜂鸣一般都能很快定位。这里有一个非常关键的选择建议采用“继电器并联按键触点”的方式而不是直接控制总电源。直接控制总电源意味着压缩机、风扇、控制板会同时断电下次上电时机器未必会自动开机而且频繁通断总电源对压缩机寿命很不利。继电器并联按键触点本质上等于“模拟人按了一下电源键”机器自身的保护逻辑仍然在场风险低很多。2.2 硬件清单与接线方案我最终的硬件清单如下器件规格/型号数量作用ESP32 开发板ESP32 DevKitC 或 NodeMCU-32S1主控WiFi/MQTT/本地逻辑温湿度传感器SHT30 模块I2C 接口1采集环境温湿度继电器模块一路 5V 光耦隔离继电器10A/250VAC1模拟按键控制除湿机水浸传感器简易触点式漏水探头1可选检测底部漏水DC-DC 降压模块220V 转 5V 或使用 USB 适配器1为 ESP32 供电杜邦线/硅胶线若干-接线绝缘盒/热缩管若干-安全防护接线示意图大概长这样SHT30模块 ESP32 继电器模块 VCC ---------------- 3.3V VCC ---------------- 5V GND ---------------- GND GND ---------------- GND SCL ---------------- GPIO 22 (I2C SCL) IN ---------------- GPIO 16 SDA ---------------- GPIO 21 (I2C SDA) 继电器触点NO/COM ---- 并联到除湿机电源键两端注意继电器模块的 VCC 我用的是 ESP32 的 5V 引脚前提是你的 ESP32 开发板从 USB 或 5V 输入供电。如果继电器模块是 3.3V 版本也可以直接用 3.3V但驱动电流会略紧张最好选带光耦的模块。除湿机按键处接线时把原来的轻触开关引脚用杜邦线或硅胶线引出来并联到继电器模块的常开NO和公共COM端。这样继电器一吸合等效于按键按下。常开接法是最安全的平时不会影响原机按键功能。2.3 安装位置与安全细节传感器放哪里非常影响控制效果。我踩过的坑是第一次把 SHT30 直接贴在除湿机出风口附近结果读数低得离谱因为出风口吹出来的是干燥空气但不代表房间整体湿度已经降下来了。后来我把传感器移到了除湿机侧面回风口的旁边离机身 5 到 10 厘米并且不让它正对出风口或冷凝器。这个位置测到的是“即将被除湿机抽进去的空气”和机器内部传感器相比代表的是房间空气状态控制逻辑更合理。另外要注意 ESP32 和继电器模块不能裸奔。除湿机内部是水汽环境一旦冷凝水流到控制板上220V 和 3.3V 混在一起就不是闹着玩的了。我建议把 ESP32 和继电器模块放进一个绝缘密封盒固定到远离冷凝器和排水槽的位置。如果条件允许给电路板喷一层三防漆能极大提高在潮湿环境下的可靠性。供电方式也值得多说一句不要直接从除湿机控制板上取 3.3V 或 5V 电源因为压缩机启动时电压跌落很厉害。我用的是一路独立的 5V/2A USB 适配器从外部供电给 ESP32 和继电器。这样既安全又不会因为电源问题导致 WiFi 掉线或复位。3. 固件设计与核心逻辑除湿机的“大脑”怎么造3.1 固件框架数据采集、状态机与控制逻辑如果你编程经验不多可以直接用 ESPHome配置 YAML 就能把传感器、继电器、MQTT 接入 Home Assistant。但如果你和我一样想精细控制压缩机保护、异常阈值、回差逻辑那还是写自定义固件更舒服。我用的是 PlatformIO Arduino 框架核心就三个模块数据采集模块每 2 秒读一次 SHT30做简单滤波后更新全局变量。控制状态机维护 Standby、Running、DelayStart、Alarm 四个状态根据当前湿度、目标湿度、压缩机启动时间决定状态迁移。通讯模块连接 WiFi 和 MQTT定时上报温湿度、设备状态订阅控制主题。核心代码骨架如下#include WiFi.h #include PubSubClient.h #include Wire.h #include Adafruit_SHT31.h Adafruit_SHT31 sht30 Adafruit_SHT31(); WiFiClient espClient; PubSubClient mqtt(espClient); const char* mqttServer 192.168.1.10; // Home Assistant / Mosquitto 地址 const int relayPin 16; // 目标湿度与回差值 float targetHum 55.0; float hysteresis 5.0; // 压缩机保护延时毫秒 unsigned long compDelay 300000; // 二次启动至少等 5 分钟 unsigned long lastCompStopTime 0; bool compRunning false; void setup() { pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); Wire.begin(21, 22); sht30.begin(0x44); connectWiFi(); connectMQTT(); } void loop() { mqtt.loop(); // 1. 读取传感器 float temp sht30.readTemperature(); float hum sht30.readHumidity(); // 2. 控制决策 if (hum targetHum hysteresis !compRunning) { // 满足启动条件且已经过了压缩机保护延时 if (millis() - lastCompStopTime compDelay) { digitalWrite(relayPin, HIGH); // 模拟按键开机 compRunning true; delay(200); digitalWrite(relayPin, LOW); } } else if (hum targetHum - hysteresis compRunning) { digitalWrite(relayPin, HIGH); // 模拟按键关机 compRunning false; lastCompStopTime millis(); delay(200); digitalWrite(relayPin, LOW); } // 3. 上报 MQTT publishSensorData(temp, hum); publishStatus(compRunning); delay(2000); }这段代码是简化版实际项目里还加了看门狗、异常数据过滤、OTA 和配置管理。但核心思路就这么简单读数据、做判断、控制继电器。3.2 关键算法湿度回差、压缩机保护与失败模式除湿控制最忌讳的就是“湿度一到 55% 就停一到 55.1% 就开”这种频繁启停会让压缩机死得很快。所以要引入回差hysteresis机制。我这里的设置是目标湿度 55%回差 5%那实际控制逻辑就是“湿度高于 60% 启动低于 50% 停机”。中间的 10% 区间就是死区避免设备在目标值附近反复横跳。压缩机保护延时同样重要。压缩机从停止到再次启动至少需要等 3 到 5 分钟因为制冷系统高低压侧需要平衡否则启动负载过大容易闷机甚至烧毁。我在状态机里专门加了一个DelayStart状态每次压缩机停机后记录时间戳如果收到新的启动指令但还没到 5 分钟就进入等待状态直到延时结束才真正给继电器发脉冲。传感器失效保护很多人会忽略。SHT30 如果接线松动或受到干扰可能读到 NaN 或者明显离谱的数值比如湿度 150%。如果不加保护设备会把错误数据当成“环境湿度”做出错误决策。我加的逻辑是连续 5 次读取失败或者数值超出物理合理范围就发布alarm/sensor_failure消息并且立即停止压缩机保持现状等待人工处理。漏水检测我建议有条件一定要加。除湿机最大的隐患不是“抽不到水”而是“水箱满/管路堵塞导致内部积水溢出”。我后来在水箱附近和机器底部各贴了一个触点式水浸探头接到 ESP32 的某个 GPIO 上。一旦监测到漏水第一时间发布告警并且强制关闭压缩机避免二次事故。这类保护功能没有技术含量但关键时刻能救命。3.3 OTA 升级与配置管理固件写完不可能一次就完美OTA 升级几乎是刚需。我在固件里内置了 ArduinoOTA 库并采用双分区ota_data app0 app1的方式这样刷机失败后还能自动回滚。OTA 这块的思路其实是借鉴了生产环境的用户策略升级不能“一把梭”得有个灰度过程。早期原型阶段我每次改了代码都是直接串口刷后来设备装到墙上不想频繁拆机才开始用 OTA。我的做法是新固件启动后立刻上报一条status/boot消息并在 60 秒内持续上报心跳。如果 Home Assistant 侧没有收到新固件的心跳判定启动失败设备在下次重启时回滚到旧分区。MQTT 收到command/ota/prepare后才允许发送升级包防止误触。当然这是家庭项目不需要真的搞什么复杂的灰度系统但“失败回滚”这个意识一定要有。否则你远程更新固件万一断电或者固件有 bug设备就变砖了。生产级 IoT 平台的 OTA 用户策略本质上也是这套分阶段推送、设备健康度确认、失败自动回滚。配置管理方面我用了 NVSNon-Volatile Storage保存目标湿度、回差、MQTT 服务器地址等参数。这样不需要重新编译固件就能改配置。最开始我用的是硬编码常量每次调参都要重新刷机后来改成 NVS 后省了太多事。4. 云端接入与可视化让除湿机“开口说话”4.1 本地 MQTT Broker 与 Home Assistant 自动发现我家的 IoT 中枢是 Home Assistant它内置了 Mosquitto MQTT Broker 插件。设备端要做的只是连接 WiFi、连上 Broker、发布消息。主题设计我用了统一前缀方便后续扩展home/dehumidifier/humidity home/dehumidifier/temperature home/dehumidifier/status/power home/dehumidifier/command/setpoint home/dehumidifier/alarm/waterHome Assistant 最方便的一点是支持 MQTT Discovery设备端发一条特殊的配置消息HA 就会自动创建对应的实体。比如温湿度传感器配置主题长这样homeassistant/sensor/dehumidifier_humidity/configpayload 是一个 JSON{ name: Dehumidifier Humidity, state_topic: home/dehumidifier/humidity, unit_of_measurement: %, device_class: humidity, unique_id: dehumidifier_humidity_01 }这条消息发出去HA 侧就自动多了一个湿度传感器实体非常解手。想在手机 App 上看数据只要配好 HA 的远程访问或者用灵动通知组件推送到手机就行。4.2 Node-RED 做自动化策略从命令到场景数据接入 HA 之后能做的事情就不只是“看个数字”了。我在 Node-RED 里搭了一套场景自动化和手动控制逻辑互补当房间湿度高于 70% 且持续时间超过 10 分钟自动开启除湿机同时打开卫生间排气扇辅助排湿。当湿度降到 50% 以下自动关闭除湿机并向手机推送一条摘要消息“本次除湿持续 3 小时 20 分从 75% 降至 48%。”如果除湿机运行超过 6 小时但湿度下降不到 10%大概率是机器故障或门窗一直开着推送告警让我检查。如果水浸传感器触发HA 立刻推送紧急通知并通过自动化关闭除湿机电源。这些自动化用 Node-RED 的 MQTT 输入节点 Function 节点就能搞定。如果你不想再装 Node-RED直接用 HA 自带的自动化编辑器写 YAML 也可以效果一样。重点是设备端只负责稳定地采集和执行真正的“智能场景”放在平台侧这样改策略不用重新刷固件。4.3 数据采集与远程告警从“能看”到“能判断”很多玩智能家居的朋友做到“能看温度湿度曲线”就停了。但数据采集的真正价值在于通过趋势判断设备健康度。把 History 插件打开保存一周的数据后你会发现正常除湿机工作时湿度曲线应该是一个接一个的“锯齿波”工作段快速下降停止段缓慢回升。如果锯齿波消失湿度一直平在高位说明除湿机大概率没在好好工作。如果湿度一天内剧烈波动可能是有窗户没关、或门经常进出。我在 Home Assistant 里定了几条告警规则其中最实用的一条是“相对湿度持续偏高且设备多次尝试启动失败”。有一次我因为水箱浮球卡住机器一直报满水保护我没注意是这条告警提醒我检查的。这套链路放到更大的场景里其实就是物联网海量数据采集场景的缩小版数据源产生数据 - 边缘节点初步处理 - 网关汇聚 - 平台存储与规则引擎 - 异常告警。家里虽然只有一台除湿机但把这个链路跑通之后再去做多设备、多传感器项目思路就是现成的了。5. 常见问题与排查实录5.1 传感器数据异常或飘移SHT30 用 I2C 接线最常见的故障是读到的温度为负数、湿度为 0 或数据频繁跳变。我在调试过程中遇到过三次第一次是杜邦线接触不良用手一碰传感器读数就乱跳后来把杜邦线换成焊接的硅胶线才稳定第二次是 I2C 地址冲突SHT30 模块默认地址是 0x44有些模块把地址引脚拉高变成 0x45如果你同时挂了两个设备就要注意第三次是线太长超过 30 厘米后信号完整性变差我把传感器放到离 ESP32 较远的位置后加了一个 4.7kΩ 上拉电阻才解决。建议你在正式固定传感器前先用 MQTT Explorer 观察半小时数据确认曲线平稳再封装。如果读数跳变超过 ±5% RH大概率是接线或供电问题不要着急用软件滤波掩盖先把硬件问题解决。5.2 继电器不吸合或一直吸合这个问题的根源通常不在继电器本身而在单片机上电瞬间的 GPIO 默认电平。ESP32 的 GPIO 在复位期间可能是高阻态或高电平如果继电器控制引脚没有做下拉模块可能会在上电瞬间吸合一下导致除湿机无故开机。解决方法是在继电器 IN 引脚和 GND 之间加一个 10kΩ 下拉电阻并在固件初始化时先把引脚设为 LOW再延迟 1 秒后进入正常逻辑。另外不要用 ESP32 的 3.3V GPIO 直接驱动没有光耦的继电器模块驱动能力不足会产生“能亮但吸合不了”的怪问题。选带光耦隔离的模块或者加一级 NPN 三极管/ULN2003 放大驱动。5.3 OTA 刷机失败与回滚家庭环境 OTA 失败的主要原因是 WiFi 信号弱、电源供电不稳、或者刷机过程中断电。我的教训是不要以为 OTA 成功就万事大吉必须在固件里预留串口刷机引导。如果设备变砖最简单的方式是按住 ESP32 的 BOOT 键用串口工具重新刷一次引导程序。我在固件里把这个模式做成了“5 秒内连续按 3 次按键进入串口恢复模式”这样哪怕设备网络配置全乱也能通过串口救回来。5.4 断网后设备“失智”我最开始的设计里控制逻辑完全依赖 MQTT 指令结果有一次路由器重启设备连着 WiFi 但连不上 MQTT就在那一动不动除湿机也不自动开。后来我把本地控制逻辑放回了 ESP32 固件里就算 MQTT 断线设备仍然依照本地目标湿度和回差自动运行只是不再上报数据。这其实是 IoT 项目里必须想清楚的一点平台是辅助决策层设备本身必须有本地独立的保底逻辑。把自动化全部放在云端看似方便但网络抖动一次就全盘崩掉。如果后续你做的设备需要本地逻辑和云端指令同时存在还要定义清楚“谁优先级更高”。我的策略是云端指令可以立即改变设备目标状态但如果云端失联超过 2 分钟设备恢复本地自动模式。6. 进一步的扩展和折腾方向6.1 从单机改造到多房间集控一台除湿机改完你会发现思路很快就想复制到第二台、第三台。如果有楼上楼下多个房间可以在每台除湿机里部署同样的 ESP32 方案只要给每台设备一个唯一 ID配置不同的主题前缀Home Assistant 里就能自动生成多个实体。我后来在地下室、衣帽间各加了一台用 HA 的 group 把两个湿度传感器和两台除湿机绑定到一张卡片上一眼就能看到整个房子的除湿状态。多设备部署后有一点要注意每个设备必须设置独立的 MQTT client_id否则 Broker 会互相踢下线。这也是批量部署设备时最容易踩的坑。6.2 小型项目里学到的生产级 IoT 经验虽然这只是一台几百块钱的除湿机改造但整个项目的架构和一个正经的物联网产品已经很像了。设备端要考虑传感器选型、数据采集频率、本地决策与保护、异常上报、OTA 升级与回滚、设备唯一标识、配置可修改。平台端要考虑设备发现、状态存储、可视化和告警、远程控制。和那些处理海量数据采集场景的生产系统相比差的只是规模不是逻辑。如果你打算做更正式的 IoT 产品我建议在文档里固定好这套主题规范、消息格式、设备状态枚举然后用模拟器跑一遍端到端流程。这些细节在家庭项目里看不出差别但一旦数量上到几十台设备就是灾难和救命的区别了。6.3 折腾完这台除湿机我学到的真正东西改造完这台除湿机后我最大的感受不是“我多了个远程开关”而是“我终于知道房间湿度到底在发生什么”。你以为家里发潮是下雨天的事打开历史曲线才发现阴天、多云、甚至冬天暖气的日子湿度都可能偷偷爬到 70% 以上。没有数据你永远靠猜有了 IoT 化改造你靠的是证据。另一个收获是这套方案的每一个环节都可以迁移。传感器换成空气质量传感器继电器换成智能插座MQTT 主题从除湿机换成新风机整个架构几乎不用大改。这大概就是物联网项目最有意思的地方——你第一眼看只是在改造一台家电但其实是在搭一个通用的感知与控制底座。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价