每年梅雨季南方朋友对“衣柜长毛”这件事应该都有一肚子苦水。皮包上泛起霉斑、羽绒服一股潮味、鞋盒里甚至能抠出绿毛打开衣柜那瞬间真的很上头。我自己做了好几年嵌入式手边最多的就是STM32的板子某天看着又开始返潮的衣柜干脆花了一个周末做了套自动除湿的东西就是标题里这个“智能除湿衣柜控制系统”。整套项目包含完整的MCU源码、PDF原理图、Proteus仿真工程全部开源这篇文章把设计思路、硬件原理、关键代码和调试过程中踩过的坑一次性讲清楚。它能做什么简单说就是给衣柜装上“鼻子”和“手”DHT11温湿度传感器实时感知柜内湿度STM32F103C8T6做主控负责逻辑判断湿度超了自动开加热器和风扇把湿气赶出去湿度降下来自动停全程不需要人干预。除了自动模式还支持手动控制、按键调节阈值、OLED屏显示当前温湿度。这套东西适合三类人参考想给家里衣柜、鞋柜、书柜做防潮改造的DIY爱好者学STM32想找一个完整练手项目的新手以及在找毕业设计题目的同学。后面每一部分都可以直接照着抄。1. 项目整体设计与思路拆解1.1 为什么做智能除湿衣柜衣柜里的潮气不是一朝一夕形成的。衣柜通常靠墙摆放柜体背板紧贴墙面墙体的水分慢慢渗透进来再加上衣柜通风条件差衣物、被褥吸收人体汗气和空气中的水分后持续释放柜内相对湿度很容易长期维持在70%到85%之间。这个湿度区间正好是霉菌最喜欢的生长环境霉菌孢子在湿度超过70%后活性迅速上升所以皮具发霉、布料产生异味几乎是必然结果。传统处理方式无非是往柜子里塞干燥剂氯化钙颗粒吸湿饱和后就失效了如果忘了更换它会反渗水分搞得更湿。硅胶干燥剂可以反复烘干但需要频繁拆装大多数人也坚持不下来。被动吸湿的问题在于不可感知、不可控制你不知道柜子什么时候湿、湿了多久只能等霉斑长出来才发现问题。智能除湿衣柜的核心思路就是把这件事做成闭环控制传感器持续监测控制器判断后主动除湿把湿度压制在安全区间里让霉菌根本没有生长的机会。我做这个项目时给自己提了两个约束。第一不改动衣柜结构所有模块通过3M胶、扎带或磁吸底座固定在柜内壁不钻孔不破坏家具。第二功耗必须可控不能为了提高除湿效率一天烧掉几度电设备只在高湿时段工作平时待机功耗可以忽略。这两条约束直接影响了后面控制逻辑和硬件选型的方向也让它从“实验室玩具”变成了能长期放在衣柜里跑的东西。1.2 系统总体架构与工作流程整套系统按功能可以拆成三层感知层、决策层、执行层。感知层是一路DHT11温湿度传感器安装在柜内中上部、靠近衣物悬挂区域的位置这个位置的空气流通性比较有代表性测出来的湿度比贴近背板或柜底更接近真实情况。决策层是STM32F103C8T6负责读取传感器数据、校验数据、刷新OLED屏、接收按键输入并按照预设的控制策略输出开关信号。执行层是两个继电器驱动单元一个控制PTC恒温加热器一个控制直流轴流风扇。系统主循环流程是这样的上电后先初始化时钟、GPIO、I2C、DHT11引脚然后进入循环。每次循环先读DHT11读取失败就保留上次有效数据并且不更新显示连续三次失败则在OLED上提示传感器异常读取成功就解析出温度和湿度刷新OLED接着把湿度交给控制逻辑控制逻辑根据当前状态决定继电器开或者关最后扫描按键处理阈值设置。整个循环实测大概耗时几十毫秒加上2秒一次的采样间隔实时性完全够用毕竟衣柜里的湿度变化是分钟级甚至小时级的。控制逻辑用的是滞回判断这也是本设计最核心的策略湿度升到75%以上才启动除湿一直运行到湿度降到60%以下才停止中间60%到75%这个区间维持上次状态。很多新手一开始会写“湿度大于65%开小于65%关”结果就是湿度在阈值附近波动时继电器疯狂吸合断开继电器触点寿命很快报废。滞回控制就是给开关加了一个缓冲带代价是湿度会稳定在60%到75%之间波动但这恰恰能避免频繁启停对机械触点类负载非常友好。1.3 除湿方案选型对比一开始我考虑过好几种除湿方式各有各的道理放一起对比其实很直观方案成本除湿效果主要缺点适合场景被动干燥剂低有限饱和后失效、无法自动控制干燥地区、临时防潮半导体制冷片冷凝中直接有效功耗大、柜内散热难、需处理冷凝水小型密封箱体PTC加热通风中高效稳定轻微升温、需控制温度上限衣柜、鞋柜等非密封空间抽湿机式整机高最好体积大、占用柜内空间、成本高全屋级除湿这个项目最终选了PTC加热加通风的组合。PTC发热元件有正温度系数特性温度升高后电阻变大、功率自动下降不会像普通电热丝那样烧到通红或者失去控制用在衣柜这种装载衣物的地方特别安全。配合风扇强制对流湿热空气被快速搅动并排出柜体除湿效率比单纯靠自然对流加热高不少。实际上就是模拟了烘干机的工作逻辑把柜内空气加热让衣物和空气中的水分蒸发出来然后换气排走。选型时还有一个细节要提醒衣柜如果不是完全密封的通常背板或柜门缝就有自然透气加热除湿效果明显如果家里的衣柜是那种密封性特别好的整体柜建议在柜门底部或背部加一个透气窗或者把风扇反过来做主动排风否则加热出来的水汽没有出路效果会打折扣。我的做法是在柜背板底部留了一条缝隙风扇对着缝隙吹实测降湿速度明显加快。2. 硬件设计与原理图要点2.1 主控选型与最小系统设计主控用的是STM32F103C8T6Cortex-M3内核72MHz主频64KB Flash20KB SRAM。这颗芯片在入门级项目里的地位不用多说资料多、例程全、开发板便宜I/O口也够用。我这个项目用到了DHT11的一根数据线、OLED的两根I2C线、两个按键、两路继电器输出再加上一个LED状态指示灯总共占用了8个GPIO对于这颗芯片来说非常宽裕后面想扩展蓝牙模块、ESP8266远程控制也还有富余。最小系统里最容易被新手忽略的是电源引脚去耦和复位电路。STM32的每个电源引脚旁边都要放一个0.1μF陶瓷电容靠近引脚放置就是用来吸收数字电路开关时产生的高频噪声。VDD主电源上还可以加一个10μF电解电容做低频滤波。NRST复位脚接一个100nF电容到地防止外部复位信号抖动干扰。BOOT0引脚建议直接通过10kΩ电阻下拉到地强制从Flash启动这样ST-Link烧录后就能正常运行。另一个关键是最小系统必然要接外部晶振我用的是8MHz贴片晶振两个引脚各接一个20pF对地电容这是最常见的HSE接法。有人图省事直接用内部HSI时钟也能跑但USB通信、精确延时、串口波特率都可能不准后期调试会非常憋屈。这个项目里DHT11对时序精度有要求所以外部晶振不能省。2.2 DHT11温湿度传感器接口DHT11是单总线数字传感器三根引脚VCC、DATA、GND。它内部自带了一个8位单片机做湿度温度采集外部只需要一根数据线就能读出40位数字量测量范围20%到90%RH、0到50℃精度±5%RH、±2℃这个精度放在衣柜监控场景里完全够用。接口电路上DATA引脚必须接一个4.7kΩ上拉电阻到VCC因为单总线协议里空闲状态是高电平所有信号都是主机和从机通过拉低总线来传输的没有上拉电阻总线就一直是低电平通信一开始就废了。供电方面DHT11常见的供电范围是3.3V到5V我实际测试3.3V供电完全正常而且数据信号的高低电平逻辑更贴近STM32的容忍范围直接接没问题。但要注意如果买的是模块而不是裸传感器很多模块板上已经带了上拉电阻接的时候不要重复加一个很大的上拉否则总线可能拉不低通信一样失败。还有个易坑点是引脚顺序。DHT11裸传感器的引脚排列常有丝印不清的情况插反了轻则读不到数据严重时可能烧传感器。最简单的确认办法是看PCB上的丝印或者说明书拿不准就尽量买带引脚的模块模块上一般标了OUT、VCC、GND怎么接都不容易错。我在原理图上把DATA特意标成PA0走线尽量短避免柜内复杂电磁干扰影响到数据线。2.3 继电器驱动与电源设计STM32的GPIO最大输出电流也就20mA左右直接接继电器线圈是不够的驱动时要加一级三极管放大。我用的是S8050三极管结构是一个典型的高电平导通开关GPIO先串联1kΩ电阻接到三极管基极三极管集电极接继电器线圈的一端和续流二极管负极发射极接地继电器线圈另一端接12V电源。GPIO输出高电平时三极管饱和导通继电器线圈通电吸合输出低电平时三极管截止继电器断开。继电器线圈是感性负载断电瞬间会产生一个反向电动势如果没有保护这个高压尖峰很容易击穿三极管。正确的做法是在继电器线圈两端反并联一只1N4148快恢复二极管负极接电源正、正极接三极管集电极断电时反向电动势通过二极管形成回路泄放掉。我第一次做继电器驱动的时候忘装这两个二极管继电器吸合断开几十次后就烧了一个S8050温度一摸滚烫后来补上二极管再没出过问题。电源部分要分开看整个系统用12V/2A适配器供电经过电源插座进来后分两路——一路直接给继电器和12V散热风扇供电另一路通过AMS1117-3.3稳压到3.3V给STM32和OLED供电。DHT11和按键也都从3.3V取电。为什么不让继电器直接从3.3V取电因为继电器线圈额定电压是12V或5V3.3V驱动电流不够容易吸合不到位导致触点电阻增大。执行部件用12V控制部件用3.3V两个电源域在PCB上尽量分开铺铜控制信号通过电阻或光耦跨越这个习惯对后期稳定性非常重要。2.4 原理图绘制与PCB布局经验原理图我用的是嘉立创EDA专业版画的因为是国产工具、云端元器件库全出BOM和PCB都非常顺手。画原理图之前先把所有模块的引脚定义列清楚STM32的PA0接DHT11 DATAPB6接OLED SCLPB7接OLED SDAPA2和PA3接按键PB0接加热继电器PB1接风扇继电器PC13接状态LED。每个元器件都加上清晰的值标注DHT11旁边明确写上“上拉4.7k到3.3V”方便后面出焊接清单。PCB布局上有一条很重要的经验继电器和大负载走线尽量远离MCU和传感器。继电器吸合瞬间会有明显的电流跳变可能造成地电位抖动干扰DHT11的时序读取表现为读数偶尔跳成85%甚至255。解决办法是采用单点接地把继电器驱动部分的“地”单独拉一条粗线回电源地MCU侧的模拟地和数字地再合并两者之间不要互相穿过。如果控制的是220V负载建议增加光耦隔离控制侧和负载侧完全分开PCB上还要开隔离槽这个不是可选项是安全红线。还有一个人人都该注意的细节DHT11的安装位置决定了测量准不准。直接贴在PCB上、被继电器和电源的热量包围测出来的湿度会明显偏低。我的做法是把DHT11通过杜邦线引出到衣柜中上部远离一切发热元件。原理图里把DHT11画在板边缘只留焊盘和连接器配合一根30cm长的线这样实际安装非常灵活。3. 软件设计与核心代码解析3.1 代码工程结构整个软件工程基于STM32标准外设库或者HAL库都能移植我开源的这个版本用的是HAL库加CubeMX图形化配置好处是初始化代码由工具生成不容易遗漏新手也能对照图形界面理解每个引脚的功能。工程目录如下Project/ ├─ Core/ │ ├─ Inc/ │ └─ Src/ │ ├─ main.c │ └─ stm32f1xx_it.c ├─ Hardware/ │ ├─ dht11.c / dht11.h │ ├─ oled.c / oled.h │ ├─ key.c / key.h │ └─ control.c / control.h ├─ Drivers/ │ └─ ...HAL库源码 └─ MDK-ARM/业务代码全部放在Hardware目录下每个外设封装成一个模块模块之间不互相依赖这是嵌入式工程最重要的组织原则。main.c里只做三件事调用初始化函数、进入主循环、循环里依次执行“读传感器、刷新显示、跑控制逻辑、扫描按键”。这样有一个明显的好处后面想加功能比如接ESP8266上报数据只需要新增一个模块并在主循环里加一行调用其他代码几乎不用动。3.2 DHT11单总线时序驱动DHT11通信是最容易让新手崩溃的地方因为它对时序非常敏感读数据的窗口窄到几十微秒。单总线协议的基本帧是这样的主机先把总线拉低至少18ms发出起始信号然后释放总线DHT11检测到后响应先把总线拉低80μs再拉高80μs接着连续输出40位数据每一位都以50μs低电平开始后面高电平持续26到28μs代表“0”持续70μs代表“1”。主机在读取每一位时要等低电平结束然后在第40μs左右去采样电平高低。这个时序用HAL库的HAL_Delay完全不行因为HAL_Delay基于SysTick中断和上下文切换会破坏微秒级精度。我推荐用DWT数据观察点与跟踪单元做精确延时或者直接读内核寄存器的计数器。另一个更稳的做法是切换GPIO到输入模式后用while循环加指令周期估算实测在72MHz主频下一个空循环约等于几十纳秒按需微调。开源代码里我写的是寄存器版延时保证在各种优化等级下都不会出问题。完整读取一帧的代码核心如下uint8_t DHT11_ReadByte(void) { uint8_t i, data 0; for (i 0; i 8; i) { while (GPIOA-IDR (1 0)); // 等待50us低电平结束 DWT_Delay_us(40); if (GPIOA-IDR (1 0)) { // 40us后仍是高电平 bit1 data | (1 (7 - i)); while (GPIOA-IDR (1 0)); // 等待高电平结束 } } return data; }读完40位数据后按照协议前4个字节分别是湿度整数、湿度小数、温度整数、温度小数第5个字节是校验码校验码等于前四个字节之和的低8位。校验通过才更新显示和控制逻辑校验失败直接丢弃这一帧这样即使偶尔受到干扰显示的数据也不会乱跳。这个“丢坏帧”的思路在工业采集里很常见属于花钱买不来的经验。3.3 滞回控制逻辑实现控制模块的设计核心是滞回比较器思路。我定义了两个阈值和一个温度上限代码里用宏定义方便调整#define HUMI_DEHUMIDIFY_TH 75 // 湿度达到75%时启动除湿 #define HUMI_STOP_TH 60 // 湿度降到60%时停止除湿 #define TEMP_SAFE_LIMIT 45 // 柜内温度安全上限超过只通风不加热具体逻辑用一个简单的状态机管理只有两个状态待机和除湿。待机状态下湿度达到75%且温度未超上限就进入除湿状态两个继电器同时吸合除湿状态下如果湿度降到60%以下说明除湿完成回到待机如果温度超过45℃说明加热过头了关闭加热器但保留风扇继续吹防止闷热。void CONTROL_Update(uint8_t temp, uint8_t humi) { static uint8_t state STATE_IDLE; if (state STATE_IDLE) { if (humi HUMI_DEHUMIDIFY_TH temp TEMP_SAFE_LIMIT) { state STATE_DEHUMIDIFY; CONTROL_RelayOn(RELAY_HEATER); CONTROL_RelayOn(RELAY_FAN); } } else { // STATE_DEHUMIDIFY if (humi HUMI_STOP_TH || temp TEMP_SAFE_LIMIT) { state STATE_IDLE; CONTROL_RelayOff(RELAY_HEATER); CONTROL_RelayOff(RELAY_FAN); } } }这里再提醒一次为什么不用单阈值因为任何一个电子器件都有离散性DHT11读数本身有±5%的误差湿度在某个点附近来回抖动时如果只有一个开启阈值继电器会在几分钟内吸合断开几十次继电器电气寿命通常在十万次左右但机械动作次数多了照样坏。双阈值把动作频率降了几个数量级实际运行下来继电器一天可能只动作三五次使用寿命完全不用担心。我还在逻辑里加了“除湿超时保护”如果连续除湿运行超过2小时说明柜体内可能有持续水源或者传感器异常这时强制关机10分钟然后再尝试。这个保护措施用时间戳实现主要是防患于未然避免加热器长时间运行带来安全隐患这个场景非常适合衣柜这种长期无人值守的环境。3.4 OLED显示与按键交互显示部分用0.96寸I2C接口OLED128x64分辨率三星的SSD1306驱动方案最普及网上驱动多如牛毛。我在显示界面上放了三行内容第一行显示当前温度和湿度第二行显示当前工作状态待机显示“IDLE”除湿中显示“DRYING”传感器异常显示“ERR”第三行只有在设置模式才出现显示当前正在调节的阈值以及提示。为了让屏幕待机时更醒目状态行做了反白显示一眼就能看出柜子当前的状态。按键设计是两个轻触开关一个负责模式切换一个负责参数调整。正常模式下短按KEY1进入设置模式此时用KEY2调整湿度启动阈值每次加减1%长按KEY2则连加。设置完成后5秒无操作自动退出并按当前值更新控制模块。按键扫描放在主循环里因为没有人会一秒钟按十次按键不需要中断反而是软件消抖更重要检测到按下后延时20ms再确认一次既能避免机械抖动误触发又不会占用中断资源。void KEY_Scan(void) { if (KEY1_PRESSED) { delay_ms(20); if (KEY1_PRESSED) { setting_mode !setting_mode; if (setting_mode) OLED_SetCursor(0, 4); } } if (KEY2_PRESSED) { delay_ms(20); if (KEY2_PRESSED) { if (setting_mode (humi_threshold 90)) humi_threshold; } } }OLED刷新频率不要太高我控制在每2秒刷新一次和DHT11采样周期同步。SSD1306虽然是I2C接口但是刷新一帧全屏内容也要传1024字节I2C在400kHz模式下大约耗掉几十毫秒如果刷得太频繁主循环会被拖慢还会挤占DHT11的敏感时序。这个问题在仿真里不明显但实机上OLED刷新期间去读DHT11非常容易读失败。4. 仿真搭建与调试实录4.1 Proteus仿真环境配置仿真部分我用的是Proteus 8.9以上版本自带了STM32F103C8T6模型。仿真工程里放置了主控、DHT11、OLED、按键、继电器、风扇指示LED元件全在库中能找到。接线和原理图保持一致然后加载Keil编译生成的HEX文件就能跑起来。第一次跑仿真最容易踩的坑是芯片不运行。Proteus里放置STM32F103C8T6后首先要双击芯片设置属性Crystal Frequency要按照实际工程配置来我用的是8MHz外部晶振就在模型里填8MHz如果工程用的是72MHz主频但模型里填的是默认值外围逻辑可能对不上。另外VDDA、VSSA这些模拟电源引脚也得接上不然内核上电检测不过去程序根本不会跑。加载HEX文件之前要确保Keil工程勾选了Output选项卡里的Create HEX File否则编译只生成AXF文件Proteus读不了。文件生成后在Proteus芯片属性里选择Program File指向工程目录下的Hex文件点击运行就能看到OLED虚拟屏幕显示数据了。4.2 仿真中的典型坑Proteus的DHT11模型行为跟实物有一点点不同实物每次通信前都要重新上电稳定至少一秒模型则可能已经认为总线空闲了所以程序里DHT11_Start()之后的等待响应时间要稍微放宽否则模型会一直不响应。我的经验是读取失败时不要立刻报传感器错误而是连续失败三次才提示同时保留上次有效数据继续显示这样仿真里即使偶尔丢帧也不会导致界面闪烁。仿真里调节湿度变化的方式也和实物不同。Proteus的DHT11模型大多是通过设定属性里的Initial Humidity和可以通过虚拟环境变量调节或者直接在模型上拖拽数值。调好后可以看到控制逻辑响应湿度从60%慢慢拨到76%继电器LED点亮风扇转动再拨回55%继电器断开。这个过程能很好地验证滞回逻辑不需要实体硬件也能跑通逻辑测试非常适合做代码逻辑的先行验证。仿真速度如果慢得受不了把OLED刷新和DHT11采样频率都调低一点就行因为我前面说过的I2C刷新在Proteus里模拟得更慢。还有一点是仿真中继电器的线圈驱动条件比较苛刻如果三极管模型选错了不吸合检查一下NPN三极管基极电阻是不是挡住了GPIO的输出改用达林顿管ULN2003模型也是个省心的选择。4.3 实物调试问题排查速查实物调试比仿真麻烦但也更能学到东西。我把从我自己做样机到实际放到衣柜里跑了一周遇到的问题整理成了一张排查表按“现象—原因—解决办法”的次序快速定位现象可能原因排查办法上电后完全没反应3.3V没输出、BOOT0悬空、ST-Link识别不了先量AMS1117输出3.3VBOOT0接地接ST-Link看能否读到内核OLED不亮或花屏I2C地址不对、SDA/SCL接反先扫描I2C地址通常为0x3C或0x3D再检查接线湿度偶尔跳出255DHT11数据线受干扰、接线过长加4.7k上拉、缩短杜邦线、校验失败丢弃一帧继电器有响动但负载不转继电器触点容量不足、负载电压不对量继电器触点两端电压确认负载额定电压和电源一致除湿启动后湿度降得慢柜体太密封、风扇方向装反在柜门留通风缝、确认风扇是向外排风而不是向内吹程序能跑但DHT11读取总失败延时函数精度差、模式切换遗漏改用DWT延时、GPIO模式先输出再输入加200ms稳定时间DHT11读取失败还有一个容易忽视的点主机发送起始信号后切换输入模式但总线释放到DHT11响应之间有个时间窗口需要做一次短延时等待。我代码里用的是DWT_Delay_us(20)太短了模型响应不过来太长了又会错过响应窗口20到30μs是比较稳的区间。5. 开源资料说明与使用指南5.1 源码与工程文件开源资料包里包含整个Keil MDK工程代码采用HAL库开发编译环境是Keil MDK 5.3x以上版本STM32CubeMX生成的初始化代码已包含在内不需要自己再重新配置一遍外设。Hardware目录下每一个模块都是独立封装想移植到自己的板子上只需要修改引脚映射即可。代码注释写得比较详细关键函数和状态机部分都有中文说明查起来会省很多时间。如果你想改成标准外设库版本原理是一样的替换HAL库函数调用延时函数改用SysTick或者软件延时其余逻辑不动。这个项目没有用到复杂外设ADC、DMA、PWM都没涉及所以移植难度很低比较适合用来熟悉两种库之间的差异。5.2 原理图与PCB文件原理图导出的是PDF格式可以直接查看接线关系。PCB工程在嘉立创EDA专业版里绘制双面板布局板子尺寸80mm乘60mm最关键的是布局稿里已经画好了三极管驱动区、电源区、MCU区和传感器接口区散热和隔离距离都考虑过了。实际打样时直接用嘉立创下单就行器件都选了容易买到的直插和贴片混合封装焊接难度不大。板上预留了DHT11外接连接器和OLED的四针接口电源输入采用DC005圆头插座5.5x2.1mm规格的12V适配器直接插就能用。如果想要做成5V供电版本只需要把风扇换成5V、去掉AMS1117前级的12V适配器限制电路板上预留了5V供电焊盘跳线切换即可。5.3 仿真工程加载方法Proteus仿真工程文件在“Simulation”目录下用Proteus 8.9及以上版本打开后先确认芯片属性里的Program File一栏指向了“Project/MDK-ARM/Objects”目录下的HEX文件。直接运行后虚拟OLED会显示DHT11的初始温湿度通过调整DHT11模型属性里的湿度参数可以看到整个控制流程的响应。这个仿真工程特别适合在焊板子之前先把逻辑跑通也能拿来修改阈值验证效果。每个文件都有版本号说明代码和仿真工程是配套的如果修改了某个功能两个部分要同步更新。这样即使后面自己改造电路、扩展功能也不会出现“代码和仿真对不上”的尴尬。我个人在实际操作中的体会是这种温湿度控制类项目难点从来不在单个模块而是模块之间的配合。DHT11时序敏感OLED刷新占用时间继电器吸合又带来电气干扰这三个问题单独看都不是大事合在一起就特别考验系统设计能力。踩过几次坑之后我的习惯是PCB布局阶段就把强弱电分开程序里所有微秒级延时一律用DWT主循环里禁止放任何阻塞型等待这样整套系统跑起来稳定太多几乎不再出现莫名其妙读数跳变的情况。这个经验后来用到别的传感器采集项目里也同样管用可以说是一次调试终身受益。最后再分享一个小技巧如果你家里衣柜潮气特别严重可以把湿度启动阈值从75%调到70%停止阈值保持60%除湿启动会更勤快代价是继电器动作频率上升、耗电略微增加。阈值改完之后最好在柜里放个独立的温湿度计对照跑几天确认传感器读数和设定值误差在可接受范围内这样调整起来心里才有底。
