基于Arduino与DHT11的自动加湿器DIY:从传感器到PWM控制全解析

📅 发布时间:2026/8/19 4:24:35
基于Arduino与DHT11的自动加湿器DIY:从传感器到PWM控制全解析
1. 项目缘起为什么需要一个自制的自动加湿器最近在捣鼓我的家庭工作室发现一个挺烦人的问题一到秋冬季节或者长时间开着空调室内的湿度就掉得厉害。干燥的空气不仅让我的木吉他面板有开裂的风险还经常让我感觉喉咙干涩皮肤紧绷。市面上的加湿器选择很多从几十块的超声波款到上千块的蒸发式高端货都有但我总觉得差点意思。要么是功能太单一只能手动开关要么是智能款价格不菲而且其内置的传感器精度和算法逻辑是个黑盒你根本不知道它什么时候加湿、加多少才合适。作为一个喜欢动手也相信“自己动手丰衣足食”的硬件爱好者我萌生了自己做一个自动加湿器的想法。我的核心需求很明确第一它得是自动的能根据环境湿度自动启停维持一个我设定的舒适范围第二它得足够简单成本可控不需要复杂的机械结构第三它得可靠不能因为程序 bug 或者传感器误差导致过度加湿那可能引发更麻烦的霉菌问题。基于这些想法我决定用 Arduino 平台来搭建这个系统。Arduino 的生态成熟有丰富的传感器和执行器模块编程也相对直观非常适合这类快速原型开发。最终我花了不到两百块用了一个周末的时间做出了这个既实用又有成就感的“简易自动加湿器”。下面我就把整个从构思、选型、组装到调试的全过程以及中间踩过的坑和总结的经验毫无保留地分享出来。2. 核心部件选型与电路设计思路做一个自动加湿器本质上是一个典型的“感知-决策-执行”物联网控制回路。我们需要一个大脑控制器、一双眼睛湿度传感器、一个执行机构加湿模块以及为它们供电和连接的身体电路与结构。2.1 控制器为什么是 Seeeduino 而非标准 Arduino Uno在控制器选择上我直接瞄准了 Arduino 兼容板。虽然热词里出现了 ESP32其自带 Wi-Fi 功能确实诱人可以实现远程监控但对于我这个初版项目我决定先聚焦核心功能——自动湿度控制。增加网络功能意味着更复杂的编程、电源管理和潜在的不稳定因素。所以我选择了Seeeduino。Seeeduino 是 Seeed Studio 推出的 Arduino 兼容板在引脚布局和核心功能上与 Arduino Uno R3 完全一致这意味着海量的 Uno 教程和代码库都能直接使用。我选择它还有一个私人原因它通常集成了更多的保护电路比如 USB 接口的过流保护对于我这种偶尔会接错线的手残党更友好一些。当然你用标准的 Arduino Uno 板子也完全没问题本项目所有代码和连接方式都是通用的。注意如果你未来想升级为联网版本ESP32 是一个完美的升级选择。它拥有更强的处理能力和双核但引脚逻辑电压是 3.3V在连接一些 5V 器件时需要额外注意电平转换。2.2 感知层Grove - TempHumi Sensor 的精度与稳定性考量湿度传感器是系统的“眼睛”它的准确性直接决定了控制效果。我选择了Grove - TempHumi Sensor (DHT11)。Grove 是 Seeed 推出的模块化电子接口系统其特点是使用统一的四针连接器VCC, GND, 信号, NC通过一条带线的 Grove 电缆就能即插即用极大简化了接线避免了面包板上跳线松动的烦恼。DHT11 是一款经典的数字温湿度复合传感器。它价格低廉足以满足家庭环境监测的精度要求湿度精度 ±5% RH温度精度 ±2°C。对于加湿控制来说我们关注的是相对湿度RH的趋势变化而不是绝对的科研级精度。±5% 的波动在室内环境中是可以接受的因为我们的控制目标通常是一个范围例如 45%-55% RH而不是一个绝对的点。它的工作原理是内部有一个电阻式湿敏元件和一个 NTC 测温元件通过一个专用的数字模块采集信号并校准后以单总线Single-Bus数字信号输出。这意味着 Arduino 只需要一个数字 I/O 引脚就能读取到温度和湿度两个值抗干扰能力比模拟传感器强很多。在代码中我们需要借助一个名为 “DHT sensor library” 的库来与它通信这个库会处理好复杂的时序问题。2.3 执行层Water Atomization 雾化片模块的工作原理与驱动加湿模块是整个系统的“手”。我选用的是常见的5V 直流供电的超声波雾化片模块。这个模块通常包含一个雾化片压电陶瓷片、一个驱动电路板和一个浮子开关。其核心是压电效应给雾化片施加高频电压通常为 1.7MHz 或 2.4MHz它会产生相同频率的机械振动将水分子“打散”成直径 1-5 微米的细小颗粒形成肉眼可见的水雾。驱动电路板是关键它内部有一个振荡电路和功率放大电路能将我们提供的直流电如 5V转换成高频交流电来驱动雾化片。我们 Arduino 不需要产生高频信号只需要像一个开关一样控制这个驱动板的供电即可。因此连接非常简单驱动板的 VCC 和 GND 接电源另外会引出一根信号线通常标记为 SIG 或 IN。这根信号线接受一个数字信号高电平5V时驱动板工作开始雾化低电平0V时驱动板停止。这里有一个非常重要的细节雾化片模块的功率较大。典型的 5V 雾化头工作电流可能在 500mA 到 1A 以上。Arduino 板载的 5V 引脚或任何一个数字 I/O 引脚都无法直接提供这么大的电流。直接连接会烧毁 Arduino 的主控芯片或稳压器解决方案是使用继电器模块或MOSFET 管作为电子开关。继电器模块像一个电磁开关用 Arduino 的小电流信号约20mA控制一个线圈线圈吸合后可以接通一个大电流回路。优点是隔离性好控制交流直流都行。缺点是体积大有机械寿命切换时有“咔嗒”声。MOSFET 管一种半导体开关速度极快无噪音寿命长。对于控制直流负载如我们的 5V 雾化模块是更优雅的选择。我选择了MOSFET 模块例如 IRF520 模块因为它更安静、更耐用。Arduino 的数字引脚输出信号给 MOSFET 的 Gate 脚控制其 Source 和 Drain 脚之间的通断从而控制雾化模块的电源回路。雾化模块的电源应直接从外部 5V/2A 以上的电源适配器获取而不是从 Arduino 取电。2.4 电路连接总图与供电设计理解了各个部件我们来把它们连接起来。整个系统的供电设计是重中之重不当的供电是项目失败的主要原因之一。连接清单Seeeduino / Arduino Uno x1Grove - DHT11 温湿度传感器 x1 通过 Grove 线连接5V 超声波雾化模块 x1MOSFET 模块如 IRF520 x1外部 5V/2A 直流电源适配器 x1 用于给雾化模块供电USB 数据线/电源 x1 用于给 Arduino 供电和编程杜邦线若干连接步骤传感器连接将 Grove 电缆一端插入 DHT11 模块另一端插入 Seeeduino 的任意一个数字引脚例如我选用 D2。记住DHT11 是单总线设备只需要一个数字口。Grove 接口的 VCC 和 GND 会自动连接好。MOSFET 模块连接MOSFET 的G(Gate) 引脚 - Seeeduino 的另一个数字引脚例如 D3。MOSFET 的S(Source) 引脚 -外部 5V 电源的 GND负极。MOSFET 的D(Drain) 引脚 -雾化模块的 GND负极。重要MOSFET 模块上可能还有VCC和GND引脚这是给模块内部光耦或逻辑电路供电的通常接 Arduino 的 5V 和 GND。请根据你购买的模块说明书确认。雾化模块连接雾化模块的VCC(正极) -外部 5V 电源的 VCC正极。雾化模块的GND(负极) -已经接到 MOSFET 的D脚。雾化模块的SIG(信号) - 可以悬空不接因为我们用 MOSFET 控制电源回路。有些模块的 SIG 脚需要接高电平才工作如果发现不雾化可以尝试将此脚接到外部电源的 VCC正极。供电连接Arduino通过 USB 线连接电脑或一个 5V USB 充电器供电。雾化模块与 MOSFET共同由一个独立的 5V/2A 直流电源适配器供电。确保这个电源的功率足够至少 5V 2A。共地操作这是保证信号正常的关键必须将外部 5V 电源的 GND与Arduino 的 GND用一根杜邦线连接起来。这样Arduino 和 MOSFET/雾化模块才有共同的电压参考点Arduino 输出的控制信号才能被 MOSFET 正确识别。电路逻辑当 Arduino 程序判断需要加湿时它让数字引脚 D3 输出HIGH(5V)。这个信号使 MOSFET 导通相当于在雾化模块的供电回路中闭合了开关雾化模块得电工作。当湿度达到设定值Arduino 将 D3 设为LOW(0V)MOSFET 关闭切断雾化模块的电源停止加湿。3. 软件编程从读取传感器到实现PID控制思想硬件搭好了接下来是赋予它“大脑”的时候。我们将使用 Arduino IDE 进行编程。如果你还没安装可以去 Arduino 官网下载。编程的核心逻辑很简单读取当前湿度与目标湿度比较根据比较结果控制雾化模块开关。3.1 基础库安装与传感器数据读取首先我们需要安装 DHT 传感器库。打开 Arduino IDE点击工具-管理库...在搜索框中输入 “DHT sensor library”找到由 Adafruit 维护的版本进行安装。这个库兼容 DHT11、DHT22 等多种型号。下面是一个最基础的读取和控制代码框架#include DHT.h // 定义引脚 #define DHTPIN 2 // DHT11 连接的数字引脚 #define FOGPIN 3 // 控制雾化模块的 MOSFET 引脚 #define DHTTYPE DHT11 // 传感器类型 // 初始化 DHT 传感器 DHT dht(DHTPIN, DHTTYPE); // 目标湿度阈值 float targetHumidity 50.0; // 目标湿度 50% float hysteresis 3.0; // 回差 3%防止频繁启停 void setup() { Serial.begin(9600); // 启动串口通信用于调试输出 Serial.println(DIY Auto Humidifier Starting...); dht.begin(); // 启动 DHT 传感器 pinMode(FOGPIN, OUTPUT); digitalWrite(FOGPIN, LOW); // 初始状态关闭加湿 } void loop() { // 每次读取间隔至少2秒DHT11传感器需要时间 delay(2000); // 读取湿度值 float currentHumidity dht.readHumidity(); // 读取温度值可选可用于更高级的补偿算法 float currentTemperature dht.readTemperature(); // 检查读取是否成功 if (isnan(currentHumidity) || isnan(currentTemperature)) { Serial.println(Failed to read from DHT sensor!); return; // 读取失败则跳过本次循环 } // 打印当前数据到串口监视器 Serial.print(Humidity: ); Serial.print(currentHumidity); Serial.print( %\t); Serial.print(Temperature: ); Serial.print(currentTemperature); Serial.println( *C); // 简单的阈值比较控制Bang-Bang Control if (currentHumidity (targetHumidity - hysteresis/2)) { // 当前湿度低于目标下限开启加湿 digitalWrite(FOGPIN, HIGH); Serial.println(Fogger: ON); } else if (currentHumidity (targetHumidity hysteresis/2)) { // 当前湿度高于目标上限关闭加湿 digitalWrite(FOGPIN, LOW); Serial.println(Fogger: OFF); } // 如果湿度在目标区间内保持原有状态不变 }这段代码实现了一个带“回差”Hysteresis的开关控制。为什么需要回差假设我们只设一个目标点 50%那么当湿度达到 50.1% 时关闭降到 49.9% 时又立即开启雾化模块会在临界点附近频繁启停这不仅降低寿命也可能导致湿度在目标值上下剧烈震荡。加入了 3% 的回差后控制逻辑变为低于 48.5% (50 - 1.5) 开启高于 51.5% (50 1.5) 关闭在 48.5% 到 51.5% 之间则保持状态。这样系统就有了一个稳定的“缓冲区”运行更加平顺。3.2 进阶引入比例控制思想让加湿更平顺开关控制简单粗暴但体验上可能不够好加湿器要么全功率开启产生大量水雾要么完全关闭。对于小空间这可能导致湿度快速冲过目标值然后长时间关闭形成锯齿波。我们可以引入一点比例P控制的思想来改善。思路是根据当前湿度与目标湿度的差值按比例控制加湿的强度。对于我们的雾化模块虽然不能直接调节功率但我们可以通过PWM脉冲宽度调制来模拟。PWM 通过快速开关比如每秒几百上千次来控制一个周期内“开”的时间比例占空比从而控制平均功率。我们需要将 MOSFET 的控制引脚连接到 Arduino 的支持 PWM 的引脚标记有~的引脚如 3, 5, 6, 9, 10, 11。然后修改代码#include DHT.h #define DHTPIN 2 #define FOGPIN 3 // 必须是一个支持 PWM 的引脚例如 3, 5, 6, 9, 10, 11 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); float targetHumidity 50.0; float Kp 5.0; // 比例系数需要根据实际调试 void setup() { Serial.begin(9600); dht.begin(); pinMode(FOGPIN, OUTPUT); } void loop() { delay(2000); // DHT11 读取间隔 float currentHumidity dht.readHumidity(); if (isnan(currentHumidity)) { Serial.println(DHT Read Failed); return; } Serial.print(Humidity: ); Serial.print(currentHumidity); Serial.println( %); // 计算误差 float error targetHumidity - currentHumidity; // 比例控制计算 PWM 值 // 将误差映射到 0-255 的 PWM 范围。误差越大PWM值越大加湿越强。 // 同时限制误差为正值只有当湿度低于目标时才加湿 int pwmValue 0; if (error 0) { pwmValue (int)(error * Kp); // 将 PWM 值限制在 0-255 之间 pwmValue constrain(pwmValue, 0, 255); } // 输出 PWM 信号 analogWrite(FOGPIN, pwmValue); Serial.print(Error: ); Serial.print(error); Serial.print( %, PWM Output: ); Serial.println(pwmValue); }在这个比例控制中Kp是比例系数需要你根据房间大小、雾化模块功率、空气流通情况来调试。如果Kp太大系统反应会过于激烈可能产生振荡如果Kp太小加湿速度太慢。调试时可以先设一个小值比如 2观察湿度变化曲线逐步调整。提示并非所有雾化模块的驱动板都支持 PWM 输入。有些驱动板在 SIG 脚收到高电平信号后就会以固定功率工作。在购买时可以咨询卖家模块是否支持 PWM 调速。如果不支持上述比例控制将无法实现只能使用开关控制。3.3 添加功能串口指令设置目标湿度为了让项目更有交互性我们可以添加通过串口监视器动态设置目标湿度的功能。这样就不用每次修改阈值都重新上传代码了。#include DHT.h #define DHTPIN 2 #define FOGPIN 3 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); float targetHumidity 50.0; float hysteresis 3.0; String inputString ; // 用于存储串口接收的数据 bool stringComplete false; // 标志是否收到完整命令 void setup() { Serial.begin(9600); dht.begin(); pinMode(FOGPIN, OUTPUT); digitalWrite(FOGPIN, LOW); Serial.println(Auto Humidifier Ready. Send SETxx.x to change target humidity.); } void loop() { // 处理串口指令 if (stringComplete) { inputString.trim(); // 去除首尾空格 if (inputString.startsWith(SET)) { float newTarget inputString.substring(4).toFloat(); if (newTarget 20 newTarget 80) { // 设定一个合理范围 targetHumidity newTarget; Serial.print(Target humidity updated to: ); Serial.println(targetHumidity); } else { Serial.println(Invalid value! Please set between 20 and 80.); } } else { Serial.println(Unknown command. Use SETxx.x); } // 清空字符串准备接收下一条指令 inputString ; stringComplete false; } // 原有的温湿度读取和控制逻辑 static unsigned long lastReadTime 0; if (millis() - lastReadTime 2000) { // 使用非阻塞延时避免影响串口读取 lastReadTime millis(); float h dht.readHumidity(); float t dht.readTemperature(); if (isnan(h) || isnan(t)) { Serial.println(Sensor error!); return; } Serial.print(H:); Serial.print(h, 1); Serial.print(% T:); Serial.print(t, 1); Serial.print(C Target:); Serial.print(targetHumidity); Serial.print(% Fogger:); // 开关控制逻辑 if (h targetHumidity - hysteresis/2) { digitalWrite(FOGPIN, HIGH); Serial.println(ON); } else if (h targetHumidity hysteresis/2) { digitalWrite(FOGPIN, LOW); Serial.println(OFF); } else { Serial.println(HOLD); } } } // 串口事件函数当有数据到达时自动调用 void serialEvent() { while (Serial.available()) { char inChar (char)Serial.read(); if (inChar \n) { // 以换行符作为命令结束标志 stringComplete true; } else { inputString inChar; } } }上传这段代码后打开 Arduino IDE 的串口监视器波特率 9600发送SET55.0并回车就可以将目标湿度设置为 55%。这大大增加了项目的可玩性和实用性。4. 结构组装、安全考量与实测调试电路和代码都准备好了接下来要把它们安全、美观地整合成一个可用的设备。4.1 外壳选择与安全隔离电子部分绝不能直接暴露在潮湿的水雾中我选择了一个大小合适的塑料收纳盒作为外壳。在盒子上开孔一个孔用于固定雾化模块确保其雾化面朝上且略低于外壳底面以便放入盛水容器。几个小孔用于传感器通风使其能感知外部环境湿度而不是盒子内部的湿度。为 USB 线和外部电源线开孔。为可能的指示灯或按钮开孔进阶功能。关键安全步骤电路板防水将所有电路板Arduino, MOSFET模块用热熔胶或螺丝固定在盒子内壁高处远离可能凝结水汽的区域。可以考虑在电路板区域涂覆一层三防漆这是一种绝缘防潮涂层能有效防止短路。电源隔离确保为雾化模块供电的 5V/2A 电源适配器是正规产品有过载和短路保护。其输出端接头部分要做好绝缘处理。水箱安全使用一个稳定的、不易打翻的容器作为水箱。可以在雾化模块下方垫一个防水的托盘以防万一漏水。务必使用纯净水或蒸馏水自来水含有矿物质水垢会很快在雾化片表面形成坚硬的垢层极大降低雾化效率甚至损坏雾化片。这是很多人DIY加湿器失败的主要原因。浮子开关大多数雾化模块自带一个浮子开关。当水位过低时浮子下沉会自动切断雾化片电源防止干烧。请务必使用这个功能干烧会在几秒钟内永久损坏雾化片。4.2 上电实测与系统调试组装完毕后按以下步骤进行调试分步上电先只连接 Arduino 和传感器上传最简单的读取程序打开串口监视器确认能稳定读取到温湿度数据。用手哈气靠近传感器看数值是否有灵敏变化。单独测试雾化模块将雾化模块直接接到 5V/2A 电源上注意正负极放入有水的容器中看是否能正常产生水雾。听声音正常工作是高频的“嘶嘶”声。连接 MOSFET 测试断开雾化模块电源。按电路图接好 MOSFET将 MOSFET 的 Gate 脚暂时用杜邦线接到 Arduino 的 5V 引脚模拟高电平信号。然后给整个系统Arduino 和外部电源上电。如果接线正确雾化模块应该开始工作。再将 Gate 脚接到 GND雾化应停止。这一步验证了控制回路是否正常。全系统联调上传完整的控制程序。通过串口监视器观察湿度读数。用嘴向传感器吹气模拟湿度升高观察控制信号是否会变化从 ON 变 OFF。拿开吹气湿度下降后观察是否会重新启动。参数整定这是最需要耐心的一步。将加湿器放在你希望使用的实际环境中比如书桌一角。设定一个目标湿度如 45%。如果使用开关控制主要调整hysteresis回差值。如果加湿器启停过于频繁就调大回差如从 3% 调到 5%。观察湿度能否稳定在目标区间内。如果使用 PWM 比例控制主要调整Kp比例系数。如果湿度上升很慢且始终达不到目标值可以适当增大Kp。如果湿度在目标值上下波动明显振荡则需要减小Kp。可以记录一段时间内的湿度数据绘制成曲线来辅助分析。4.3 常见问题与排查踩坑实录在制作过程中我遇到了几个典型问题这里列出来帮你避坑问题一传感器读数全是NaN或明显错误。可能原因 1接线错误或接触不良。检查 Grove 线是否插紧或者杜邦线连接是否牢固。确保 VCC, GND, 信号线对应正确。可能原因 2读取频率太快。DHT11 两次读取之间需要至少 2 秒的间隔。确保你的loop()中使用了delay(2000)或类似的非阻塞延时逻辑。可能原因 3电源问题。确保 Arduino 和传感器供电稳定。尝试给 Arduino 单独供电而不是仅靠 USB 连接电脑有些电脑 USB 口供电不足。问题二雾化模块不工作但电源指示灯亮。可能原因 1MOSFET 接线错误。最常见的是 Source (S) 和 Drain (D) 接反了。不同型号的 MOSFET 引脚定义可能不同务必查阅数据手册。对于 IRF520 模块通常印有引脚标识。可能原因 2MOSFET 模块未使能。有些 MOSFET 模块需要给其逻辑供电引脚VCC, GND供电才能工作。确认这些引脚已连接到 Arduino 的 5V 和 GND。可能原因 3浮子开关未触发。确保雾化片完全浸入水中浮子开关处于“浮起”状态。可能原因 4水质问题。立即换用纯净水或蒸馏水测试。自来水中的水垢可能已经附着在雾化片上可以用白醋浸泡清洗后试试。问题三雾化模块一直工作无法关闭。可能原因 1程序逻辑错误。检查if-else判断条件确保在湿度高于阈值时控制引脚被设置为LOW。使用串口监视器打印控制状态来调试。可能原因 2MOSFET 击穿。如果 MOSFET 管因过流或静电损坏可能会处于常通状态。更换一个 MOSFET 模块测试。问题四加湿效果不明显湿度上升很慢。可能原因 1雾化量太小。检查雾化模块的功率瓦数。小功率模块如 5W只适合极小空间。对于卧室或客厅可能需要更大功率的模块或多个模块。可能原因 2环境空间太大或通风太好。加湿器的作用范围有限。尝试关闭门窗或将加湿器放置在更靠近你的位置。可能原因 3传感器位置不当。传感器不应放在水雾直接喷到的地方也不应放在离加湿器太远或空气不流通的角落。应放在能代表你所在区域平均湿度的位置。5. 项目总结与进阶玩法探讨经过一个周末的折腾这个自制的自动加湿器已经稳定运行了好几周。它完美地解决了我工作室湿度波动的问题将湿度维持在 50% ±3% 的舒适区间。相比购买成品这个过程让我对传感器、执行器、控制逻辑有了更深刻的理解这种成就感是花钱买不到的。回顾整个项目有几点心得值得分享供电是基石分开为控制部分Arduino和大功率执行部分雾化模块供电并做好“共地”是项目稳定的前提。一个劣质的电源适配器可能导致各种诡异的故障。水质决定寿命使用纯净水/蒸馏水这是保护雾化片、维持雾化效率最关键也最容易被忽视的一点。定期比如每周清洗水箱和雾化片也能延长设备寿命。调试需要耐心控制参数回差、比例系数没有放之四海而皆准的值。必须放在实际环境中结合数据观察耐心地一点点调整才能达到最佳效果。这个项目作为一个起点还有很多可以扩展和优化的方向增加显示与交互接一个 I2C 的 OLED 屏幕实时显示当前温湿度、目标值和工作状态比看串口监视器方便多了。升级联网与远程控制将主控换成 ESP32 或 ESP8266接入家庭 Wi-Fi。你可以开发一个简单的网页界面或者使用 Home Assistant、MQTT 等平台实现手机远程查看、控制湿度甚至设置定时任务和湿度曲线。多传感器与风扇在房间不同位置放置多个 DHT11 传感器取平均值作为控制依据更精准。增加一个小风扇帮助将水雾更均匀地扩散到空气中。数据记录与分析利用 SD 卡模块或通过网络将温湿度数据上传到服务器绘制长期的变化曲线分析房间的湿度规律。DIY 的乐趣就在于从一个简单的需求出发亲手搭建、调试、优化最终得到一个完全符合自己心意的作品。这个自动加湿器项目涵盖了硬件选型、电路设计、编程逻辑、调试排错等多个环节是一个非常好的嵌入式入门实践。希望我的这份详细记录能帮你少走弯路成功做出属于自己的智能小设备。