尧图精选

STM32与ESP8266仓库环境监控系统:从传感器选型到OneNET上云实战

🕒 发布时间:2026/10/1 7:18:59 📁 来源:尧图网络
仓库环境控制系统听起来不是什么高精尖的项目但真正把它从方案落到实物、从实物调到稳定运行你会发现里面牵扯的东西远比想象中多传感器选型、采样时序、控制策略、串口通信、网络协议、电源抗干扰哪一个环节没处理好系统都会在某个半夜给你“掉链子”。我这次做的是一套以STM32F103C8T6为主控搭配DHT22温湿度传感器和GP2Y1010粉尘传感器通过继电器控制风机和除湿机再由ESP8266模块把传感器数据和设备状态上报到OneNET云平台手机端实时查看曲线和告警的完整方案。整个项目从画原理图、焊接、写驱动、调控制逻辑到上云联调走完一遍之后我对“感知-决策-执行-上云”这条物联网闭环有了非常具体的理解。这篇文章就把这套系统的整体设计思路、硬件选型、控制策略、ESP8266上云的具体玩法以及调试中踩过的坑全部摊开来讲给正在做嵌入式课设、毕业设计或者想在仓库、机房、车间这类场景搭一套环境监控系统的朋友一个可以直接参考的完整版本。1. 项目概述与整体方案设计1.1 仓库环境问题的真实痛点先说需求。做仓库环境控制第一件事不是选芯片而是搞清楚你到底要解决什么问题。仓库里的温湿度和粉尘问题和家里卧室完全不是一个量级。电子元件仓库湿度一高引脚氧化速度明显加快焊接良率会断崖式下跌纸品、木制品、布料仓库相对湿度长期超过70%就开始发霉变形粉尘浓度高的场景比如建材仓、饲料原料库粉尘超标不仅影响设备寿命在极端情况下还存在安全隐患。这些场景对系统的要求不是“能用就行”而是稳定、可靠、可追溯。还有一个容易被忽视的点仓库大多是无人值守的或者只有白天有人。晚上、节假日出了异常如果没有人知道损失往往要等到第二天才被发现。所以在这个项目里远程监控和自动控制的价值是同等重要的甚至自动控制更重要。如果只是做个采集器把温湿度显示在本地屏幕上值班人员一旦疏忽系统形同虚设。设计目标从一开始就定下来本地自动决策优先云端远程监控辅助。1.2 方案选型为什么是STM32加ESP8266市面上做环境监控的方案很多Arduino、NodeMCU、树莓派都有人用。我实际对比过最后选了STM32F103C8T6配ESP8266原因是这套组合最适合“可靠性优先”的仓库场景。Arduino做原型验证确实快但它的生态决定它更像实验性质的东西长时间挂在220V继电器、风机这种负载旁边稳定性和可裁剪性都差一些。树莓派性能强能跑数据库和复杂算法但在工业环境里发热大、启动慢、意外断电还容易伤存储卡成本也高。STM32F103C8T6的资源对这类项目来说恰到好处72MHz主频、64KB Flash、20KB RAM跑传感器采集和控制状态机绰绰有余工作温度范围宽可靠性有保障配合STM32CubeMX生成初始化代码Keil里写业务逻辑整个开发链路非常成熟。ESP8266在这里只负责一件事联网上云。它通过串口和STM32通信不参与任何传感器采集和控制决策职责单一出问题的概率就低。这套双芯片方案的好处在于软硬件解耦。如果让ESP8266单独做整个系统也不是不行但它在Wi-Fi发射时对模拟信号采样干扰明显而且引脚资源和ADC通道都有限。STM32管底层实时控制和采集ESP8266只管数据转发后面想换云平台、换Wi-Fi模块都很灵活。1.3 系统总体架构整个系统的数据流向是这样的传感器层DHT22采集温度和相对湿度走单总线协议读取数字量GP2Y1010采集粉尘浓度输出模拟电压由STM32的ADC采样。控制层STM32读取传感器数据执行滞回比较控制逻辑通过GPIO控制继电器模块进而通断轴流风机、除湿机、加热器。通信层STM32通过UART2向ESP8266发送AT指令完成Wi-Fi连接和数据透传。云平台层OneNET接收HTTP数据点保存历史数据并生成实时曲线手机端通过App或网页查看。这里有一个必须坚持的设计原则控制逻辑必须在本地完成不能依赖云端。万一断网仓库仍然能靠本地传感器数据自动通风除湿。很多刚开始做上云项目的人容易把判断逻辑放到云平台的规则引擎里一断网整个系统就变成“瞎子”。本地决策、云端监控这才是仓库控制系统该有的姿态。后面所有的代码和硬件设计都是围绕这个原则展开的。2. 核心硬件选型与传感器实测2.1 温湿度传感器DHT22还是SHT30温湿度传感器市面上最常用的是DHT11、DHT22AM2302、SHT30三款。DHT11便宜到几块钱但精度实在不够看湿度误差±5%RH温度误差±2℃做桌面小摆件可以放在仓库里作为控制依据说实话有点赌运气。DHT22的湿度精度能做到±2%RH温度±0.5℃单总线数字接口接线简单稳定性和性价比平衡得比较好。SHT30精度更高走I2C接口但价格更高对新手来说还要处理上拉电阻和地址配置。我最终选了DHT22理由很实际接口简单一根数据线就能通读驱动代码成熟网上参考很多改一改就能跑测量范围覆盖仓库场景绰绰有余-40到80摄氏度、0到100%RH。SHT30的精度确实更好但在这个应用场景里DHT22的误差完全可以接受控制逻辑本来就不需要小数点后两位的精度。必须说一个DHT22的经典坑读取时序。DHT22的通信是主机主动拉低总线启动传感器应答后连续输出40位数据每一位的高低电平宽度决定数据是0还是1。这个时序非常依赖微秒级的精确定时如果用延时函数模拟正巧被中断抢占或者编译器优化级别一改就很容易出现读取超时或者校验失败。我的做法是采样周期固定间隔2秒以上微秒延时用空指令循环实现不嵌套调用系统滴答定时器。实测下来只要时序稳定DHT22的数据相当靠谱。如果数据线太长还要在数据线上加一个4.7kΩ上拉电阻到3.3V不然长线状态下信号边缘变形读取照样会出问题。2.2 粉尘传感器GP2Y1010和PMS5003的取舍粉尘检测我试了两款方案Sharp的GP2Y1010AU和攀藤PMS5003。GP2Y1010是模拟量输出检测原理是红外LED照射空气中的尘埃光电二极管接收散射光输出一个和粉尘浓度正相关的电压。它便宜电路简单一个分压电阻加一个电容就能接到STM32的ADC上。缺点也有一致性一般个体之间的输出电压差异明显需要标定对PM2.5和PM10的区分能力弱只能当作一个综合“粉尘浓度”指标。PMS5003是激光散射原理串口直接输出数字浓度值PM1.0、PM2.5、PM10三个数值都有精度高出很多但价格贵了不少内部风扇几年内要考虑磨损和维护成本。如果只是监控“灰大不大”GP2Y1010够用如果想沉淀数据做精细化分析PMS5003值得加预算。我这次用的是GP2Y1010预算有限是主要原因。它的数据手册给出一个典型电压-浓度转换曲线但个体差异实在大千万别直接套用网上例程里的固定系数就宣称精度达标。最靠谱的做法是做一个简单标定把传感器放在干净环境中记录零漂电压再放到已知粉尘浓度的环境中记录对应电压求出实际系数后写进程序。如果条件不允许那就把它当“趋势传感器”用看相对变化而不是绝对数值。我这个项目里主要用粉尘数据做阈值触发和趋势判断精度损失完全可以接受。2.3 执行机构驱动与电源设计要点执行机构方面我用了带光耦隔离的5V继电器模块一个控制轴流风机一个控制除湿机还预留了一个加热通道。核心经验是继电器不能直接拿STM32引脚去推。很多新手直接把GPIO接在继电器模块的IN引脚上运气好能工作但继电器吸合瞬间电流抖动、感性负载断电时的反电动势轻则让MCU复位重则烧坏引脚。我的做法是GPIO先经过限流电阻驱动光耦再由光耦推动继电器线圈。如果不用成品模块用三极管S8050或ULN2003驱动线圈也行关键是线圈两端要并联续流二极管1N4007极性不要接反。交流负载接线时继电器输出触点只串接在火线上零线直接进负载这样断开的是火线更安全。我一开始图省事直接驱动继电器几天后就开始出现随机复位加了续流和保护之后才算稳定。电源部分是整个硬件设计里我最想强调的。系统统一用12V供电经过DC-DC降到5V再分成两路一路给GP2Y1010和继电器模块另一路经3.3V LDO给STM32、DHT22和ESP8266供电。这里有个教训ESP8266发射瞬间电流能到300mA甚至更高AMS1117-3.3这种压差大、热耗大的LDO会被瞬间拉低电压Wi-Fi发包时3.3V剧烈波动经常触发STM32的欠压复位。后来我把ESP8266的供电换成了独立的ME6211低压差LDO峰值输出500mA输出端并了10uF和100nF组合电容并且让ESP8266的电源走线和STM32、ADC采样电路完全分开。这一点改完系统的随机重启问题基本绝迹。布局上我也让ESP8266尽量远离GP2Y1010的模拟采样线Wi-Fi发射对ADC的干扰明显减小。3. 控制逻辑与关键代码实现3.1 传感器数据采集与滤波处理传感器数据采回来不能直接用。DHT22读数有瞬时抖动GP2Y1010电压值受气流、灰尘沉降、传感器发热各种因素干扰直接拿原始值去判断阈值系统会频繁误动作。我做了两层处理。第一层是剔除异常值DHT22校验失败直接丢弃本次数据连续5次失败才触发传感器故障标志GP2Y1010采样值如果超出量程上限或者低于零漂阈值也直接丢弃。第二层是一阶低通滤波公式是y[n] α * x[n] (1-α) * y[n-1]α取0.3左右。这个滤波对缓慢变化的环境量特别合适既平滑了毛刺又不会把真实变化削太多。如果用滑动平均数组占用RAM多响应还慢。采样周期定在2秒α0.3实测下来波形很舒服。GP2Y1010的ADC采样不是随便采的它有一个固定的采样脉冲时序先拉低LED控制引脚等待0.32ms让光电信号稳定然后执行ADC转换转换结束后拉高LED引脚再等待0.28ms进入下一次循环。这个时序不能错否则采到的电压和粉尘浓度的对应关系就对不上。我最初直接用软件延时去卡这个时序后来改成用定时器触发采样把脉冲时序交给硬件PWM管理软件只负责在固定时间点读ADC值既稳定又省CPU。核心采样代码大概是这样的// 粉尘传感器GP2Y1010采样LED_Pin为控制脚ADC值经滤波后转电压 void dust_sensor_sample(void) { HAL_GPIO_WritePin(LED_Pin, GPIO_PIN_RESET); // LED打开 delay_us(320); // 等待光电信号稳定 uint16_t adc 0; for (uint8_t i 0; i 8; i) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); adc HAL_ADC_GetValue(hadc1); } adc / 8; // 8次采样取平均去噪声 HAL_GPIO_WritePin(LED_Pin, GPIO_PIN_SET); // LED关闭 dust_voltage adc * 3.3f / 4096.0f; // 实际电压值 dust_filtered 0.3f * dust_voltage 0.7f * dust_filtered; }这是简化版本。实际工程里我加了DMA和环形缓冲区避免ADC转换阻塞主循环。新手可以先把这个逻辑跑通熟悉之后再去做DMA优化完全来得及。3.2 自动通风除湿的滞回控制策略仓库环境控制的难点不是采集而是怎么判断“该动了”。如果只用单一阈值比如湿度超过70%开风机低于70%关风机会出现一个非常讨厌的现象继电器在阈值附近反复吸合释放风机频繁启停继电器触点寿命几个月就被耗光。这个问题在控制领域叫“临界点抖动”。解决方式是用滞回控制也叫迟滞比较。给上限阈值和下限阈值之间划一个缓冲区环境量落在缓冲区内时维持上一状态不变。以除湿为例湿度高于75%启动除湿机同时打开风机辅助循环。湿度降到60%以下之前维持运行状态不变。湿度降到60%以下关闭设备系统回到待机。这样把临界点附近的来回抖动变成了两个明确的稳定区间回差设定15%既保护了继电器也符合仓库实际需求。控制代码用状态机写比一堆if嵌套好维护得多。我的状态机大概长这样typedef enum {STATE_IDLE, STATE_VENT, STATE_DEHUMIDIFY, STATE_FAULT} sys_state_t; sys_state_t auto_control(float temp, float hum, float dust) { static sys_state_t state STATE_IDLE; switch (state) { case STATE_IDLE: if (hum 75.0f) state STATE_DEHUMIDIFY; else if (dust 200.0f) state STATE_VENT; else if (temp 35.0f) state STATE_VENT; break; case STATE_VENT: if (hum 75.0f) state STATE_DEHUMIDIFY; else if (dust 120.0f temp 30.0f) state STATE_IDLE; break; case STATE_DEHUMIDIFY: if (hum 60.0f) state STATE_IDLE; break; default: state STATE_IDLE; break; } relay_ctrl(state); return state; }这段代码里体现了一个优先级湿度超限时除湿优先于通风。因为粉尘超标开风机可能会把外面潮湿的空气带进来加剧湿度问题。这个优先级是实际调试中总结出来的。最开始我先做通风后做除湿结果梅雨季越通风湿度越高后来把除湿提到最高优先级问题才解决。温度控制单独说一下仓库温度过高开轴流风机强制换气通常能降下来。如果湿度和温度同时高先除湿再通风或者两者一起开取决于执行机构容量。如果装了加热器用于冬季防冻场景加热和除湿不能同时开这是控制逻辑里必须加的互斥保护否则一边加热一边除湿能耗翻倍还可能出现局部过热。工业现场的安全边界都是靠这些状态机里的互斥条件保证的。3.3 STM32与ESP8266的串口通信协议STM32和ESP8266之间的通信我用了UART2波特率1152008N1。通信协议没有做得太复杂全部是明文字符串方便调试。上报数据帧格式#REPORT,T25.6,H63.4,D88.5,ST2;T是温度H是湿度D是粉尘浓度微克每立方米ST是当前控制状态机编号。STM32每10秒通过串口发送一次ESP8266收到后解析字段打包成HTTP请求体上送云平台。为什么让STM32自己拼好字段而不是直接传JSON因为STM32解析和拼接简单字符串最轻量ESP8266只做透传这样就避免在单片机里引入JSON库。虽然系统RAM够用但能把复杂度往后端挪就往后端挪这是我做嵌入式的一个习惯。接收方向云平台的远程手动控制指令也走ESP8266转发。ESP8266收到云端下发指令后通过同一根UART发送给STM32。指令格式定义成#CTRL,1,0;第一位控制风机第二位控制除湿机1开0关。STM32在主循环里每50ms检查一次串口接收缓冲区有完整帧就解析执行。这里有个常见误区串口接收如果不做超时帧判断很容易把两条数据帧读碎。我的方案是用DMA接收不定长数据配合空闲中断判断一帧结束。总而言之不能只依赖固定长度的接收缓存去猜数据边界数据量大了之后一定会出错。远程手动控制和本地自动控制怎么兼容我的约定是收到手动控制指令后本地自动控制暂停1小时1小时之后重新回到自动模式。这样既照顾了现场人工干预的需求又不会因为长时间没人操作系统就一直靠手动状态“裸奔”。这个细节在真实仓库场景非常实用比如有工人临时进库搬运货物时想加大通风量手动开一下之后系统自动恢复。4. 上云实现与远程监控4.1 上云方案AT指令透传还是SDKESP8266上云本质上两条路一条是烧写AT固件STM32通过AT指令控制它连接Wi-Fi和服务器数据由STM32递过去另一条是给ESP8266刷NodeMCU固件或者自定义SDK程序让ESP8266自己跑协议栈直接连接云平台MCU只负责把数据交给它。两条路我都试过说下结论。如果是快速原型验证AT指令方式最省事不涉及ESP8266二次开发只要会串口就能把它当做一个“Wi-Fi猫”来用。项目里我的ESP8266刷的是官方AT固件烧录工具用ESP Flash Download Tool固件版本选1.7.x或2.2.x都比较稳。如果要在量产级项目里追求低延迟、高吞吐建议把ESP8266刷成独立固件内部直接跑MQTT库连接云平台这样能减轻单片机侧的压力但调试成本也相应增加。我最终选了AT指令方式。原因很实在整个系统的决策核心在STM32ESP8266就是一个纯链路层设备AT指令完全够用而且出问题时能通过串口直接看到模块返回的报错信息排查速度快。在做“ESP8266接OneNET”这类云端接入时AT方式的路由非常清晰模块负责TCP连接应用层数据由STM32组装。4.2 AT指令集联调与数据上报实战AT指令联调第一步先用USB-TTL单独把ESP8266接到电脑上在串口助手里把指令一条条测通不要直接焊在STM32板子上就开始调试否则出了问题分不清是模块问题还是单片机程序问题。推荐顺序发送AT确认模块返回OK波特率匹配。发送ATCWMODE1设置成Station模式。仓库场景用不到AP模式选1就好。发送ATCWJAPWiFi名称,WiFi密码确认返回WIFI CONNECTED再返回OK。密码错误或信号太弱这里就会卡住。发送ATCIFSR查看模块获取到的IP地址确认已经连上局域网。发送ATCIPSTARTTCP,183.230.40.40,80建立TCP长连接。这里是OneNET平台的接入地址端口80。实际项目建议用域名接入通过ATCIDDNS解析避免平台IP维护变更导致连接失效。发送ATCIPSEND数据长度随后发送数据模块返回SEND OK。在STM32程序里执行AT指令不是一次性写完就完事关键在于每一步都要等待模块返回对应的关键字比如“OK”、“WIFI CONNECTED”、“CONNECT”。我在程序里写了一个esp_onenet_task状态机把上电、配网、连接、上报、重连拆成多个状态出错只复位当前一步不把整个流程重启。这个设计让系统在Wi-Fi闪断后可以自行恢复实测连续运行一周都没掉线。有一个细节非常影响联调效率AT指令的每条响应都可能带有多余字符比如模块上电时会打印一长串乱码般的日志信息。程序里搜索关键字时要用“包含匹配”而不是“完全匹配”并且每次发送新指令前先清空串口接收缓冲区避免把上一轮残留的响应当成当前指令的结果。4.3 OneNET数据上报与手机端展示OneNET的数据上报走HTTP协议请求体是一个JSON数组格式如下{datastreams:[{id:temp,datapoints:[{value:25.6}]}, {id:humi,datapoints:[{value:63.4}]}, {id:dust,datapoints:[{value:88.5}]}]}HTTP头要带上api-key字段这是OneNET识别设备的鉴权信息。每一个数据流需要在平台上提前创建否则上报会报错。上报周期我控制在10秒一次OneNET免费版对这个频率没有压力。在平台上创建了温度、湿度、粉尘浓度和历史控制状态四个数据流之后直接就能看到实时折线图还能配置阈值告警规则触发后通过App推送消息到手机上。手机端展示我用的OneNET官方App登录后绑定设备仓库的温湿度、粉尘曲线和当前控制状态就都在手机上了。界面虽然不算漂亮但胜在不用自己写前端。如果你想要更灵活的看板也可以把数据通过Webhook转发到自己的服务器画图表那工程量大很多不建议在项目初期就做。有一点必须反复提醒api-key是设备的访问凭证千万不要在代码里写死之后上传到公开代码仓库。我见过太多人把api-key公开之后设备数据完全暴露。至少要用宏开关区分调试配置和出厂配置出厂固件里不要带真实密钥。5. 调试过程与常见问题实录5.1 高频故障排查速查表整个项目调试过程中遇到的问题我列了一张速查表基本按出现频率排序每一行都是实战换来的经验现象可能的根本原因解决办法ESP8266发AT无任何返回波特率不匹配、模块没上电、TX/RX接反先用USB-TTL串口助手确认模块能回OK确认模块与STM32共地执行ATRESTORE后死循环循环体等不到“OK”模块重启期间没有响应程序死等关键字发送复位命令后延时2-3秒再发AT探测所有等待都加超时重试密码正确但Wi-Fi连不上模块只支持2.4GHz路由器开了5GHz或WPA3切换到2.4G频段关闭WPA3混合模式或更换SSID继电器频繁吸合抖动控制逻辑没有滞回区间用滞回控制替换单阈值判断风机断电瞬间STM32复位感性负载反电动势串扰继电器线圈并续流二极管交流感性负载加RC吸收电路上云数据时断时续ESP8266供电不足或电源纹波大模块独立LDO供电输出端加大电容走线缩短DHT22偶尔读全0或卡死数据线上拉电阻缺失或采样时序被打断数据线接4.7kΩ上拉到3.3V采样间隔大于2秒粉尘ADC值跳动剧烈采样时序不对或者传感器地与MCU不共地严格按LED脉冲时序采样确保传感器地和MCU地良好连接这张表里最让我印象深刻的就是ATRESTORE那个坑。发完命令后模块会恢复出厂设置并自动重启重启后第一条响应不是立即出现的有些固件还会把波特率恢复默认。如果程序发完命令立刻死等“OK”模块重启慢一点就卡进死循环。我刚联调的时候被这个卡了半天代码里喂了看门狗都救不回来因为死等本身就不喂狗。后来改成发送命令后先延时2到3秒然后清空串口接收缓冲区再重新发AT探测用重试机制代替死等问题才彻底解决。5.2 几个容易翻车的工程细节第一ESP8266进入下载模式的方式。直接用USB-TTL刷AT固件时GPIO0必须拉低才能进入下载模式EN脚要接上拉电阻并保证复位时序正常。很多人第一次刷固件失败一查全是GPIO0悬空。如果是自己画板建议加自动下载电路或者先用带自动下载电路的NodeMCU开发板刷好固件再把模块拆下来焊到自己的电路上。我两种方式都试过后者最省心。第二ESP8266和STM32的串口电平匹配问题。ESP8266的UART引脚电平是3.3V不能用5V的USB-TTL去直接连会存在引脚损伤风险。用STM32的3.3V等级UART去接没问题但用电脑上的USB-TTL调试时一定要确认模块是3.3V供电和3.3V电平否则模块要么不工作要么用一段时间就坏了。第三时间基准问题。很多项目忽视网络时间同步到了云端看历史数据发现时间戳和本地对不上。OneNET可以使用服务器接收时间作为时间基准但如果要在本地生成时间戳可以让ESP8266通过ATCIPSNTPCFG1,8,ntp.aliyun.com同步网络时间。时间基准不统一后面做数据分析会非常痛苦。第四日志接口和业务接口分离。STM32的调试打印口如果和ESP8266共用UARTAT指令的调试信息和业务数据会混在一起。我在项目里把UART1专门留作调试打印UART2接ESP8266两个互不干涉。打日志只管发UART1完全不走业务通道。排查问题的时候能看到干净的AT指令交互记录效率高很多。第五看门狗必须加。用STM32的IWDG主循环里喂狗周期控制在1秒内。这样即使某个传感器挂住导致主循环卡死系统也会自动复位恢复。有人担心复位会打断云端的连接状态不用怕ESP8266上电后重新执行连接流程就行状态机是自愈的。这个理念要从设计之初就纳入代码结构而不是等出了问题再补。第六关于供电和地线。所有模块的GND必须和STM32的GND严格共地否则串口信号、ADC参考都会乱套。很多“数据漂移”和“通信间歇失败”最后都查出来是地线没接好。模块供电线尽量短而粗尤其ESP8266的峰值电流大线长压降明显建议用较粗的导线或者铺铜连接。最后分享一点个人体会。做完这套系统以后我给家里的小储藏室也装了一套简化版。回看整个过程最划算的投入不是买更贵的传感器而是先把串口通信链路调通再去细化控制逻辑。很多人做完硬件就把精力全放在传感器精度上联网上云迟迟搞不定结果整个项目卡在“数据到不了手机”这一步。先把链路跑通让数据能实时看到再回头看控制策略是否合理整个项目的推进节奏会顺畅很多。控制策略永远可以后续优化但通信链路不通一切都白搭。如果以后想升级还可以给系统加一块OLED本地显示模块把粉尘传感器换成PMS5003多读一组PM2.5数据或者把继电器改成可控硅实现风机无级调速。这些都是现成的扩展方向只要保持当前这套“本地决策、云端监控”的架构不变加功能只是时间问题而不是推倒重来的问题。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →