
简介面向嵌入式开发、物联网毕设及智能家居应用场景这份设计文档围绕STM32F103RCT6主控整合60GHz毫米波雷达、MLX90614红外测温、DHT11温湿度、MQ7一氧化碳传感器与WiFi模组实现独居老人呼吸心率检测、跌倒识别、体温测量、环境质量监测并通过腾讯云与微信小程序完成远程告警和数据展示。资源包共1个PDF文件大小52.65MB内容涵盖系统需求分析、硬件选型对比、整体架构设计、各模块电路连接、通信协议及软件流程还详细讲解了毫米波雷达非接触式生命体征检测原理与阈值预警机制。目前已有281人学习下载。文档从需求定义到调试验证逐层展开既给出可直接引用的设计思路与硬件清单也包含数据上云和微信小程序对接的关键细节适合用于课程设计、毕业设计或相关项目预研帮助读者快速搭建一套完整的居家监护系统方案。 做这套基于STM32的独居老人居家监护系统是我前后折腾了大半个月才跑通完整链路的项目MCU端采集各种传感器数据ESP8266模块负责联网上云最后在微信小程序里实时展示和推送告警。整个项目做下来踩了不少坑也把硬件选型、通信协议、小程序联调这些环节摸了一遍。今天不写那种学院派的项目介绍就按我实际动手的顺序把整体方案、硬件细节、通信链路、小程序端开发和问题排查完整过一遍。准备做物联网方向毕业设计或者想给家里长辈搭一套低成本监护设备的朋友这里面的思路和代码可以直接参考。1. 系统总体架构与技术选型思路1.1 系统架构如何分层这套系统的架构一句话就能说清STM32做数据汇聚和控制ESP8266做网络通路MQTT做消息管道微信小程序做监护人和设备之间的交互界面。从数据流向上看整个系统分成了三层。感知层是挂在STM32上的各路传感器负责采集心率血氧、环境温湿度、人体红外感应、烟雾浓度再加上一个SOS紧急按键。传输层是ESP8266 WiFi模块它通过串口和STM32通信把传感器数据打包发到云端MQTT服务器。应用层就是微信小程序订阅对应主题把数据解析后展示给监护人并负责告警提醒。为什么拆成这三层最大的好处是每一层都能独立调试。传感器先挂在STM32上不接ESP8266用串口打印数据先把采集问题排查干净ESP8266单独用串口调试助手发AT命令确认它能连上路由器、能连云平台最后再把两层接起来联调。我这次项目里绝大部分时间都花在传感器稳定性和小程序联调上分层架构让我不用同时猜两个环节的问题效率高很多。1.2 核心硬件为什么这么选主控我选的是STM32F103C8T6。这颗芯片虽然发布很多年了但做这类监护项目非常合适72MHz主频、64KB Flash、20KB RAM跑传感器采集和串口协议完全够用价格在6到10块钱左右开发资料更是多到看不完。有人可能会纠结用不用ESP32ESP32本身自带WiFi和蓝牙确实省掉了一个模块但考虑到题目限定STM32而且STM32的外设教学资源丰富我还是坚持了F103C8T6加ESP8266的方案。通信模块选ESP8266-01S主要原因就是便宜且成熟十来块钱AT指令固件用起来简单。传感器方面心率血氧用MAX30102I2C接口代码好写温湿度用DHT11精度虽然一般但监护场景看趋势变化完全够用人体存在检测用HC-SR501红外模块便宜感应范围大燃气烟雾检测用MQ-2模拟量输出用一个ADC通道就能读。这套选型方案的整体成本大约在50元以内对于家庭场景来说接受度很高。硬件选型最终确定之前我对比过几种方案模块备选型号实际选择选型理由主控ESP32、STM32F407STM32F103C8T6成本低、资料多、外设满足需求通信蓝牙BLE、4G模组ESP8266-01SWiFi覆盖好、开发简单、成本低心率血氧模拟前端方案MAX30102I2C接口库成熟代码量少温湿度SHT30DHT11精度够用单总线时序简单蓝牙方案首先被排除掉不是不好而是手机离开家之后数据就断了没法实现远程告警这和监护系统的核心需求冲突。4G模组的稳定性更好但流量成本和模块成本都上去了对个人项目不太友好。WiFi加MQTT的路线在家庭场景里是性价比最高的选择。2. 感知层硬件设计与数据采集要点2.1 各传感器接线与工作特性感知层是整个系统里硬件上最需要耐心的一层。所有传感器共地是基本要求ESP8266和STM32之间的地线也必须接好否则串口电平参考不一致收到的全是乱码。MAX30102是通过I2C总线接入的设备地址是0x57供电电压3.3V。需要注意它的SCL和SDA两根线上必须接上拉电阻一般用4.7kΩ如果不接通信会时好时坏。DHT11的DATA引脚悬空状态下默认是高电平要和单片机通信必须由主机主动拉低启动我外接了一个10kΩ上拉到VCC避免信号不稳定。HC-SR501红外人体感应模块的供电是5V输出三线制检测到人时输出高电平它背面有两个可调电位器一个调感应距离一个调延时时间。MQ-2模块同样需要5V供电模拟量输出接STM32的ADC引脚它属于加热型半导体传感器上电后需要预热一分钟左右输出电压才会稳定下来。给各模块供电的时候5V和3.3V要分清楚。ESP8266和MAX30102、DHT11都是3.3V但ESP8266模块的峰值电流比较高我用的是AMS1117-3.3稳压芯片输入端接5V输出端加一个100uF电解电容和0.1uF陶瓷电容去耦。电源这关没处理好后续会出现各种随机问题比如传感器读数跳变、MQTT连接不稳定。2.2 数据采集周期与软件滤波采集周期设置是很多人容易忽略的细节。我的实际配置是温湿度每5秒读一次因为DHT11的采样周期本身就要求不低于1秒心率血氧每1秒循环读取并做滑动平均人体红外每200毫秒轮询一次引脚电平烟雾浓度每500毫秒读取一次ADC。分开配置的好处是避免所有传感器挤在同一时刻触发也降低了单片机瞬时负载。ADC读取MQ-2的输出时单次采样容易被抖动干扰我做了最简单的滑动平均滤波uint16_t read_gas_adc_filtered(void) { uint32_t sum 0; for (int i 0; i 10; i) { sum HAL_ADC_GetValue(hadc1); HAL_Delay(10); } return sum / 10; }10次采样取平均够用于烟雾趋势检测了。DHT11的读取代码要特别注意时序主机拉低总线后必须延时18ms以上然后释放总线读数据的时候每一位的高低电平持续时长是微秒级的用CubeMX生成的HAL库延时函数在这个场景下最好改用微秒级硬延时。我之前用HAL_Delay(1)去读DHT11的位信号读出来全是0后来改成DWT的微秒延时才正常。心率血氧的MAX30102读取相对友好初始化好寄存器后从中断引脚或者轮询状态寄存器拿数据就行。真正需要注意的不是代码而是佩戴位置和手指放置方式。我调试时发现手指放歪或者按压过重血氧值会直接掉到90以下容易误报所以代码里加了数据有效性判断连续采集5秒数据偏差太大就丢弃等波形稳定后再上报。提示MAX30102的I2C频率不要配置太高我实测默认100kHz最稳400kHz模式在部分线材稍长的连接下会出现通信错误。这个问题在STM32CubeMX里直接把I2C时钟降到100kHz就能解决。3. 通信链路设计STM32与ESP8266的串口协作3.1 AT指令链路搭建ESP8266模块默认走AT指令控制这是最简单也最稳定的方式。STM32用串口2和ESP8266通信波特率设为115200串口1保留给调试信息。模块工作在STA模式就是只连接家里WiFi路由器的模式不需要它自己开热点。建立连接的AT指令流程是固定的ATCWMODE1设置STA模式ATCWJAP你的WiFi名,你的WiFi密码连接路由器ATCIPSTARTTCP,broker.emqx.io,1883和MQTT服务器建立TCP连接ATCIPSEND长度进入透传数据发送发送MQTT报文数据先说一下不走透传模式的原因。AT指令固件的透传模式只能和一个TCP连接绑定后面要换服务器或者重连还得先退出透传处理起来比较绕。我最后用的是普通发送模式每帧数据都带ATCIPSEND前缀虽然废一点点指令开销但整个流程可控性更好出现异常时重连和状态恢复都简单。发送一帧MQTT数据的核心代码简化之后长这样char mqtt_msg[256]; sprintf(mqtt_msg, {\device_id\:\01\,\hr\:%d,\spo2\:%d,\temp\:%.1f,\hum\:%.1f,\gas\:%d,\pir\:%d,\sos\:%d}\r\n, heart_rate, spo2, temp, hum, gas_level, pir_status, sos_flag); char at_cmd[128]; sprintf(at_cmd, ATCIPSEND%d\r\n, strlen(mqtt_msg)); uart2_send_string(at_cmd); HAL_Delay(50); uart2_send_string(mqtt_msg); HAL_Delay(100);这个写法虽然可用但真正工程里不能这么裸奔。ESP8266返回的字符串是多行、带换行符的如果只对OK和ERROR简单做匹配连接慢或者服务器响应超时的时候状态机就会卡死。我后来用环形缓冲区收串口数据每收到一行就解析一次判断行首是OK、ERROR还是IPD再根据当前状态跳转到下一个命令。这样即使某一条AT指令超时程序也能重发或者重启连接流程不会让整个设备卡住。3.2 MQTT主题与数据帧设计MQTT协议的选择没什么悬念物联网项目里它就是事实标准。发布订阅模型非常适合这种设备端和App端一对多的场景设备只管往主题里发数据小程序端订阅同一个主题就能收到设备完全不需要关心有几个App在线。我定义的主题结构是joy/device/01/data设备上行数据主题设备发布小程序订阅joy/device/01/alert设备告警主题设备发布小程序订阅主题里的01是设备编号以后如果家里有多套设备扩展成02、03就行。数据格式统一走JSON方便小程序端解析。设备上行数据的一帧JSON长这样{device_id:01,hr:72,spo2:97,temp:36.5,hum:45.6,gas:120,pir:1,sos:0}字段含义分别是心率、血氧、温度、湿度、烟雾ADC值、人体红外状态、SOS按键状态。设备端要发送MQTT报文时提前组好这一帧数据再算好长度填到ATCIPSEND命令里就行。这里我做过一个决策就是没自己定义二进制私有协议。之前想过用固定帧头加校验字节的方式比如0xAA 0x55开头再加CRC但实际调试中发现自定义的二进制协议一旦出问题网上搜不到任何参考定位起来全靠自己猜。JSON虽然多占一点传输字节但出问题的时候可以拿MQTT调试工具直接看报文内容定位问题要方便得多。MQTT服务器我用的是公共的EMQX测试服务器broker.emqx.io开发阶段完全够用。如果后续要长期部署可以考虑自己搭一个服务器部署方式就是普通的EMQX或者Mosquitto配置起来都不复杂。数据上报周期我设成了5秒一次每次报文不到200字节公共服务器的免费额度完全够用。4. 微信小程序端开发与联调要点4.1 原生小程序还是uni-app小程序端开发之前我纠结过是用原生微信小程序还是uni-app。最后选了原生原因很直接这个项目的小程序页面不多主要是实时数据、历史曲线、告警记录和设置页原生开发完全能应付而且原生对蓝牙、订阅消息等原生能力的支持和调试工具更直观。uni-app的优势在于跨平台但它引入的编译层会带来一些不可控的问题尤其是不熟悉的开发者经常被框架层的bug卡住。原生开发的环境准备要注意几点。微信开发者工具安装后需要扫码登录这步很简单。小程序开发的时候request和WebSocket请求在开发者工具上是默认拦截的需要在详情-本地设置里勾选不校验合法域名否则开发阶段就会报域名错误。真机预览的时候这个选项就失效了必须配置合法域名这个问题我放到第五部分讲。4.2 核心页面与数据交互小程序端的数据交互逻辑是这样的因为小程序本身不支持直接从TCP端口读数据我让小程序通过WebSocket连接同一台MQTT服务器mqtt.js库在npm上可以直接拉下来放到项目的utils目录里使用。连接MQTT服务器的核心代码const mqtt require(../../utils/mqtt.min.js) Page({ data: { heartRate: 0, spo2: 0, temp: 0, hum: 0, gas: 0, sos: 0, online: false }, onLoad() { const client mqtt.connect(wss://broker.emqx.io:8084/mqtt, { clientId: mini-program- Date.now() }) client.on(connect, () { console.log(MQTT连接成功) client.subscribe(joy/device/01/data) client.subscribe(joy/device/01/alert) }) client.on(message, (topic, payload) { const json JSON.parse(payload) this.setData({ heartRate: json.hr, spo2: json.spo2, temp: json.temp, hum: json.hum, gas: json.gas, sos: json.sos, online: true }) }) } })页面布局上首页是实时数据卡片温度、湿度、心率、血氧每项一张卡片数据异常时卡片边框变红。卡片下面放一个人体红外状态指示检测到有人在就显示正常长时间没人就提示可能外出或异常。历史曲线用canvas画线我用的是简单的折线没有引图表库因为每5秒一条数据30分钟也就360个点canvas原生的绘图能力足够。4.3 自定义导航栏与网络状态处理的坑微信小程序的顶部导航栏高度问题是很多新手会卡住的地方。小程序自定义导航栏的时候状态栏高度必须用wx.getSystemInfoSync()获取然后根据机型的statusBarHeight动态调整标题栏高度不能在wxml里写死。我的做法是在app.js里封装一个方法返回statusBarHeight和菜单按钮的位置各页面onLoad的时候统一设置顶部padding。网络状态处理也是实际使用中的重点。老年人家里的WiFi可能有波动设备端离线了但小程序端还在等数据页面就一片空白。我加了一个全局的监听wx.onNetworkStatusChange(res { if (!res.isConnected) { wx.showToast({ title: 网络不可用请检查网络, icon: none, duration: 3000 }) } })同时在首页加了在线状态标记设备端超过20秒没有上报数据就自动显示离线状态区分是设备掉线还是网络断连。实际用下来这条提示语对远程监护的帮助很大防止监护人误以为数据正常而放松警惕。小程序从开发到上线有几个配置项很容易被忽略。一个是服务器域名配置在mp.weixin.qq.com后台的开发管理-服务器域名里把wss://broker.emqx.io加入socket合法域名否则真机预览直接连接失败。另一个是小程序不是个人主体时可能涉及类目审核个人开发者如果只是自己家里人用开发阶段扫码预览体验就够了。5. 常见问题与排查技巧实录5.1 硬件与通信问题速查做这个项目期间遇到的典型问题不少我整理成了一个速查表基本覆盖了从硬件到平台层面的高频坑现象可能原因解决办法下载程序时报 no stm32 target foundSTM32的Debug Authentication被使能用STM32CubeProgrammer的Reset Option Bytes恢复或者按住复位引脚再点击下载串口1下载后看不到打印信息波特率不匹配确认串口调试助手波特率和代码配置一致一般用115200或9600ESP8266发AT没反映波特率错误或模块损坏逐个尝试74880、115200、9600确认模块VCC和GND正常DHT11一直读全零启动时序不对或上拉电阻缺失增加18ms以上起始低电平DATA引脚加10k上拉MAX30102读不到设备IDI2C地址错误或总线被拉低确认设备地址是0x57检查SCL/SDA上拉电阻ESP8266连接WiFi失败WiFi密码错误或2.4G信道干扰用ATCWJAP重新配置确认路由器开启2.4G频段小程序真机预览连不上服务器socket合法域名未配置后台配置wss://broker.emqx.io重新编译这里重点说一下no stm32 target found这个问题。我遇到这报错是在一次断电重启之后ST-Link突然连不上芯片控制台一直提示error: no stm32 target found! if your product embeds debug authentication。原因是烧录器第一次连接时芯片的调试口因为上一次烧录的代码配置被锁住或者进入了异常状态。解决办法是拔掉STM32的供电按住复位键不放点击下载按钮后再松开复位键多试一两次就能连上。更彻底的办法是用STM32CubeProgrammer连接MCU在Option Bytes页面把Debug Authentication的配置恢复默认值。这个问题在新手期特别容易把人吓住其实不是芯片坏了只是调试口状态被改了。电脑端装了驱动但设备管理器里stm32 virtual com port还是黄色叹号也是常见问题。这种情况通常是USB驱动版本不对或者电脑上装过多个版本的ST-Link驱动产生冲突。卸载掉所有STLink驱动重新装STSW-LINK009这个官方驱动基本能解决。5.2 软件与平台问题速查小程序端的问题往往比硬件端更隐蔽。我遇到过几次比较典型的坑都和自己写的代码关系不大而是平台机制导致的。开发工具真机预览时发现WebSocket连接不了EMQX服务器排查后发现是wss端口配置问题。EMQX公共服务器的WebSocket端口是8084走的是wss加密连接不能写成ws://否则真机环境下会被微信强制拦截。这个问题开发者工具上不暴露真机上才出现容易误判成网络问题。开发阶段用内网穿透或者直接扫码预览时要注意使用的工具本身是否满足要求比如hbuilder提示不是开发者之类的问题实际上是你扫码的微信号没有在开发者管理中添加为项目成员去mp后台加一下就行。另外一个反复出现的问题是设备端数据已经推送成功但是小程序端收不到。我用第三方MQTT调试工具先订阅了同一主题发现设备数据确实到达了服务器问题锁定在小程序端订阅连接上。最后发现是小程序端的mqtt.js库版本差异新版库对clientId的格式有要求不能包含非法字符。改成clientId: mini- Date.now()之后连接就稳定了。小程序端的调试也有几个技巧。真机上如果怀疑网络数据有问题可以直接用微信开发者工具自带的抓包功能在Network面板查看WebSocket帧的内容不用额外装抓包软件。我用这个方法定位过一次设备端JSON格式错误的问题比打印日志直观很多。提示MQTT公共服务器开发没问题但要长期给家人用建议还是用自己部署的服务。不然公共服务器一旦维护或者限制连接数整个监护系统就会处于不可用状态这是远程监护场景不能接受的。写在最后这套系统做下来我最大的体会是它真正的难度不在STM32本身而在传感器数据稳定性和小程序联调这两个环节。STM32端只要按部就班配置外设出问题的概率不大但传感器和通信链路需要反复验证和调试尤其是数据采集的时序、通信的协议、异常的重连机制这些设计细节才是真正决定系统好不好用的地方。最后分享一个小技巧在STM32CubeMX里生成初始化代码时把串口2的中断优先级设置成略高于心率采集的定时器中断。否则ESP8266返回的数据量大的时候串口中断会频繁抢占CPU导致MAX30102的数据采集时序被打破心率波形会周期性丢失。这个优先级问题不调系统的稳定性会有明显差距。本文还有配套的精品资源点击获取