☰
ESP32冰箱状态监测系统:温度、门磁与告警推送实战
2026/10/11 11:07:23 网站建设 项目流程

1. 从一个被忽略的生活痛点说起:冰箱到底出了什么问题

冰箱大概是家里最"沉默"的家电。它不像空调有遥控器可以随时调温,不像洗衣机有面板显示剩余时间,更不像路由器有指示灯告诉你它是不是在干活。你唯一能感知到它存在的方式,是某天打开门发现里面的牛奶变温了、冷冻层的雪糕软了,或者更糟——一开门一股异味扑面而来。

我最初动这个项目的念头,来自一次出差回来后的惨痛经历。出门五天,家里那台用了六年的冰箱因为门封条老化没关严,压缩机一直在拼命工作但冷气持续外泄。回来的时候,冷藏室温度接近室温,一整抽屉的食材全部报废,冷冻层的东西半化不化,清理了整整一个下午。更让人后怕的是,如果当时压缩机因为长时间高负荷运转出了问题,损失就不只是食材了。

这件事之后我一直在想:能不能给冰箱装一个"体检仪",让它能实时告诉我内部温度、门有没有关好、压缩机是不是在正常工作?市面上确实有一些蓝牙温湿度计,但它们的通病是:需要你主动打开手机App去查看,没有主动告警能力,而且电池续航普遍一般。我需要的是一个能自己判断异常、主动推送通知、并且能长期稳定运行的低功耗方案。

这就是Smart FridgeGuard这个项目的由来。它的核心定位很明确:基于 ESP32 微控制器,构建一套冰箱状态监测系统,实时采集冷藏室与冷冻室的温度、湿度、门磁开关状态,通过本地逻辑判断异常(比如温度超阈值、门长时间未关、温度骤变),并通过网络推送告警到手机。整套硬件成本控制在百元以内,固件开源可改,适合有一定动手能力的爱好者、想给家里老人冰箱加一层保障的子女、以及做物联网入门项目的学习者。

这篇文章我会把整个项目的设计思路、硬件选型逻辑、固件架构、传感器标定、告警策略、实测踩坑全部拆开讲清楚。不是那种"照着接线图插上去就完事"的教程,而是把每个决策背后的"为什么"讲透,让你看完之后能根据自己的冰箱情况做定制化改造。

2. 硬件选型:为什么是 ESP32,传感器怎么挑

2.1 主控为什么锁定 ESP32 而不是 ESP8266 或 Arduino

先说主控。市面上做物联网监测项目,最常见的三个选择是 Arduino Uno + 网络模块、ESP8266、ESP32。我最终选 ESP32,理由不是"它更高级",而是这个项目的几个硬性需求把它推到了唯一解的位置。

第一是双核处理能力。这个项目需要同时做两件事:一是持续高频采集传感器数据(温度采样需要稳定节奏,不能被网络任务阻塞),二是维持网络连接并处理告警推送。ESP8266 是单核,当它忙着处理 WiFi 握手或 MQTT 重连时,传感器读取的时序会被打乱。ESP32 的双核可以一个核专门跑采集任务,另一个核跑网络任务,互不干扰。这一点在实测中差异非常明显——用 ESP8266 时温度曲线会出现周期性毛刺,换成 ESP32 后曲线平滑了很多。

第二是深度睡眠功耗控制。冰箱监测不需要每秒都上报数据,合理的策略是每隔几分钟唤醒一次采集、判断、上报,然后立刻回到深度睡眠。ESP32 的深度睡眠电流可以做到 10 微安级别,配合合理的唤醒周期,用一节 18650 电池能撑好几个月。ESP8266 虽然也支持深度睡眠,但唤醒后的重连速度和外设初始化开销更大。

第三是内置霍尔传感器和丰富的 ADC。ESP32 内置霍尔效应传感器,虽然这个项目里我最终用的是外部门磁开关,但内置霍尔在某些磁感应场景下能省一个元件。更重要的是它的 ADC 通道多,可以同时接多个模拟传感器而不需要外部多路复用器。

至于 Arduino Uno,它本身没有网络能力,要加 WiFi 模块、要加 RTC 模块、要加存储模块,堆起来成本和体积都上去了,而且功耗控制远不如 ESP32。所以主控这一项没有太多纠结。

2.2 温度传感器的取舍:DS18B20、DHT22 还是 SHT31

温度传感器是这个项目的核心,选错了后面全是坑。我把常见的几个方案列出来对比一下:

传感器型号测温精度湿度支持接口方式防水性单价区间适用场景
DS18B20±0.5°C不支持单总线有防水探头版低冷冻室、液体测温
DHT22±0.5°C支持单总线不防水低冷藏室常温区
SHT31±0.3°C支持I2C不防水中高精度冷藏监测
BME280±0.5°C支持I2C/SPI不防水中需气压数据的场景

我最终的方案是冷藏室用 SHT31,冷冻室用 DS18B20 防水探头。为什么这么搭配?

冷藏室的温度范围通常在 2°C 到 8°C,这个区间对精度要求高,因为判断"是否失温"的阈值往往只差一两度。SHT31 的 ±0.3°C 精度和出色的长期稳定性让它成为冷藏室的首选。而且冷藏室湿度变化大(开门时湿度会骤升),SHT31 的湿度读数比 DHT22 可靠得多——DHT22 在湿度超过 90% 的环境下读数会漂移,而冰箱冷藏室开门瞬间湿度轻松破 90%。

冷冻室则是另一回事。冷冻室温度在 -18°C 左右,而且经常有结霜、凝露。DHT22 和 SHT31 这类非防水传感器在冷冻室里很快就会因为凝露而失效甚至损坏。DS18B20 的防水探头版本可以直接埋在冷冻室里,金属探头耐低温,单总线接口只需要一个 GPIO 加一个 4.7kΩ 上拉电阻就能工作,而且支持多个探头挂同一条总线——这意味着你可以在冷冻室不同位置放两三个探头,取平均值或监测温度分布。

注意:DS18B20 一定要买"防水探头版"而不是裸片版。裸片版在冷冻室的凝露环境下,引脚间很容易短路,读数会直接跳到 85°C(这是 DS18B20 的默认上电值,出现这个值基本就是通信出问题了)。

2.3 门磁开关:干簧管还是霍尔传感器

门磁检测看起来简单,但选型也有讲究。常见方案是干簧管(磁簧开关)和霍尔传感器。

干簧管是机械式触点,磁铁靠近时簧片吸合导通,优点是零功耗(不需要供电,纯被动元件),缺点是寿命有限(机械触点有动作次数上限)、玻璃管体脆弱。霍尔传感器是电子式,需要供电,但无机械磨损、寿命长、响应快。

我最终选了干簧管,原因很实际:门磁开关的动作频率其实很低(一天开关几十次),机械寿命完全够用;而且干簧管不需要供电,在深度睡眠方案里少一个常供电元件就少一份静态功耗。霍尔传感器虽然更"现代",但需要持续供电才能检测磁场变化,在低功耗场景下反而不划算。

安装位置上,干簧管装在冰箱门框侧,磁铁装在门体对应位置。这里有个细节:磁铁和干簧管的间距要留 5-10mm 的余量,不要贴死。因为冰箱门关合时会有轻微晃动,贴太死容易在门没完全关严时就误判为"已关闭"。我一开始贴得太近,结果门虚掩着系统也显示关闭,后来拉开间距才解决。

2.4 供电方案:电池还是适配器

这个要分场景说。如果冰箱背后有常电插座(大多数家庭都有),直接用 5V USB 适配器供电最省心,不用担心续航。但如果你的冰箱位置不方便拉线,或者你想做一个完全无线的方案,那就得走电池。

电池方案我推荐18650 锂电池 + TP4056 充电模块 + 低压差稳压器。18650 容量大(常见 2600mAh 到 3500mAh),放电曲线平稳,配合 ESP32 深度睡眠,实测每 5 分钟唤醒一次采集上报,续航能到 2-3 个月。如果延长到 15 分钟一次,续航能到半年以上。

这里有个关键细节:ESP32 的深度睡眠唤醒后,WiFi 重连是最耗电的环节。一次完整的 WiFi 连接建立大约消耗 100-200mA 持续 2-3 秒。所以唤醒周期不能太短,否则大部分电量都花在重连上了。我的经验是 5 分钟是平衡点,再短就得不偿失。

3. 固件架构:双核任务怎么分工,深度睡眠怎么配合

3.1 采集任务与网络任务的核间分工

ESP32 是双核(Core 0 和 Core 1),FreeRTOS 默认会把setup()和loop()跑在 Core 1 上,Core 0 主要处理 WiFi 协议栈。我的做法是显式地创建两个任务,用xTaskCreatePinnedToCore()把它们钉在指定核心上。

采集任务钉在 Core 1,优先级设高一点(比如 5),负责按固定周期读取 SHT31 和 DS18B20、读取门磁 GPIO 状态、做本地阈值判断。网络任务钉在 Core 0,优先级低一点(比如 3),负责 WiFi 连接、MQTT 发布、告警推送。两个任务之间用队列(Queue)传递数据,采集任务把打包好的数据结构丢进队列,网络任务从队列取出来发送。

为什么要这么分?因为传感器读取对时序敏感。DS18B20 的单总线协议对时序要求很严格,如果读取过程中被 WiFi 中断打断,很容易读出 85°C 这种错误值。把采集任务独立出来并给较高优先级,能最大程度保证时序稳定。

// 任务创建示例 xTaskCreatePinnedToCore( sensorTask, // 采集任务函数 "SensorTask", // 任务名 4096, // 栈大小 NULL, // 参数 5, // 优先级 &sensorTaskHandle, 1 // 钉在 Core 1 ); xTaskCreatePinnedToCore( networkTask, // 网络任务函数 "NetworkTask", 8192, // 网络任务栈要大一些 NULL, 3, &networkTaskHandle, 0 // 钉在 Core 0 );

3.2 深度睡眠与任务模型的冲突处理

这里有个很多人会踩的坑:深度睡眠和 FreeRTOS 任务模型是冲突的。深度睡眠会关闭几乎所有外设和 CPU,唤醒后相当于重新启动,所有任务都要重建。所以你不能一边跑着多任务一边进深度睡眠。

我的处理方式是分模式运行。系统有两种工作模式:

  • 常供电模式:如果检测到 USB 供电(通过一个 GPIO 检测 VBUS),系统就保持常开,双任务持续运行,数据上报频率可以高一些(比如每 30 秒一次),适合调试和需要高频监测的场景。
  • 电池模式:如果没有 USB 供电,系统走"唤醒-采集-判断-上报-睡眠"的单次循环,每次唤醒只做一轮操作,然后立刻回到深度睡眠。这种模式下不需要 FreeRTOS 多任务,用最简单的顺序执行反而更省电更可靠。

判断供电状态的代码很简单,用一个分压电阻把 VBUS 降到 3.3V 以内接到一个 ADC 引脚,读电压值就能判断。

float vbusVoltage = analogRead(VBUS_PIN) / 4095.0 * 3.3 * 2; // 分压比2:1 bool usbPowered = (vbusVoltage > 4.0);

这个设计让我在调试时用 USB 供电跑高频监测,部署时拔掉 USB 自动切换到电池低功耗模式,不用改固件。

3.3 数据上报协议:MQTT 还是 HTTP

上报协议我选了MQTT,理由有三。第一是开销小,MQTT 的报文头最小只有 2 字节,而 HTTP 每次请求都要带一堆头部信息,在低功耗场景下每字节都珍贵。第二是支持长连接和 QoS 等级,QoS 1 能保证消息至少送达一次,对于告警这种不能丢的消息很重要。第三是天然适合发布/订阅模型,后面如果要加多个监测节点(比如同时监测冰箱和冷柜),MQTT 的 topic 结构能很自然地扩展。

Topic 设计我用了这样的结构:

fridgeguard/{device_id}/temperature fridgeguard/{device_id}/humidity fridgeguard/{device_id}/door fridgeguard/{device_id}/alert

device_id用 ESP32 的 MAC 地址后六位,保证多设备不冲突。告警消息单独走一个 topic,方便在手机端做特殊处理(比如高优先级通知)。

如果不想自己搭 MQTT 服务器,也可以用一些公共的物联网消息服务,或者干脆用 HTTP POST 推到一个简单的 Webhook。但如果你打算长期用,我还是建议自己搭一个 MQTT Broker,数据完全自己掌控。

4. 传感器标定与阈值设定:让告警不误报也不漏报

4.1 温度阈值的科学设定

阈值设定是这个项目里最需要"动脑子"的部分。设得太松,等告警时食材已经坏了;设得太紧,天天误报你会直接把通知关掉,那系统就形同虚设。

先说冷藏室。食品安全的角度,冷藏室应该保持在 4°C 以下。但实际冰箱运行中,温度是波动的——压缩机启动时温度下降,停机时温度缓慢回升,正常波动范围在 2°C 到 6°C 之间。所以我的告警阈值是这样设的:

  • 预警阈值:持续 10 分钟高于 7°C,推送"冷藏室温度偏高"提醒
  • 告警阈值:持续 5 分钟高于 10°C,推送"冷藏室失温"紧急告警
  • 恢复通知:温度回到 6°C 以下并稳定 5 分钟后,推送"温度已恢复"

为什么要加"持续时间"这个条件?因为开门瞬间冷藏室温度会快速上升,如果只看瞬时值,每次开门都会触发告警。加上持续时间判断,就能过滤掉开门这种正常操作。

冷冻室阈值相对简单,-18°C 是标准,我设的是:

  • 预警:持续 15 分钟高于 -12°C
  • 告警:持续 5 分钟高于 -8°C

冷冻室温度变化比冷藏室慢,所以预警的持续时间设长一些,避免因为化霜周期导致的正常温度回升触发误报。

4.2 门磁状态的去抖与超时逻辑

门磁检测有两个关键逻辑:去抖和超时。

去抖是因为干簧管在门关合的瞬间会有机械抖动,可能产生多次通断。我的做法是在中断里记录时间戳,如果两次状态变化间隔小于 500ms,就忽略后一次。软件去抖比硬件加电容更灵活,参数好调。

超时逻辑是门磁告警的核心。门开着多久算异常?我的设定是:

  • 开门超过 2 分钟:推送"冰箱门未关"提醒
  • 开门超过 5 分钟:推送"冰箱门长时间未关"紧急告警

2 分钟这个值是根据实际使用习惯定的——正常拿取食材很少超过 2 分钟,超过这个时间大概率是忘了关或者门被东西挡住了。5 分钟则是明确异常,必须立即处理。

提示:门磁超时告警一定要做"状态恢复检测"。也就是说,门关上之后要推送一条"门已关闭"的通知,否则用户收到告警后不知道问题是否已经解决,会反复去检查。

4.3 温度骤变检测:一个容易被忽略的异常信号

除了绝对阈值,我还加了一个温度变化率检测。正常情况下,冰箱温度变化是缓慢的,每分钟变化不超过 0.5°C。如果检测到温度在短时间内急剧变化(比如 1 分钟内变化超过 2°C),这往往意味着异常——可能是门大开、可能是制冷剂泄漏、也可能是传感器故障。

这个逻辑用滑动窗口实现:保存最近 5 分钟的读数,计算首尾差值和时间差,得出变化率。如果变化率超过阈值,触发"温度异常波动"告警。

这个功能在实际使用中帮我发现过一次门封条老化的早期迹象——温度没有超过绝对阈值,但波动率明显比平时大,提前提醒我检查门封条,避免了后面更严重的问题。

5. 实测踩坑记录:那些文档里不会写的问题

5.1 冷冻室传感器的凝露问题

第一个大坑来自冷冻室的 DS18B20。刚装上去前几天读数正常,一周后开始出现间歇性的 85°C 读数。我一开始以为是接线松动,重新焊了一遍还是这样。后来把探头拿出来检查,发现探头引线和金属管的交界处有凝露,水汽顺着引线渗进了热缩管内部。

解决办法是在探头引线根部打一圈硅胶密封,然后用热缩管包两层,最外层再缠一层防水胶带。处理之后再也没有出现过 85°C 的问题。这个细节在大多数教程里都不会提,但只要你把传感器放进冷冻室,几乎一定会遇到。

5.2 WiFi 信号被冰箱金属外壳屏蔽

第二个坑更隐蔽。我把 ESP32 模块贴在冰箱侧面,结果 WiFi 信号强度一直在 -85dBm 左右徘徊,频繁掉线。排查了半天才发现,冰箱的金属外壳对 2.4GHz 信号有很强的屏蔽和反射作用,模块贴得越近信号越差。

解决方案是把 ESP32 模块移到冰箱顶部或者侧面远离金属的位置,用延长线连接传感器。移动之后信号强度提升到 -55dBm,连接非常稳定。如果你家冰箱位置信号本来就弱,可以考虑用 ESP32 的外接天线版本,或者加一个简单的反射板把信号引出来。

5.3 深度睡眠唤醒后的 GPIO 状态漂移

第三个坑和深度睡眠有关。ESP32 从深度睡眠唤醒后,GPIO 的状态会恢复到默认值,我用来检测门磁的引脚在唤醒瞬间会有一个短暂的电平跳变,导致误判为"门开了"。

解决办法是在门磁检测代码里加一个唤醒后的稳定延时——唤醒后先等 100ms 让 GPIO 电平稳定,再读取状态。同时在硬件上给门磁引脚加一个 10kΩ 的下拉电阻,确保默认状态是确定的低电平,避免浮空引脚导致的随机跳变。

5.4 电池电压监测的精度问题

最后一个坑是关于电池电量监测的。ESP32 的 ADC 在测量电池电压时,因为内部参考电压有偏差,读数误差比较大。我一开始直接用analogRead读分压后的电压,算出来的电量经常跳变。

改进方法是用 ESP32 的内部校准功能,或者更简单粗暴——在代码里加一个校准系数,用万用表实测电压和 ADC 读数对比,算出修正系数。我实测下来,加校准系数后电压读数误差从 ±0.3V 降到了 ±0.05V,电量估算准确多了。

// 带校准的电压读取 float readBatteryVoltage() { int raw = analogRead(BATTERY_ADC_PIN); float voltage = raw / 4095.0 * 3.3 * 2.0; // 分压比2:1 voltage *= 1.05; // 校准系数,根据实测调整 return voltage; }

6. 告警推送与手机端接收:怎么让通知真正有用

6.1 推送通道的选择

告警推送的通道选择直接决定了这套系统"有没有用"。如果推送不及时或者被系统拦截,那再好的监测逻辑也白搭。

我试过几种方案。邮件推送最稳定但延迟高,而且手机邮件通知容易被忽略。短信推送需要第三方服务,有成本。即时通讯工具的机器人推送延迟低、免费、手机通知醒目,是我最终采用的方案。具体做法是在即时通讯工具里创建一个机器人,通过 Webhook 把告警消息 POST 过去,手机端就能收到实时通知。

推送消息的格式我做了精心设计,包含:设备 ID、告警类型、当前温度/湿度值、发生时间、建议操作。比如:

[冰箱告警] 冷藏室温度异常 当前温度:11.2°C(阈值:10°C) 持续时间:6分钟 时间:14:32 建议:检查冰箱门是否关严,或确认制冷是否正常

这样的消息一眼就能看懂发生了什么、严重程度如何、该做什么。

6.2 告警抑制与分级

告警系统最容易犯的错误是"告警风暴"——同一个问题反复推送,用户很快就麻木了。我加了两层抑制机制。

第一层是同类告警冷却时间。同一个类型的告警,在 30 分钟内只推送一次。如果 30 分钟后问题依然存在,再推一次提醒。这样既不会漏掉持续性问题,也不会刷屏。

第二层是告警分级。我把告警分成三个级别:

级别触发条件推送方式示例
提醒预警阈值普通通知温度偏高
警告告警阈值高优先级通知温度失温
紧急多重异常同时触发高优先级+重复推送门开+温度骤升

紧急级别只在多个异常同时出现时触发,比如门磁显示门开着同时温度快速上升,这基本可以确定是门没关导致的失温,需要立即处理。

6.3 数据记录与趋势查看

光有告警还不够,我还希望能在手机上看温度趋势曲线。做法是把每次上报的数据同时存一份到本地数据库(我用的是轻量级的时序数据库),然后做一个简单的 Web 页面展示曲线。

这个页面不需要多复杂,能看最近 24 小时的温度曲线、标注出告警时间点就够了。有了趋势图,你能直观地看出冰箱的运行规律——什么时候压缩机启动、什么时候化霜、温度波动是否正常。这些信息对于判断冰箱健康状态非常有价值。

7. 外壳与安装:让这套东西看起来不像"实验品"

7.1 外壳设计的基本考量

电子项目做出来能不能长期用,外壳很关键。裸板放在冰箱旁边,一来不美观,二来容易积灰受潮,三来家里有小孩的话可能被拽下来。

我用 3D 打印做了一个简单的外壳,设计时考虑了这几点:散热孔开在侧面而不是顶部(防止灰尘直接落入)、传感器引线出口做防水弯(引线向下弯再出去,防止水顺着线流进盒子)、预留 USB 调试口(不用拆壳就能插线调试)。外壳材料用 PLA 就够,如果环境潮湿可以考虑 PETG。

如果你没有 3D 打印机,用现成的防水接线盒改造也行,关键是保证传感器引线出口的防水处理。

7.2 传感器在冰箱内的固定方式

冷藏室的 SHT31 我用一个小的塑料支架固定在中间层搁板侧面,不要贴在冰箱内壁上——内壁温度受制冷管影响,读数不能代表空气温度。也不要放在最上层或最下层,这两个位置温度分布不均匀。中间层、远离内壁、不挡风道的位置是最佳选择。

冷冻室的 DS18B20 探头我用扎带固定在冷冻室中间位置的搁架上,同样避开内壁和出风口。如果你放了多个探头,可以一个放中间、一个放靠近门的位置,这样能监测温度分布是否均匀。

7.3 走线处理

传感器引线从冰箱内部到外部,需要经过门封条或者专门的穿线孔。走门封条的话,要选扁平排线,从门封条缝隙穿过去,对密封性影响最小。走穿线孔的话,穿完之后要用密封胶把孔封好,防止冷气外泄。

引线在冰箱外部要留一段滴水弯——线先向下垂一段再往上走,这样冷凝水会滴在弯的最低点,不会顺着线流进设备盒。

8. 后续可以怎么扩展

这套系统跑了大半年,稳定性我很满意。如果你也想做,或者已经做出来了想继续折腾,有几个方向可以扩展。

第一个方向是加压缩机电流检测。用一个非侵入式的电流互感器夹在压缩机供电线上,监测压缩机的工作电流和启停周期。如果发现压缩机启停频率异常增高,往往意味着制冷效率下降或者门封有问题,这是比温度更早期的预警信号。

第二个方向是多节点组网。如果你家里有多个冰箱、冷柜、酒柜,可以用多个 ESP32 节点,通过 MQTT 统一上报到一个中心,在手机端统一查看。每个节点的固件可以完全一样,只需要改一下 device_id。

第三个方向是本地边缘判断。现在的告警逻辑都在 ESP32 本地做,这已经比纯云端方案可靠了。但如果想更智能,可以在本地加一些简单的机器学习——比如学习你家冰箱的正常温度波动模式,然后检测偏离这个模式的异常。ESP32 跑 TinyML 模型是可行的,不过这个就属于进阶玩法了。

第四个方向是断电检测与备用电源。冰箱断电是另一个常见故障场景。可以加一个电压检测电路监测市电,断电时立即推送告警,同时切换到备用电池维持监测。这样即使停电,你也能知道冰箱已经断电多久、内部温度上升到了多少。

我个人在实际操作中的体会是,这类项目的价值不在于技术多复杂,而在于它真正解决了一个你会在意的问题。冰箱监测听起来简单,但当你出差在外收到一条"冷藏室温度异常"的告警,远程指导家人处理,避免了一整箱食材的损失时,这套东西的价值就体现出来了。硬件成本不到一百块,换来的是对家里最重要食材储存设备的持续掌控,这笔账怎么算都划算。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询