news 2026/10/5 5:57:17

DHT11+继电器:手把手教你制作Arduino智能孵化器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DHT11+继电器:手把手教你制作Arduino智能孵化器

去年冬天,我给自己家的芦丁鸡做了一台孵化器,核心就用了一颗DHT11温湿度传感器加一个5V继电器模块。这台设备在Makerbuddy上是很经典的入门选题,英文叫Smart Egg Incubator,说穿了并不神秘:让单片机读环境温湿度,再通过继电器自动接通或断开加热垫和加湿器,把孵化箱里的温度压在一个小范围内。

这个项目特别适合第一次玩温湿度传感器和继电器控制的新手,也适合家里养观赏禽类、想低成本体验人工孵化的朋友。你不需要去买几百块的专用孵化器,手头有一块Arduino兼容板、一个DHT11、一个继电器模块、一个12V加热垫和一个小加湿器就可以跑起来。后面我会把整体设计、电路连接、控制代码、调试经验完整复盘一遍,也会分享几个我实际踩过的坑。如果你想画成PCB打样,我还单独写了用嘉立创EDA画原理图时要注意的细节。

1. 孵化器项目的整体设计思路

1.1 为什么偏偏是DHT11加继电器

DHT11这颗传感器被很多人嫌弃,说它精度一般、采样慢,但在孵化器场景里它反而是最合适的选择。孵化对温度要求是“稳定在目标值附近”,不是“精确到小数点后两位”。绝大多数蛋类的适宜孵化温度在37℃到38℃之间,DHT11的±2℃误差听起来很大,但你在做阈值控制时可以通过实际校准把误差吃掉,真正影响破壳率的不是那零点几度的偏差,而是温度长时间偏离或反复波动。

DHT11另一个优点是接线简单、库成熟。它只需要一根数据线,单片机端随便找个数字口就能读,Arduino生态里直接搜DHT库装上就能工作。相比SHT30、BME280这些传感器,DHT11的响应速度确实慢,读取一次大概需要250ms,但对继电器控制来说完全够用,毕竟加热和加湿本身就有惯性,温度不可能一瞬间跳变。

继电器模块的作用是“以小控大”。单片机IO口只能输出几毫安电流,不可能直接驱动大功率加热丝或水泵,所以需要通过继电器触点去控制外部供电回路。继电器本质上是一个电磁开关,单片机动一下线圈,触点那边就能通断220V或12V的大电流电路。要注意的是,孵化箱里加热设备最好选12V直流加热垫或陶瓷加热灯,不要用交流220V直连,尤其是新手操作,安全风险会低很多。

1.2 温湿度控制的基本原理

这个项目的本质是一个带滞回区间的开关控制,说人话就是:温度低于下限就加热,高于上限就停,中间区间什么都不做。

很多新手第一次写控制逻辑时会犯一个经典错误:代码写成“温度低于37.5℃就开,高于37.5℃就关”。听起来没问题,但实际运行起来继电器会在目标点附近疯狂抖动,因为传感器有一点噪声,热气流有一点波动,温度在37.5℃上下反复横跳,继电器跟着每秒开关几次,继电器触点很快就会被电弧烧黑,加热垫的寿命也会缩短。

正确的做法是给控制加一个滞回区间,比如目标温度37.5℃,启动加热温度设为37.2℃,停止加热温度设为37.8℃。这样温度只有降到37.2℃以下时才开始加热,加热到37.8℃以上时才停止。区间内继电器保持原状态,不会频繁动作。湿度控制同理,目标湿度55%左右,可以设定低于50%启动加湿,高于60%停止加湿。

这个逻辑你可以想象成家里的空调:你设定26℃,实际上空调是室内温度降到25℃以下开始制冷,升到27℃以上停止制冷,中间是“压缩机休息区”。没有这个区间,压缩机就会因为室内温度变化的微小波动而频繁启停,既费电又伤机器。孵化器的控制思路一模一样。

2. 硬件选型与电路搭建

2.1 材料清单与选型理由

我用到的材料不多,大部分都能从普通电子元件店买到。下面这张表可以当作采购参考。

器件型号/规格选型说明
主控板Arduino Nano 兼容板便宜、体积小、USB供电方便,引脚够用
温湿度传感器DHT11 模块版模块版自带上拉电阻和LED,接线比裸芯片省事
继电器模块5V低电平触发,1路或2路与单片机隔离控制外部电源,低电平触发更安全
加热设备12V加热垫或40W陶瓷加热灯功率控制在20W-40W,别用220V交流设备
加湿设备5V超声波雾化模块或小加湿器功率小,继电器可以直接控制通断
电源12V/3A适配器 + USB 5V电源给加热垫和单片机分开供电
其他面包板、杜邦线、塑料收纳箱、铝箔搭电路和做箱体

DHT11模块版和裸DHT11芯片之间有区别,新手我建议直接买模块版。模块版已经把4.7k上拉电阻和滤波电容做好了,只需要接VCC、GND、DATA三个脚;裸芯片则需要自己在数据线上加电阻,容易漏。模块版上会有一个小的蓝色电位器,有些版本还能微调输出,不过我实测下来用处不大,主要还是靠代码里的校准。

继电器模块我特别强调要选低电平触发。低电平触发意味着单片机把控制脚拉低时继电器吸合,拉高时断开。Arduino在上电瞬间,IO口大多处于高阻态或默认电平,如果用高电平触发,可能在主控还没初始化完成时继电器就意外吸合,加热设备直接启动。低电平触发配合初始化时把控制脚置高,能有效避免这种上电误动作。这是孵化器这类设备很重要的一点,因为加热设备一旦失控,箱内会迅速升温,蛋就废了。

2.2 电路连接方式

我使用的是Arduino Nano,硬件连接非常简单,大家可以直接照着接。

  1. DHT11模块的VCC接5V,GND接GND,DATA接D3引脚。
  2. 继电器模块的VCC和GND接5V和GND,IN接D4引脚。
  3. 如果加湿也要自动控,可以用两路继电器模块,第二路IN接D5。
  4. 加热垫的电源回路:12V适配器的正极接到继电器模块的COM端,常开触点NO端接加热垫正极,加热垫负极直接回12V适配器负极。
  5. 加湿器回路和加热垫完全一样,但注意两路要独立,不能把两个负载串在一起。

关于继电器触点,一定要分清公共端COM、常闭端NC、常开端NO。默认状态下COM和NC是导通的,继电器吸合后COM和NO导通。因为我们要平时断电、需要时加热,所以负载接COM和NO,绝不能接NC。我第一次做的时候接反了,结果上电后加热垫一直热着,继电器动作反而是关掉它,差点把箱体烤变形。

供电方面还有一个容易被忽略的点:继电器的吸合线圈电流在几十毫安到上百毫安,DHT11也需要电流,如果直接从Nano的5V引脚取电,当继电器吸合瞬间可能把Nano的5V电压拉低,导致DHT11读数异常甚至重启。我的做法是用一个外部5V/1A电源给继电器模块供电,Nano只通过数据线驱动继电器的IN引脚,两块电源的地线要接在一起,这样才能保持电平一致。如果坚持从Nano取电,建议用供电能力更强的Arduino板,并且继电器选光电隔离版本。

2.3 用嘉立创EDA画原理图的要点

如果你想把面包板电路做成正式的PCB,嘉立创EDA是个上手很快的工具。直接用标准库里的元件符号画图,需要注意几个关键点。

DHT11模块版虽然方便,但打印PCB时我更建议用裸DHT11元件,这样才能把传感器小板设计在箱内合适位置,主控板放箱外。裸DHT11有4个引脚,不同封装脚位定义不太一样,最常用的是直插四脚封装,1脚接VCC,2脚接DATA,3脚空脚,4脚接GND。这部分必须对照数据手册确认,不能凭记忆画。

裸DHT11的数据线必须加上拉电阻,阻值选4.7k到10k。模块版内部已经焊好了,所以用模块版时不用额外接。画原理图时我会在DATA到VCC之间放一个4.7k电阻,同时在VCC和GND之间放一个100nF的滤波电容,尽量靠近DHT11引脚,这样供电更干净,读数会稍微稳定一些。

继电器模块在原理图里不能直接当成一个简单开关画。模块内部通常有三极管驱动、续流二极管、LED指示灯,这些都可以直接用模块符号替代。如果你把继电器画成线圈加触点,就一定要在线圈两端反向并联一个续流二极管,比如1N4148或1N4007。否则断开瞬间线圈会产生反电动势,电压可能超过几十伏,直接打坏单片机引脚。

至于加热负载端子,画原理图时用螺丝端子或接线端子引出,标清楚“12V_HEAT+”“12V_HEAT-”,打样回来只接外部电线,维护方便也安全。我在第一版PCB上忘了加白色丝印标识,接线的时候全靠记忆,后来维护非常痛苦,这一步千万别省。

3. 控制逻辑与代码实现

3.1 控制策略:温度优先还是湿度优先

孵化器需要同时控制温度和湿度,但这两个量会互相影响。加热垫工作时会烤干箱内空气,湿度会掉得很快;加湿器喷雾时水汽蒸发会带走热量,温度会小幅度下降。如果把两个控制通道同时打开,就会陷入一种“加热导致湿度下降,加湿导致温度下降”的循环里。

我的策略是温度优先。主循环每2秒读一次DHT11,先判断温度,再判断湿度。温度低于下限就打开加热,高于上限就关闭;然后湿度低于下限就打开加湿,高于上限就关闭。两个通道互不干扰,但阈值不要挨得太近。例如温度目标37.5℃,控制在37.2-37.8℃;湿度目标55%,控制在50%-60%。这样即使两个设备同时启动,也不会因为互相干扰而让继电器反复切换。

还有一个小细节:DHT11在通电后的第一次读取经常失败,返回值是nan。代码里一定要做isnan判断,如果读不到数据就跳过本轮控制,不能让系统因为一次错误读数就把加热器关掉。我在调试时遇到过,传感器偶发一次失败,结果代码直接走else分支把所有继电器都关了,晚上温差大了不少。

3.2 Arduino核心代码实现

这里直接用Arduino IDE写,需要先安装DHT传感器库。我使用的是Adafruit DHT传感器库,库管理器里搜DHT sensor library安装就行。控制部分我用DHT11库,其实核心逻辑和库关系不大,关键是滞回判断。

#include <DHT.h> #define DHTPIN 3 // DHT11数据引脚 #define DHTTYPE DHT11 #define RELAY_HEAT 4 // 加热继电器控制引脚 #define RELAY_HUMID 5 // 加湿继电器控制引脚 DHT dht(DHTPIN, DHTTYPE); // 滞回控制阈值 const float TEMP_ON = 37.2; // 低于此值启动加热 const float TEMP_OFF = 37.8; // 高于此值停止加热 const float HUMI_ON = 50.0; // 低于此值启动加湿 const float HUMI_OFF = 60.0; // 高于此值停止加湿 unsigned long lastRead = 0; const unsigned long interval = 2000; // 每2秒读取一次 void setup() { Serial.begin(9600); pinMode(RELAY_HEAT, OUTPUT); pinMode(RELAY_HUMID, OUTPUT); // 上电先断开继电器,低电平触发时置高就是断开 digitalWrite(RELAY_HEAT, HIGH); digitalWrite(RELAY_HUMID, HIGH); dht.begin(); delay(2000); // 给传感器一个稳定时间 } void loop() { if (millis() - lastRead >= interval) { lastRead = millis(); float t = dht.readTemperature(); float h = dht.readHumidity(); // 读取失败跳过本轮 if (isnan(t) || isnan(h)) { Serial.println("DHT11 read failed!"); return; } // 温度控制 if (t < TEMP_ON) { digitalWrite(RELAY_HEAT, LOW); // 打开加热 } else if (t > TEMP_OFF) { digitalWrite(RELAY_HEAT, HIGH); // 关闭加热 } // 湿度控制 if (h < HUMI_ON) { digitalWrite(RELAY_HUMID, LOW); // 打开加湿 } else if (h > HUMI_OFF) { digitalWrite(RELAY_HUMID, HIGH); // 关闭加湿 } // 调试输出 Serial.print("Temp: "); Serial.print(t); Serial.print(" C, Hum: "); Serial.print(h); Serial.println(" %"); } // 这里可以放其他非阻塞任务,后面要加LCD显示就是放在这个循环里 }

这段代码里最关键的是温度控制用了else if,不是两个独立的if。这样可以保证温度落在37.2到37.8之间时,什么都不做,维持继电器上一个状态。很多人一开始写成“低于37.5开,高于37.5关”,结果就是继电器一直在跳。你把阈值拉开,设备动作次数会明显下降,箱内温度反而更稳。

另外注意我把读取间隔设成了2秒。DHT11的典型采样周期是1秒,你如果每100ms疯狂读,它大概率会一直返回同一个值,或者直接报错。2秒对孵化这种大惯性系统足够及时,也减少继电器无谓动作。

3.3 如果换STM32:HAL库驱动DHT11的简易指南

用Arduino写DHT11非常无脑,但很多朋友手边只有STM32F103系列开发板,也想做孵化器。DHT11是单总线协议,STM32没有现成的硬件外设直接用,必须用GPIO模拟时序。用STM32CubeMX配置好一个普通GPIO作为开漏输出,后面用HAL库代码来操作。

基本流程是这样的:

  1. 用CubeMX选择STM32F103C8T6,配置一个GPIO引脚为开漏输出,速度设为高速,其他引脚按需配置串口和继电器输出。
  2. DHT11的DATA线接这个GPIO,同时必须外接4.7k上拉电阻到3.3V或5V。
  3. 单片机先拉低18ms再拉高,等待DHT11响应信号,之后切换GPIO为输入模式读取40bit数据。
  4. 40bit按顺序是湿度整数、湿度小数、温度整数、温度小数、校验和。注意DHT11数据手册上温度小数位通常为0,实际使用时基本只看整数位,加0.5℃修正后就能用。
  5. 继电器控制用普通推挽输出即可,同样选择低电平触发模块,初始化先把引脚置高。

HAL库驱动DHT11网上的例程不少,但核心就这十几行。要注意的是,不要用HAL_Delay做微秒级延时,那个误差太大,最好自己写一个基于SysTick的微秒延时函数。另外开漏输出改成输入模式后,引脚状态会受上拉电阻影响,读取时要加一定的延时,特别是等待每个bit的开头低电平。

STM32方案相对Arduino的好处是后续升级空间大,比如同时接LCD1602、蜂鸣器、多个传感器,性能都绰绰有余。但如果你第一次做孵化器,我不建议直接上STM32,Arduino能让你的注意力集中在控制逻辑上,先把温湿度的“脾气”摸清楚再说。

4. 调试与实测记录

4.1 上电前的检查清单

我做样机的时候吃过不少亏,总结了一份检查清单,每次上电前过一遍,能省很多排查时间。

  1. 确认继电器模块的电源和单片机电源共地,否则信号电平无法对齐。
  2. 确认加热垫接的是继电器COM和NO,不是NC。用万用表蜂鸣档测一下,继电器不通电时输出端应该是断开状态。
  3. 确认DHT11的VCC和GND没有接反。DHT11接反很快会发热发烫,我之前烧过一颗,教训很深刻。
  4. 先不接加热垫和加湿器,单独给单片机烧录程序,串口监视器能看到正常温湿度数据后,再接功率负载。
  5. 如果继电器模块是低电平触发,程序里最好在setup里先把所有控制引脚置高,再初始化其他外设。
  6. 加热垫独立供电,不要和单片机写到一个适配器里,否则继电器动作瞬间会把单片机电源拉崩。

这套检查流程看起来繁琐,但最多花两分钟。孵化器这种长时间通电设备,上电瞬间最容易出问题,电源端、输出端多确认一遍,后面就不会半夜爬起来抢救。

4.2 实测中的校准与稳定问题

第一次试运行时,我把DHT11直接贴在加热垫上方,结果箱内温度指针显示38.5℃,代码读出来只有35.4℃,偏差将近3℃。原因是传感器离热源太近,热空气直接冲到传感器上,反而箱内中部温度还没上来。后来我把传感器移到和蛋托差不多的高度,离开墙面5厘米左右,读数才和标准水银温度计对得比较接近。

DHT11的校准也很简单。在水银温度计和箱内实测稳定后,记录几个点的差值,然后在代码里加上一个固定偏移量。比如实测发现传感器读数比真实温度低0.8℃,你可以直接在读取值上加0.8。湿度校准比较难,家用湿度计精度本身就一般,凑合够用就行,不要追求DHT11读数和几万一台的恒温恒湿箱完全一致。

还有一个容易踩坑的地方是加湿器。超声波雾化头如果正对着DHT11喷,湿度读数会瞬间冲到90%以上,然后系统立刻关掉加湿。解决办法是把传感器放在雾化口侧面,或者用一个挡板隔开,让水汽在箱内先扩散再被传感器感知。我现在的方案是加湿器放在箱体角落,雾化口朝上,DHT11放在另一侧,效果好了很多。

箱体盖子的开关也会造成温湿度骤变。孵化过程中每天要给蛋翻面,一开盖温度立刻掉出区间,这是正常的。不要急着去改控制阈值,盖上盖子后大约10分钟,系统自己就会追回来。我一开始看到开盖后温度掉到35℃就怀疑电路有问题,查了半天才发现是箱体密封太差。

4.3 常见问题排查表

现象可能原因处理办法
串口输出nan接线松脱、供电不足、DHT11损坏重新插好线路,检查VCC和GND,换一颗传感器测试
温度读数明显偏低传感器离加热源太近把传感器放到蛋托附近,加个小风扇混匀空气
继电器不动作模块供电不足、触发电平不对给继电器独立5V电源,确认是低电平触发并接对引脚
上电瞬间加热设备启动一下单片机初始化前IO口状态不定用低电平触发模块,程序里先置高控制引脚再延时初始化
加热垫连续工作不停继电器触点接错,接到NC端改成COM和NO端,用万用表确认默认断开
湿度读数忽高忽低雾化口直吹传感器移动传感器位置或加挡板
继电器频繁啪啪响控制阈值没有滞回区间检查代码,确认用的是else if和两个不同阈值

排查时我习惯把串口打印打开,先看传感器读数正不正常,再看继电器动作是否和逻辑一致。你可以在串口里把“温度低于阈值,打开加热”这类状态信息打出来,对照实际听到继电器咔哒声的时间点,能非常快定位问题。比如你看到打印“打开加热”,但继电器没声音,就说明不是程序问题,是硬件接线或供电问题。

5. 进阶优化建议

5.1 加一块LCD1602实时显示

孵化器一旦开始运行,你不可能天天抱着电脑看串口。我后续给这台孵化器加了一块I2C接口的LCD1602显示屏,两根线走I2C协议,占用Arduino的A4和A5引脚,改动很小。

接线步骤很简单。LCD1602 I2C模块的SDA接A4,SCL接A5,VCC和GND接5V和GND。代码里引入LiquidCrystal_I2C库,初始化时填0x27或0x3F作为I2C地址。首行显示温度,第二行显示湿度以及当前加热、加湿状态。这样每次翻完蛋,直接扫一眼屏幕就知道系统是否正常。

加LCD后要注意I2C和DHT11共用5V供电,电流没问题,但继电器模块还是建议独立供电。LCD背光会增加几十毫安电流,Arduino板载稳压器一般都能顶住,但保险起见,可以用外部5V给LCD供电,只把信号线和单片机连在一起。

加显示不仅是为了好看,更重要的是让你学会观察系统状态。我通过屏幕发现湿度经常在65%以上,后来才发现加湿器开启时间太长,把控制阈值从45%-55%调低,箱内湿度才稳定到目标范围。没有屏幕,这种问题你可能要开串口看几天才能发现。

5.2 加风扇匀温、超温报警和远程监控

基础版孵化器有一个很大的缺点:箱内温度不均匀。加热垫只能加热局部区域,蛋托边缘和中心温差可能达到1℃以上。我的解决方法是加了一个5V小风扇,放在箱体侧面,以最低转速持续运转,让热空气在箱内慢慢循环。风扇不要直接对着DHT11吹,否则风冷效果会让传感器读数偏低,风扇转速也尽量选低速,安静且节能。

超温报警也非常值得加。虽然滞回控制能避免继电器频繁动作,但如果继电器触点粘连,或者单片机程序跑飞,温度会一路飙升。我用一个无源蜂鸣器接D9引脚,温度超过39℃时直接响起,提醒人工介入。更保险一点,还可以串一个可恢复保险丝在加热垫供电回路上,过热自动断开,从物理层面兜底。

如果你想手机远程看温湿度,可以换ESP8266或者ESP32做主控,代码逻辑不变,只把DHT11和继电器控制移植过去,再借助MQTT上报数据。远程监控的意义不在于追求炫技,而是孵化周期长达20多天,你不可能24小时守着箱子。有一次我出门半天,手机弹警告说温度到40℃,赶紧打电话让家人去断电,才发现是继电器模块坏了,被加热垫死死粘在闭合状态。

最后再分享一点个人经验。做完这台孵化器后,我又陆陆续续做了一次水床孵化器、补光灯控制器、加热床垫,核心逻辑几乎都是“传感器+继电器/可控硅+滞回控制”。DHT11的精度确实算不上好,但在这个场景里,真正影响孵化率的不是那零点几摄氏度,而是整个系统的稳定性和你对设备的熟悉程度。DHT11便宜,坏了两三块钱就换一颗,继电器模块也不值钱,舍得折腾才是Maker最需要的东西。如果后续你想进一步减小温湿度波动,可以把继电器换成固态继电器,控制周期从2秒缩短到500毫秒,效果立竿见影。但不管怎么改,传感器布点、阈值设置、断电保护这三件事永远排在第一位。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 5:56:51

S32K3双核CANFD配置实战:EB tresos中断与轮询方案详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 5:56:36

ROS2扫地机器人开发实战:从SLAM建图到Nav2导航全栈指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 5:56:06

SOEM主站控制伺服驱动器:PDO配置与状态机切换高频误区详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 5:55:52

STM32移植AUTOSAR BSW的常见雷区与实战排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 5:55:05

OpenCV三维点云重建:法线估计与表面网格生成优化指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 5:54:56

SPSS信度检验实操:Cronbach‘s Alpha与问卷数据分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华