基于ESP32与多传感器融合的饮品重量温度监控器设计与实现

📅 2026/8/19 2:45:33
基于ESP32与多传感器融合的饮品重量温度监控器设计与实现
1. 项目缘起为什么我们需要一个饮品重量与温度监控器几年前我还在一个硬件创业团队里折腾当时我们想做一个智能咖啡杯。团队里有个哥们每天早上雷打不动要喝一杯手冲水温、粉水比、萃取时间讲究得不行。他总抱怨办公室的饮水机水温不准自己烧水又得盯着温度计冲咖啡时还得用电子秤称重一套流程下来手忙脚乱。我当时就想能不能把这些零散的步骤整合到一个设备里一个能实时告诉你“水烧到93度了可以冲了”并且能精确计量“已经注入了150克热水”的工具。这个想法就是今天这个“饮品重量与温度监控器”项目的雏形。后来项目虽然没继续但这个需求场景我一直记着。它远不止于咖啡。想想看给宝宝冲奶粉需要特定温度的水和精确的奶粉克数在家小酌调一杯鸡尾酒需要精准的基酒和配比甚至只是日常喝水想监控自己一天的饮水量和水温是否适宜。一个能同时感知重量和温度的设备就像一个沉默的助手让这些需要“量化”和“控温”的场景变得简单、优雅。所以这个项目本质上是一个多传感器数据融合的物联网终端。它通过高精度的称重传感器和温度传感器实时采集物理世界的状态再通过微控制器进行处理和显示甚至可以通过无线模块将数据同步到你的手机。它不只是一个玩具而是一个能切实融入生活、提升体验的实用工具。无论你是硬件爱好者想练手还是生活达人想打造个性化装备这个项目都值得一试。接下来我会带你从零开始拆解它的每一个技术细节和实现步骤。2. 核心硬件选型传感器、主控与供电的权衡硬件是项目的骨架选型直接决定了最终成品的精度、稳定性和成本。我们需要三个核心部件称重模块、温度传感器、微控制器。此外供电和显示也是必须考虑的。2.1 称重模块HX711与应变片式传感器称重是精度要求最高的部分。业余电子项目里最成熟、性价比最高的方案是应变片式称重传感器配合HX711模数转换芯片。为什么是应变片应变片是一种电阻值会随着其附着物形变而变化的元件。我们将它粘贴在一个金属弹性体通常是铝合金上当弹性体受力弯曲时应变片的电阻值会发生微小的、线性的变化。市面上常见的“单点式称重传感器”或“悬臂梁式传感器”内部就是这种结构。它的优点是量程选择多从500g到50kg都有、线性度好、价格便宜。为什么是HX711应变片电阻的变化极其微弱直接用单片机的ADC模数转换器去读取噪声会淹没信号。HX711是一款专为电子秤设计的24位高精度ADC芯片。它内部集成了可编程增益放大器能把这个微弱的信号放大并转换成数字信号通过简单的两线串行接口DT和SCK发送给单片机。其24位的分辨率意味着它能将满量程信号划分为2^24约1677万个等级对于家用级别的称重精度到0.1g或1g绰绰有余。注意购买传感器时一定要关注其“额定负载”和“灵敏度”。例如一个额定负载1kg灵敏度1.0mV/V的传感器在5V激励电压下满负载时最大输出信号只有5mV。HX711正是为放大这种毫伏级信号而生的。实操心得我推荐使用常见的“5kg单点式传感器”搭配一个HX711模块。模块已经帮你做好了稳压、滤波和接口引出直接用杜邦线连接单片机即可省去了自己设计放大电路的麻烦。初次使用前最好用标准砝码比如100g、500g进行一次简单的校准记录下空载和满载时的ADC原始读数用于后续的软件标定。2.2 温度传感器DS18B20与它的挑战者温度测量看似简单但在液体、尤其是可能飞溅的饮品环境中可靠性和封装是关键。DS18B20经典之选。这是一款单总线数字温度传感器意味着只需要一根数据线外加电源和地线就能与单片机通信。它出厂已校准精度可达±0.5°C且具有唯一的64位ROM地址允许在同一条总线上挂载多个传感器。其不锈钢封装探头版本非常适合液体测温。它的缺点是通信时序要求较严格且单总线协议在代码编写上需要一些技巧。挑战者防水型NTC热敏电阻。NTC负温度系数热敏电阻的电阻值随温度升高而降低。你需要搭配一个固定电阻组成分压电路利用单片机的ADC读取电压值再通过查表或公式计算温度。它的优点是成本极低响应可能更快。但缺点是需要额外的ADC通道如果单片机ADC不够用且每个NTC的阻值有偏差需要单独校准。防水封装好的NTC探头也很常见。我的选择与理由对于这个项目我更倾向于DS18B20。原因有三第一数字接口抗干扰能力强长导线传输更稳定第二免去了ADC和校准的麻烦开箱即用第三其不锈钢探头可以直接浸入液体安全卫生。虽然编程稍复杂但有成熟的库如OneWire, DallasTemperature支持实际使用并不难。2.3 微控制器ESP32的全面胜出主控芯片是大脑需要在性能、接口、功耗和成本间平衡。候选人有Arduino UnoATmega328P、ESP8266和ESP32。Arduino Uno经典生态好但资源有限2KB RAM32KB Flash没有内置Wi-Fi/蓝牙需要额外模块且ADC精度一般。ESP8266性价比之王内置Wi-Fi性能远超Uno但ADC只有10位且仅有一个通道同时读取重量HX711用数字接口和温度如果用NTC会受限。ESP32全面升级版。双核处理器更丰富的GPIO多个12位ADC通道更重要的是同时集成了Wi-Fi和蓝牙。这意味着我们不仅可以本地显示还能轻松地将数据发送到手机App或云端实现远程监控和历史记录。结论显而易见ESP32是该项目的最佳选择。它提供了未来功能扩展的所有可能性如OTA升级、连接智能家居平台而价格与ESP8266相差无几。我们使用它的一个核心Core 0来处理传感器数据、驱动显示另一个核心Core 1可以专门处理网络通信互不干扰系统更流畅。2.4 供电、显示与结构供电考虑到可能移动使用一个18650锂电池搭配充放电管理模块是最佳方案。选择带有TP4056充电芯片和DW01A保护芯片的模块它可以安全地充电并在电池过放、过流时切断输出保护电池。ESP32的工作电压是3.3V而18650电池满电约4.2V所以需要一个降压模块如AMS1117-3.3将电压稳定在3.3V。HX711和DS18B20也兼容3.3V供电。显示一个0.96英寸或1.3英寸的OLED屏幕I2C接口足够显示当前重量、温度和一些状态信息。OLED自发光的特性使其在暗光环境下也有很好的可视性且功耗低。I2C接口只需要两根数据线节省GPIO。结构这是项目从“开发板堆叠”走向“产品化”的关键。你需要设计或购买一个容器来放置杯具。核心思路是将称重传感器固定在底座测温探头通过支架悬置于容器上方或侧方可浸入液体的位置主控和屏幕集成在底座或侧面。可以使用亚克力板激光切割或者用3D打印来制作外壳确保传感器只承受垂直方向的力避免侧向力影响精度。3. 电路连接与系统集成从原理图到实物选好器件后我们需要把它们正确地连接起来。下面是一个基于ESP32的核心连接示意图。接线表元件引脚/接口连接到ESP32说明HX711模块VCC3.3V电源正极GNDGND电源地DTGPIO 16数据线SCKGPIO 4时钟线DS18B20VDD (红)3.3V电源正极GND (黑)GND电源地DATA (黄)GPIO 17数据线需接4.7K上拉电阻至3.3VOLED (I2C)VCC3.3V电源正极GNDGND电源地SDAGPIO 21I2C数据线SCLGPIO 22I2C时钟线锂电池管理模块BAT18650电池正极BAT-18650电池负极OUT降压模块IN输出约3.7-4.2VOUT-降压模块IN-降压模块 (至3.3V)IN管理模块OUTIN-管理模块OUT-OUT所有元件的3.3V系统主供电OUT-所有元件的GND系统地关键细节与避坑指南共地与电源滤波务必确保所有模块的GND地线都连接在一起形成一个共同的参考地。在ESP32的3.3V输入引脚附近建议并联一个100μF的电解电容和一个0.1μF的陶瓷电容用于滤除电源噪声这对ADC和传感器读数稳定性至关重要。DS18B20的上拉电阻单总线协议要求数据线在空闲时保持高电平。必须在DS18B20的数据线和3.3V电源之间连接一个4.7KΩ的上拉电阻否则通信会失败。很多防水探头内部没有这个电阻需要自己外接。HX711的速率选择HX711模块上通常有一个跳线帽用于选择输出数据速率10Hz或80Hz。对于称重这种变化相对缓慢的信号选择10Hz即可它具有更好的噪声抑制能力。机械安装的隔离在焊接和安装时确保称重传感器只承受垂直方向的压力。固定传感器的底座和承载平台之间最好用螺丝配合橡胶垫圈避免硬连接传递侧向应力或振动。测温探头要固定牢靠防止其重量或晃动影响到称重传感器。4. 软件逻辑与代码实现驱动、滤波与校准硬件连接好后大脑程序需要知道如何与器官传感器对话并理解它们传来的信息。4.1 开发环境与库准备我们使用Arduino IDE进行开发。首先需要安装ESP32的开发板支持。然后在“工具-管理库”中搜索并安装以下库HX711_ADC用于驱动HX711它提供了校准、去皮、稳定读数等高级功能比基础库更易用。OneWire DallasTemperature前者是单总线协议驱动后者是DS18B20的专用库简化温度读取。Adafruit SSD1306 Adafruit GFX用于驱动OLED屏幕显示图形和文字。4.2 核心代码流程解析程序的整体逻辑是一个循环主要包含初始化、数据读取、滤波处理、显示和网络上报如果启用几个部分。#include HX711_ADC.h #include OneWire.h #include DallasTemperature.h #include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h // 引脚定义 #define HX711_DT 16 #define HX711_SCK 4 #define ONE_WIRE_BUS 17 // 对象初始化 HX711_ADC LoadCell(HX711_DT, HX711_SCK); OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(oneWire); Adafruit_SSD1306 display(128, 64, Wire, -1); // 全局变量 float weight 0.0; float temperature 0.0; unsigned long lastUpdate 0; const long updateInterval 200; // 更新间隔200ms void setup() { Serial.begin(115200); // 初始化称重传感器 LoadCell.begin(); LoadCell.start(2000); // 启动并稳定2秒 LoadCell.setCalFactor(696.0); // 设置校准因子这个值后续通过校准得出 // 初始化温度传感器 sensors.begin(); // 初始化OLED if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F(SSD1306 allocation failed)); for(;;); } display.clearDisplay(); display.setTextSize(2); display.setTextColor(SSD1306_WHITE); Serial.println(System Ready.); } void loop() { unsigned long currentMillis millis(); // 定时更新数据 if (currentMillis - lastUpdate updateInterval) { lastUpdate currentMillis; // 1. 读取重量非阻塞式 if (LoadCell.update()) { weight LoadCell.getData(); // 获取已滤波的数据 } // 2. 读取温度 sensors.requestTemperatures(); temperature sensors.getTempCByIndex(0); // 获取第一个传感器的摄氏温度 // 3. 数据处理与显示 updateDisplay(); // 4. 可选通过网络发送数据 // sendDataToServer(weight, temperature); } } void updateDisplay() { display.clearDisplay(); display.setCursor(0, 0); display.print(W:); display.print(weight, 1); // 显示一位小数 display.print( g); display.setCursor(0, 25); display.print(T:); display.print(temperature, 1); // 显示一位小数 display.print( C); // 可以添加一些状态指示比如电池图标 display.display(); }4.3 传感器的校准让数据变得可信未经校准的传感器读数毫无意义。校准是赋予其“标尺”的过程。称重传感器校准将传感器空载不放任何东西运行程序记录下LoadCell.getData()的原始读数raw_zero。放置一个已知重量的标准砝码如500.0g再次记录稳定后的读数raw_weight。计算校准因子calibration_factor (raw_weight - raw_zero) / 已知重量。在setup()中使用LoadCell.setCalFactor(calibration_factor)设置这个因子。重新上电测试空载和加载砝码看显示是否准确。可以多次微调因子以达到最佳精度。实操心得校准环境很重要。确保传感器放置水平、稳定无风吹或振动。校准用的砝码越精确越好。HX711_ADC库也提供了tare()函数可以随时执行“去皮”操作将当前重量设为零点非常实用。温度传感器校准DS18B20出厂精度已经很高但如果追求极致可以用一个高精度温度计作为参考。将两者同时放入冰水混合物0°C和沸水当地沸点考虑海拔中记录DS18B20的读数计算出一个偏移量offset在代码中读取温度后加上这个偏移值即可。4.4 数字滤波从波动中提取真实信号传感器原始数据难免有噪声。直接显示会跳变严重用户体验极差。必须进行软件滤波。对于重量数据HX711_ADC库内部已经实现了移动平均滤波。LoadCell.getData()返回的已经是滤波后的稳定值。你可以通过LoadCell.setSamplesInUse(4)来设置用于平均的样本数数值越大越平滑但响应越慢需要根据实际抖动情况调整。对于温度数据DS18B20的读数相对稳定但也可以采用简单的一阶低通滤波指数加权平均float filteredTemp 0.9 * filteredTemp 0.1 * currentTemp; // 0.9和0.1是滤波系数这个公式让新读数的影响占10%历史滤波值占90%能有效平滑毛刺系数可以根据需要调整。更高级的融合在某些场景下你甚至可以基于重量变化的速率来辅助判断温度读数的有效性。例如当重量急剧增加正在倒水时温度传感器可能还未与液体充分热平衡此时可以延迟更新显示的温度或给出“测温中”的提示。5. 功能扩展与场景化应用基础功能实现后这个平台就像一块璞玉可以根据不同场景进行雕琢衍生出许多有趣的应用。5.1 无线连接与数据可视化ESP32的核心优势这是让项目从“本地工具”升级为“智能设备”的关键一步。利用ESP32的Wi-Fi功能我们可以轻松地将数据发送出去。Web服务器模式让ESP32自己作为一个Wi-Fi热点手机连接后访问一个简单的网页就能看到实时数据和图表。适合没有外部网络的环境。MQTT协议上报将数据发布到MQTT服务器如本地搭建的Mosquitto或云服务如EMQX Cloud。然后你可以用Node-RED这样的工具订阅数据并制作出精美的仪表盘或者在数据达到阈值时发送手机通知。对接云平台直接将数据发送到物联网云平台如阿里云IoT、ThingsBoard等。这些平台提供了完整的数据存储、分析和可视化套件。一个简单的MQTT上报代码片段#include WiFi.h #include PubSubClient.h const char* ssid 你的Wi-Fi; const char* password 你的密码; const char* mqtt_server broker.hivemq.com; // 示例公共服务器 WiFiClient espClient; PubSubClient client(espClient); void setup_wifi() { WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } } void reconnect() { while (!client.connected()) { if (client.connect(DrinkMonitorClient)) { client.publish(home/drink/weight, String(weight).c_str()); client.publish(home/drink/temp, String(temperature).c_str()); } else { delay(5000); } } } // 在loop()中连接成功后定期发布数据 if (client.connected()) { client.loop(); static unsigned long lastPub 0; if (millis() - lastPub 5000) { // 每5秒发布一次 lastPub millis(); client.publish(home/drink/weight, String(weight).c_str()); client.publish(home/drink/temp, String(temperature).c_str()); } }5.2 场景一智能冲煮助手针对咖啡、茶等场景可以预置配方。例如在代码中定义一个结构体struct Recipe { String name; float targetWeight; float targetTemp; int bloomTime; // 焖蒸时间 }; Recipe myCoffee {手冲咖啡, 300.0, 93.0, 30};然后在OLED屏幕上不仅显示当前值还显示目标值和进度条。当检测到重量开始增加开始注水时启动一个定时器并在达到目标重量时发出提示音可以用ESP32的PWM驱动一个蜂鸣器。5.3 场景二饮水习惯追踪长时间监测一个水杯的重量变化。程序可以记录每次重量显著下降喝水的时间和量并估算出总摄入量。通过Wi-Fi将每日数据汇总生成简单的饮水报告。甚至可以设置提醒“您已两小时未饮水当前水温25°C适宜饮用。”5.4 场景三实验室或厨房的通用计量工具将其作为一个高精度的温度和重量记录仪。通过SD卡模块将时间戳、重量、温度数据记录到文件中用于实验数据分析或烹饪过程复盘。6. 调试、优化与量产化思考即使代码烧录成功硬件组装完毕距离一个稳定可靠的产品还有一段路要走。6.1 常见问题与调试重量读数漂移或不准检查供电电池电压是否充足3.3V稳压输出是否稳定用万用表测量。电压波动是HX711读数不稳的首要原因。检查机械结构传感器是否安装平稳有无侧向力承载平台是否触碰其他物体检查滤波参数HX711的采样速率和滤波样本数是否合适在setup()中增加LoadCell.setSamplesInUse(8)试试。接地与屏蔽传感器信号线是否远离电源线尝试用铝箔包裹HX711模块并接地屏蔽电磁干扰。DS18B20读取失败返回-127或85检查接线这是最常见的问题。确认VCC、GND、DATA线是否正确4.7K上拉电阻是否接在DATA和3.3V之间。检查电源确保3.3V电源能提供足够电流。可以尝试在DS18B20的VCC和GND之间并联一个0.1uF电容。代码排查使用oneWire.search()函数搜索总线上的设备地址确认传感器是否被正确识别。OLED屏幕不显示检查地址I2C设备有地址。使用I2C扫描程序Arduino IDE有示例确认OLED的地址是否是代码中写的0x3C常见或0x3D。检查电源OLED模块是否供电有些模块需要5V有些3.3V确认你的供电电压匹配。6.2 功耗优化如果希望电池续航更久必须优化功耗。降低工作频率ESP32可以降低CPU主频setCpuFrequencyMhz(80)。使用深度睡眠如果没有无线传输需求可以在闲置一段时间后让ESP32进入深度睡眠仅通过外部中断如称重传感器数值变化唤醒。但这需要更复杂的电路设计来保持HX711的状态。间歇性工作对于饮水监测这类场景可以每10秒唤醒一次读取数据如果变化不大立刻又进入睡眠。关闭不用的外设在初始化时可以关闭ESP32的蓝牙模块。6.3 从原型到产品量产化考量如果你真的想把它做成一个可以送朋友的小礼物需要考虑PCB设计用EDA软件如立创EDA将ESP32、HX711、电源管理等电路集成到一块定制PCB上取代杜邦线和面包板体积更小可靠性极大提升。结构设计使用3D建模软件如Fusion 360设计一个美观、坚固的外壳将传感器、PCB、电池仓、屏幕开口都精确规划好。防水防潮如果用于水杯附近PCB需要做三防漆防潮、防霉、防盐雾处理外壳接缝处可能需要硅胶密封圈。用户交互增加1-2个实体按键用于切换模式、去皮、清零等操作比纯代码控制更直观。固件升级OTA利用ESP32的OTA功能未来可以通过Wi-Fi直接推送新固件修复bug或增加功能无需再连接数据线。这个“饮品重量与温度监控器”项目就像一把钥匙打开了一扇通往物理世界数据化的大门。它融合了传感器技术、嵌入式编程和无线通信是一个绝佳的综合性实践。从看到一个个跳动的数字到它们最终稳定、准确地反映出一杯水的温度和重量这个过程充满了工程师独有的乐趣。希望这份详尽的拆解能帮你少走弯路更快地享受到自己动手创造智能工具的成就感。