ESP-01S / ESP8266 AT指令连接阿里云物联网平台
- 阿里云物联网平台
- 新建设备
- 获取AT参数
- AT指令介绍
- 连接阿里云AT指令介绍
- MQTT固件
- 固件下载
- 硬件连接
- 固件烧录
- 串口助手调试
- 硬件连接
- 测试指令
- AT_Command移植
- 总结
- 问题排查
- 源码获取
关注+星标公众号,不错过精彩内容
作者 | MakingClub
微信公众号 | electronic造物实验室
阿里云物联网平台
新建设备
- 注册阿里云账号并搜索物联网服务。选择并进入物联网平台产品页。
- 点击管理控制台,进入物联网平台管理界面。
- 选择公共实例(如果尚未开通,需要先进行开通,具体步骤不再赘述),然后点击进入。
- 创建一个新的产品。填写产品名称、所属品类等必要信息,并完成产品创建步骤。
- 在创建完成的产品页面上,添加设备。输入设备名称并确认。
- 输入设备名称,输入完成后点击确认;
至此,阿里云物联网平台创建设备完成,接下来获取MQTT连接参数。
获取AT参数
创建设备成功后进入设备详情页,查看MQTT连接参数,并进行保存。
通过上述步骤,你可以获取到阿里云物联网平台上设备的MQTT连接参数,并进行保存。这些参数将用于在ESP-01S / ESP8266上配置AT指令,实现设备与物联网平台之间的通信。
AT指令介绍
AT命令,用来控制TE(TerminalEquipment)和MT(Mobile Terminal)之间交互的规则。AT指令可以参考乐鑫官方提供的AT 命令集。
连接阿里云AT指令介绍
- AT+RST 复位ESP-01S / ESP8266模块;
- AT+CWMODE=3 设置ESP模块为Station+SoftAP模式;
- AT+CWJAP=“SSID”,“PWD” 设置ESP模块连接无线网络 *注意双引号为英文;
- AT+MQTTUSERCFG=0,1,“NULL”,“username”,“password”,0,0,“” 设置 MQTT 用户属性;
- AT+MQTTCLIENTID=0,“clientId” 设置MQTT 的clientId参数;
- AT+MQTTCONN=0,“host”,1883,1 连接 MQTT Broker;
- AT+MQTTCLEAN 断开MQTT连接。
以上为连接阿里云MQTT服务器需要的配置命令,接下来在阿里云新建设备,获取AT指令需要填充的参数。
MQTT固件
ESP-01S 1M Flash固件下载1MB AT MQTT
ESP8266 4M Flash固件下载4MB AT MQTT
固件下载
硬件连接
USB转TTL推荐使用带有独立LDO的模块,因为ESP8266EX通讯时电流较大,如无独立LDO可能导致ESP8266EX掉电重启。
可以使用下图模块,带独立LDO,可以提供一定带负载能力;
下图模块不推荐使用,无独立LDO,3V3为CH340提供,带负载能力弱。
ESP-01烧录固件
VCC -----> TTL 3.3V
GND -----> TTL GND
TXD -----> TTL RXD
RXD-----> TTL TXD
EN-------> TTL 3.3V
RST ----> TTL RST
GPIO0 ---> GND
GPIO2 ---> 3.3V (不接也可以)
基本接法如下图所示:
ESP-01S烧录固件
VCC -----> TTL 3.3V
GND -----> TTL GND
TXD -----> TTL RXD
RXD-----> TTL TXD
RST ----> TTL RST
GPIO0 ---> GND
固件烧录
下载AT指令固件到本地后,需要使用乐鑫提供的flash_download_tool
工具。下载后直接解压即用,运行烧录工具。乐鑫官网 - 支持 - 相关下载 - 工具-Flash 下载工具
选择型号,选择ESP8266
打开烧录软件, 从"…“选择要烧录的bin文件: ESP8266-AT_MQTT-1M.bin;填写烧录地址"0x0000”;SPI MODE选择 “DOUT”;FLASH SIZE选择 “8Mbit”;"DoNotChgBin"不变;“COM” 选择你USBtoTTL的COM口;波特率默认即可。
上述配置完成后, 点击START开始烧录, 若一直停在等待上电同步可以就将RST连接GND再断开, 就可以开始下载了。
串口助手调试
在进行串口助手调试之前,需要进行正确的硬件连接。
硬件连接
对于ESP-01,需要使用两个上拉电阻将EN和RST引脚上拉到3.3V,如下图所示:
对于ESP-01S,只需要连接3.3V、RXD、TXD和GND即可。
测试指令
在串口软件中打开COM口,选择波特率115200,加回车换行;发送AT指令,并等待接收到回复的"OK"。
接下来将MQTT信息填充进AT命令中进行连接测试。
- AT+RST 复位ESP-01S / ESP8266模块;
- AT+CWMODE=3 设置ESP模块为Station+SoftAP模式;
- AT+CWJAP=“SSID”,“PWD” 设置ESP模块连接无线网络 *注意双引号为英文;
- AT+MQTTUSERCFG=0,1,“NULL”,“username”,“passwd”,0,0,“” 设置 MQTT 用户属性;
- AT+MQTTCLIENTID=0,“clientId” 设置MQTT 的clientId参数;
- AT+MQTTCONN=0,“host”,1883,1 连接 MQTT Broker;
- AT+MQTTCLEAN 断开MQTT连接。
AT+MQTTUSERCFG中的username和passwd与下图对应填写,AT+MQTTCLIENTID中的clientId也与下图对应,AT+MQTTCONN的host与下图mqttHostUrl对应。
需要注意AT+MQTTCLIENTID指令中的clientId中的逗号前需要加’ \ '符号进行转义,假设clientId为“a1Tt5hwk2af.Device1|securemode=2,signmethod=hmacsha256,timestamp=1685260171273|”,那么发送的AT指令应为AT+MQTTCLIENTID=0,“723712|securemode=2,signmethod=hmacsha256,timestamp=1685260171273|”
发送完以上指令后,在阿里云物联网平台中刷新设备网页,你将会看到设备已成功上线的信息。
[18:24:44.609]发→◇AT
□
[18:24:44.613]收←◆AT
OK
[18:30:14.787]发→◇ATE0
□
[18:30:14.791]收←◆ATE0
OK
[18:30:31.339]发→◇AT+CWMODE=3
□
[18:30:31.344]收←◆
OK
[18:31:21.198]发→◇AT+CWJAP="Xiaxxxx81","dsssxx1"
□
[18:31:22.397]收←◆WIFI CONNECTED
[18:31:23.908]收←◆WIFI GOT IP
OK
[19:24:10.517]发→◇AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"
□
[19:24:10.530]收←◆
OK
[19:24:53.745]发→◇AT+MQTTUSERCFG=0,1,"NULL","Devixx1&a1Ttxxxaf","05314xxxxxxxxxxxxxxxxxxxxxxc5de74",0,0,""
□
[19:24:53.755]收←◆
OK
[19:25:09.562]发→◇AT+MQTTCLIENTID=0,"a1xxxxf.Device1|securemode=2\,signmethod=hmacsha256\,timestamp=1685260171273|"
□
[19:25:09.571]收←◆
OK
[19:25:21.162]发→◇AT+MQTTCONN=0,"a1xxxxxaf.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883,1
□
[19:25:21.347]收←◆+MQTTCONNECTED:0,1,"a1Tt5wtm2af.iot-as-mqtt.cn-shanghai.aliyuncs.com","1883","",1
OK
可以看到设备已成功上线。
AT_Command移植
AT_Command由魔罗大佬开发,是一款管理AT命令通信交互组件, 适用于Modem、WIFI模块、蓝牙等使用AT命令或者ASCII命令行通信的场景。本次AT连接使用AT_Command移植到STM32F103C8T6进行运行。AT_Command Gitee链接
本次的项目环境为HAL库+CubeMx进行配置开发。
-
首先需要定义适配器,完成驱动接口及缓冲区设置
在wifi_uart.c文件中,进行了串口发送和接收回调的实现。/* * @brief 向串口发送缓冲区内写入数据并启动发送 * @param[in] buf - 数据缓存 * @param[in] len - 数据长度 * @return 实际写入长度(如果此时缓冲区满,则返回len) */ unsigned int wifi_uart_write(const void *buf, unsigned int len) { unsigned int ret; ret = ring_buf_put(&rbsend, (unsigned char *)buf, len); HAL_UART_Transmit(&wifi_uart,(unsigned char *)buf,len,0xffff); // wifi串口数据发送 return ret; } /* * @brief WIFI串口接收 * @param[in] none * @return none */ void WIFI_UART_RxCpltCallback(unsigned char *data, uint8_t len) { ring_buf_put(&rbrecv, data, len); /*将数据放入接收缓冲区*/ }
串口数据接收使用串口2(TX为PA2, RX为PA3)的是DMA+空闲中断的方式进行接收,在
stm32f1xx_it.c
文件中:/** * @brief This function handles USART2 global interrupt. */ void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */ if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) // 空闲中断 { __HAL_UART_CLEAR_IDLEFLAG(&huart2); // 清除空闲中断标志位 HAL_UART_DMAStop(&huart2); // 停止DMA接收 if( wifiConnectFlag == 0) // 未完成配置 WIFI_UART_RxCpltCallback(uart2_rx_buf, strlen(uart2_rx_buf)); // 数据处理函数 else // 配置完成 等待设备连接 wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf)); memset(uart2_rx_buf, 0, strlen(uart2_rx_buf)); // 清除数据 HAL_UART_Receive_DMA(&huart2, uart2_rx_buf, buf_size); // 重新打开DMA接收 } /* USER CODE END USART2_IRQn 1 */ }
-
使用AT适配器创建AT通信对象,在
wifi.c
文件中:static at_obj_t at;static at_obj_t at; /* * @brief wifi初始化 配置8266 */ void wifi_init(void) { static char wifi_msg[128] = {0}; // WIFI 串口初始化 wifi_uart_init(115200); at_obj_init(&at, &at_adapter); // 关闭回显 at_send_singlline(&at, NULL, "ATE0"); // OK // AT测试 at_send_singlline(&at, NULL, "AT"); // OK ERROR * // 配置工作模式 AP模式 at_send_singlline(&at, NULL, "AT+CWMODE=3"); // 创建路由器 sprintf(wifi_msg, "AT+CWJAP=\"%s\",\"%s\"", SSID, PWD); at_send_singlline(&at, NULL, wifi_msg); // 设定域名 at_send_singlline(&at, NULL, "AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\""); // 设定MQTT账号 at_send_singlline(&at, NULL, "AT+MQTTUSERCFG=0,1,\"NULL\",\"username\",\"passwd",0,0,\"\""); // 设定Clinent ID at_send_singlline(&at, NULL, "AT+MQTTCLIENTID=0,\"clientid注意逗号需反义\""); // 链接MQTT at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,\"host\",1883,1"); };
-
加入轮询任务,
wifi.c
中实现了wifi_task
函数,并在初始化中进行循环调用,如下:wifi_init(); do { wifi_task(); HAL_Delay(10); }while(wifiConnectFlag == 0);
wifiConnectFlag
标志位会在at_send_singlline(&at, connnect_calback, "AT+MQTTCONN=0,\"host\",1883,1");
中的connnect_calback
回调函数中进行判断。
如上进行配置后可基本完成AT_Command的配置,可以进行串口测试。 -
数据上报,数据上报通常使用标准格式如下:
首先需要在产品中找到属性上报的Topic类,注意要将${deviceName}
替换为设备名。
STM32中可使用如下的代码进行motorstatus
属性上报char sendmsg[256]; sprintf(sendmsg,"AT+MQTTPUB=0,\"/sys/a1Tt5wtm2af/${deviceName}/thing/event/property/post\",\"{\\\"id\\\":1685082419785\\\,\\\"params\\\":{\\\"motorstatus\\\":%d}\\\,\\\"version\\\":\\\"1.0\\\"\\\,\\\"method\\\":\\\"thing.event.property.post\\\"}\",1,0\r\n", motorstatus); HAL_UART_Transmit(&huart2, (unsigned char *)sendmsg, strlen(sendmsg), 0xffff); // wifi串口数据发送 HAL_Delay(1000);
-
云端属性获取,当云上产生设备属性操作时会通过MQTT发送到对应的设备中,此时需要进行相应的解析操作,首先通过判断
wifiConnectFlag
标志位判断是否链接阿里云成功,若成功后之后的云端下发的属性命令将在wifi.c
中的wifi_connnect_calback(uart2_rx_buf, strlen(uart2_rx_buf));
函数进行解析:
本部分代码的逻辑为判断字符串数组中是否有特定的三位字符与motorstatus
属性吻合,从而解析出对应的属性值。/* * @brief wifi 连接成功后数据解析 */ // +MQTTSUBRECV:0,"/sys/a1U3gCVc2Lh/Device1/thing/service/property/set",104,{"method":"thing.service.property.set","id":"1199288712", // "params":{"windowControl":3},"version":"1.0.0"} void wifi_connnect_calback(unsigned char *data, uint8_t len) { int i = 0; unsigned char *p ; p = data; // 指针p指向接受数组的第一个元素 for(i=50;i<strlen(data);i++) { if(*(p+i)=='t' && *(p+i+1)=='u' && *(p+i+2) == 's') // 寻找"motorstatus" { motorstatus = *(p+i+5)-0x30; } } }
总结
首先,在wifi_uart.c
文件中实现了串口发送和接收回调函数。wifi_uart_write
函数用于向串口发送缓冲区写入数据并启动发送,同时使用HAL_UART_Transmit
函数进行串口数据发送。WIFI_UART_RxCpltCallback
函数用于处理串口接收到的数据,将数据放入接收缓冲区。
在stm32f1xx_it.c
文件中,使用DMA和空闲中断的方式进行串口2的接收。当空闲中断触发时,会调用WIFI_UART_RxCpltCallback
函数处理接收到的数据。
在wifi.c
文件中,创建AT适配器对象,并在wifi_init
函数中进行AT指令的配置和发送。通过调用at_send_singlline
函数发送AT命令。在wifi_task
函数中循环调用,通过判断wifiConnectFlag
标志位判断是否连接成功。
对于数据上报,你可以根据标准格式构造要发送的数据,使用sprintf函数将数据格式化为AT命令的形式,然后通过HAL_UART_Transmit
函数发送到串口。例如,使用sprintf
函数将motorstatus
属性格式化为要发送的字符串,然后通过HAL_UART_Transmit
函数发送到串口。
对于云端属性获取,当云端发送设备属性操作时,通过判断wifiConnectFlag
标志位和解析接收到的数据进行相应的操作。在wifi_connnect_calback
函数中,你可以解析接收到的数据,判断是否含有特定的属性命令,并提取属性值。
需要注意的是,以上只是一个简单的示例,具体的实现可能需要根据你的项目需求进行适当的修改和调整。同时,确保在使用AT命令进行通信时,正确配置串口和波特率,并根据具体的硬件连接情况进行适配。
问题排查
除了上述提到的移植和配置外,以下是一些可能需要的步骤和流程:
-
确定硬件连接:根据AT_Command库的要求,确认将STM32F103C8T6与Modem、WIFI模块、蓝牙等设备正确连接。确保使用的串口、引脚和电源连接正确。
-
配置CubeMX:使用CubeMX配置STM32F103C8T6的引脚和时钟设置,确保与硬件连接一致。在CubeMX中选择正确的串口配置,包括波特率、数据位、停止位等参数。
添加库文件和代码:将AT_Command库的源代码和相应的头文件添加到你的项目中。确保在编译过程中包含这些文件,并链接到正确的位置。
-
初始化串口和DMA:在代码中初始化串口和DMA相关的设置,确保正确配置串口的接收和发送功能。确保正确启动DMA进行接收,并在空闲中断中处理接收到的数据。
-
实现适配器函数:根据AT_Command库的要求,实现适配器函数,包括串口发送和接收的函数。这些函数将作为AT_Command库的回调函数,在相应的事件发生时被调用。
-
初始化AT_Command对象:在代码中创建AT_Command对象,并使用之前实现的适配器函数进行初始化。这将使AT_Command库能够使用正确的串口进行通信,并通过回调函数处理接收到的数据。
-
配置AT指令和发送数据:根据你的项目需求,使用AT_Command库提供的函数配置AT指令,例如发送AT测试命令、配置工作模式、创建路由器等。使用AT_Command库提供的函数发送数据到串口,实现数据上报等功能。
-
解析接收数据:根据AT_Command库的回调函数,解析接收到的数据。根据具体的协议和数据格式,提取需要的信息并进行相应的处理。例如,在
wifi_connnect_calback
函数中解析云端下发的属性命令,并根据属性命令进行相应的操作。 -
循环调用AT_Command库:在主循环中循环调用
AT_Command
库的相关函数,确保AT指令的正常运行。可以通过wifi_task
函数进行循环调用,并在循环中添加适当的延时。 -
调试和测试:进行逐步调试和测试,确保
AT_Command
库在STM32F103C8T6上正常工作。验证AT指令的发送和接收功能,检查数据上报和云端属性获取的正确性。
以上是一个大致的流程,具体的实现可能需要根据你的项目需求和AT_Command库的要求进行调整。确保按照库的文档和示例进行
源码获取
关注公众号electronic造物实验室
并发送AT指令
即可获取测试源码。