news 2026/9/25 1:54:02

基于STM32的智能除湿衣柜DIY:从硬件选型到代码调试全记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于STM32的智能除湿衣柜DIY:从硬件选型到代码调试全记录

1. 为什么我要做这个智能除湿衣柜

南方回南天那段时间,我家衣柜里的衣服摸上去总是潮乎乎的,有几件羊毛衫甚至长了霉点。市面上带除湿功能的衣柜动辄三四千,而一个普通的半导体除湿模块才几十块钱。我本身是做嵌入式开发的,手头常备STM32F103C8T6最小系统板,就想着干脆自己搭一套控制系统,把普通衣柜改造成能自动控湿的智能衣柜。

这个项目的核心思路很直接:用DHT11采集衣柜内部的温湿度,STM32根据设定的湿度阈值决定是否启动除湿模块和风扇,OLED屏实时显示当前状态,按键用来调整目标湿度。整套东西成本不到一百块,代码、原理图、仿真全部开源。适合有STM32基础、想找一个完整小项目练手的同学,也适合想低成本解决衣柜潮湿问题的动手派。

我前后花了大概两周的业余时间,从画原理图到打板焊接再到调代码,中间踩了不少坑。下面把整个项目的设计思路、关键电路、代码架构和调试经验完整梳理一遍,你照着做基本能复现出来。

2. 系统整体方案与硬件选型逻辑

2.1 为什么选STM32F103C8T6而不是其他MCU

这个项目对算力要求极低,DHT11是单总线协议,OLED是I2C,继电器是普通GPIO控制,随便一个8位单片机都能胜任。选STM32F103C8T6主要考虑三点:第一,这颗芯片资料极其丰富,网上随便一搜就有大量参考设计,出了问题容易找到答案;第二,它的GPIO驱动能力足够直接驱动继电器模块的光耦输入端,不需要额外加三极管;第三,我手头囤了好几块最小系统板,零成本。

如果你手头只有STC89C52或者合泰的单片机,也完全可以做,逻辑是一样的,只是代码要重新适配。选型这件事没有绝对的对错,关键看你手上有什么、熟悉什么。

2.2 除湿方案对比:半导体制冷片 vs 压缩机 vs 干燥剂

这是整个项目最关键的决策点。我一开始考虑过用压缩机除湿,除湿量大、效率高,但体积太大,衣柜里根本塞不下,而且噪音和震动都不适合放在卧室。干燥剂方案最简单,但需要频繁更换,谈不上"智能"。

最终选了半导体制冷片方案。它的原理是帕尔贴效应:通电后一面制冷一面发热,冷面温度降到露点以下,空气中的水蒸气就会在冷面凝结成水滴。优点是体积小、无噪音、无震动、控制简单,缺点是除湿量有限、效率比压缩机低。但对于衣柜这种密闭小空间(大约0.5立方米),半导体制冷片完全够用。

我用的是一片TEC1-12706,12V供电,最大温差能到60度以上。实际使用中冷面温度大概在5到10度之间,配合一个小风扇把潮湿空气吹过冷面,除湿效果很明显。热面必须加散热片和风扇,否则热量散不出去,制冷效率会急剧下降。

2.3 传感器选型:DHT11够不够用

DHT11的湿度测量范围是20%到90%RH,精度正负5%RH,温度精度正负2度。有人觉得精度太差,想换DHT22或者SHT30。我的看法是:对于衣柜除湿这个场景,你只需要知道"湿度是不是超过60%"这一个判断,正负5%的误差完全可以接受。DHT22精度更高但价格贵好几倍,SHT30是I2C接口精度最好但成本更高。

DHT11最大的问题是采样频率不能太快, datasheet要求两次读取间隔至少1秒,实际使用中我建议间隔2秒以上,否则容易读到0或者校验失败。这一点在后面代码部分会详细说。

2.4 整体硬件框图

系统由五个部分组成:STM32主控、DHT11温湿度传感器、OLED显示模块、按键输入、继电器驱动模块。继电器控制两个负载:半导体制冷片和散热风扇。另外还有一个状态指示灯,用来快速判断系统是否在除湿状态。

供电方面,STM32和OLED用3.3V,DHT11用3.3V或5V都可以,继电器模块用5V,半导体制冷片和风扇用12V。所以需要一个12V电源适配器,然后通过降压模块得到5V和3.3V。我用的是一块LM2596降压模块调到5V,再用AMS1117-3.3得到3.3V。

3. 原理图设计与关键电路细节

3.1 STM32最小系统与引脚分配

我用的是STM32F103C8T6最小系统板,上面已经包含了晶振、复位电路和稳压芯片,所以原理图部分只需要画外围电路的连接。引脚分配如下:

功能引脚说明
DHT11数据PA0单总线,需要4.7K上拉
OLED SCLPB6I2C1时钟
OLED SDAPB7I2C1数据
按键1(加)PA1内部上拉,按下为低
按键2(减)PA2内部上拉,按下为低
按键3(确认)PA3内部上拉,按下为低
继电器1(制冷片)PA4高电平触发
继电器2(风扇)PA5高电平触发
状态指示灯PC13低电平点亮

这里有个细节要注意:PA0作为DHT11的数据线,必须接一个4.7K到10K的上拉电阻到3.3V。DHT11的数据线是开漏输出,没有上拉电阻的话读不到数据。我一开始忘了加上拉,调试了半天以为是时序问题,后来用示波器一看数据线一直是低电平,才反应过来。

3.2 继电器驱动电路与隔离设计

继电器模块我直接买的是成品模块,上面已经带了光耦隔离和续流二极管。但即使是成品模块,也要注意几点:第一,继电器模块的VCC和GND要单独走线到电源,不要和MCU共用一条细线,否则继电器吸合瞬间的电流冲击可能导致MCU复位;第二,控制信号线最好串联一个100欧姆的电阻,限流保护光耦输入端;第三,如果继电器模块是低电平触发,代码里的逻辑要反过来。

我用的模块是高电平触发,所以PA4和PA5输出高电平时继电器吸合。半导体制冷片和风扇分别由两个继电器控制,这样可以独立控制:先开风扇再开制冷片,关的时候先关制冷片再关风扇,让风扇多转一会儿把残余冷量吹出来,也保护制冷片不会因为热量积聚而损坏。

3.3 电源部分:12V转5V转3.3V

电源是整个系统最容易出问题的地方。半导体制冷片TEC1-12706的额定电流是6A,启动瞬间电流更大。如果用普通的12V 1A适配器,根本带不动。我一开始用了一个12V 2A的适配器,结果制冷片一启动电压就掉到8V,MCU直接复位。

后来换了一个12V 5A的适配器才稳定下来。这里给个经验值:TEC1-12706实际工作电流在3到4A左右(取决于散热条件),加上风扇和MCU,总电流至少需要5A余量。适配器选12V 6A或更大比较稳妥。

5V部分用LM2596降压模块,输入接12V,输出调到5V给继电器和DHT11供电。3.3V用AMS1117-3.3从5V降压得到,给STM32和OLED供电。注意AMS1117的压差要求至少1V,5V转3.3V没问题,但如果输入低于4.3V输出就不稳定了。

3.4 嘉立创画图注意事项

原理图我用嘉立创EDA画的,这个工具对个人用户免费,元件库也比较全。画图时有几个点要注意:第一,DHT11的封装要确认清楚,有的是三脚直插,有的是四脚,买之前先看数据手册;第二,OLED模块的I2C地址通常是0x78或0x3C,画图时不用管,代码里扫描一下就知道;第三,继电器模块如果是外接的,原理图上只需要画一个排针接口就行,不用把继电器线圈和触点都画出来。

PCB布局时,12V大电流走线要尽量宽,我用了2mm线宽。制冷片和风扇的接线端子要靠近继电器输出端,减少走线长度。DHT11的走线要远离电源线和继电器,避免干扰。

4. 代码架构与核心模块实现

4.1 工程目录结构与开发环境

我用Keil MDK 5开发,工程目录结构如下:

SmartWardrobe/ ├── Core/ │ ├── main.c │ ├── stm32f1xx_it.c │ └── system_stm32f1xx.c ├── Drivers/ │ ├── STM32F1xx_HAL_Driver/ │ └── CMSIS/ ├── Hardware/ │ ├── dht11.c / dht11.h │ ├── oled.c / oled.h │ ├── key.c / key.h │ └── relay.c / relay.h ├── App/ │ ├── app_control.c / app_control.h │ └── app_display.c / app_display.h └── MDK-ARM/ └── SmartWardrobe.uvprojx

分层原则:Hardware层只负责硬件驱动,App层负责业务逻辑,main.c只做初始化和主循环调度。这样后面如果要换传感器或者改控制逻辑,只需要改对应的层,不会牵一发动全身。

4.2 DHT11驱动:时序是最大的坑

DHT11的单总线协议对时序要求很严格。STM32F103C8T6主频72MHz,一个时钟周期约13.9ns。DHT11的时序要求是:主机拉低至少18ms,然后拉高20到40us,然后释放总线等待DHT11响应。

我用的是HAL库的微秒延时函数,但HAL_Delay只能做到毫秒级,所以需要自己写一个微秒延时。可以用SysTick或者DWT。我用的是DWT方案,代码如下:

void DWT_Delay_Init(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } void DWT_Delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = us * (SystemCoreClock / 1000000); while ((DWT->CYCCNT - start) < ticks); }

读取DHT11的完整流程是:主机拉低至少18ms,拉高20到40us,然后切换为输入模式,等待DHT11拉低80us作为响应信号,再拉高80us,然后开始传输40位数据。每一位数据以50us低电平开始,高电平持续26到28us表示0,持续70us表示1。

这里有个大坑:如果在中断里调用DWT_Delay_us,而中断优先级又比较高,可能会打断时序导致读取失败。我的做法是在读取DHT11期间关闭全局中断,读完再打开。虽然会稍微影响系统实时性,但DHT11读取只需要几毫秒,影响可以忽略。

4.3 OLED显示:I2C驱动与界面布局

OLED我用的是0.96寸128x64的I2C模块,驱动芯片是SSD1306。I2C地址通常是0x78(8位地址)或0x3C(7位地址)。HAL库的I2C函数用的是7位地址,所以代码里填0x3C。

显示界面我设计了四行内容:第一行显示当前温度和湿度,第二行显示设定的目标湿度,第三行显示除湿状态(工作中/待机),第四行显示运行时间。字体用的是6x8和8x16两种,标题用8x16,数据用6x8。

OLED刷新频率不需要太高,我每500ms刷新一次。如果刷新太快,I2C总线占用时间过长,可能影响DHT11的读取。另外OLED的I2C速率我设的是400kHz,实际测试100kHz也够用,但400kHz刷新更流畅。

4.4 继电器控制逻辑与状态机

控制逻辑用一个简单的状态机实现,状态定义如下:

typedef enum { STATE_IDLE, // 待机,湿度低于阈值 STATE_DEHUMID, // 除湿中,制冷片和风扇都开 STATE_COOLDOWN, // 制冷片关闭,风扇继续运行 STATE_ERROR // 传感器读取失败 } SystemState_t;

状态转换条件:当湿度大于目标湿度加3%时,进入DEHUMID状态,先开风扇,延时500ms再开制冷片。当湿度小于目标湿度减3%时,进入COOLDOWN状态,先关制冷片,风扇继续运行30秒后关闭,然后回到IDLE。这个3%的迟滞区间是为了防止湿度在阈值附近波动导致继电器频繁吸合。

传感器读取失败时进入ERROR状态,关闭所有负载,OLED显示错误信息,每2秒重试一次。如果连续10次失败,就认为传感器故障,保持ERROR状态并闪烁指示灯。

4.5 按键处理与参数存储

三个按键分别对应加、减、确认。短按加/减调整目标湿度,每次1%,范围30%到80%。长按加/减可以快速调整,每200ms变化一次。确认键用来保存设置到Flash。

参数存储我用的是STM32内部的Flash,地址选在0x0801F800(最后一页)。写入前要先擦除整页,然后按半字写入。读取时直接指针访问。注意Flash写入期间CPU会暂停,所以不要在中断里写Flash。

#define FLASH_SAVE_ADDR 0x0801F800 void SaveTargetHumidity(uint8_t humidity) { HAL_FLASH_Unlock(); FLASH_EraseInitTypeDef erase; erase.TypeErase = FLASH_TYPEERASE_PAGES; erase.PageAddress = FLASH_SAVE_ADDR; erase.NbPages = 1; uint32_t pageError; HAL_FLASHEx_Erase(&erase, &pageError); HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FLASH_SAVE_ADDR, humidity); HAL_FLASH_Lock(); }

5. 仿真验证与实物调试中的真实踩坑记录

5.1 Proteus仿真能验证什么、不能验证什么

我在打板之前先用Proteus做了仿真。Proteus里有DHT11的模型,也有OLED和继电器模型,可以验证基本的逻辑是否正确。但仿真有几个局限:第一,DHT11的时序在仿真里是理想化的,实际硬件的时序偏差仿真体现不出来;第二,继电器的电流冲击仿真不了;第三,I2C总线的实际波形仿真看不到。

所以我的建议是:仿真用来验证代码逻辑和状态机是否正确,硬件时序和电源问题必须实物调试。不要因为仿真跑通了就以为万事大吉。

5.2 DHT11读取失败的三种典型情况和排查方法

调试期间我遇到过三种DHT11读取失败的情况,排查过程如下:

第一种,读到的全是0。用示波器看数据线,发现主机拉低之后DHT11根本没有响应。检查后发现是上拉电阻没焊,数据线一直是低电平。补焊4.7K上拉电阻后解决。

第二种,偶尔读到校验和错误。这种情况通常是时序偏差导致的。我用逻辑分析仪抓了波形,发现高电平持续时间在临界值附近波动。原因是DWT延时在中断干扰下不准确。解决办法是读取期间关中断,并且把两次读取间隔从1秒增加到2秒。

第三种,刚开始正常,运行几小时后读取失败。用手摸DHT11发现有点热,怀疑是供电问题。测量VCC发现只有2.8V,原来是AMS1117-3.3发热导致输出下降。在AMS1117上加了一个小散热片,并把输入电压从5V降到4.5V(用LM2596调),问题解决。

5.3 继电器吸合导致MCU复位的电源问题

这是我最头疼的一个问题。每次继电器吸合,MCU就复位,OLED黑屏重启。一开始以为是继电器模块的光耦隔离没做好,换了模块还是一样。后来用示波器看3.3V电源轨,发现继电器吸合瞬间3.3V上有一个很大的负向尖峰。

根本原因是:继电器线圈和MCU共用同一个5V电源,继电器吸合瞬间电流突变,在电源线上产生感应电动势,通过AMS1117耦合到3.3V。解决办法有三个:第一,继电器模块的VCC单独从12V经过一个独立的LM2596降压得到,不和MCU共用;第二,在继电器模块的VCC和GND之间并联一个1000uF电解电容和一个0.1uF陶瓷电容;第三,在MCU的3.3V电源引脚旁边加一个10uF钽电容。

三个措施一起上之后,继电器吸合时3.3V纹波从原来的300mV降到了50mV以内,MCU再也不复位了。

5.4 半导体制冷片的散热与凝露处理

半导体制冷片的热面散热非常关键。我一开始只加了一个小散热片,没有风扇,结果制冷片工作5分钟后热面温度超过80度,冷面反而不冷了。后来换了一个大散热片加12V风扇,热面温度稳定在45度左右,冷面能到5度。

凝露处理也很重要。冷面上凝结的水滴如果直接滴到电路板上会短路。我在冷面下方放了一个小接水盘,并且把制冷片和电路板用塑料隔板隔开。另外,衣柜本身不是完全密封的,湿度降下来之后要记得关掉制冷片,否则会过度除湿,衣服变得太干。

5.5 代码诊断与调试技巧

调试STM32代码时,我主要用三种手段:第一,用ST-Link Utility查看Flash内容,确认参数是否正确写入;第二,用串口打印调试信息,把DHT11的原始数据、状态机状态、继电器状态都打印出来;第三,用逻辑分析仪抓DHT11和I2C的波形。

串口打印我建议用DMA方式,不要用阻塞发送,否则会影响时序。我用的波特率是115200,每500ms打印一次状态,信息量足够又不至于刷屏太快。

另外,Keil的Debug模式里可以实时查看变量值,配合断点使用很方便。但要注意,在Debug模式下DHT11的时序会被打断,所以不要在全速运行DHT11读取的时候设断点。

6. 开源资料说明与复现建议

6.1 代码、原理图、仿真文件的组织方式

开源包我按以下结构组织:

SmartWardrobe_OpenSource/ ├── Hardware/ │ ├── Schematic.pdf // 原理图 │ ├── PCB_Layout.pdf // PCB布局图 │ └── BOM.xlsx // 物料清单 ├── Firmware/ │ ├── SmartWardrobe.uvprojx // Keil工程 │ └── Source/ // 所有源码 ├── Simulation/ │ ├── Proteus/ // Proteus仿真文件 │ └── Screenshots/ // 仿真截图 ├── Docs/ │ ├── 调试记录.md │ └── 常见问题.md └── README.md

BOM表里我标注了每个元件的型号、封装、数量和参考购买渠道。半导体制冷片和散热片建议买成套的,省得自己配。

6.2 复现时的物料采购避坑

采购时有几个坑要注意:第一,DHT11买带PCB板的模块版,比裸传感器好焊接,而且自带上拉电阻;第二,继电器模块买光耦隔离的,不要买那种只有三极管驱动的;第三,12V电源适配器一定要选电流足够的,我推荐12V 6A;第四,OLED买I2C接口的,SPI接口的接线更多但速度更快,看个人选择。

半导体制冷片TEC1-12706有很多种,有的标称6A但实际只有4A,买的时候看评价。散热片要选面积足够大的,至少40x40mm,配合12V风扇。

6.3 从仿真到实物的移植注意事项

Proteus仿真里用的元件模型和实物可能有差异。比如仿真里的DHT11响应是即时的,实物需要等待;仿真里的继电器是理想开关,实物有吸合时间和弹跳。移植时要把这些因素考虑进去,在代码里加足够的延时和容错。

另外,仿真里的电源是理想的,实物电源有纹波和压降。建议在实物调试时先用示波器看一遍所有电源轨,确认纹波在可接受范围内再上电运行。

6.4 后续可扩展的方向

这个项目目前只做了基础的除湿控制,后面还可以加不少东西。比如加一个ESP8266模块,把温湿度数据上传到手机,实现远程监控;加一个RTC时钟模块,记录每天的除湿时长;加一个SD卡模块,把历史数据存下来做趋势分析。

如果要做OTA升级,STM32F103C8T6的Flash只有64KB,跑OTA会比较紧张,建议换F103RCT6或者F407。不过对于这个项目来说,OTA不是刚需,用ST-Link烧录就足够了。

我在实际使用中最大的体会是:硬件项目里,电源和时序永远是最容易出问题的地方,代码逻辑反而很少出错。把电源做好、把时序调准,项目就成功了一大半。另外,不要迷信仿真,实物调试才是检验真理的唯一标准。

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

STM32高效解析SBUS:DMA循环接收与IDLE中断实战

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

作者头像 李华
网站建设 2026/9/25 1:53:52

AI财报分析提示词设计:从杜邦拆解到DCF估值避坑

简介&#xff1a;面向金融分析、投资决策场景的AI财报分析提示词合集&#xff0c;适合借助大模型快速解读上市公司财务报告的投资者、分析师与金融从业者使用。包内含单个PDF文件&#xff0c;压缩包仅484KB&#xff0c;便于直接下载、阅读与复制调用&#xff0c;目前已有185人学…

作者头像 李华
网站建设 2026/9/25 1:53:50

京东淘宝竞品分析报告:从数据采集到策略输出的完整框架

简介&#xff1a;京东与淘宝竞品分析报告是一份PDF格式的互联网产品竞品分析案例&#xff0c;主要面向产品经理、运营人员、电商相关内容学习者以及正在求职的互联网从业者&#xff0c;旨在提供一套可供参考的电商竞品对比思路。资源为单个PDF文件&#xff0c;大小8.75MB&#…

作者头像 李华
网站建设 2026/9/25 1:53:21

fruits分类数据集.rar实战:图像分类pipeline健壮性验证指南

简介&#xff1a;本资源是面向人工智能与机器学习初学者及计算机视觉实践者的水果图像分类数据集&#xff0c;专为图像识别模型训练与评估设计&#xff0c;覆盖监督学习、特征工程与模型泛化等核心环节。压缩包共1310个文件&#xff0c;主体为1306张高质量JPG格式水果图像&…

作者头像 李华
网站建设 2026/9/25 1:53:09

极域工具包1.1:窗口化与解键盘锁技术解析

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

作者头像 李华
网站建设 2026/9/25 1:52:44

领航杯网络安全题库拆解:从背题到懂题的高效备赛指南

简介&#xff1a;面向“领航杯”江苏省青少年网络信息安全知识竞赛的备考资源&#xff0c;以Word文档形式汇总网络信息安全核心考点与选择题题库&#xff0c;适合青少年参赛者及指导教师赛前系统复习与实战刷题。压缩包内共1个doc文件&#xff0c;整体大小243KB&#xff0c;内容…

作者头像 李华