厨房安全这个题目,几乎是每年嵌入式毕业设计和电子竞赛里最稳的选择之一。原因很简单:它同时踩中了三个加分点——传感器采集、物联网通信、上位机/小程序展示,硬件部分还要画一块 PCB,整个流程一跑通,就是一个完整的“端-云-端”产品雏形。
但这恰恰也是大多数同学最容易卡住的地方。单片机能点灯,传感器能读数据,可一旦要跟云平台通信,就开始连环踩坑:ESP01S 发不出 TCP 请求、OneNET 上的 APIKey 不知道去哪里生成、连上了又掉线、小程序端拿不到数据……最后明明功能都做了,却浪费了最多时间在联调上。
这篇文章不讲虚的,直接给你一套从硬件选型、PCB 设计、STM32 代码、ESP01S 联网、OneNET 云端配置到小程序显示的完整思路。同时会把我在这个项目里见过的高频问题,比如“no stm32 target found!”“ESP8266 连接 OneNET 失败”“CH340 串口驱动”等,集中放到最后逐一排查。无论你是做毕业设计、参加电子设计大赛,还是想把这个项目写进求职简历,这条链路都值得完整走一遍。
1. 这篇文章真正要解决的问题
1.1 多数厨房安全项目,不是死在功能上,而是死在链路上
很多同学做厨房安全监测系统时,会陷入一个误区:以为核心难点是“采集传感器数据”。实际上,DS18B20 测温、MQ-2 烟雾检测、火焰传感器这些模块,随便一个单片机教程都有现成例程。真正拉开差距的,是从“本地采集”到“远程报警”的物联网链路。
这个链路包括:
- STM32 如何读取各类传感器数据。
- STM32 如何通过串口控制 ESP01S。
- ESP01S 如何通过 AT 指令连接 OneNET 云平台。
- 云平台如何创建设备、生成 APIKey、接收数据。
- 小程序/APP 如何从云平台拉取数据,并推送报警消息。
其中任何一环断了,项目都算不上完整。很多人的项目做了一半就卡在“ESP01S 连不上 OneNET”或者“小程序请求不到数据”,不是因为代码难,而是因为对协议、云平台机制和调试手段缺乏整体认识。
1.2 这套项目为什么值得做
从学习价值看,这个项目覆盖了嵌入式开发的经典技能点:STM32 标准库/ HAL 库编程、ADC 采样、串口 DMA、AT 指令解析、MQTT/TCP 数据上报、JSON 数据格式、微信小程序网络请求、PCB 设计基础。做完一遍,相当于把整个物联网应用从底层到顶层都看了一遍。
从实用价值看,厨房安全监测的现实需求非常明确:燃气泄漏、烟雾、高温、火焰,每一项都关系到家庭安全。如果把传感器换成工业级、通信换成 4G/NB-IoT,整个方案可以直接往产品方向迭代,这也是很多公司招聘物联网岗位时看重的项目类型。
1.3 本文读者范围
最适合读这篇文章的是这三类人:
- 正在做毕业设计、需要快速跑通项目的本科生。
- 参加电子设计大赛、需要一套稳定可靠方案的学生。
- 想从单片机开发转向物联网开发、需要在简历里放一个完整项目的工程师。
如果你已经能熟练点灯、调串口,这篇文章可以帮你把眼界从“芯片裸机”拉高到“系统链路”。
2. 系统整体架构与工作原理
2.1 系统数据链路
我把这套厨房安全监测系统抽象成四层结构:
| 层级 | 组成 | 作用 |
|---|---|---|
| 感知层 | 烟雾传感器、可燃气体传感器、火焰传感器、温度传感器 | 采集厨房环境模拟量/开关量,交给主控处理 |
| 控制与网络层 | STM32F103C8T6 主控 + ESP01S WiFi 模块 | 处理数据、通过串口 AT 指令联网,连接 OneNET |
| 平台层 | OneNET 云平台 | 创建设备、接收上行数据、开放 API 接口 |
| 应用层 | 微信小程序 / Android APP | 实时展示数据、远程报警、历史记录 |
数据流动方向如下:
传感器 → STM32 ADC/GPIO 采集 → 本地 LCD/蜂鸣器报警 ↓ ESP01S(AT指令) ↓ OneNET 云平台 ↓ 微信小程序 / APP 展示从“本地点灯”到“远程报警”,中间最关键的转换是:STM32 把传感器数据打包成字符串或 JSON,然后通过串口发给 ESP01S,ESP01S 通过 WiFi 网络用 TCP/MQTT 协议上传到 OneNET。云平台把数据存入后,小程序再通过 OneNET 开放的 HTTP API 把数据拉下来渲染。
2.2 核心选型判断
关于主控,选择 STM32F103C8T6 而不是更便宜的 51 单片机,原因是它具备:
- 足够的 Flash(64KB)和 RAM(20KB),可以承载多传感器逻辑和协议解析。
- 多路 ADC 通道,可同时采集烟雾、燃气、火焰等模拟量。
- 多个 USART,一路接 ESP01S,一路预留调试串口。
- STM32 生态资料丰富,无论是标准库还是 HAL 库,遇到问题都好查。
关于 WiFi 模块,选择 ESP01S 是因为它内置 ESP8266 芯片,出厂自带 AT 固件,STM32 只需要用串口发 AT 指令即可控制。相比直接用 ESP8266 裸片开发,ESP01S 省去了重新烧录固件的步骤,更适合课程设计和毕业设计。
关于云平台,选择 OneNET 是因为它对中文开发者友好,设备接入门槛低,API 文档完善,支持 TCP、HTTP、MQTT 等多种协议,而且有一个明显的优势:可以创建免费项目用于学习和毕设演示。不过要注意,OneNET 平台策略和界面经常调整,接入参数要以控制台实际显示为准。
关于应用端,微信小程序比独立 APP 更合适。原因在于:小程序不需要安装、调试方便、能直接调用wx.request请求接口,对前后端分离的毕业设计展示非常友好。
3. 硬件方案与核心元器件选型
3.1 主控最小系统
STM32F103C8T6 最小系统包含:
- 8MHz 晶振,配合两个 20pF 左右的负载电容。
- 复位电路,常用 10kΩ 上拉电阻加 100nF 电容。
- 3.3V 供电,注意纹波控制。
- BOOT0/BOOT1 跳线,用于串口下载和正常启动模式切换。
- SWD 调试接口,连接 ST-Link。
晶振电容的取值不一定要死记公式,实际项目里常用的组合是 8MHz 晶振配 2 个 20pF 电容。如果系统时间基准偏差不大,就说明匹配正确;如果串口通信出现不可解释的乱码,可以优先检查晶振是否起振、电容是否焊接正确。
3.2 传感器模块选择
| 传感器 | 类型 | 输出方式 | 使用说明 |
|---|---|---|---|
| MQ-2 烟雾传感器 | 模拟量 | ADC | 上电预热几分钟后再采样,数据更稳定 |
| MQ-5 / MQ-4 可燃气体传感器 | 模拟量 | ADC | 检测天然气/液化气,注意需校准阈值 |
| 火焰传感器 | 红外敏感 | ADC/数字量 | 检测火焰光谱,避免日光直射误报 |
| DS18B20 温度传感器 | 数字量 | 单总线 | 测量厨房温度,注意总线时序 |
需要注意一个通用问题:MQ 系列传感器内部是加热电阻,工作时电流较大、发热明显,功耗不低。如果用电池供电,要慎重考虑电源设计。另外,这类传感器的“绝对浓度值”意义不大,实际项目里更常用的是“相对变化量 + 阈值报警”。
3.3 ESP01S WiFi 模块接线
ESP01S 是 8 脚模块,引脚定义要记住几个关键的:
| ESP01S 引脚 | 作用 | 接法 |
|---|---|---|
| VCC | 3.3V 电源 | 注意电流要足够,建议单独供电 |
| GND | 地 | 与 STM32 共地 |
| TX | 串口发送 | 接 STM32 的 RX(PA3 或配置的串口接收脚) |
| RX | 串口接收 | 接 STM32 的 TX(PA2 或配置的串口发送脚) |
| CH_PD(EN) | 使能脚 | 必须拉高,否则模块不工作 |
| GPIO0 | 模式选择 | 正常运行悬空或拉高,烧录固件时拉低 |
这里有一个高频翻车点:ESP01S 的供电电流峰值可能达到几百毫安,如果直接从 STM32 开发板的 3.3V LDO 取电,WiFi 发射瞬间可能导致电压跌落,进而造成模块重启或 STM32 复位。稳妥做法是使用独立的 3.3V 稳压芯片(如 AMS1117-3.3)或专门的 ESP01S 供电底座。
3.4 报警与显示电路
报警部分可用蜂鸣器加 LED。蜂鸣器建议使用有源蜂鸣器,单片机给高电平/低电平就能驱动,不需要额外写 PWM 频率。如果需要“火警优先级”,可以用不同报警节奏表达。
显示部分可以选 OLED 或 LCD1602。OLED(I2C 接口)连线少、显示效果好,更适合毕业设计答辩展示;LCD1602 并行接线多但更传统。如果想省事,直接用 0.96 寸 OLED 即可。
4. PCB 设计要点
4.1 用嘉立创 EDA 还是一键打样?
对于这个项目,我建议使用嘉立创 EDA 专业版画原理图和 PCB,理由有三:
- 元件库丰富,ESP01S、STM32F103C8T6、AMS1117 等常用封装可以直接调用。
- 在线协作方便,导出 Gerber/BOM 都比较容易。
- 国产工具教程多,遇到软件操作问题搜索成本低。
画图流程是:先画原理图,确认网络连接无误,再转入 PCB 编辑器。如果是从头画,建议先不做六层板、四层板这种复杂层叠,用双面板就可以了。双面板的“层叠厚度”常规是 1.6mm,铜厚 1oz,完全满足本项目的信号和电源需求。
4.2 布局与布线规则
PCB 设计是这个项目里最容易“看起来不专业”的环节,也是答辩评委最爱问的部分。下面几条规则是基础中的基础:
- 先按功能分区布局:电源区、主控区、传感器接口区、通信模块区。
- 晶振要靠近 STM32 的 OSC_IN/OSC_OUT 引脚,走线尽量短,周围不要走高速数字线。
- 电源线加宽,至少 20mil 以上;GND 尽量铺铜,减少回路阻抗。
- ESP01S 模块下方尽量挖空铜皮,减少天线区域的信号干扰。
- 传感器接口用排针或接线端子引出,方便拆换模块。
- 丝印字号不要小于软件默认下限,否则打样回来容易“丝印模糊”、看不清标注。
- 按键、排针、微调电阻等器件要放在板边方便操作的位置。
布局布线完成之后,一定要做 DRC(设计规则检查)。很多同学在画完 PCB 后直接下单打样,结果板子回来短路、断线,低级的 DRC 错误就能把项目拖慢两周。
4.3 从 PCB 到 Gerber 文件
打样需要提交 Gerber 文件。在嘉立创 EDA 中可以直接“导出 Gerber”,会生成一堆文件,包括顶层线路、底层线路、顶层丝印、阻焊层、钻孔文件等。下单时压缩成 zip 上传即可。
还需要提一点:很多板厂支持在线预览 Gerber,下单前务必确认预览图和自己在软件里看到的 PCB 一致,特别是孔的位置和数量。
关于“Gerber 文件转成 PCB 文件”,这个操作其实不常用。Gerber 是制造文件,不是可编辑工程文件。如果你拿到的是一个 Gerber 包,想改成自己的设计,一般不能用它还原成 PCB 源文件,只能重新画。所以如果你准备在开源社区找一个现成 PCB 工程,一定要下载的是 EDA 源工程文件,而不是 Gerber。
5. 开发环境搭建
5.1 软件工具链
这个项目主要需要以下软件:
| 工具 | 作用 |
|---|---|
| Keil MDK 5 | 编写、编译、调试 STM32 工程 |
| STM32F1xx 芯片包 | Keil 中识别 STM32F103C8T6 |
| ST-Link 驱动 | 连接 ST-Link 调试器 |
| CH340 驱动 | 使用 USB 转串口模块看日志 |
| 串口助手 | 调试 AT 指令和查看传感器数据 |
| 微信开发者工具 | 编写和调试小程序 |
Keil 5 在安装时需要注意兼容 C51 和 STM32 的问题:Keil 5 本身通过 Pack 安装器支持多家芯片,默认情况下可以同时安装 C51 和 ARM 两种编译器支持。如果你之前装过 C51 版,再装 MDK 版时注意统一安装目录结构,避免两个版本互相覆盖。更稳妥的做法是分开安装,或者用“Keil 5 兼容 C51 和 STM32”这种一键整合包,但前提是来源可靠。
5.2 STM32 工程创建
推荐用标准库创建工程,因为网上案例最多,适合快速移植。工程结构大致如下:
Project/ ├── Libraries/ │ ├── CMSIS/ │ └── STM32F10x_StdPeriph_Driver/ ├── User/ │ ├── main.c │ ├── stm32f10x_it.c │ └── system_stm32f10x.c ├── Hardware/ │ ├── sensor.c │ ├── sensor.h │ ├── esp01s.c │ └── esp01s.h └── Project.uvprojx在 Keil 中新建工程时,选择芯片型号 STM32F103C8,然后在 Manage Run-Time Environment 里勾选标准外设库必要的组件。如果嫌麻烦,可以直接找一个“STM32F103C8T6 标准库模板”修改,这是最省时间的路径。
5.3 ST-Link 调试配置
STM32 下载调试最常用的工具是 ST-Link。在 Keil 中配置方式如下:
- 点击魔法棒(Options for Target)。
- 选择 Debug 标签页,右侧下拉框选择 ST-Link Debugger。
- 点击 Settings,确认能识别到设备。
- 如果 Debug 信息显示 “no stm32 target found! if your product embeds debug authentication, please...”,多半是连接问题。
常见原因如下:
- 接线错误:SWDIO、SWCLK、GND 要一一对应。
- 目标板未供电:ST-Link 不一定能提供足够电流。
- BOOT0 引脚状态异常。
- 芯片锁死或进入低功耗模式。
- 复位电路设计不当,导致调试器无法正确复位芯片。
排查时可以先断开 ST-Link,重新插拔 USB,再按住复位键尝试连接。如果还是不行,用 ST-Link Utility 连接,必要时执行 “connect under reset” 模式下载。
5.4 串口驱动与虚拟串口问题
很多同学的板载串口芯片是 CH340。如果电脑设备管理器里看到“USB-SERIAL CH340”旁边有黄色感叹号,说明驱动没装好,或者被其他驱动占用了 PID/VID。解决办法是卸载设备后重新安装官方驱动,特别要注意 Windows 的驱动签名机制。
还有一类情况是 STM32 的 USB 虚拟串口(VCP)出现感叹号。这是因为 ST 的 VCP 驱动和系统不兼容,或者设备描述符未被正确识别。这个项目里如果只是调试,建议直接用 CH340 外接串口,不要依赖 STM32 内部 USB 虚拟串口。
5.5 OneNET 账号与设备准备
在开始写代码之前,先在 OneNET 控制台注册账号,然后创建产品、添加设备。
一般步骤是:
- 登录 OneNET 控制台。
- 选择“多协议接入”或“设备接入”,创建产品。
- 产品类型选择适合 Wi-Fi 设备的协议,例如 MQTT 或 HTTP/TCP。
- 添加设备,记录设备 ID(device_id)、APIKey 和鉴权信息。
- 生成或查看 APIKey,后面小程序端拉取数据时要使用。
需要注意:OneNET 的界面改版比较频繁,“APIKey 在哪里生成”在不同时期可能位置不同。更稳妥的做法是到 OneNET 官方文档中心查找当前版本的操作路径。本文后续示例会以通用的接入参数为准,你实际使用时把 IP、端口、设备 ID、APIKey 替换成自己控制台里的值即可。
6. STM32 端代码实现
6.1 传感器数据采集
这里以 MQ-2 烟雾传感器为例。它输出的是模拟电压,接在 STM32 的 ADC 引脚(例如 PA1)上。使用标准库的 ADC 采集,核心代码如下:
// 文件路径:Hardware/sensor.c #include "sensor.h" #include "adc.h" uint16_t ADC_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); } float Get_SmokeVoltage(void) { uint16_t adc_val = 0; float voltage = 0.0f; adc_val = ADC_GetValue(); voltage = (float)adc_val * 3.3f / 4096.0f; return voltage; }代码说明:STM32F103 的 ADC 是 12 位,所以满量程值是 4096。用 ADC 采样值除以 4096,再乘以参考电压 3.3V,就能得到传感器的输出电压。阈值报警则是在业务逻辑里比较voltage和阈值。
建议对 ADC 做多次采样取平均,例如连续采 10 次再去掉最大最小值求平均,能明显减少波动。
6.2 串口初始化与 ESP01S 通信
STM32 与 ESP01S 通信使用 USART。下面给出一个使用标准库的串口初始化示例:
// 文件路径:Hardware/esp01s.c #include "esp01s.h" #include "stm32f10x.h" void ESP01S_UART_Init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // TX: PA9, RX: PA10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); }串口初始化后,向 ESP01S 发送 AT 指令很简单:
void ESP01S_SendCmd(char *cmd) { while (*cmd) { USART_SendData(USART1, *cmd++); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } }发送 AT 指令时,记得加上回车换行\r\n。例如:
ESP01S_SendCmd("AT\r\n");一般建议在发送每条 AT 指令后,用延时等待响应。从实际项目经验看,ESP01S 在重新连接 WiFi 时响应较慢,如果延时不充分,容易出现“指令发送了但没收到返回”的假象。
6.3 打包数据并上传
传感器数据采集到后,需要拼成云端能识别的格式。这里以“JSON 数据上报”为例,把数据放到一个字符数组里:
// 文件路径:User/main.c(节选) #include <stdio.h> #include <string.h> char data_buf[128]; void Build_And_Upload(void) { float smoke_voltage = Get_SmokeVoltage(); float temperature = Get_Temperature(); // 来自 DS18B20,省略具体读取逻辑 uint8_t flame = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0); // 火焰传感器 memset(data_buf, 0, sizeof(data_buf)); sprintf(data_buf, "{\"smoke\":%.2f,\"temp\":%.2f,\"flame\":%d}", smoke_voltage, temperature, flame); // 将 data_buf 通过 ESP01S 发送到 OneNET ESP01S_SendData(data_buf); }这里注意:不同云平台的上行数据格式不同。OneNET 老版 MQTT 或 HTTP 设备通常要求按平台规定的数据流格式上报;新版设备可能直接支持 JSON。实际开发时,先查阅你的设备接入文档,确认数据格式再决定如何拼包。
7. ESP01S 与 OneNET 云平台通信
7.1 先跑通 ESP01S 基础指令
拿到 ESP01S 之后,不要把 STM32 直接接上去,先用 USB 转 TTL 模块在电脑串口助手里调通 AT 指令。这样可以快速排除“模块坏没坏”“波特率对不对”的问题。
ESP01S 出厂固件默认波特率常见是 115200。基础指令一般如下:
AT # 测试模块是否正常,返回 OK AT+CWMODE=1 # 设置为 Station 模式 AT+CWJAP="你的WiFi名","你的WiFi密码" # 连接路由器 AT+CIFSR # 查询 IP,确认已经拿到局域网地址如果发送 AT 后模块无响应,常见原因是:
- 串口波特率不匹配。
- TX/RX 接反。
- CH_PD 没有拉高。
- 供电不足。
建议按这个顺序检查。
7.2 建立 TCP 连接与数据上报
OneNET 老版的多协议接入里,不少设备是通过 TCP 透传方式上传数据。基本流程是:
- 用
AT+CIPSTART建立 TCP 连接。 - 用
AT+CIPSEND进入透传模式。 - 发送数据。
- 发送
+++退出透传。
AT 指令示例:
AT+CIPSTART="TCP","183.230.40.40",1811 AT+CIPSEND需要注意:OneNET 服务器地址和端口以你在控制台创建的“多协议接入”产品文档为准。我在这里不写死所有 IP,避免平台调整后误导你。替换为“OneNET 文档给出的接入地址”即可。
很多同学卡在这里,通常会遇到:
- TCP 连接成功后立刻断开,原因是 OneNET 要求先发送注册包或鉴权包。
- 发送数据后平台上没数据,原因是 JSON 格式、数据流名称不匹配。
- 重连太慢,原因是心跳间隔不合理。
这里强调一个核心概念:设备和云平台之间不是“把数据发出去就完了”,还需要按平台规则完成鉴权、心跳保活和数据流映射。如果你想减少协议适配成本,可以考虑用 OneNET 的 MQTT 对接。MQTT 有 PUBLISH 和心跳机制,比裸 TCP 更稳定。但代价是要在 STM32 端实现 MQTT 报文解析,对工程能力要求更高。对新手而言,用 AT 指令走 TCP 透传,先把“数据能到平台”跑通,再考虑升级到 MQTT,是比较合理的路径。
7.3 为什么 ESP8266 连接 OneNET 经常失败
从大量反馈来看,“ESP8266/ESP01S 连接 OneNET 失败”的最常见原因有四个:
| 原因 | 表现 | 解决思路 |
|---|---|---|
| 鉴权信息错误 | 报错或连接后无数据 | 检查设备 ID、APIKey、鉴权信息是否复制完整,注意隐藏字符 |
| 接入协议不匹配 | TCP 连上但服务端断开 | 确认你创建产品时选的协议是 TCP 还是 MQTT,并下载对应接入文档 |
| 数据格式不符合平台要求 | 平台在线但无数据流 | 对照文档确认 JSON/二进制格式、数据流名称 |
| 网络或供电不稳 | 模块反复重启 | 单独供电,检查 WiFi 信号强度,不要用长杜邦线连接天线区域 |
如果你使用的是“ESP8266 通过 MQTT 协议连接 OneNET”的方式,还要特别注意用户名和密码分别对应设备的鉴权信息,而不是 WiFi 的账号密码。这是新手最容易混淆的地方。
8. 微信小程序 / APP 实时监测端
8.1 为什么推荐小程序
这个项目的展示端,我优先推荐微信小程序。它对前端基础要求不高,一个简单的wx.request就能完成 HTTP 请求,再加上setInterval定时刷新,页面就能“实时”更新数据。缺点是微信开发者工具调试时对 HTTPS 域名有要求,但本地开发可以勾选“不校验合法域名”来绕过,仅限开发调试用。
8.2 小程序请求 OneNET 数据示例
小程序端的主要逻辑是:通过 OneNET 提供的 API 获取设备最新数据流,再把数据渲染到页面。
// 文件路径:pages/index/index.js Page({ data: { smoke: '--', temp: '--', flame: '--' }, onLoad() { this.getDeviceData(); // 每 5 秒刷新一次数据 this.timer = setInterval(() => { this.getDeviceData(); }, 5000); }, onUnload() { clearInterval(this.timer); }, getDeviceData() { const apiUrl = 'https://your-onenet-api-url'; const headers = { 'api-key': '你的APIKey' }; wx.request({ url: apiUrl, method: 'GET', header: headers, success: (res) => { if (res.statusCode === 200) { const data = res.data; this.setData({ smoke: data.smoke, temp: data.temp, flame: data.flame }); } else { console.error('请求失败', res.statusCode); } }, fail: (err) => { console.error('网络异常', err); } }); } });这个示例里,apiUrl和headers需要根据你实际的 OneNET API 地址和密钥替换。不能直接把代码里的占位字符串用于生产环境。
8.3 APP 端思路
如果你不想做小程序,也可以用 Android 原生或 Flutter 写一个简易 APP。基本逻辑完全一样:
- 用 OkHttp / Dio 请求 OneNET API。
- 解析 JSON 后刷新 UI。
- 通过推送或轮询实现报警通知。
APP 的优点是界面自由度更高,可以做更复杂的图表;缺点是开发周期比小程序长。对大多数毕设和竞赛来说,小程序已经足够撑起“应用层”这个环节。
9. 运行结果与效果验证
9.1 联调顺序建议
不要一上来就把所有模块都接通,分步验证会节省大量时间:
- 先给 STM32 烧录一个“ADC 采集 + 串口打印”的程序,确认传感器数据稳定。
- 用电脑串口助手单独测试 ESP01S,确认 AT 指令和 WiFi 连接正常。
- 用 ESP01S 在电脑上连接 OneNET,确认 TCP 连接和数据上报格式正确。
- 再把 ESP01S 接到 STM32,复用同一套 AT 指令流程,完成自动化上报。
- 最后开发小程序,调 API 拉取数据。
9.2 预期现象
当系统正常工作时,你会在串口助手里看到类似下面的周期性输出:
smoke:0.35V temp:26.5C flame:0 AT+CIPSTART OK send data okOneNET 控制台的设备列表中,设备状态为“在线”,数据流中可以看到最新上报的数值。小程序端则能看到烟雾、温度、火焰状态的实时刷新。
如果设备显示“在线”,但没有数据流,优先检查数据上报格式。如果设备显示“离线”,优先检查心跳和 TCP 连接保活。
9.3 报警逻辑验证
触发报警的方式很简单:把烟雾传感器放在燃烧的蜡烛附近,或者用打火机短暂靠近(注意安全),观察阈值比较后是否触发蜂鸣器和云端报警。如果是真实燃气场景,不要用明火测试,建议用烟气替代。
10. 常见问题与排查思路
10.1 调试下载类
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Keil 提示 no stm32 target found | SWD 接线错误、目标板没电、芯片锁死 | 检查 ST-Link 接线,确认目标板供电,查看 ST-Link Utility 是否能识别 | 重新接线,单独给目标板供电;必要时用 ST-Link Utility 执行 connect under reset |
| STM32 virtual com port 黄色感叹号 | VCP 驱动异常或被占用 | 查看设备管理器,更新驱动 | 卸载设备重启后重装驱动;改用 CH340 调试 |
| Keil 编译正常但下载失败 | 芯片型号选择错误 | 检查工程 Target 芯片型号 | 确认选择 STM32F103C8 |
| 程序跑起来但串口乱码 | 波特率不匹配、晶振频率不对 | 检查串口助手和代码波特率 | 保持双方波特率一致,检查晶振配置 |
| 串口发送 AT 无反应 | TX/RX 接反、CH_PD 未拉高、供电不足 | 测试模块单独供电 | 用独立 3.3V 电源,检查接线 |
10.2 通信与云平台类
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| ESP8266 连接 OneNET 失败 | 鉴权信息填错、协议不匹配 | 对照控制台的设备 ID、APIKey 和接入文档逐项检查 | 复制时去掉空格和隐藏字符,重新创建设备 |
| 设备在线但无数据流 | 数据包格式不符合平台定义 | 使用串口打印实际发送的字符串,与平台文档对比 | 修正 JSON 字段名或数据流名称 |
| 数据上报后小程序拿不到 | API URL 或 APIKey 错误、小程序校验域名 | 先用浏览器或 Postman 请求一次 | 确保请求头正确;开发时开启不校验合法域名 |
| 连接一段时间后断开 | 心跳包未发送 | 抓取串口日志,观察断开时间点 | 定时发送心跳或重连指令 |
10.3 ESP01S 相关细节
还有一个很多人会忽略的问题:ESP01S 串口打印了很多ready或乱码,但 AT 指令仍然可用。这是正常的,ESP01S 上电时有可能输出一些启动信息,不代表模块故障。
另外,GPIO0 在运行时不能接地,否则模块会进入烧录模式,AT 指令无法执行。这是一个非常隐蔽的问题,建议在焊接或插接 ESP01S 时用万用表确认 GPIO0 状态。
11. 最佳实践与工程建议
11.1 代码模块化
不要把所有逻辑都堆在 main.c 里。建议这样划分模块:
sensor.c —— 传感器采集 esp01s.c —— AT 指令封装 onenet.c —— 云端协议数据组装 alarm.c —— 蜂鸣器/LED 报警逻辑 usart.c —— 串口驱动AT 指令不要散落在业务代码里,封装成函数后,后续更换云平台只需要改 onenet.c。
11.2 阈值与标定
MQ-2 这类传感器受温度和湿度影响明显,直接用一个固定阈值容易误报。更好做法是在系统开机时读取一定时间的基线电压,然后根据基线动态设置报警阈值。这个设计在答辩时也很加分,因为体现了“工程思维”。
11.3 安全与合规提醒
这是重要的一条。如果你数据来自燃气探测器或烟雾探测器,请一定在文档和演示中明确说明:本项目的传感器和电路仅用于学习和原型验证,不能作为正式家庭安全设备使用。真正的工业级厨房燃气报警,需要通过消防认证、可靠性测试和定期校准。不要在演示中使用真实燃气进行危险操作。
11.4 生产环境要考虑的坑
如果后续你想把它做成一个可交付的 Demo 或小批量产品,建议提前考虑:
- 低功耗休眠与 WiFi 唤醒。
- 定时器和看门狗,防止程序跑飞。
- Flash 掉电保存阈值配置。
- 外壳、三防漆、传感器防油污设计。
- 掉线自动重连与数据补传机制。
这些点单个看起来不难,但真正能体现你“有工程意识”。
11.5 国产替代与平台适配
APM32、GD32 等国产芯片在指令和引脚上兼容 STM32,很多工程可以直接移植。如果你在竞赛中遇到芯片缺货,可以尝试把项目切换到这些兼容芯片。但要注意,不同厂商的时钟树和外设库细节有差异,不能保证“直接改名就行”,还是需要逐个外设验证。在简历和答辩中,写出“使用 STM32,并验证了同系列国产兼容方案”会是一个加分项。
12. 总结与后续学习方向
到这里,一条从传感器采集到小程序展示的厨房安全监测链路已经完整梳理出来。核心要点是:不要把注意力只放在“读传感器”上,真正的难点和亮点在于 STM32 与 ESP01S 的串口指令交互、OneNET 云平台的接入配置,以及小程序端的数据请求与展示。把这三段跑通,你的项目就能形成完整的物联网闭环。
做完这个项目后,有几个方向可以继续深入:
- 把 ESP01S 换成 4G 模块(例如合宙 Air724 系列),熟悉 AT 指令和 MQTT 协议,应用场景会从 WiFi 环境拓展到移动网络。
- 把数据存储放到时序数据库,实现历史曲线和统计报表。
- 接入更多传感器,比如湿度、PM2.5、人体红外,做成一套“智慧厨房”整体方案。
- 用 RT-Thread 或 FreeRTOS 把任务调度起来,让系统具备更复杂的并发能力。
如果你正在准备毕业设计或竞赛,建议先把本文第 9 节的联调顺序走一遍,做一步验证一步,不要等到所有模块焊好才开始调。硬件项目里,最浪费时间的往往不是“功能没实现”,而是“不知道 bug 出在哪一层”。
这个项目不难,但它值得你认真把每一层都走通。等你完整调完一遍,回头看会发现,你已经悄悄掌握了物联网开发中最常用的一套链路。