1. 为什么选择ESP01S加STM32这套组合来做智能配网
1.1 从两个真实痛点说起
做过智能硬件项目的人大概都经历过这样的场景:板子焊好了,传感器跑通了,屏幕也能亮了,结果卡在最后一步——怎么让设备连上网络。用手机热点调试的时候一切正常,换个路由器就歇菜;实验室里跑得好好的,到了客户现场死活连不上。更头疼的是,产品要量产了,总不能每台设备都拿串口线接电脑手动改WiFi密码吧。
这就是配网要解决的问题。所谓配网,说白了就是让设备知道该连哪个WiFi、密码是多少,并且把这个信息安全地存下来,下次上电自动连上。听起来简单,但实际做起来坑不少。
我这次选的是机智云 + STM32 + ESP01S这套组合。STM32负责主控逻辑,ESP01S负责网络通信,机智云提供云端服务和手机APP。为什么这么选?ESP01S便宜,一颗不到十块钱,STM32大家手头都有,机智云对个人开发者免费,APP还能自动生成。这套方案特别适合做毕业设计、课程项目、小批量智能家居产品,成本低、上手快、资料多。
1.2 三种配网方式怎么选
市面上主流的配网方式有三种:AP热点配网、SmartConfig一键配网、蓝牙配网。我一开始也纠结过选哪个,后来把三种都试了一遍,说说实际感受。
AP热点配网是最稳的。ESP01S自己开一个热点,手机连上去,把WiFi信息通过TCP发过去,设备收到后切换到Station模式连路由器。缺点是用户要手动切换WiFi,体验稍微麻烦一点,但成功率接近百分之百。SmartConfig是手机APP把WiFi信息编码后通过UDP广播出去,ESP01S在混杂模式下抓包解析。这个方式用户体验最好,不用切WiFi,但成功率受路由器、手机、环境干扰影响很大,我实测大概七成左右。蓝牙配网需要ESP32或者额外的蓝牙模块,ESP01S没有蓝牙,直接排除。
最后我选了AP热点配网为主、SmartConfig为辅的方案。产品化的时候默认走AP,用户嫌麻烦可以试试一键配网。这篇文章重点讲AP配网,因为它最可靠,也最能讲清楚配网的底层逻辑。
1.3 整体架构长什么样
先把整个系统的数据流理清楚,后面写代码才不会乱。
STM32和ESP01S之间通过UART串口通信,波特率一般用115200。STM32发AT指令控制ESP01S,ESP01S把执行结果返回给STM32。ESP01S连上路由器后,通过MQTT协议和机智云服务器通信。手机APP也是通过机智云云平台和设备交互,不直接连设备。
数据流向是这样的:手机APP下发控制指令 → 机智云服务器 → ESP01S → 串口 → STM32解析执行 → 传感器数据回传 → ESP01S → 机智云 → 手机APP。
这里有个关键点:ESP01S烧录机智云的GAgent固件。GAgent是机智云提供的固件,跑在ESP01S上,负责处理MQTT连接、数据点解析、配网协议这些脏活累活。STM32只需要通过串口和GAgent通信,用一套简单的协议就能完成数据上报和指令接收。不用自己写MQTT协议栈,省了大力气。
注意:ESP01S有不同版本,建议买安信可原厂或者靠谱渠道的,Flash至少1MB。有些便宜货Flash只有512KB,烧不下GAgent固件。
2. 核心细节解析与实操要点
2.1 ESP01S的AT指令到底怎么用
ESP01S出厂自带AT固件,但我们要烧机智云的GAgent固件。烧录之前,先用AT指令确认模块是好的,这个步骤不能省。
接线很简单:ESP01S的VCC接3.3V,GND接GND,TX接STM32的RX,RX接STM32的TX。注意ESP01S是3.3V电平,千万别接5V,会烧。CH_PD要拉高,不然不工作。
上电后用串口助手发AT,正常返回OK。然后发AT+GMR看版本信息。如果返回一堆乱码,大概率是波特率不对,ESP01S默认波特率是115200,但有些批次是74880,试试看。
几个常用的AT指令先熟悉一下:
| 指令 | 作用 | 典型返回 |
|---|---|---|
| AT | 测试通信 | OK |
| AT+RST | 重启模块 | OK + 启动信息 |
| AT+CWMODE=1 | 设为Station模式 | OK |
| AT+CWMODE=2 | 设为AP模式 | OK |
| AT+CWMODE=3 | AP+Station共存 | OK |
| AT+CWLAP | 扫描附近WiFi | 列表 |
| AT+CWJAP="ssid","pwd" | 连接WiFi | OK |
| AT+CIPSTART | 建立TCP连接 | CONNECT |
| AT+CIPSEND | 发送数据 | > |
这些指令在调试阶段很有用,但烧了GAgent之后就不需要手动发了,GAgent会自动处理。不过理解这些指令对排查问题很有帮助,因为GAgent底层也是调这些。
2.2 GAgent固件的烧录与验证
GAgent固件从机智云官网下载,选ESP01S对应的版本。烧录工具用乐鑫官方的Flash下载工具,接线需要把GPIO0拉低进入下载模式,烧完再拉高重启。
烧录参数:地址0x00000,波特率选115200或者更高。烧录完成后,ESP01S重启,串口会打印一堆启动日志,看到GAgent字样就说明成功了。
这里有个坑:烧录时GPIO0和GPIO2的电平要正确。GPIO0拉低进下载模式,GPIO2要拉高,否则可能烧录失败或者启动异常。我第一次烧的时候没注意GPIO2,折腾了半天。
烧好之后,用串口助手发AT+GMR,如果返回的是GAgent的版本信息而不是AT固件的,就对了。GAgent启动后会尝试连接机智云服务器,如果还没配网,它会进入配网模式,串口会打印等待配网的提示。
2.3 STM32端的串口配置要点
STM32和ESP01S通信,串口配置有几个关键点。
波特率必须和GAgent一致,默认是9600。对,不是115200。GAgent默认串口波特率是9600,这个和AT固件不一样,很多人在这里翻车。如果你改了GAgent的波特率,STM32这边也要同步改。
串口要用中断接收,不能用轮询。因为GAgent会主动往STM32发数据,比如配网状态变化、云端下发的指令,轮询会丢数据。我用的是HAL库的HAL_UART_Receive_IT,配合一个环形缓冲区,收到数据先存起来,主循环里再解析。
数据帧格式:8位数据位,1位停止位,无校验。这个和GAgent默认一致,不用改。
还有一个细节:串口接收要处理粘包和断包。GAgent发过来的数据可能一次发完,也可能分几次发。我的做法是定义一个缓冲区,每次收到数据就追加,然后检查是否收到完整的帧。GAgent的协议帧有固定格式,帧头是0xFF 0xFF,后面跟长度和命令字,收到完整帧后再解析。
// 串口中断回调,把数据存入环形缓冲区 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { ring_buffer_write(rx_byte); HAL_UART_Receive_IT(&huart1, &rx_byte, 1); } }2.4 机智云数据点的定义逻辑
在机智云开发者中心创建产品后,要定义数据点。数据点就是设备能上报和接收的数据项,比如温度、湿度、开关状态。
定义数据点的时候要注意:数据类型和读写权限要匹配实际需求。比如温度是只读的,开关是可读可写的。数据点有布尔型、数值型、枚举型、扩展型几种,选错了后面APP上显示会不对。
我定义了几个典型数据点:一个布尔型的开关,一个数值型的温度,一个枚举型的工作模式。定义好之后,机智云会自动生成STM32端的协议代码,直接拿来用就行。
这里有个经验:数据点不要定义太多。每个数据点都会占用通信带宽和内存,而且APP上显示一堆没用的数据点很乱。只定义真正需要的,后面要加再改。
3. 实操过程与核心环节实现
3.1 硬件接线与供电检查
先把硬件接好。STM32最小系统板一块,ESP01S模块一个,USB转TTL一个(调试用),杜邦线若干。
接线方案:
- ESP01S VCC → STM32 3.3V
- ESP01S GND → STM32 GND
- ESP01S TX → STM32 PA10 (USART1_RX)
- ESP01S RX → STM32 PA9 (USART1_TX)
- ESP01S CH_PD → 3.3V(通过10K电阻上拉)
- ESP01S GPIO0 → 悬空或上拉(正常运行模式)
- ESP01S GPIO2 → 上拉
供电是重点。ESP01S在发射数据的时候瞬间电流能到300mA,STM32板子上的3.3V LDO如果功率不够,会导致ESP01S重启或者工作不稳定。我建议单独给ESP01S供电,用一个AMS1117-3.3或者专门的3.3V电源模块,和STM32共地就行。
我第一次做的时候就是直接从STM32板子上取电,结果ESP01S一发包就重启,查了半天才发现是供电不足。后来加了个100uF的电解电容在ESP01S的VCC和GND之间,情况好很多。
3.2 STM32端协议解析代码实现
机智云生成的协议代码里,核心是gizwits_protocol.c和gizwits_product.c。我们需要做的是把串口收到的数据喂给协议解析函数,然后把要上报的数据填到数据点结构体里。
主循环里这样处理:
while(1) { // 从环形缓冲区读取数据,喂给协议解析 while(ring_buffer_has_data()) { uint8_t byte = ring_buffer_read(); gizPutData(&byte, 1); } // 处理协议 gizwitsHandle(&gizwitsProtocol); // 定时上报数据 if(report_timer_expired()) { // 更新数据点 currentDataValue.temperature = read_temperature(); currentDataValue.switch_status = get_switch_state(); // 上报 gizwitsHandle(&gizwitsProtocol); } }gizPutData是协议库提供的函数,把串口字节喂进去,它会自动组帧解析。解析到云端下发的控制指令时,会回调gizwitsEventProcess函数,我们在里面处理具体的控制逻辑。
void gizwitsEventProcess(eventInfo_t *info, uint8_t *data, uint32_t len) { if(info->event == EVENT_SWITCH) { if(data[0] == 1) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); } } }3.3 配网流程的完整实现
配网是整个项目最核心的部分。AP配网的流程是这样的:
第一步,设备上电,GAgent检查是否已经配过网。如果Flash里存了WiFi信息,直接尝试连接。如果没配过或者连接失败,进入AP模式。
第二步,ESP01S开一个热点,热点名字一般是XPG-GAgent-XXXX,XXXX是MAC地址后四位。手机连上这个热点。
第三步,打开机智云APP,APP会自动发现设备,弹出配网页面。用户在APP里输入家里的WiFi名称和密码,点击确认。
第四步,APP把WiFi信息通过TCP发给ESP01S。ESP01S收到后,切换到Station模式,用收到的信息连接路由器。
第五步,连接成功后,ESP01S通过串口通知STM32配网成功,STM32点亮一个LED或者做其他提示。同时ESP01S连接机智云服务器,设备上线。
整个流程中,STM32其实不需要做太多事情,主要是监听串口的状态通知。GAgent会通过串口发送配网状态变化的事件,STM32解析后做相应的UI提示。
这里有个细节:配网超时处理。如果用户连上了ESP01S的热点但一直不输入WiFi信息,ESP01S会一直等着。我的做法是设一个3分钟的超时,超时后重启ESP01S,重新进入配网模式。这个逻辑可以在STM32里做,检测到配网状态长时间不变就发重启指令。
3.4 手机APP联动与数据上报
机智云的好处是APP可以自动生成。在开发者中心配置好数据点后,点击生成APP,选Android或者iOS,等几分钟就能下载安装包。
APP装好后,登录机智云账号,就能看到自己的设备。设备在线的话,APP上会显示数据点的当前值,也能下发控制指令。
数据上报的频率要注意。机智云免费版对上报频率有限制,太快了会被限流。我一般设5秒上报一次,对于温度、湿度这种变化慢的数据足够了。如果是开关状态变化,可以主动上报一次,不用等定时器。
APP联动方面,机智云支持场景联动。比如温度超过30度自动打开风扇,这个可以在APP里配置,不需要改设备代码。对于做智能家居演示来说,这个功能很加分。
4. 常见问题与排查技巧实录
4.1 配网失败排查速查表
配网失败是最常见的问题,原因很多。我整理了一个排查表,按顺序检查:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| ESP01S热点搜不到 | 模块没启动 | 检查供电、CH_PD电平 |
| 热点搜到但连不上 | 热点密码错 | 默认密码是12345678 |
| APP发现不了设备 | 手机没连ESP热点 | 检查手机WiFi设置 |
| 输入WiFi后一直转圈 | 路由器密码错 | 确认密码,注意大小写 |
| 配网成功但设备离线 | 路由器限制了 | 检查路由器MAC过滤 |
| 串口无输出 | 波特率不对 | 试9600和115200 |
| 数据上报失败 | 数据点未定义 | 检查机智云数据点配置 |
4.2 串口通信乱码与丢包处理
串口乱码一般是波特率不匹配或者电平不匹配。GAgent默认9600,如果你STM32设的115200,收到的就是乱码。另外ESP01S是3.3V电平,如果STM32是5V的,中间要加电平转换。
丢包问题更隐蔽。我遇到过一次,设备运行几分钟就掉线,重启又好了。查了很久发现是串口缓冲区溢出。GAgent在配网或者网络波动的时候会发大量日志数据,如果STM32的缓冲区太小,来不及处理就会丢数据,导致协议解析失败。
解决办法:把环形缓冲区开大一点,至少512字节。另外解析函数要高效,不要在中断里做复杂处理,中断只负责存数据,解析放到主循环。
还有一个坑:printf重定向和串口冲突。如果你用printf调试,而printf又重定向到了和ESP01S通信的串口,那调试信息会干扰GAgent的通信。我的做法是调试用一个串口,通信用一个串口,分开。
4.3 设备频繁掉线的原因分析
设备连上之后频繁掉线,原因可能有几个。
供电问题是最常见的。ESP01S发射时电流大,如果电源纹波大或者供电不足,模块会重启。用示波器看VCC波形,如果有明显跌落,就要加电容或者换电源。
路由器兼容性也要考虑。有些路由器对ESP01S支持不好,特别是开了WPA3加密的。把路由器加密方式改成WPA2-PSK,或者开一个2.4G的访客网络专门给设备用。ESP01S只支持2.4G,不支持5G,这个要注意。
心跳超时也会导致掉线。机智云服务器如果长时间收不到设备的心跳,会认为设备离线。GAgent会自动发心跳,但如果网络不稳定,心跳丢了就会掉线。可以在STM32里监测连接状态,掉线了自动重连。
4.4 固件烧录失败的几种情况
烧录GAgent失败,先检查接线。GPIO0拉低,GPIO2拉高,这个组合不能错。烧录工具选对COM口,波特率可以先试115200,不行降到74880。
如果烧录工具一直显示"等待上电同步",试试先点烧录按钮再给模块上电。有些USB转TTL的供电能力不足,烧录时要用外部电源。
烧录成功后模块不启动,检查Flash大小。GAgent固件大概500多KB,如果模块Flash只有512KB,可能刚好不够。换1MB的模块。
还有一个容易忽略的:烧录地址。GAgent要烧到0x00000,如果烧到别的地址,模块启动不了。
5. 调试工具与效率提升技巧
5.1 串口调试助手的进阶用法
串口调试助手不只是看数据,用好了能省很多时间。
时间戳功能一定要开,这样能看到每条数据的时间,分析超时问题很有用。自动换行和HEX显示切换着用,AT指令用文本模式,协议数据用HEX模式。
我习惯把常用的AT指令存成快捷按钮,点一下就能发。比如AT+RST、AT+CWMODE=1、AT+CWJAP这些,调试的时候不用手打。
数据保存功能也很有用,把串口日志存成文件,出问题了慢慢分析。特别是配网失败的时候,日志里往往有线索。
5.2 用逻辑分析仪抓串口波形
串口通信出问题,有时候光看数据看不出来,要用逻辑分析仪抓波形。
逻辑分析仪接在TX和RX线上,设置波特率9600,就能看到实际的波形。如果波形畸变严重,说明电平或者波特率有问题。如果波形正常但数据不对,那就是软件解析的问题。
我遇到过一次,STM32发的数据ESP01S收不到,用逻辑分析仪一看,TX线上有波形,但幅度只有1.5V,达不到3.3V的逻辑高电平。查了半天发现是串口线太长,压降太大。换了根短线就好了。
5.3 机智云调试工具的使用
机智云提供了虚拟设备调试功能,在开发者中心可以模拟设备上线,测试APP和云端的数据交互。这个在硬件还没做好的时候特别有用,可以先验证数据点定义和APP逻辑。
还有串口调试工具,可以模拟GAgent和STM32通信,测试STM32的协议解析代码。不过这个工具需要配合机智云的协议文档用,稍微有点门槛。
实际调试的时候,我一般是先用虚拟设备确认云端和APP没问题,再用真实硬件调STM32和ESP01S的通信,最后联调。这样分层排查,效率高很多。
6. 从Demo到产品的几个关键考量
6.1 配网信息的存储与安全
配网成功后,WiFi信息存在ESP01S的Flash里。GAgent会自动保存,下次上电自动读取。但这里有个安全问题:WiFi密码是明文存在Flash里的。如果是产品化,要考虑加密存储。
机智云的企业版支持配网信息加密,个人版没有这个功能。如果对安全要求高,可以在STM32端做一层加密,把WiFi信息加密后再发给ESP01S。不过这样GAgent就用不了了,要自己写配网逻辑。
对于大部分项目和毕业设计来说,明文存储够用了。但要知道这个风险点,答辩的时候老师可能会问。
6.2 断网重连与异常恢复
产品化必须考虑异常恢复。网络断了要自动重连,ESP01S死机了要能重启。
我的做法是在STM32里加一个看门狗定时器,定期检查ESP01S的状态。如果连续几次心跳失败,就发AT+RST重启ESP01S。如果重启也不行,就控制ESP01S的电源重新上电。
STM32自己的看门狗也要开,防止程序跑飞。IWDG设个几秒的超时,主循环里定期喂狗。
6.3 OTA升级的预留设计
产品化还要考虑OTA升级。机智云支持OTA,但需要企业版账号。个人版做不了OTA,但可以在代码里预留接口。
我的做法是把固件版本号存在Flash的某个地址,STM32启动时读取并上报给云端。虽然现在不能OTA,但以后升级了企业版,直接对接就行。
ESP01S的GAgent固件也支持OTA,同样需要企业版。个人版就手动烧录吧。
7. 我踩过的坑和最后分享几个技巧
这个项目我做下来,最大的感受是配网的成功率取决于细节。硬件供电、串口配置、固件版本、路由器设置,任何一个环节出问题都会导致配网失败。
几个我踩过的坑:第一,ESP01S的CH_PD引脚一定要拉高,我一开始悬空,模块时好时坏。第二,GAgent的串口波特率是9600不是115200,这个坑了我一个下午。第三,机智云的数据点定义后要点击"应用"才生效,我定义完直接生成代码,结果数据点没同步。
最后分享几个实用技巧。调试的时候,在STM32里加一个串口透传模式,把ESP01S的数据直接转发到调试串口,这样能看到GAgent的完整日志,排查问题很方便。还有,机智云的APP有调试模式,能看到设备上下线的详细日志,配网失败的时候看看这个日志,往往能找到原因。
这个方案做毕业设计绰绰有余,做小批量产品也够用。成本低,资料多,社区活跃,遇到问题容易找到答案。后面如果要加功能,比如多设备联动、数据存储、语音控制,机智云都支持,扩展性不错。