☰
STM32+WiFi远程温度控制系统实战:从硬件到答辩全流程解析
2026/10/19 7:38:54 网站建设 项目流程

先说明一下:我不是电商转行做嵌入式,也没有参加过任何培训,就是普通做毕设一路踩坑过来的。当时选这个题目,纯粹是觉得“STM32 + WiFi + 温度控制”听起来完整度高,既能秀单片机底子,又能扯上物联网,答辩时也好讲故事。但真做下来才发现,这个题目远不是“让风扇转起来”那么简单——它背后藏着一整套从传感器采集、控制算法到网络通信、移动端交互的闭环逻辑。这篇文章就结合我自己的实际经历,从硬件选型、固件架构、通信协议、上位机开发到调试和答辩,把整套系统拆开讲一遍。准备做类似毕设、想搞远程控制类项目的朋友,可以把它当成一份“可复制”的地图。

1. 题目背后的三个隐藏考点

很多同学拿到这个题目的第一反应是“STM32控制风扇转”这个功能。但你要记住,毕设答辩本身看的是“你在解决什么问题、怎么解决问题”,而不是“风扇会不会转”。这个题目里的每一个词,其实都对应了一类能力考核。

1.1 你以为做的是风扇,其实做的是闭环控制系统

风扇只是执行机构,系统的核心价值在于“温控”两个字。什么叫温控?就是环境温度变化时,系统能自动调节风扇转速,让温度稳定在某个区间。这本质是一个闭环控制系统:温度传感器作为测量环节,STM32作为控制器,PWM输出作为执行环节。

我见过不少同学的毕设就是把温度读出来,大于30度就开风扇,小于30度就关。你说它错了也没错,但这样做的复杂度只停留在“开关量控制”级别。要想让答辩老师觉得你有思考,就得引入比例控制甚至PID概念。温度低于目标值时,风扇低速转;温度逼近目标值时,速度逐渐提高;温度下降时,速度再慢慢降回来——这才叫温控。

我在做这个项目时,把控制策略分成了两档:普通模式用滞回控制防止风扇频繁启停,进阶模式加了增量式PID,让转速跟随温度偏差平滑过渡。这样做的好处是,论文里既有基础方案又有优化方案,工作量看起来非常扎实。

1.2 WiFi通信不只是“能连上”

远程控制的关键在WiFi模块与STM32之间的数据交互。很多初学者以为WiFi模块通电、AT指令连上路由器就完事了,实际上这里至少有四个环节要打通:第一,STM32和WiFi模块之间的串口通信要稳定;第二,WiFi模块要能联网,并且能连接到MQTT服务器或者TCP服务器;第三,数据格式要统一,温度和开关状态需要编码成可解析的结构;第四,手机App或者网页要能订阅同一个主题,才能收到推送。

我在项目里选择了ESP8266作为WiFi模块,工作模式是AT指令。因为STM32本身并没有TCP/IP协议栈,ESP8266可以独立完成网络协议的处理。它在出厂固件里内置了MQTT和TCP/IP相关指令,我只需要通过串口发送AT指令来配置WiFi名称、密码、服务器地址和订阅主题,就能完成数据收发。

这里有个特别容易踩的坑:串口波特率不匹配。ESP8266默认波特率跟STM32的USART配置如果不一致,吐出来的全是乱码。我后来把所有通信都统一成115200,并且给WiFi模块单独供电,才彻底稳定下来。

1.3 交互端设计决定项目上限

远程温控系统不能只做单向上报,必须做到双向控制。手机端要能实时显示当前温度、风扇转速,还要能设置目标温度、启停风扇。很多人的毕设只有温度曲线显示,没有下控功能,这在答辩时会显得“只有监测没有控制”,系统完整性会打折扣。

交互端我建议优先考虑微信小程序或者网页,而不是原生App。为什么?因为原生App需要安装包、适配不同手机,还要准备签名证书,这些东西在毕设阶段特别浪费时间。而小程序或者网页天然跨平台,评委直接用手机扫码就能看效果,演示成本极低。我用的是小程序加MQTT,通过一个公共的MQTT服务器中转消息,手机端订阅设备状态主题,设备端订阅控制主题,两边通过JSON消息对话。

这样一来,系统从数据采集、控制决策、网络传输再到人机交互,形成了一个完整的闭环,无论从功能还是PPT架构图角度,都站得住脚。

2. 硬件选型与最小系统搭建

硬件选型不追求最贵,追求的是“够用、好调、资料多”。毕设项目周期短,尽量回避那些冷门芯片和模块,否则出了问题连个参考代码都搜不到。

2.1 主控芯片怎么选:Flash、引脚、封装如何权衡

温度风扇这类项目,主控根本不需要跑复杂的算法,但至少需要满足三个条件:有足够多的定时器输出PWM,有至少两个USART(一个接WiFi模块,一个接调试串口),还要有足够的Flash存放代码和协议栈数据。我当时用的是STM32F103C8T6,64KB Flash、20KB RAM、3个USART、4个16位定时器,完全够用。而且它的最小系统板遍地都是,原理图资料非常详细,焊接也不难。

选型时要注意封装。C8T6是LQFP48封装,引脚间距比较挤,建议直接用开发板或者画一个最小系统板,不要从零开始焊接LQFP48,否则很容易虚焊。如果你更熟悉F103ZET6那种大板子,也可以直接用正点原子的探索者或者迷你板,反正核心逻辑是一样的,只是引脚资源更充裕。

还有一点,尽量预留一个SWD调试接口。我在最初画板的时候为了省空间没有引出SWD,后来程序跑飞只能靠串口打印猜问题,效率极低。重新加了一个4针的SWD排针后,烧录和在线调试都变得非常舒服。

2.2 温度传感器选型:DS18B20与NTC的实测对比

温度传感器我对比过两种:DS18B20和NTC热敏电阻。DS18B20是数字输出,单总线协议,直接读出来就是温度值,不需要ADC采样,精度在±0.5℃左右;NTC是模拟输出,需要配合分压电阻接STM32的ADC引脚,还需要查表或者公式计算。

DS18B20的优势是代码简单、精度稳定,但它有个麻烦事:单总线协议对时序要求非常严格。如果你用了RTOS或者中断优先级设置不当,很容易出现读不到温度或者温度跳变。我曾经在主循环里读一次DS18B20要花大概200ms,而且期间如果来了串口中断,时序会乱,温度直接变成85℃(就是读到了复位脉冲)。

NTC的优势是响应快、不需要严格时序,只要ADC采样读数就可以。缺点是需要自己标定,而且长导线容易引入噪声。最终我在项目里用了DS18B20,因为它的资料最多,而且不占ADC资源。为了让时序稳定,我用了单总线库,在读取期间关闭高优先级中断,实测下来连续跑24小时温度值都很平滑。如果你手头有现成的NTC,也可以用,ADC滤波做好,实际效果同样不差。

2.3 WiFi模块的三种玩法:串口透传、AT指令、SDK二次开发

WiFi模块选的是ESP8266,玩法有三种:第一种是纯串口透传,ESP8266建立TCP连接后把串口收到的数据直接发出去,反之把收到的数据转发到串口;第二种是AT指令模式,通过串口发送“AT+CWJAP=”“AT+MQTTCONN=”“AT+MQTTSUB=”这样的命令来连接网络和服务器;第三种是刷写自定义固件,在ESP8266内部直接跑MQTT代码,STM32只负责采集和控制。

我用的第二种AT指令模式,适合文档阅读能力强、不想碰二次开发的同学。AT指令最大的问题是不太稳定,比如连接AP的时候如果密码错一次,它可能会直接进入错误状态,需要发送“AT+RST”才能恢复。所以我在STM32固件里加了一个WiFi状态机:初始化、复位、检测应答、连接AP、连接MQTT、订阅主题。每一步都有超时判断,超时后自动重试。这样就避免了程序卡死在某个AT指令的等待上。

如果你有余力,可以试试第三种玩法,在ESP8266里用Arduino或者ESP-IDF写一段代码,直接通过MQTT协议连接服务器。这样STM32只通过串口给ESP8266发温度值和接收控制指令,网络稳定性会好很多。缺点是开发周期会增加一两天。

2.4 驱动电路:MOS管与三极管驱动风扇的区别

这是很多毕设最容易忽略的环节。STM32的GPIO输出能力只有几毫安,不能直接驱动12V风扇。必须加一级驱动电路。最基础的做法是用NPN三极管做开关,比如S8050,基极串联1k电阻接STM32的PWM引脚,发射极接地,集电极接风扇负极,风扇正极接12V。三极管方案结构简单、成本低,但通过大电流时压降比较明显,饱和导通时Vce大约0.3V到0.5V,对转速有影响。

更好的方案是用N-MOS管,比如AO3400。这种MOS管只是符合逻辑电平驱动,3.3V的GPIO就能完全导通。我实际对比过,用三极管驱动12V风扇,最大转速时感觉到明显乏力;换成MOS管后转速立即上去,而且PWM频率可以提高到20kHz以上,听不到刺耳的啸叫。MOS管的栅极需要加一个10k左右的下拉电阻,防止单片机上电瞬间引脚悬空导致风扇误转。同时在电流回路加一个续流二极管,防止关断时反向电动势打坏MOS管。

3. 固件代码架构与核心算法

固件代码不是把外设例程拼在一起就完了,而是要分清哪些功能是周期任务、哪些功能是异步事件,然后以清晰的结构把它们串起来。

3.1 任务拆解:三线程还是状态机

市面上很多STM32教程都是裸机大循环,但你这个项目有温度采集、PWM控制、串口通信、WiFi指令交互,如果全部堆在主循环里,顺序执行时会遇到“正在处理AT指令,温度采集没及时响应”的情况。最合理的拆法是用一个简单的时间片轮询调度器,或者直接用RTOS。

我实际项目里使用的是裸机时间片轮询:系统定时器每1ms触发一次,里面维护几个标志位——1ms标志、10ms标志、100ms标志、1s标志。主循环里不断查询这些标志位,分别调度不同任务:10ms处理PWM变速和按键扫描,100ms处理温度采集和滤波,1s处理WiFi心跳和状态上报。这样代码清晰,也不会出现任务之间的互相堵塞。

比时间片轮询更进阶一点的是状态机。WiFi连接过程天然适合用状态机描述,比如“上电检测-连接WiFi-建立MQTT-连接成功-运行中-掉线重连”,每一个状态都有对应的入口动作和超时时间。我建议WiFi相关代码单独写成一个模块,用状态机管理,因为AT指令交互不是一次性完成,而是流水线式的。否则一旦某条指令失败,整个系统就乱了。

3.2 温度采样滤波:滑动平均与限幅滤波

DS18B20虽然温度值稳定,但在风扇附近测温度时还是会受到气流扰动影响。风扇转过之后,温度读数往往会在±1℃范围内快速波动,如果直接把这些波动当成控制输入,PWM转速也会跟着抖。这里就需要滤波。

我是做了两级滤波:第一步限幅滤波,若当前采样值和上一次的差超过2℃,就认为是一次异常跳动或传感器读数错误,直接丢弃本轮数据;第二步滑动平均,保留最近5次有效的采样值,取平均作为滤波后的温度。这种两级滤波组合在去掉毛刺的同时还能保持响应速度,不会让控制环节变得迟钝。

这里有个细节:滑动窗口的长度不要过大,5个采样点是我试过比较合适的。窗口太长,遇到真实升温时会反应很慢,给人感觉“温度半天不变”;窗口太短,滤波效果又不明显。而且滤波只针对采样值,不要影响控制算法的独立运行,否则系统会出现自激振荡。

3.3 温控策略:滞回控制与PID控制怎么选

控制策略直接决定了系统的智能化程度。如果你只是大于某温度就全速转、小于就停,这种开关控制在风扇频繁启停时不仅耗电,还容易给人“没做控制”的感觉。我用两种方案做了比较。

滞回控制是:设定目标温度T和回差值H。当温度大于T+H时,风扇启动;当温度降到T以下时,风扇才停止。中间温度区间内保持上一次状态不变。这样风扇不会在临界点附近疯狂切换。滞回控制适合论文里作为基础功能,逻辑简单,容易实现,也能展示出你考虑过工程问题。

更进阶的方案是PID控制。这里说的PID不是温度PID,而是风扇转速PID。目标温度设为30℃,当前温度35℃时,误差是5℃,PID输出的占空比随着误差变化。增量式PID不需要累计所有历史误差,它输出的是每一次占空比的增量,限制输出范围后更安全。

我最后在项目里做了一个模式切换:默认滞回控制,方便演示;按一下按键进入PID模式,可以看到温度越接近目标,风扇转速越柔和。这种方式在答辩现场演示时非常有视觉冲击力,因为你能明显看到转速平滑变化,而不是开开关关。

3.4 MQTT数据上报与下发:JSON解析的坑

MQTT是物联网场景下最常用的轻量级协议。我在ESP8266的AT固件里直接配置了MQTT参数,发送AT+MQTTCONN连接到公共MQTT服务器,然后通过AT+MQTTPUB发布主题消息。

数据格式我用的是JSON。设备和App之间约定两个主题和一个消息格式:

设备状态上报:{"temp":28.5,"speed":40,"mode":"auto","on_off":1,"target":30}

远程控制指令:{"on_off":0,"target":26,"mode":"manual"}

STM32收到ESP8266串口转发过来的JSON字符串后,因为STM32资源有限,不能直接用大型JSON库,而是自己写了一个极简键值对解析函数,用字符串查找的方式截取数字值。这个方法虽然看起来土,但在控制指令只有固定几个字段的情况下特别稳定,解析耗时不到几毫秒。

要注意的是MQTT的心跳机制。如果设备长时间不发消息,服务器会判定设备离线,从而清除连接。我在1秒上报任务里也顺手发送心跳信息,让服务器始终保持在线状态。另外所有Topic都要设计得有意义,比如设备端是student/device/001,不要用宽松的全局Topic,否则多个设备会串控。

4. 上位机端设计与远程交互

这一部分很多做单片机的同学不熟,但恰恰是评分老师关注的“亮点模块”。远程温控系统如果没有可靠的交互端,整个项目就缺了入口。

4.1 手机App、小程序还是网页?

上位机选择,我的排序是:微信小程序 > 网页 > 原生Android App。原因很现实:原生App开发要安装Android Studio、写Java/Kotlin代码、生成APK、连接USB调试,调试效率低;而且如果你只做了一个简单的单Activity应用,评委一眼就能看出工作量不足。

小程序的好处是开发工具轻量、调试方便,真机测试用微信扫码即可,还可以直接用手机号授权登录,省去了用户注册模块。我在小程序里做了三个页面:设备列表页、监控面板页、历史曲线页。监控面板页是核心,展示了当前温度、目标温度、风扇转速、启停状态,还有控制按钮和温度设置滑块。

如果你不想写小程序,做一个网页Dashboard也完全OK。用HTML加JavaScript连接WebSocket,把SPA界面做好看一点,远程控制功能一样能实现。而且网页部署成本低,答辩时直接打开浏览器演示,效果也不差。

4.2 MQTT服务器选择与Topic设计

公共MQTT服务器有很多,我用的EMQX公共服务器。它支持匿名接入,不用注册,直接填一个ClientID就能收发消息,非常适合毕设演示。但注意公共服务器不稳定,随时可能重启,所以论文里一定要写“本系统采用本地可部署的MQTT Broker,答辩演示时使用公共服务器”,表明你懂原理而不只是依赖免费服务器。

Topic设计建议采用三层结构:类型/设备ID/属性。比如:

  • device/001/state:用于上报温度、转速、模式
  • device/001/control:用于手机下发控制指令

设备订阅control主题,手机订阅state主题,就实现了双向通信。每个设备的ID要在固件里写死,或者通过AT指令配置,避免两个设备用同一套Topic。

这里有个容易出问题的点:MQTT QoS等级。实测下来,QoS0够用,因为温度和转速是高频周期上报,偶尔丢一帧没有影响;但是控制指令必须用QoS1,因为如果你点了“关闭风扇”指令,这一帧丢了,风扇就不会响应。我在小程序的发布函数里强制指定qos=1,而设备上报主题使用qos=0。

4.3 消息格式设计:别只看温度

远程控制系统只上报温度显然不够,因为用户需要知道执行器的状态。我上报的JSON里包含4类信息:温度、风扇转速百分比、运行模式、开关状态。转速用0-100之间的整数表示,不要用浮点数,因为MQTT消息越短越好,整数也更容易解析。

控制指令里,我允许设置目标温度、开关、模式。但注意禁用在远程端“直接设置PWM占空比”这种透传操作,因为那样等于绕过控制算法,让用户直接碰执行器,安全上非常危险。我在固件里做了指令过滤:收到控制指令后,必须先校验模式的边界,温度设置在15-40℃之间才生效,否则忽略并返回错误状态。这个小细节在答辩时如果展示出来,会很加分,说明你考虑了异常输入。

状态上报的周期我设成了1秒。太快会给MQTT服务器增加压力,太慢会让人感觉界面卡顿。1秒刷新配合1Hz的动画过渡,视觉上看起来是实时变化。如果你想省流量,可以改成5秒,但在演示时建议调短。

5. 调试实录:三个最容易崩的心态瞬间

做这个项目最大的成本不是连接电路,而是调试。我把三个最典型的坑写下来,给后来者一个心理预期,免得跟我一样半夜怀疑人生。

5.1 串口打印乱码:晶振、波特率与电压域的三角关系

第一个坑是串口打印乱码。STM32在串口1打印“hello”,电脑端用9600波特率看,全是“烫烫烫”。最开始我以为是代码问题,折腾了半天才发现是波特率不匹配。ST官方的HAL库例程默认是115200,而我电脑串口助手设置的是9600。

更隐蔽的是在WiFi模块接入后,ESP8266的串口如果和调试串口共用同一个USART,或者两个设备复用同一路电平转换芯片,就会出现互相干扰。ESP8266的IO电平是3.3V,但如果某一根线上接触不良或接地环路,串口数据就会偶发丢字节。解决办法是:让STM32的USART1接调试,USART3接ESP8266,两个串口完全独立,电压域都是3.3V,不用多电压转换,减少硬件梗。

5.2 WiFi频繁掉线:DHCP、AP信道与供电毛刺

我的项目在某段时间WiFi模块每3分钟掉线一次,关掉重连后能坚持几分钟又掉。排查了路由器信道、AP兼容性都没用,最后发现是供电问题。

ESP8266在发射瞬间的电流可以达到300mA以上,如果你的主板用AMS1117-3.3从5V降压供电,那在发射瞬间电压会被拉低,导致模块复位或者自动重启。我在原理图里给ESP8266加了一个470μF的电解电容和一个0.1μF的陶瓷电容,相当于给它加了一个小储能池。效果立竿见影:WiFi连续跑了48小时没掉线。

另外,DHCP租约时间短也可能导致IP过期,但这种现象一般在7天左右,毕设阶段不会遇到。如果你用的静态IP,需要把路由器的DHCP租期调长,或者干脆给模块分配一个静态IP,让它在固定IP上运行,减少重连后的协商时间。

5.3 风扇一开单片机重启:PWM引脚与功率地的耦合干扰

这是我调试时最崩溃的问题:WiFi正常、温度正常,但只要一开风扇,单片机立刻重启。用示波器测PWM引脚,发现存在大量毛刺,再测3.3V,发现电压在风扇开启瞬间被拉低到2.7V。

问题出在共地。风扇是大电流功率地,单片机的逻辑地是信号地,两者如果直接连在一根细细的杜邦线上,大电流跳变会在地线上产生压降,地电位漂移直接导致MCU复位。

解决方案是在PCB布线时做成单点接地,或者至少用粗线把功率地单独引回电源负极,不要让风扇电流经过MCU的数字地。如果你画板时没注意,现在拿杜邦线飞线,也要遵循“功率地尽量短、尽量粗,信号地单独走”的原则。我在风扇负极和MOS管源极之间串了一个0.5mm直径的导线,实测效果改善了很多。

6. 论文撰写与答辩演示要点

代码跑通只是毕设的一部分,论文和答辩是另一个层面的工作量。很多同学代码做得猛,答辩讲不明白,最后分数反而一般。我就说说我怎么组织答辩材料的。

6.1 论文结构:从功能需求到系统测试

论文我采用了“需求分析—总体设计—硬件设计—软件设计—系统测试”的五章结构。不需要太学术,但每一章必须能回答审阅老师的疑问。

需求分析里,我把系统用户分为两类:使用者和管理者。使用者需要实时监控温度和手动控制风扇;管理者需要查看历史记录和设置温度范围。这个分类直接引出系统功能列表,功能列表再对应到硬件选型和软件模块,逻辑链条是闭合的。

硬件设计章节不要贴大段代码,而是画清楚系统的框图、各模块之间的接口。使用引脚分配表列出每个外设和STM32引脚的对应关系,这比写三百字“采用XX芯片”有用得多。

软件设计章节重点展示状态机和时序图。我当时写了WiFi模块的状态机转换表,审阅老师一眼就能看出你的代码有状态管理思想。系统测试章节必须包含实验数据,比如目标温度30℃时,不同起始温度条件下,系统达到稳定的时间和超调量,最好有三组数据表。这是“有说服力”的关键。

6.2 答辩演示的“90秒电梯法则”

答辩演示时间有限,你要在90秒内让评委看懂你的系统亮点。我的演示流程固定为四步:

第一步,展示硬件实物,手指指出STM32主板、传感器、WiFi模块、风扇驱动电路的位置,说明这是个完整系统。

第二步,打开手机小程序,点击刷新,让温度曲线跳出来,同时用手握住DS18B20温度传感器,看着温度上升,风扇转速自动提高。这一步是视觉冲击,比任何PPT都直接。

第三步,在手机上修改目标温度,比如从30℃改成40℃,风扇会立刻降速,证明远程下行控制有效。

第四步,打开串口调试助手,指向串口日志里的AT指令和MQTT发布记录,说明通信链路是透明、可验证的。

这样90秒不到,但“监测、控制、远程、通信”四个核心能力全部展示到位,评委也节省了追问时间。

6.3 如何应对“这有什么难点”的灵魂拷问

答辩老师经常问:“这个项目网上案例一大堆,你觉得有什么难点?”这时候千万不要说“没有难点”,也不要说“这个系统很复杂”。

我的回答思路是:从“工程问题”角度回答,而不是从“原理创新”角度。具体说三点:

第一点是确定性时序问题。DS18B20单总线时序对中断敏感,我在设计固件时考虑了临界区保护,避免WiFi模块串口中断干扰温度读取,这是一类工程细节问题。

第二点是功率与信号地隔离。风扇大电流开启瞬间会造成逻辑地电位波动,我通过单点接地和储能电容解决了MCU复位问题,这需要从系统级角度去排查,不是搭个电路就能跑通的。

第三点是M2M通信语义。设备上报数据和控制下发的Topic、QoS策略都不相同,如何保证控制指令可靠到达、状态数据不至于淹没服务器,这些需要在协议层去设计。

这样回答,既承认了项目工程难度,又展示了你对底层机制的理解。评委听了会觉得你不是在“抄代码”,而是真在做系统设计。

我在整个项目里最大的体会就是:毕业设计不是一个“功能列表”,而是一套“取舍逻辑”。你做的每一个选型,背后都对应着可靠性、成本、开发时间之间的权衡。把“为什么选它”讲清楚,比“我用了它”值钱得多。最后再分享一个实战小技巧:答辩前一定要把Demo从“网线供电”改成“电池供电”或者“稳压电源直供”测一遍,我就因为临时换电源导致WiFi模块掉线,差点在答辩现场翻车。现在多留一份冗余,才敢去讲台。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询