
仓库上周刚出过一次事。东侧货架第三排纸箱表面凝了一层水珠最底下的几箱食品包装已经发霉。查下来就是湿度超标——仓库晚上关窗之后相对湿度飙到78%排风没开因为没人值守也没人知道。这个教训让我花了三周做了这套基于STM32的仓库环境控制系统把温湿度粉尘监测、自动通风除湿和ESP8266上云全部打通。这篇记录从选型、电路、固件、上云到调试踩坑的完整过程给准备做类似项目的人一个可以直接抄作业的参考。1. 仓库环境控制这件事为什么值得自己动手做一套1.1 三个参数到底管什么仓库环境不是温度别太离谱这么简单。我这次梳理需求时把影响仓库质量的参数拆成三个维度温度食品、化工原料、电子元器件对温度都很敏感。温度过高加速氧化和微生物繁殖温度骤降会导致凝露尤其春季昼夜温差大的时候金属货架和墙面上全是水珠。湿度这是最容易翻车的参数。相对湿度超过70%霉菌会进入快速繁殖期超过80%纸箱吸潮变软堆垛稳定性都受影响。很多仓库管理者只关注不漏雨却忽略了大面积凝露。粉尘仓库里如果存放面粉、木屑、塑料颗粒粉尘浓度过高不仅影响工人健康还有粉尘爆炸风险。即便不是易燃粉尘粉尘沉积在电子设备表面也会导致接触不良和散热恶化。我给自己定的控制目标是温度超过35℃自动通风降到32℃停止湿度超过65%自动通风除湿降到60%停止粉尘浓度超过设定阈值启动过滤风机。这套阈值不是拍脑袋定的可以参考食品仓库和一般工业厂房的环境标准再结合当地气候和经验调整。1.2 成品方案够用但总觉得憋屈市面上不是没有仓库环境监测设备。工业级的环境监控主机加传感器报价几千上万很正常而且存在三个我接受不了的问题数据封闭。很多成品方案数据只进厂家自己的平台想导出到本地数据库或者和公司内部的仓储管理系统对接接口要么没有要么收费。联动逻辑写死。我希望湿度超限时先开排风机如果湿度继续上升再开除湿机风机延迟启动5分钟——这种自定义逻辑成品设备很难改。故障不透明。传感器坏了、网线断了设备只会亮红灯具体哪一路出问题你还得拿说明书去猜。自己动手做一套成本可以压到三四百元而且每一行逻辑都看得见、改得动传感器数据想上哪台服务器都行。1.3 系统整体数据流这套系统的架构可以分成四层采集层温湿度传感器AHT20和粉尘传感器GP2Y1010AU0负责感知环境。控制层STM32F103C8T6作为主控跑采集、滤波、阈值判断和继电器驱动。传输层ESP8266通过串口和STM32通信把数据送到云端。展示层云平台仪表盘看实时数据、历史曲线超限时推送报警。数据从传感器进入MCUMCU处理后一方面驱动继电器控制风机和除湿机另一方面打包成JSON数据通过串口交给ESP8266上报云端。本地自动控制不依赖网络——就算WiFi断了通风除湿逻辑照常跑只是云端暂时看不到数据而已。这一点很重要仓库环境控制必须先保证本地闭环上云只是锦上添花。2. 硬件选型与引脚规划一块蓝板加四个模块的取舍2.1 主控为什么是STM32F103C8T6STM32F103C8T6这颗芯片在这个项目里属于降维打击但我就是故意选它。原因有三资源绰绰有余72MHz主频、12位ADC、3路USART、2个I2C、4个16位定时器环境控制这种任务只用掉不到一半资源。资料多到不用背手册不管是标准库还是HAL库网上随便搜都是现成工程。价格稳定蓝板核心板十几块钱单独买芯片散片也就几块钱坏了不心疼。有人会问为什么不用Arduino。Arduino做快速原型确实方便但ADC是10位而且串口、定时器资源少如果想扩展风机转速测量、多路传感器引脚就很紧张。STM32虽然上手门槛高一点但后面扩展空间大得多。开发环境我用的是Keil5 标准库。新项目可以选HAL库但环境控制逻辑不复杂标准库的例程和中文资料最齐全遇到问题好排查。要注意一点Keil5装好之后第一件事是把STM32F1系列的Device Pack装上否则新建工程找不到芯片型号。如果你之前装了C51的Keil再装STM32版时注意Pack要单独装两者可以共存但Target芯片列表必须选对。2.2 温湿度传感器DHT11、AHT20还是SHT30我在设计时对比过三款主流温湿度传感器也实际焊过测试板。直接看表格型号接口精度温度/湿度价格采样周期我的评价DHT11单总线±2℃/±5%RH3元左右≥1s够用但精度一般时序要求严格AHT20I2C±0.3℃/±2%RH6元左右≥80ms精度好、驱动简单性价比之王SHT30I2C±0.2℃/±1.5%RH12元左右可配置性能好但仓库场景没必要多花钱最终主方案选了AHT20。DHT11也不是不能用但它的单总线时序对中断处理特别敏感一被其他任务打断就容易读到错误值。AHT20走I2C只要初始化正确读取稳定性高一个档次。我会在固件部分保留DHT11的备用驱动代码方便预算极限压缩的读者参考。2.3 粉尘传感器GP2Y1010AU0还是PMS5003粉尘监测是这个系统里最容易踩坑的部分因为粉尘浓度这个词太宽泛了。我跑了两个方案做对比GP2Y1010AU0是夏普的模拟输出粉尘传感器价格二十块左右输出0.5V到0.9V的电压对应粉尘浓度变化。它需要PWM脉冲驱动内部LED且对采样时序有要求。优点是便宜、能反映相对浓度趋势缺点是精度不高只能做定性半定量监测。PMS5003是激光散射式传感器串口直接输出PM2.5和PM10数值精度高一个数量级但价格贵很多而且内部有个小风扇功耗更大风道一旦积灰读数会漂移。仓库粉尘监测的核心需求是浓度是否越限和变化趋势不是做空气质量科研所以GP2Y1010AU0完全够用。如果预算够把GP2Y换成PMS5003也只是把ADC采样换成串口读帧整体架构不用动。2.4 执行与联网模块执行机构用了两路继电器一路控制排风机一路控制除湿机。继电器模块我踩过坑后面详细说这里先记住两个原则一是尽量选带光耦隔离的模块二是触发方式选高电平触发不要选低电平触发。联网模块选了ESP8266-01S。这个模块虽然天线性能一般但串口AT指令模式非常成熟功耗也低。如果WiFi信号弱可以换成ESP-12F引脚多、天线好只是接线稍复杂。注意ESP8266是3.3V供电别直接接5V稳压模块要单独考虑。另外加了一个手动/自动切换按键还有两个状态LED。现场调试和检修时手动模式可以直接控制风机启停不用拔线。2.5 引脚分配表我的完整引脚规划如下仅供抄作业参考功能引脚说明AHT20 SDAPB7I2C1上拉4.7kAHT20 SCLPB6I2C1上拉4.7k粉尘LED驱动PA1TIM2_CH2输出PWM脉冲驱动GP2Y内部LED粉尘电压采样PA0ADC1_IN0采样GP2Y输出继电器1排风机PB12高电平触发光耦隔离继电器2除湿机PB13高电平触发光耦隔离本地按键PB14外部下拉长按3秒切换手动/自动状态LEDPB1自动模式常亮手动模式闪烁ESP8266 TXPA2USART2_TX接ESP8266 RXESP8266 RXPA3USART2_RX接ESP8266 TX调试串口PA9/PA10USART1调试日志输出备用DHT11PA4预留单总线引脚规划的一个原则把容易受干扰的模拟采样引脚放在电源引脚附近数字通信引脚分开走。PA0和PA1相邻正好GP2Y的采样和PWM驱动放在一起走线尽量短后面实测效果明显比之前乱飞的杜邦线稳定。3. 从原理图到现场电源分配、信号调理与接线防坑3.1 电源架构为什么不能一个降压芯片走到底仓库现场通常有220V市电我用一个24V开关电源给风机回路供电再把24V降成5V和3.3V给控制板。没有直接买220V转5V的模块原因是风机和除湿机的启动电流冲击很大控制电路必须和动力回路做好隔离。电源链路24V开关电源 → MP1584降压模块 → 5V5V → AMS1117-3.3 → 3.3V给STM325V直接给ESP8266、继电器模块、AHT20为什么ESP8266不共用3.3V因为WiFi发射瞬间电流能冲到300mA以上如果和MCU共用一颗AMS1117会导致3.3V电压跌落STM32复位。我一开始图省事共用结果ESP8266每次联网上报主控就重启查了半天才定位到是电源问题。功率估算STM32板载功耗约50mAESP8266峰值300mA继电器每个线圈约70mAGP2Y加上LED驱动约20mA5V总电流峰值不到600mA。MP1584可以轻松带但如果以后加PMS5003要把余量留足。3.2 传感器接口的细节GP2Y1010AU0的输出电压是模拟信号范围大约0.5V到0.9V直接进STM32的ADC没问题。但它的输出阻抗不低现场线一长就容易叠加噪声。我的做法是在ADC引脚前面加一个简单的RC低通滤波1k欧姆电阻串联加0.1uF电容到地截止频率约1.6kHz能滤掉大部分高频干扰又不影响正常的缓慢变化信号。AHT20是I2C接口两个引脚都需要上拉电阻。芯片数据手册建议4.7k但如果传感器到主控板的距离超过20厘米我会把上拉电阻改成2.2k否则上升沿太缓I2C容易读错。3.3 继电器开关的隔离问题继电器控制风机本质上是让弱电控制强电。这里我不建议直接拿STM32 GPIO去灌继电器模块不管你用低电平还是高电平触发都要选带光耦隔离的模块让主控电路和继电器触点电路在电气上完全分开。低电平触发的继电器模块有个隐患STM32上电瞬间GPIO处于高阻态如果模块内部上拉不够强三极管基极浮空可能导通导致继电器误动作。我第一版就用了低电平触发模块结果每次断电重启风机会莫名其妙启动一两秒。换高电平触发模块后GPIO浮空不会导通三极管问题消失。感性负载打火也不能忽视。风机电机是感性负载继电器触点断开瞬间会产生电弧除了触点寿命下降还会向外辐射电磁干扰。正规做法是触点两端并联RC吸收电路一般用100欧姆和0.1uF串联外加一个压敏电阻吸收浪涌。我第一批板子没加后来发现ESP8266偶尔离线用示波器看电源线上全是继电器断开时的毛刺加上RC后明显改善。3.4 芯片第一脚怎么确认调试过程中如果遇到程序烧不进去八成是芯片焊接方向错了或者焊盘连锡。STM32F103C8T6是LQFP48封装芯片一角有一个圆形凹点或者斜切角对应的就是第一脚。从第一脚开始逆时针数依次是1到24脚左半侧然后从另一边数25到48脚。用风枪拆装之后一定要先用放大镜检查有没有连锡再上电测3.3V对地阻抗确认无短路再烧程序。3.5 现场布线原则仓库现场不是实验室桌面布线比焊接更要用心传感器线和风机动力线分开走线槽不要并排。我实测过动力线电流超过2A时靠近它走的单总线温湿度数据会周期性出错。控制板装进金属盒但ESP8266的天线要伸出盒外。金属盒会屏蔽WiFi信号装在铁皮配电箱里信号能掉两三格。所有外部接线用带卡扣的端子排防止工人误拉碰掉。传感器接头用防呆插头按错方向插不进去。电源入口加一个2A保险丝这个钱不能省一次短路故障能烧掉一堆模块。4. 固件开发的三大核心时序读取、滑动滤波与回差控制4.1 工程建立与基础外设初始化固件用标准库写的工程结构是经典的启动文件加外设驱动。新建工程时记得在Pack Installer里装好STM32F1系列的Device Pack否则编译器会报找不到芯片。基础初始化包括SysTick延时这个后面单独讲因为踩了坑USART1调试串口波特率115200USART2接ESP8266波特率9600I2C1接AHT20ADC1_IN0接粉尘传感器TIM2_CH2输出PWM驱动GP2YGPIO控制继电器和按键4.2 读取AHT20温湿度I2C驱动要点AHT20上电后需要等40ms然后发0xBE命令初始化之后每读一次数据的流程是发0xAC命令进入测量等待至少80ms然后连续读6个字节。6个字节中前两个半字节是湿度数据接着两个半字节是温度数据最后1个字节是校验和。湿度和温度的计算公式湿度 原始湿度值 / 2^20 × 100%温度 原始温度值 / 2^20 × 200 - 50代码里需要注意一个细节读取6字节时I2C主机每接收一个字节都要回ACK只有最后一个字节回NACK。如果ACK处理错了数据会错位读出来的温湿度经常是离谱值。这个错误很难排查我当时在逻辑分析仪上看波形才发现。连续读取失败3次时我直接沿用上一次有效值同时在串口日志里打一个错误码。仓库环境变化很慢几十秒内用旧值完全不影响控制。给预算紧张的读者说一句如果改用DHT11驱动核心就是单总线时序。主机拉低总线18ms发出起始信号然后释放传感器回80us低电平响应再输出40位数据。每个数据位都以50us低电平开头之后的高电平持续26到28us表示0持续70us表示1。判断位0还是位1要靠延时读取时等待高电平结束的时间来区分。DHT11对中断延时很敏感所以读取前最好关中断或者用定时器精确捕获。4.3 粉尘浓度换算从ADC电压到mg/m³GP2Y1010AU0的驱动不是通电就行的。它的内部LED需要PWM脉冲驱动典型参数是周期320us高电平时间10us占空比约3.1%。我用TIM2_CH2输出PWMARR设为319CCR设为9频率约31.25kHz实测符合数据手册要求。采样时序有个讲究LED点亮之后传感器输出要等约0.28ms才稳定所以需要在PWM高电平开始后延时0.28ms再打开ADC采样窗口取电压。如果随时乱采读到的电压和粉尘浓度对不上。ADC读到的数字量要先换算成电压电压 ADC值 × 3.3V / 4096然后电压再换算成粉尘浓度。GP2Y1010的典型灵敏度是0.5V/0.1mg/m³无尘环境下输出电压约0.5V。简化公式浓度(mg/m³) (电压 - 0.5) / 0.5这个换算只是半定量精确标定需要拿标准粉尘源校准。仓库场景更多看相对变化趋势所以我在代码里把单位名称直接写成PM_INDEX而不是mg/m³避免误导。ADC抖动是必然的。我做了两层处理第一层是每次读取连续采10次去掉最大最小值后取平均第二层是保留一个长度为20的滑动窗口窗口内再做一次平均。两层下来数据平滑度肉眼可见地改善。这里有个现场经验GP2Y用久了内部风道积灰输出会整体偏高。我后来在日志里加了一个长期漂移提醒如果连续12小时粉尘基线比历史平均值高出0.15V以上就提示清理传感器。这个功能让我在系统跑了一个多月后及时清了一次灰。4.4 控制逻辑回差和最小动作间隔控制逻辑是整个系统的灵魂。直接说我的实现思路阈值判断加回差外加最小动作间隔保护。回差的必要性用一个例子解释如果设定湿度高于65%开排风机低于65%关排风机那么传感器读数在64.8%到65.2%之间波动时继电器会不停吸合释放一分钟能跳几十次。触点寿命很快耗尽。所以必须设置两个阈值开启阈值和关闭阈值。我的控制表如下控制对象开启条件关闭条件排风机高温温度≥35℃温度≤32℃排风机高湿湿度≥65%RH湿度≤60%RH除湿机湿度≥70%RH湿度≤62%RH过滤风机粉尘粉尘指数≥4.0粉尘指数≤2.0代码用一个简单的状态机构实现typedef struct { float on_th; // 开启阈值 float off_th; // 关闭阈值 uint8_t state; // 0关闭, 1开启 uint32_t last_toggle_time; // 上次切换时间 } CtrlChannel; void ctrl_update(CtrlChannel *ch, float val) { // 最小动作间隔保护5分钟内不允许频繁切换 if (HAL_GetTick() - ch-last_toggle_time 300000) { return; } if (ch-state 0 val ch-on_th) { ch-state 1; ch-last_toggle_time HAL_GetTick(); relay_on(ch); } else if (ch-state 1 val ch-off_th) { ch-state 0; ch-last_toggle_time HAL_GetTick(); relay_off(ch); } }注意最小动作间隔是下限保护只在正常控制路径里生效。如果温度超过45℃这种危险值我会无视间隔直接开启风机这是安全优先的逻辑。本地按键切换手动/自动长按3秒切换。自动模式下控制逻辑正常跑手动模式下继电器由两个按键或者一个按键循环切换控制。每次切换都用状态LED反馈自动模式常亮、手动模式500ms闪烁。我还额外用定时器输入捕获做了风机堵转监测。很多风机带FG脉冲输出转速越高脉冲频率越高。用PA8定时器输入捕获量一下脉冲频率如果风机在已开启状态下频率低于正常值的30%判定堵转或皮带脱落立即报警。这个功能在一次皮带断裂时真的派上了用场。4.5 串口数据帧设计STM32每隔5秒向ESP8266发一帧JSON数据格式固定为{d:dev01,t:25.6,h:58.2,pm:0.3,fan:1,dry:0}字段含义d是设备编号t是温度h是湿度pm是粉尘指数fan是排风机状态dry是除湿机状态。把执行器状态也一起上报云端就能知道系统有没有在干活。拼帧时统一用snprintf缓冲区开128字节杜绝用手动拼接导致的内存越界。5. ESP8266上云的两种路径AT指令透传与MQTT对接5.1 先想清楚上云要解决什么问题有人把ESP8266上云想得很玄其实就两件事把数据送达服务器再把服务器的指令传回来。路径不同代价不同只需要把数据送到自己的服务器存库用AT指令加TCP透传最直接想用云平台现成的仪表盘、报警和App刷MQTT固件更省事。我两条路都跑过下面把各自的关键步骤和坑都写出来。5.2 路径AAT指令加TCP透传ESP8266-01S出厂自带AT固件串口发指令即可控制。初始化序列如下ATE0 ATCWMODE1 ATCWJAP你的WiFi名,你的WiFi密码 ATCIPSTARTTCP,你的服务器IP,8080 ATCIPMODE1 ATCIPSENDCIPMODE1进入透传模式之后所有串口数据自动转发到TCP服务器服务端下发的数据也能通过串口收到。自己的服务器可以先用Python写一个极简TCP接收脚本测试import socket srv socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind((0.0.0.0, 8080)) srv.listen(1) while True: conn, addr srv.accept() while True: data conn.recv(1024) if not data: break print(data.decode(utf-8, errorsignore))AT指令透传的缺点很明显不知道ESP8266什么时间掉线透传模式下串口又被占用重新初始化需要退出透传模式。我用这套方案做过临时数据验证稳定跑了三天但没敢作为正式方案。5.3 路径B刷MQTT固件对接云平台正式方案我采用了刷MQTT固件的方式对接的是国内常见的物联网平台OneNET、巴法云这类。ESP8266刷入MQTT固件后STM32侧发的AT指令变成ATMQTTCONN平台服务器地址,端口,设备ID,Token ATMQTTSUB主题A ATMQTTPUB主题A, {t:25.6,h:58.2,pm:0.3} 具体地址和Token格式以平台文档为准每家略有差异但流程是一致的。平台控制台新建一个产品、一个设备拿到连接参数填进代码就行。MQTT的价值在于消息主题和QoS机制。环境数据用QoS0上报丢了就丢了下一帧5秒后还会来但报警消息我用QoS1确保平台能收到。设备上下线状态用遗嘱消息设备异常掉线时平台能第一时间知道。云平台侧配置也不难创建几个数据流比如temp、humi、pm然后添加仪表盘组件绑定数据流曲线和阈值报警就出来了。手机端用平台配套的App或者小程序随时随地看仓库数据。5.4 断线重连的完整策略上云之后最怕的不是数据不准而是设备悄悄掉线你却不知道。我的重连策略分两级一级重连WiFi断开。STM32定时发送ATPING检查链路连续失败两次说明WiFi可能断了。这时先发ATCWJAP重新连WiFi再发ATMQTTCONN重新连MQTT。二级重连MQTT连接超时。连续3次ATMQTTCONN失败用GPIO拉低ESP8266的RST引脚强制重启或者发ATRESTORE恢复出厂后重新初始化。所有AT指令的等待都必须带超时。这是无数血泪教训换来的下一章专门说。5.5 数据兜底方案如果云平台临时挂了数据也不能丢。我在STM32的Flash里保存最近200条数据等MQTT重连成功后按时间戳补发。补发时降低频率每秒最多补发5条避免拥塞服务器。后来我还在SD卡上存过一份但Flash的方案对这套系统足够了因为仓库环境数据5秒一条200条能覆盖约17分钟断线基本够用。6. 现场调试踩过的五个坑从delay卡死到ATRestore死循环6.1 STM32延时函数delay卡死原来卡在SysTick系统跑到第二天出现一个诡异现象主循环偶尔卡死看门狗也喂不上整机灯全灭。仿真器连上后发现程序停在delay_us函数里出不来。排查链路是这样的先怀疑晶振频率配置错对照启动文件检查没问题再怀疑优化等级导致延时函数被内联优化把优化等级从-O2改成-O0没改善最后用示波器看SysTick引脚发现SysTick中断确实在触发但中断里调用的回调函数又等了一个更长的延时——实际上是我的中断处理函数里不小心调用了延时函数造成SysTick中断被低优先级事件阻塞主循环的delay永远等不到挂起的SysTick中断响应。解决方法是三管齐下SysTick中断优先级设为最低数值15中断处理函数里绝不调用任何阻塞延时主循环的延时改用查询SysTick计数寄存器的方式而不是依赖中断。改完之后稳如老狗。6.2 粉尘ADC抖动为什么消不掉GP2Y读数一开始抖动特别离谱换算成浓度后从0.2跳到4.5。排查过程按顺序走先测ADC参考电压3.29V稳定再查PWM驱动脉冲波形占空比正常然后怀疑RC滤波参数加大电容到0.47uF效果有限最后拆下传感器发现内部风道积了一层灰探头表面还有疑似水汽痕迹。清理后看波形纹波立刻小了一半。这个坑说明传感器本身的污染是任何软件滤波都救不回来的现场运维必须包含定期清洁传感器。6.3 ESP8266恢复出厂设置时循环体中检测不到OK进入死循环这个问题我觉得很多新手都会遇到必须单独写。最初我的代码是esp8266_send(ATRESTORE\r\n); while (1) { if (strstr(recv_buf, OK)) { break; } }看似正常对吧但ATRESTORE这个指令执行时ESP8266会先断开当前连接、恢复出厂设置、然后重启。回复OK的时机和模块重启输出混在一起可能先输出乱码再输出OK甚至因为重启过程没完成这句OK根本来不及发到串口。我的循环没有超时一旦收不到OK就死等整个控制器直接瘫痪。正确做法是所有AT指令的等待都改成带超时的轮询#define AT_TIMEOUT 3000 uint8_t esp8266_wait_response(char *expected, uint32_t timeout_ms) { uint32_t start HAL_GetTick(); while (HAL_GetTick() - start timeout_ms) { if (strstr(recv_buf, expected)) { return 1; } // 继续收串口数据到缓冲区 } return 0; // 超时 }对ATRESTORE这种特殊指令干脆不等待回复发完之后固定延时5秒然后重新发ATE0、ATCWMODE、ATCWJAP做初始化。重启会比等待回复更可靠。6.4 继电器打火和上电误动作这个在前面电路部分说过了这里补充一个现场案例。有一次凌晨仓库系统自动重启风机会立刻转几秒声音很大工人以为是闹鬼。查下来就是低电平触发继承模块加上GPIO浮空导致的误触发。解决的完整措施换成高电平触发的继电器模块GPIO外部加10k下拉电阻到地主程序上电第一步先把所有继电器控制引脚配置为推挽输出并输出低电平然后再初始化其他外设感性负载触点两端加RC吸收。处理后上电测试十余次没有再出现任何误动作。6.5 长线干扰温湿度偶尔跳到98%I2C线布了2米长偶尔读到湿度98%、温度-18℃一看就是干扰。用示波器抓I2C时钟线发现上升沿非常缓杂波叠加严重。解决组合拳线缆换成屏蔽双绞线屏蔽层单端接地I2C上拉电阻从4.7k改成2.2k软件加连续三次一致性校验三次读数差异超过阈值就丢弃本次测量。改完之后用万用表实测I2C波形干净很多再没出现过离谱跳变。6.6 顺带说两句Keil下载失败的问题调试过程中遇到过连接不上仿真器的情况。最常见原因有两个一是Keil的Pack没装对STM32F103C8T6在Keil里选的Target不对二是代码里禁用了JTAG后标准JTAG接口不能下载但SWD接口仍然可用。如果之前烧过GPIO重映射和JTAG禁用代码用SWD模式下载就能恢复。用VSCode加PlatformIO开发STM32也是一种选择调试配置需要手动改launch.json对新手来说门槛比Keil高但代码编辑体验确实好。7. 跑了一个月后的实际效果与后续扩展这套系统在朋友的食品仓库里跑了一个月效果可以量化湿度从晚上关窗后的76%-82%降到常年稳定在55%-62%温度控制在26℃到33℃之间排风机每天动作约20次继电器触点没有明显拉弧痕迹ESP8266掉线自动重连了三次最长一次断线约40分钟Flash缓存的数据在重连后完整补传没有丢帧。最值钱的体会是传感器数据要敢信但也要敢怀疑。敢信才能放心地把控制逻辑交给自动程序敢怀疑才能在读数异常时想到是传感器脏了、线松了、还是电源纹波大了。这套系统继续扩展的方向我也列一下给后来者参考加一个臭氧发生器或者紫外灯开关逻辑和高湿场景联动能进一步抑霉再加一路烟雾传感器和火焰传感器环境控制和消防预警合到一块如果仓库面积大、点位多可以改成LoRa节点加网关的模式每个仓库一个STM32节点网关统一上云硬件端把GP2Y换成PMS5003粉尘数据会更精确能测量PM2.5和PM10两个指标Flash缓存加一个时间戳队列断线时长做到3小时以上不丢数据。最后分享一个调试期的小技巧我在串口命令里加了一条本地指令通过串口助手下发类似set_humi_on 63.5的文本就能在运行状态下修改阈值不用每次改完重新烧固件。仓库环境要求变了、季节变了阈值跟着调这个功能让我少烧了至少二十次程序。