
1. 项目缘起为什么我要用Arduino测加湿器效率去年冬天我家里那台用了好几年的超声波加湿器突然变得有点“不给力”。明明水箱里的水在肉眼可见地减少但放在房间另一头的湿度计读数却爬升得异常缓慢。我开始怀疑是不是机器老化导致效率下降了或者我买的这台机器其标称的“300ml/h加湿量”从一开始就是个虚标参数作为一个喜欢动手折腾的电子爱好者我第一个念头不是去查评测而是能不能自己动手搭建一个系统来客观、量化地测量它的真实效率这就是今天要分享的这个项目的由来基于Arduino的加湿器效率测定系统。简单来说就是利用Arduino微控制器配合温湿度传感器实时监测加湿器工作前后环境湿度的变化并结合时间、加湿器水箱的水位或重量变化计算出它单位时间内向空气中实际添加了多少水分从而评估其效率。你可能会问买个专业的温湿度记录仪不行吗当然可以但那只能看到湿度变化曲线无法直接与加湿器的“投入”消耗的水关联起来计算效率。我们这个DIY系统的核心价值在于建立“输入-输出”的量化关系。输入是加湿器消耗的水量通过称重或水位传感获得输出是环境湿度的实际提升通过传感器阵列获得。通过Arduino将这两组数据同步采集、记录并处理我们就能得到诸如“每消耗1毫升水能将1立方米空间的湿度提升多少百分比”这样的硬核指标。这个项目非常适合对智能家居、环境监测或Arduino编程感兴趣的玩家。它不只是一个简单的数据记录更涉及传感器选型、数据采集同步、简单的物理模型建立以及数据处理分析等多个环节。无论你是想验证自家加湿器的性能还是作为一个综合性的电子制作练手项目它都能带来十足的乐趣和成就感。接下来我就把从构思、选件、搭建到数据分析的全过程毫无保留地拆解给你看。2. 系统核心设计测量什么如何测量在动手写代码和接线之前我们必须先把测量原理和系统架构想清楚。加湿器的“效率”是一个比较宽泛的概念在我们的DIY语境下我将其定义为“加湿器将电能和水转化为空气中水蒸气的有效速率”。要量化这个速率我们需要测量两个最关键的物理量水量消耗和湿度变化。2.1 核心测量参数的确定水量消耗这是加湿器的“输入”。最直接的方法就是测量加湿器工作一段时间前后水箱的重量差。为此我们需要一个称重传感器比如常见的HX711模块搭配电阻应变式称重传感器。另一种间接方法是监测水位变化使用超声波测距模块测量水箱液面高度再根据水箱横截面积换算体积。考虑到水箱形状可能不规则且水位传感器安装复杂称重法是更通用、更准确的选择。我们将采用一个量程在5kg左右的传感器精度能达到1克对于测量几百毫升的水量消耗绰绰有余。湿度变化这是加湿器的“输出”。我们需要知道加湿器工作时其影响范围内的空气湿度是如何随时间变化的。这里有几个关键点传感器选型DHT22或SHT31是常见选择。DHT22成本低但响应速度和精度一般SHT31更贵但精度和稳定性好得多。为了获得更可靠的数据我选择了SHT31。传感器布点加湿器的出雾口湿度接近100%但这没有意义。我们需要测量的是房间整体混合后的湿度。因此传感器应放置在距离加湿器一定距离如1-2米、与出雾口高度相当、且空气流通相对顺畅的位置。为了更科学我甚至建议使用两个传感器一个放在加湿器近处监测输出强度一个放在房间远端监测整体效果通过对比可以评估加湿器的空间均匀性。采样频率湿度变化相对较慢每秒采样1次1Hz完全足够。过高的采样率只会产生海量冗余数据。2.2 系统整体架构与组件清单基于以上分析系统的硬件架构就清晰了主控单元Arduino Uno R3。它接口丰富社区支持强大完全能满足本项目的需求。数据采集单元称重模块HX711 ADC转换模块 5kg电阻应变式称重传感器。用于高精度测量水箱重量变化。温湿度传感单元1-2个SHT31温湿度传感器I2C接口。用于监测环境湿度变化。数据记录单元Micro SD卡模块。用于将采集到的重量、湿度、时间戳数据以CSV格式存储到SD卡中便于后续在电脑上分析。辅助单元实时时钟模块DS3231。为每一次数据记录提供精确的时间戳这对于计算速率至关重要。OLED显示屏0.96寸I2C OLED。用于实时显示当前重量、湿度、运行时间等关键信息方便现场监控。按键用于启动/停止记录、清零皮重等操作。所有组件通过一块面包板或PCB连接由一台5V/2A的手机充电器供电确保系统长时间稳定运行。整个系统的数据流是这样的加湿器水箱放在称重传感器上Arduino周期性地读取重量和湿度值附加上RTC提供的时间戳然后将这一行数据时间重量湿度1湿度2写入SD卡同时在OLED上更新显示。3. 硬件搭建与电路连接详解理论设计完成后就到了动手环节。硬件连接是项目的基础务必仔细。3.1 分模块接线指南我将整个系统分解为几个核心模块逐一连接这样可以降低出错概率。1. Arduino Uno 基础供电与I2C总线搭建首先将Arduino的5V和GND引脚引到面包板的电源轨上为所有模块供电。I2C总线是本次项目的“主干道”SHT31、DS3231、OLED都使用I2C通信。将它们并联接入SDA- ArduinoA4引脚SCL- ArduinoA5引脚 每个I2C设备都有唯一的地址需要提前确认。例如SHT31默认地址是0x44DS3231是0x68OLED通常是0x3C。如果使用两个SHT31其中一个的地址可以通过改变引脚电平来修改。2. HX711称重传感器连接这是接线中需要特别注意的部分。HX711模块将称重传感器的模拟信号转换为数字信号。HX711模块 → ArduinoVCC-5VGND-GNDDT(数据) - 数字引脚3SCK(时钟) - 数字引脚2称重传感器 → HX711模块传感器通常有4根线红(E)、黑(E-)、白(S)、绿(S-)。红线接HX711的E黑线接E-。白线接A绿线接A-。如果读数出现负值可以交换白绿线。3. Micro SD卡模块连接SD卡模块使用SPI通信。VCC-5VGND-GNDCS(片选) - 数字引脚10MOSI- 数字引脚11MISO- 数字引脚12SCK- 数字引脚134. 其他组件按键一端接GND另一端接数字引脚如7并在该引脚启用Arduino内部上拉电阻。OLED除了接入I2C总线SDA, SCL其VCC接5VGND接GND。重要提示在连接所有线缆之前务必断开电源。所有连接务必牢固接触不良是硬件项目最常见的“玄学”bug来源。建议使用质量较好的杜邦线并在连接完成后仔细检查两遍。3.2 结构组装与物理布置电路连接好后物理结构同样重要。称重平台将称重传感器牢固地粘贴或固定在一個平整、坚固的底座如一块亚克力板上。传感器上方的承重板放置加湿器水箱必须只与传感器的受力点接触确保力垂直传递避免侧向力影响精度。传感器屏蔽SHT31对周围空气流动敏感。不要把它直接放在加湿器的出雾路径上否则凝结的水珠会损坏传感器。可以给它加一个简单的塑料防护罩罩上开一些小孔以保证空气流通。整体布局将Arduino、面包板、模块等整合到一个盒子里但为称重传感器和温湿度传感器留出接口和空间。确保加湿器工作时产生的水雾不会直接喷溅到电子设备上。4. 软件逻辑与核心代码实现硬件是躯体软件是灵魂。本项目的代码主要完成初始化、数据采集、存储和显示四大功能。4.1 库文件管理与初始化首先在Arduino IDE中安装所有必需的库HX711_ADC用于驱动称重传感器。Adafruit_SHT31用于驱动SHT31传感器。RTClib用于驱动DS3231 RTC。SDArduino内置SD卡库。Adafruit_GFXAdafruit_SSD1306用于驱动OLED。初始化部分的关键在于设置稳定的采样率和处理好各模块的启动。#include HX711_ADC.h #include Adafruit_SHT31.h #include RTClib.h #include SD.h #include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h // 引脚定义 const int HX711_dout 3; const int HX711_sck 2; const int sdChipSelect 10; // 对象声明 HX711_ADC LoadCell(HX711_dout, HX711_sck); Adafruit_SHT31 sht31 Adafruit_SHT31(); RTC_DS3231 rtc; Adafruit_SSD1306 display(128, 64, Wire, -1); File dataFile; unsigned long lastLogTime 0; const long logInterval 1000; // 记录间隔1000毫秒 1秒 float tareWeight 0; // 皮重空水箱承重板重量 void setup() { Serial.begin(9600); Wire.begin(); // 1. 初始化OLED if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F(SSD1306 allocation failed)); for(;;); } display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0,0); display.println(System Booting...); display.display(); // 2. 初始化称重传感器 LoadCell.begin(); long stabilisingtime 2000; // 初始稳定时间 LoadCell.start(stabilisingtime); LoadCell.setCalFactor(415.0); // 校准因子需通过校准获得 LoadCell.tare(); // 执行去皮 // 3. 初始化SHT31 if (!sht31.begin(0x44)) { display.clearDisplay(); display.setCursor(0,0); display.println(SHT31 Init FAIL!); display.display(); while (1); } // 4. 初始化RTC if (!rtc.begin()) { display.clearDisplay(); display.setCursor(0,0); display.println(RTC Init FAIL!); display.display(); while (1); } if (rtc.lostPower()) { // 如果RTC失电可以在这里设置时间例如rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } // 5. 初始化SD卡 if (!SD.begin(sdChipSelect)) { display.clearDisplay(); display.setCursor(0,0); display.println(SD Card FAIL!); display.display(); while (1); } // 6. 创建数据文件如果不存在 dataFile SD.open(humidifier.csv, FILE_WRITE); if (dataFile) { // 写入CSV表头 dataFile.println(Timestamp, Weight(g), Humidity1(%), Temp1(C), Humidity2(%), Temp2(C)); dataFile.close(); } display.clearDisplay(); display.setCursor(0,0); display.println(System Ready.); display.display(); delay(1000); }4.2 主循环数据采集、记录与显示逻辑主循环以固定的时间间隔如1秒执行核心是读取数据、格式化、存储和显示。void loop() { unsigned long currentMillis millis(); // 到达记录间隔时间 if (currentMillis - lastLogTime logInterval) { lastLogTime currentMillis; // 1. 读取称重数据 LoadCell.update(); // 获取最新数据 float currentWeight LoadCell.getData(); // 单位克 float netWeight currentWeight - tareWeight; // 净重水的重量 // 2. 读取温湿度数据 float humidity1 sht31.readHumidity(); float temp1 sht31.readTemperature(); // 3. 获取当前时间 DateTime now rtc.now(); // 4. 格式化数据为CSV一行 String dataString ; dataString String(now.year()) / String(now.month()) / String(now.day()); dataString String(now.hour()) : String(now.minute()) : String(now.second()); dataString ,; dataString String(netWeight, 1); // 重量保留1位小数 dataString ,; dataString String(humidity1, 1); // 湿度保留1位小数 dataString ,; String(temp1, 1); // 如果有第二个传感器在这里读取并追加 // 5. 写入SD卡 dataFile SD.open(humidifier.csv, FILE_WRITE); if (dataFile) { dataFile.println(dataString); dataFile.close(); } // 6. 更新OLED显示 display.clearDisplay(); display.setCursor(0,0); display.print(W:); display.print(netWeight, 1); display.println( g); display.print(H:); display.print(humidity1, 1); display.println( %); display.print(T:); display.print(temp1, 1); display.println( C); display.print(now.hour()); display.print(:); display.print(now.minute()); display.print(:); display.println(now.second()); display.display(); } // 处理按键事件例如按一下按键将当前重量设为皮重 // ... 按键检测代码 ... }关键技巧数据稳定性处理。对于称重数据HX711_ADC库提供了getData()函数它内部已经做了一些平滑处理。但对于需要更高稳定性的场合可以在代码中实现一个简单的移动平均滤波例如连续读取5次取平均值。对于SHT31单次读取精度已经很高通常不需要额外滤波。5. 校准与测试让数据值得信赖在正式测量加湿器之前我们必须对系统进行校准确保每一个读数都真实可靠。5.1 称重传感器的校准这是最关键的一步。校准的目的是找到正确的CalFactor校准因子。准备已知重量的砝码最好是100g、200g、500g的标准砝码。如果没有可以用未开封的矿泉水如500ml≈500g作为替代但精度会稍差。执行校准程序在setup()函数中或通过一个单独的校准按键来触发。核心是使用LoadCell.getCalFactor()的初始值然后通过已知重量来修正它。许多HX711库的示例代码中都包含校准例程。基本逻辑是先去皮tare()然后放上已知重量的砝码调用LoadCell.refreshDataSet()和LoadCell.getNewCalibration(known_weight)来计算出新的CalFactor。验证校准结果用不同重量的砝码测试看读数是否准确。将最终得到的、稳定的CalFactor值比如上面代码中的415.0硬编码到setup()的LoadCell.setCalFactor()函数中。5.2 温湿度传感器的交叉验证SHT31虽然精度高但出厂也有偏差。我们可以用一个经过校验的、精度较高的温湿度计作为参考在稳定的室内环境中同时读取DIY系统和参考仪器的数值记录下偏差。这个偏差值可以在后期数据处理时进行软件补偿。更重要的是检查传感器的响应速度。可以用一个湿毛巾靠近传感器观察读数变化是否灵敏、平滑排除传感器老化或接触不良的问题。5.3 系统集成测试与“空跑”在连接加湿器之前进行长时间例如2-4小时的“空跑”测试。目的检查系统长时间运行的稳定性SD卡写入是否正常数据有无异常跳变是否存在内存泄漏表现为运行一段时间后死机。方法将加湿器水箱装满水放在称重平台上但不开机。让系统持续记录重量和湿度。理想情况下重量读数应基本稳定可能有极微小的波动湿度读数应随室内环境正常缓慢变化。检查生成的CSV文件看数据是否连续时间戳是否正确递增。6. 正式实验与数据采集流程校准测试无误后就可以进行正式的加湿器效率测量实验了。一个科学的实验流程能极大提升数据的可信度。6.1 实验环境设置与基线记录环境封闭选择一个大小适中的房间比如15-20平方米的卧室关闭门窗尽量减少空气交换。记录下房间的近似体积长×宽×高后续计算会用到。设备布置将加湿器放在房间中央位置。称重平台置于其下。主传感器SHT31-1放置在距离加湿器1.5米左右、高度约1米的位置。辅助传感器SHT31-2可以放在房间角落或远端。记录初始状态启动数据记录系统让加湿器处于关闭状态。持续记录10-15分钟这期间的重量和湿度数据将作为实验的“基线”。此时的湿度是房间的初始湿度重量是水箱满水时的初始重量。6.2 执行加湿过程与数据记录开始实验在记录系统运行的状态下打开加湿器并设置为最大档位为了获得最明显的变化。同时在记录中手动标记开始时间可以在代码里加一个特殊标记或者简单记下电脑时间。持续监测让系统自动运行。期间可以通过OLED屏幕观察实时数据。实验持续时间建议至少1-2小时或者直到湿度达到一个相对稳定的平衡状态湿度不再显著上升。结束实验关闭加湿器。但数据记录系统不要立即停止继续记录15-30分钟观察关闭加湿器后湿度的自然下降情况这有助于理解房间的密封性。6.3 实验中的注意事项与常见问题“零漂”问题称重传感器在长时间工作后可能会有微小的零点漂移。这就是为什么需要记录“基线”和实验后数据。在数据分析时我们可以取实验开始前和结束后稳定段的平均值作为参考基准而不是依赖某个绝对零点。湿度饱和与冷凝如果加湿器功率过大或房间太小传感器附近的湿度可能达到露点导致传感器表面结露使读数失准甚至损坏传感器。如果发现湿度长时间停留在99%以上应调低加湿器档位或停止实验。数据完整性检查实验结束后立即将SD卡中的数据文件复制到电脑。打开CSV文件快速浏览一遍检查是否有异常的空行、乱码或时间戳中断的情况。确保数据完整是分析的前提。7. 数据分析从原始数据到效率指标拿到数万行的CSV数据后真正的乐趣——数据分析开始了。我习惯使用Python的Pandas和Matplotlib库来处理和可视化。7.1 数据清洗与预处理首先将CSV数据读入Pandas DataFrame。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(humidifier.csv) # 检查数据 print(df.head()) print(df.info())需要处理的问题可能包括无效值由于传感器偶尔读取失败可能会产生NaN值。用df.dropna()或前后值插补df.interpolate()来处理。时间戳转换将日期时间字符串列转换为Pandas的datetime类型方便作为索引进行时间序列分析。df[Timestamp] pd.to_datetime(df[Timestamp]) df.set_index(Timestamp, inplaceTrue)基线校正计算实验开始前5分钟的平均重量作为初始重量W0实验结束后5分钟的平均重量作为最终重量W1。那么总耗水量ΔW W0 - W1单位克约等于毫升。7.2 核心效率计算模型加湿器效率可以从两个维度衡量加湿速率单位时间内的耗水量。Rate_water ΔW / ΔT其中ΔT是加湿器开启的总时间小时。这个值可以直接和加湿器标称的“ml/h”对比。湿度提升效能这是更本质的效率。它衡量加湿器消耗单位质量的水能提升多少室内湿度。计算需要一点简单的物理模型。假设房间空气均匀混合且实验期间房间密闭空气体积V不变。已知空气的绝对湿度单位体积空气含水的质量与相对湿度、温度有关。但我们可以做一个简化估算在温度变化不大的情况下相对湿度的变化百分比大致与空气中水蒸气含量的变化成正比。计算找到湿度从开始到进入平台期的变化量ΔH百分比。那么效能系数 η ≈ (ΔH * V) / ΔW。其中V是房间体积立方米。η的单位是%·m³/g其物理意义是每消耗1克水能在1立方米空间内提升的湿度百分比。这个值越大说明加湿器将水雾化并扩散到空间中的效率越高。7.3 数据可视化与解读图表能让一切一目了然。fig, axes plt.subplots(2, 1, figsize(12, 8)) # 子图1重量和湿度随时间变化 ax1 axes[0] ax1.plot(df.index, df[Weight(g)], b-, labelWater Weight (g)) ax1.set_ylabel(Water Weight (g), colorb) ax1.tick_params(axisy, labelcolorb) ax1.legend(locupper left) ax1_twin ax1.twinx() ax1_twin.plot(df.index, df[Humidity1(%)], r-, labelHumidity (%)) ax1_twin.set_ylabel(Humidity (%), colorr) ax1_twin.tick_params(axisy, labelcolorr) ax1_twin.legend(locupper right) ax1.set_title(Weight and Humidity vs Time) # 子图2计算瞬时加湿速率重量变化率 # 使用差分计算重量变化并转换为每小时耗水量 df[Weight_diff] df[Weight(g)].diff() # 相邻时间点重量差 time_diff_hours (df.index.to_series().diff().dt.total_seconds() / 3600).fillna(0) df[Water_rate_ml_per_h] -(df[Weight_diff] / time_diff_hours) # 取负号因为重量在减少 ax2 axes[1] ax2.plot(df.index, df[Water_rate_ml_per_h], g-, labelInstant Water Consumption Rate (ml/h)) ax2.axhline(yrated_rate, colork, linestyle--, labelfRated Rate ({rated_rate} ml/h)) # 标称值 ax2.set_ylabel(Water Rate (ml/h)) ax2.set_xlabel(Time) ax2.set_title(Instantaneous Humidifier Water Consumption Rate) ax2.legend() ax2.grid(True) plt.tight_layout() plt.show()通过图表你可以清晰地看到湿度是如何随着重量下降而上升的两者曲线的趋势是否吻合。加湿器关闭后湿度是否缓慢下降说明房间有泄漏。瞬时加湿速率是否稳定是否达到或接近产品标称值。对比两个湿度传感器的曲线可以评估加湿的均匀性。8. 项目总结与扩展思考做完这个项目我手头的那台加湿器算是被“扒光了底裤”。实测下来它的加湿速率只有标称值的85%左右并且在运行半小时后由于水垢或元件发热效率还有所下降。这些发现是任何产品说明书都不会告诉你的。回顾整个项目最难的不是编程或接线而是如何设计一个可靠的测量方案并排除各种干扰。比如称重传感器对震动非常敏感有人走过地板都可能引起读数跳动这就需要良好的机械固定和软件滤波。再比如温湿度传感器需要时间与环境达到平衡快速读数可能不准这就需要理解传感器的响应时间常数。这个项目的框架具有很强的扩展性。你可以很容易地把它改造成一个智能加湿控制器在代码里设定一个目标湿度比如50%当传感器检测到湿度低于该值时通过一个继电器模块自动打开加湿器达到目标后自动关闭。这样你就得到了一个成本极低的自动恒湿系统。更进一步你可以增加更多的传感器比如PM2.5传感器来监测加湿器是否会导致室内可吸入颗粒物浓度升高某些超声波加湿器可能存在这个问题。或者接入ESP8266/ESP32这样的Wi-Fi模块将数据实时上传到物联网平台实现远程监控和历史数据分析。动手搭建这样一个系统其价值远超得到一个简单的“效率数字”。它训练了你定义问题、设计实验、处理数据、分析结果的完整工程思维。下次当你对任何家电的性能产生怀疑时或许第一个想到的不再是上网搜索而是“我能不能用Arduino测一下它” 这种通过亲手实践来探寻真相的能力才是这个项目带给我的最大收获。