STM32智能仓库监测系统设计:传感器、PCB与MQTT实战
简介:本资源是一套面向本科毕业设计的完整嵌入式安防系统实战方案,适用于STM32初学者及电子类专业毕设学生,解决智能仓库环境监测、多源入侵报警与远程协同管控等典型工程问题。压缩包共524个文件,涵盖86个.h头文件与74个.c源码(含STM32F103底层驱动与应用逻辑)、44份PDF文档(含完整论文参考、原理图说明、元件清单)、2个PCB工程文件、2个原理图文件、1个可直接安装的Android APK应用及配套MP4演示视频,整体达684.32MB,结构清晰、模块解耦明确,便于分阶段学习与调试。已有835人下载学习,资源提供从硬件设计(含可编辑PCB)、固件开发、APP通信到论文撰写的全链路支撑,特别包含GSM短信报警触发逻辑、WIFI透传协议适配代码、多传感器数据融合显示等关键实现细节,是少有的兼具工程规范性与教学完整性的毕设级项目范例。
1. 先把“智能仓库”拆成你能交付的东西
做毕设第一个坑就是一上来就想“我要做一个智能仓库”,然后打开STM32CubeMX发呆。仓库监测和安防拆开来看,其实是三块互相独立、又能拼在一起的功能:
- 环境感知:温湿度、烟雾/可燃气体,这些数据要实时采集,还要能看历史趋势,否则“远程监测”没有落地。
- 安防报警:人体红外、门窗磁、火焰检测,触发之后要声光报警,同时把告警事件推到远程端。
- 远程通道:仓库里没有人在,但数据要能传到手机或电脑网页上,这套系统才叫“远程”。
把这三个功能列出来,选题的框架就清楚了:传感器采集端用STM32F103C8T6做主控,外挂DHT22(温湿度)、MQ-2或MQ-135(烟雾/可燃气体)、HC-SR501(人体红外)、火焰传感器模块,加上OLED显示屏做本地看板,远程通信用ESP8266走MQTT协议上云(或者走局域网TCP也行),报警执行端用有源蜂鸣器和继电器模块。整套系统供电用12V适配器,板载AMS1117-3.3转换成3.3V给MCU和传感器用。
选择STM32F103C8T6而不是F407或者GD32,原因很实在:例程多、资料全、CubeMX一键生成工程,芯片价格也稳定。本科毕设最怕的不是技术难,是卡在一个问题上三天没人问,而F103系列的踩坑记录几乎全网都是,这对毕设进度的保障比性能参数重要得多。这块板子本身资源也够用:64KB Flash跑得下全部固件,20KB RAM足够缓冲多路ADC采集数据和MQTT报文,USART、I2C、SPI、ADC外设应有尽有,控制这类传感器绰绰有余。
PCB部分这一篇我会详细讲。因为很多人以为画完原理图拉完线投板就结束了,实际上布局、布线规则、电源完整性、丝印处理这些才是真正拉开差距的地方。
2. 环境感知模块选型:别只看“能用”,要看“好调”
仓库环境监测最常见的参数就是温湿度和空气质量。二者选型的逻辑完全不一样,分开说。
2.1 温湿度传感器:DHT22(AM2302)的性价比与坑
DHT22单总线协议,一根数据线搞定通信,便宜、资料多,非常适合本科毕设。我也见过有人用SHT30或者AHT20,I2C接口精度更高、稳定性更好,但DHT22足够应付仓库环境,且例程遍地都是,不需要自己抠时序。
但DHT22有它的毛病:采样周期必须大于2秒。很多人一上来就死循环里读,结果读出来的数据全是0或者跳变。这是因为DHT22内部上电后需要时间完成转换,你读得太快,传感器根本来不及响应。正确做法是在主循环里搞一个状态机或者简单的定时器标志,2秒读一次就够了。仓库环境本来就是个慢变量,2秒刷新绰绰有余。
另外一个坑是上拉电阻。DHT22的数据线需要接一个4.7kΩ到10kΩ的上拉电阻到VCC,如果模块自带电平转换电路就无所谓,但你裸片焊在PCB上的时候,忘了加上拉,数据线在空闲状态是高阻态,通信必然失败。我在PCB设计那一节会专门画出来。
2.2 气体传感器:MQ-2还是MQ-135?
MQ-2可检测丙烷、丁烷、液化气、烟雾,MQ-135对氨气、硫化物、苯系蒸汽更敏感,同时也对烟雾有响应。对于仓库场景,我推荐MQ-135,原因不是灵敏度,而是它的交叉响应更适合做“空气质量综合指标”——你要的不是精确到“某种气体浓度是多少ppm”,而是“仓库空气是不是变质了”,MQ-135输出一个随空气污染程度变化的模拟电压,阈值可调,逻辑简单。
而MQ系列传感器有个所有新手都会忽视的问题:它内部有加热电阻,上电后需要预热。冷启动的几分钟内输出是不稳定的,可能乱跳,也可能一直高电平。所以程序里不要在初始化后立刻读ADC,要延时个3到5分钟再开始判断,否则误报率极高。另外这类传感器工作电流不小(加热丝大概150mA左右),不能用单片机3.3V引脚直接供,最好单独用5V供电,PCB上留一颗100uF电解电容给它储能缓冲。
MQ-135输出的是模拟电压,连接到STM32的ADC引脚。信号量与浓度是非线性的,但毕设阶段不需要拟合精确曲线,直接在程序里设阈值判断“正常/警告/危险”三档就好。真要显示浓度值,可以把ADC值直接映射成“空气质量指数0-100”,百分比显示,人看得懂就行。
2.3 ADC多通道采集的关键配置:不是每个引脚都能随便接
STM32F103C8T6的ADC是12位逐次逼近型,最多支持16个外部通道。但要注意:ADC引脚分布在PA0到PA7、PB0、PB1等特定引脚上,不是任意GPIO都能当模拟输入。网上最常见的翻车就是把传感器输出接到了PA8或者PB3上,软件里怎么配置都读不到有效值,最后只能用万用表量电压发现引脚根本不通。
我自己做这版系统用了ADC的扫描模式+连续转换+DMA搬运。MQ-135接PA0,火焰传感器接PA1,两个通道一起采样,DMA自动把结果搬到内存数组里,CPU完全不用参与,等标志位即可。这个写法和轮询读ADC的代码量其实差不多,但架构上舒服得多,以后加传感器通道只需要改CubeMX配置。
ADC初始化里有个关键参数是采样时间。STM32的ADC采样时间可以设1.5到239.5个周期,如果引脚源阻抗高,采样时间太短会导致采集电压偏低。MQ-135模块输出经过一个电压比较器或者直接分压输出,源阻抗不算太低,我建议把采样时间设为55.5周期以上,稳定不漂。
3. 安防子系统:无源蜂鸣器与有源蜂鸣器千万别选错
安防报警执行端,很多人第一反应是“蜂鸣器呗”。但蜂鸣器分为无源和有源两种,无源蜂鸣器需要外部提供一定频率的方波才能响,有源蜂鸣器内部自带振荡源,给个高电平就响。毕设系统里强烈建议用有源蜂鸣器,否则你得用定时器输出PWM驱动,麻烦且有源蜂鸣器的响度通常更大,仓库环境需要响度。
驱动方式上也不要直接用GPIO高电平触发就完事。有源蜂鸣器工作电流大概30mA,GPIO引脚直接驱动会拉低电压也可能烧引脚。正确方案是加一颗S8050三极管做开关,蜂鸣器接在5V和三极管集电极之间,GPIO接基极串1kΩ限流电阻。PCB设计时这颗三极管的位置尽量靠近蜂鸣器,走线短可以减少压降和干扰。
人体红外模块HC-SR501输出的是数字信号,触发时输出高电平。这个模块最容易被忽略的是它有两个可调电位器:灵敏度调节和延时时间调节。延时时间调太长,你测试的时候按一次触发,它可能持续输出半分钟高电平,逻辑上看起来就像“卡死了”。推荐把延时调到最小(逆时针旋到底),让它输出一个短暂脉冲,便于程序判断边沿。
火焰传感器也是模拟输出,但它的光谱响应决定了它只能在一定距离内有效。距离几十厘米能测到打火机火焰,再远就瞎了。所以整机联调的时候千万别把它放在仓库门口说“我看不到火焰”——物理特性摆在那里,选型和安装位置本来就是系统方案的一部分。
安防联动逻辑不能太复杂。我的策略是:人体红外触发且持续10秒以上,判定为非法闯入,蜂鸣器响;火焰传感器输出超阈值立即响;MQ-135浓度超过警告阈值响一下提示而不是持续报警,超过危险阈值持续报警。报警事件同时通过ESP8266推送到MQTT服务器,手机上收到消息。
有一个问题必须提前想好:远程端网络断开了,报警还灵不灵?正确答案是:本地报警必须任何时候都生效,远程推送只是锦上添花。所以逻辑写成“检测到事件->本地声光报警->尝试网络推送”,顺序不能反。仓库安防的本体是现场的响应能力,不是手机上那条通知。
4. 远程通道选型与数据协议设计:ESP8266 + MQTT 怎么搭才稳
远程监测是本系统的灵魂,这部分的方案选型一度让我纠结了很久,最后定了ESP8266+MQTT。
先说为什么不用蓝牙:BLE通信距离在仓库场景下太短,穿墙之后基本废了。为什么不用GSM模块(比如SIM800C):资费问题、信号问题、还要备用卡,毕设阶段没必要引入这种可变因素。ESP8266模块十几块钱,WiFi覆盖率在校园里几乎百分百,做局域网远程够了,加一个云平台(比如巴法云、OneNET)就能实现互联网远程。
4.1 ESP8266与STM32的通信协议
STM32和ESP8266之间走串口,AT指令通信,波特率115200(ESP8266默认是115200,有些模块出厂是9600,先确认)。ESP8266要配成透传模式还是非透传模式,我推荐使用非透传+自定义帧协议,而不是开透传。透传模式看着方便,但数据没有任何帧头帧尾和校验,一旦WiFi丢包或者串口误码,上位机拿到一坨乱数据根本没辙。
我设计的帧格式很简单:
帧头(0xAA) + 长度(1字节) + 数据负载 + 校验和 + 帧尾(0x55)负载里放传感器数据字符串,例如:
TEMP:25.3,HUMI:60,SMOKE:12,FLAME:0,PIR:1STM32发完一帧后等ESP8266返回“OK”,收到才发下一帧。这样链路上有基本的状态同步。
4.2 MQTT消息设计:主题分层是关键
MQTT的Topic设计直接决定你扩展性。不要用一个大主题“data”把所有东西都塞进去,按设备类型和设备ID分层:
wh/device01/env -- 环境数据 wh/device01/alarm -- 报警事件 wh/device01/status -- 在线状态(遗嘱消息)这样手机端APP只需要订阅wh/device01/#就能收到该设备所有消息。报警消息是遗嘱也好、主动推送也好,都能区分。
云平台你可以用巴法云(免费、接入简单)或者自己搭一个EMQX服务器。自己搭EMQX要多一台服务器,作为毕设演示不划算。巴法云提供一个MQTT Broker地址和主题,ESP8266直接连接就行,微信小程序端用WebSocket接口同样连到巴法云就能刷出数据。
不过这里要提醒一点:巴法云是公众MQTT服务,没有加密认证,Topic名字不要用容易被猜的,加个随机串后缀。同时也别指望它做数据持久化,历史曲线展示建议自己在本地写个Python脚本订阅消息并存储,这也能在答辩的时候展示你的“数据链路”理解。
4.3 ESP8266本身是一个“小坑王”
给ESP8266供电是个隐蔽的坑。它的峰值电流在发送WiFi数据时能到300mA甚至更高,如果直接从STM32的3.3V稳压输出取电,一发送数据电压就下坠,串口通信立刻乱码。这也就是为什么很多人调试时发现:ESP8266单独测试一切正常,一接上STM32就疯狂输出垃圾字符。
解决方法是:ESP8266独立供电。在PCB上把3.3V走线分成两路,一路给MCU和传感器,一路单独给ESP8266模块,两路在AMS1117输出端汇合但经过磁珠或0Ω电阻隔离。同时ESP8266模块旁边加一个470uF的电解电容和0.1uF的陶瓷电容,给它“兜底”。
串口连接上,STM32的TX接ESP8266的RX,STM32的RX接ESP8266的TX,如果模块是3.3V电平就直连(F103的IO也是3.3V,可以直连)。别接反了,接反的后果是上位机收到全0xFF。
5. PCB设计实战:从原理图到投板前,我踩完的坑都在这
这一节是本题的重头戏。智能仓库监测系统包含数字电路、模拟电路、电源和无线模块,正好是练习PCB设计的绝佳载体。我用的是嘉立创EDA专业版,免费、有海量元器件库、能直接生成Gerber下单,对毕设来说完全够用。
5.1 原理图设计:模块化不要一坨连到底
原理图不是连线工具,是设计记录。我是按电源模块、主控最小系统、传感器接口、执行器接口、无线通信模块五个模块画的,模块之间用网络标签(Net Label)连接,不要用线跨过图纸拉成一团。这样不仅自己看得清,评审老师扫一眼就知道你系统设计有条理。
电源模块是原理图里最容易被忽略但又是最重要的部分。我用的拓扑是:12V DC适配器输入 -> 通过接线端子接入 -> 一路直通继电器(继电器线圈需要12V驱动),另一路经MP1584降压模块转5V -> AMS1117转3.3V。AMS1117输入输出各接一颗10uF钽电容和0.1uF陶瓷电容,这是基本功但很多人漏。
主控最小系统除了STM32F103C8T6本身之外,最关键的是三颗电容和一颗10kΩ上拉电阻:VDD引脚每颗就近放0.1uF去耦电容;BOOT0引脚经10kΩ下拉到GND(否则可能进不了Flash启动模式,芯片跑不起来);NRST复位引脚接10kΩ上拉到3.3V,并联0.1uF电容到地。这些件每一颗都有存在的理由,少了、位置放错了,系统就可能概率性死机。
STM32F103C8T6是LQFP48封装,引脚间距0.5mm,新手焊接容易连锡。如果你的焊接经验不足,建议用QFN封装的替代型号(不过一般不建议换)或者直接买一块最小系统板插在PCB上,留出排针接口。我个人建议还是直接焊,毕竟毕设含PCB指的就是你亲手做板,焊接一次LQFP48对你的动手能力提升非常明显,不试一次太可惜了。
5.2 PCB布局:顺序比走线更决定成败
拿到板框先别急着布线,布局决定了你这个板子好不好走、性能稳不稳。我的布局顺序六步走:
- 固定接口件:电源端子、传感器排针、ESP8266模块座、OLED排针放在板边,方向朝外,方便插线和操作。
- 固定电源模块:DC-DC和LDO靠近电源输入端子,这样电源路径最短,压降和纹波最小,避免电源走线绕过大半个板子再回来给MCU供电,那种走法板子电磁兼容一定不理想。
- 放置主控:STM32放在板子中心偏一侧,所有IO外设朝向对应的接口方向,避免交叉走线。VCAP引脚(105)对应的1uF电容放在引脚边上,这个电容不能省。
- 放置传感器接口:MQ-135的引脚是从底部伸出来的,注意封装方向要留出足够的空间给传感器本体。MQ-135本体会发热,别跟温湿度传感器贴在一起,否则DHT22测到的是MQ-135旁边的热空气,数据必然偏高。这个坑我实测过,温差能到4到5摄氏度。
- 放置执行器件:蜂鸣器和继电器放在远离模拟信号传感器的一侧,防止电磁干扰影响ADC采样。继电器线圈断电瞬间会产生反向电动势,PCB上要给继电器线圈并联一颗1N4007续流二极管(注意方向),否则可能把MCU旁边电路打挂。
- ESP8266布置到板边:天线区正下方整层掏空,不要走任何铜皮和走线,否则WiFi信号被PCB铜皮挡住,信号强度骤降,远程通信会时不时断连,排查起来非常头疼。
5.3 布线规则:电源、地、信号线的优先级
布线之前先在规则管理器里把线宽设好:
| 信号类型 | 建议线宽 | 说明 |
|---|---|---|
| 电源主干线(12V、5V) | 40mil以上 | 走电流,线宽不够压降大 |
| GND铺铜/走线 | 20mil以上 | 回流路径阻抗要低 |
| 3.3V电源线 | 15~20mil | 给MCU和传感器供电 |
| 普通信号线 | 10mil | IO、UART、I2C |
| 差分/高频信号 | 无 | 本系统无高频要求,ESP8266走线尽量短 |
布线这个环节,我想强调三点:
第一,布线顺序应该是先电源后信号。先把电源和地走完,再走信号线,最后统一铺地铜。很多人反过来,信号线走得七扭八歪之后电源线没地方走了,只能绕大圈,结果就是电源回路长、压降大、纹波高。
第二,信号线不要走直角和锐角。直角走线在转角处会形成阻抗突变,高速信号下有反射风险,生产时酸液也可能在直角根部残留导致细线被蚀刻断。所有转角用45度斜角或者圆弧过渡,EDA软件里都有这个设置。
第三,晶振要放在主控芯片附近,晶振下面和周围不要走其他信号线。8MHz晶振给MCU提供时钟,时钟线上的噪声会直接耦合进系统,导致UART通信偶发乱码。晶振周围放了两个负载电容(典型值20pF),它们要靠近晶振引脚,而不是靠近MCU引脚,这是很多参考设计都没画对的地方。
5.4 Gerber输出与投板检查
投板之前做这几件事,能省回来一版:
- DRC检查必须清零。开短路、线距不足、钻孔距离近这些是硬性错误,任何一个在生产环节都可能直接报废整板。嘉立创EDA的检查包含孔到线、线到线、孔到板边等规则,跑完有红叉就得回去改。
- 检查丝印位号大小。位号文字太小的话,打印出来根本看不清。嘉立创EDA里面选中全部位号,统一把字高改成60mil,大概1.5mm左右就清晰了。这个细节在热搜词里有人专门问“如何批量修改位号尺寸”,说明很多人前期被小字折磨过。
- 生成Gerber文件之后用在线查看器预览一遍。只看PCB编辑器里的样子是不算数的,因为EDA软件里隐藏了层,到Gerber里看到的才是生产实际用的东西。预览时重点看:所有层是否对齐、丝印有没有盖在焊盘上(丝印压焊盘会导致焊接不良)、钻孔文件是否包含所有孔位。
- 确认PCB板厚和铜厚。常规1.6mm板厚、1oz铜厚对这块板是够用的。如果你把电源走线设计得特别细,生产的时候就该发现并改粗了,不要投板后才发现。
5.5 PCB打样回来后的验证清单
板子到手第一件事不是插电,是先用万用表量一遍电源对地阻抗。3.3V和GND之间正常应该有几百欧姆以上,如果用的是成品模块,量出来短路的话,先检查AMS1117有没有焊反。AMS1117封装是SOT-223,引脚顺序是GND脚比输入输出长一截,装反的概率极高。
接着上电之后用手摸芯片温度。如果发热异常,赶紧断电查反向连接。再然后才是烧录程序。
调试顺序建议是:先点亮电源指示灯 -> 初始化OLED显示 -> 读DHT22 -> 读ADC -> 测试UART与ESP8266 -> 本地报警输出 -> 远程平台联调。一步一步来,每一步都有明确验证点,出了问题能立刻锁定范围,不会出现“整个系统没反应但不知道是哪的问题”。
6. 系统联调顺序与常见问题排查表
整个系统联调我踩的坑不少,把最典型的列出来,你可以按表自查。
现象一:OLED白屏或花屏。九成是I2C地址不对。OLED的I2C地址通常是0x3C,但有些模块是0x3D,在代码里先扫描一遍地址,别硬编码。还有个原因是SCL和SDA接反了,这种低级错误我犯过一次,补了几秒才反应过来。
现象二:DHT22读出来永远是0。检查单总线引脚有没有接上拉,检查引脚有没有在CubeMX里配成开漏输出模式。开漏输出配合上拉电阻才能实现真正的双向总线协议,推挽模式下信号会被拉死。
现象三:ADC值满量程或者一直跳。MQ-135模块上通常有个电位器调节比较电压,如果模块设计成“模拟输出+数字输出”两路,别接错引脚。模拟输出的电压范围是0到VCC,如果读到4095(12位满量程),多半是引脚悬空或者接错线了。另外前一版PCB如果ADC走线挨着继电器线,采样值会在继电器动作瞬间跳变,这是电磁耦合,解决方法是加大走线间距或者加一个RC低通滤波,10kΩ加0.1uF,截止频率大概160Hz,够用。
现象四:ESP8266发送AT没反应。这个问题先分两部分排查:一是串口波特率是不是对的;二是模块供电够不够。手头有USB转TTL的话把ESP8266单独接电脑上测试,如果单独测试正常但接STM32不正常,就是串口电平或者电源问题,重点查TX/RX有没有接反、ESP8266电源是不是独立供的。
现象五:本地报警正常但远程收不到消息。先在PC上用MQTT客户端软件订阅对应主题,看有没有消息进来。能收到的话,问题在手机端APP;收不到的话,分段排查:ESP8266有没有成功连接路由器?连接上巴法云没有?巴法云上创建的主题和代码里写的是不是完全一致?MQTT是明文传输,主题名打个大小写就能把你坑半小时。
上面这些问题的共性都是:先看硬件再看软件,先查物理层再查协议层。很多人一上来就刷固件换代码,结果换了半小时发现是杜邦线接触不良或者引脚定义搞错了,很浪费时间的。
7. 一个能提升答辩含金量的思路:本地数据记录
远程平台确实能看实时数据和报警,但偶尔网络断开那几分钟的数据就丢了。所以我建议在STM32端加一个Flash存储模块或者简单的SD卡记录。STM32F103C8T6内部Flash只有64KB,扣掉程序空间,剩下的空间虽然不大,但用协议组织好的话存几天的关键数据(每分钟采样一次温湿度和气体浓度)是够的。
思路是:把数据以固定长度结构体存储,包含时间戳、温度、湿度、气体浓度、报警标志。存满一块区域就循环覆盖最旧的一条。如果板子上挂了ESP8266,远程端断线重连后,把离线期间的数据补传上去。
这个设计成本极低,但答辩的时候很能体现你的系统设计思维:不是“实现了基本功能”,而是你考虑到了真实环境中网络不可靠的问题,并提出了降级方案。这在本科毕设里算是一个相当不错的加分项。
实现方式上用片内Flash模拟EEPROM,初始化时预留最后一页(1KB)做数据区,擦除后按地址偏移写入。注意写Flash之前必须整页擦除,这是STM32的物理特性,只能按“页”操作。
8. 走完一版之后,我对这个系统的几个复盘点
如果再来一遍,有些地方我会调整,这里写出来给你做个参考。
第一,MQ-135这个传感器在仓库场景其实不是最优解,它更偏“空气质量综合指标”而不是“火灾烟雾检测”。如果你想更贴近“仓库安防”这个主题,可以换成真正的光电式烟雾传感器(比如MQ-2或者更专业的离子式烟雾报警器模块),响应速度和灵敏度完全不在一个级别。但代价是贵一些、代码也要重新调。毕设选题是“安防系统”的话,烟雾这块值得投入。
第二,ESP8266到云平台的接入虽然简单,但答辩容易被追问数据安全。哪怕只是演示级系统,也建议把Topic命名得看不出业务逻辑,同时写一句“实际落地应使用TLS加密和设备认证”在论文的不足与展望部分。这句不是套话,是真的会被问到。
第三,PCB版图上,OLED的接口方向与外壳冲突是我在这版最后悔的地方。当时只想着放板边方便插线,但没考虑整个装置如果放进有机玻璃外壳里,排针朝上的话OLED就没法固定在外壳上。如果你的毕设有外壳设计,PCB布局阶段就必须把外壳的结构尺寸拿过来对齐,不然后期全是手工改造和热熔胶找补。
第四,在功耗上也有优化空间。仓库场景如果要对UPS供电或者感应取电,整个系统的静态电流可以压到很低:把OLED做成10秒刷一次、关掉ESP8266的空闲连接、用STM32的待机模式配合RTC定时唤醒。当时赶进度没做,但这是“智能”两个字很值得展开的落点。
最后再说一个做整机小技巧:把上位机或者微信小程序端的界面截图、调测过程录屏、实物样机照片这三样提前整理到一个文件夹里,写论文、答辩PPT和项目展示会用到,不要到最后答辩前才到处翻。系统的功能演示流畅度,比代码写得漂亮更直观。
这套系统做下来,嵌入式开发、传感器应用、无线通信、PCB设计这些本科能力点基本上都覆盖了。祝你的板子一版点亮,跑完整个调测流程顺利过答辩。如果投板或调测过程中卡住了,带着你的具体现象去对应板块找答案通常都能解决,别蹲在那硬想。
本文还有配套的精品资源,点击获取
