STM32传感器模块编程实践(二十)ESP8266实现MQTT连接OneNET上传温湿度数据

文章目录

一.概要

ESP8266 是一款高性能的 WIFI 串口模块,实现透明传输。只要有一定的串口知识,不需要知道 WIFI 原理就可以上手,在业内应用广泛。

ESP8266 是一个非常强大的 WIFI 模块,可以利用串口与单片机进行通讯,从而编程实现控制 ESP8266。利用 ESP8266 可以访问电脑服务器实现TCP/IP协议通讯。该系列模块支持标准的IEEE802.11b/g/n协议,内置完整的TCP/IP协议栈。用户可以使用该系列模块为现有的设备添加联网功能,也可以构建独立的网络控制器。

本文主要介绍使用ESP8266+STM32F103C8T6单片机使用MQTT协议把温湿度数据上传到OneNET平台,在平台上能显示温湿度数据。

主要包含ESP8266的介绍,ESP8266固件的升级,OneNET平台的配置,STM32F103C8T6单片机用AT指令驱动ESP8266连接OneNET平台。

二.ESP8266 WIFI模块主要性能参数

1.最小的 802.11b/g/n Wi-Fi SOC 模块

2.采用低功率32位CPU,可兼作应用处理器

3.主频最高可达160MHz

4.内置 10 bit 高精度 ADC

5.支持UART/GPIO/IC/PWM/ADC/HSPI等接口

6.集成 Wi-FiMAC/ BB/RF/PA/LNA

7.支持多种休眠模式,深度睡眠电流低至20uA

8.内嵌 Lwip 协议栈

9.支持STA/AP/STA+AP 工作模式

10.支持 Smart Config/AirKiss;一键配网

11.串口速率最高可达4Mbps

12.通用 AT 指令可快速上手

13.支持 SDK 二次开发

14.支持串口本地升级和远程固件升级(FOTA)

ESP8266模块接口引脚说明:

1.TX 模块UART串口发送脚

2.GND 接地

3.EN 芯片使能端,高电平有效

4.IO2 GPIO脚

5.RST 模块复位脚

6.IO0 模式选择脚,下载模式:外部拉低;运行模式:悬空或者外部拉高

7.3V3 3.3V 供电,外部供电电源输出电流建议在500mA以上

8.RX 模块UART串口接收脚

三.ESP8266 WIFI模块与USB转TTL模块连接

ESP8266 WIFI模块与USB转TTL模块连接,主要是为了验证AT指令,或者下载更新烧录固件才用的上,串口波特率115200,8位数据,1位停止位,无校验,接线连接如下:

因为 USB 转 TTL 模块的 3.3V 输出‌带载能力不足(<100mA),所以得需要5V的电压,可以用来临时烧录固件代码,正常ESP8266 WIFI模块的使用需要用3.3V供电。

实物连接示意图如下:

四.使用USB转TTL烧录MQTT固件

我们买到的ESP8266模块一般里面是不带MQTT固件的,需要升级,需要下载(1471)ESP8266-AT_MQTT-1M.bin,模块才能支持MQTT指令。下载软件如图所示,选用flash_download_tool_3.9.7。

双击flash_download_tool_3.9.7.exe,就是下载界面,如下图所示。

下载MQTT固件步骤:

1.接线:ESP8266模块的IO0脚,用杜邦线把这引脚与GND相连 (IO0脚用于进入固件烧写模式,低电平->烧写,高电平->运行模式(默认)),同时用杜邦线把USB转TTL模块与ESP8266模块相连,接线如下:
USB转TTL模块 ESP8266模块

5V---------------------3V3

TXD-------------------RX

RXD------------------TX

GND------------------GND

2.USB转TTL模块插电脑,双击flash_download_tool_3.9.7.exe,进入下载界面。

3.勾选对应的配置,如下图所示,勾选结束后,点击START。

4.烧录过程中,进度条会更新。

5.烧录结束,会显示FINISH。

6.烧录完成后,拔掉ESP8266模块上的杜邦线,固件烧录升级完成。

五.OneNET平台搭建

1、登录云平台,OneNET - 中国移动物联网开放平台,点击开发者中心。

2、进入开发者中心,点击产品开发,创建产品。

3.选择环境感知下温湿度检测。

4.设备接入,选择直连设备,MQTT,Wi-Fi。

5、添加设备,点击设备管理。

6、设备名称就是设备ID,输入DHT11。

7.点击设备管理,设备详情。

8.显示设备ID,产品ID,设备密钥,可以用来生成Token(OneNET Token 是由中国移动 OneNET 物联网平台为设备或应用生成的‌临时访问凭证‌,用于在 API 调用或 MQTT 连接中完成身份认证)。

六.OneNET的Token 生成

OneNET Token是由中国移动OneNET 物联网平台为设备或应用生成的‌临时访问凭证‌,用于在 API 调用或 MQTT 连接中完成身份认证。需要用到设备ID,设备密钥,产品ID,还有时间戳,用Token 软件工具(OneNET-token计算工具V1.00)生成,如下图所示。

设备ID,产品ID,设备密钥,我们前面OneNET创建平台的步骤8处就能复制。时间戳,我们可以在百度上找到转换时间戳的网站,输入有效时间,就能转成时间戳,获取时间戳如下图所示。

生成的Token,我们保存下来,后续AT指令上会用到。

七.ESP8266模块MQTT连接OneNET相关AT指令介绍

在ESP8266的开发过程中,AT指令方法是最常用的方法,无需花大量的时间去熟悉环境,开发速度快。

AT指令是一种串口通信协议,是以AT开头的一个字符串,每个指令执行成功与否都有相应的返回,都是ASCII码字符串操作,每个发送的AT指令都需要回车换行符结束。

最常见的就是AT指令就是查询模块通讯是否正常,指令如下:

单片机发送:AT+(回车换行符)

模块响应:OK

ESP8266模块的MQTT主要AT指令如下:

串口波特率115200,8位数据,1位停止位,无校验

AT+CWMODE=1//设置Wi-Fi工作模式为Station模式

AT+CWJAP="your_SSID","your_PASSWORD"//连接家里或者单位里的路由器wifi用户名,密码,也可以是手机热点,手机热点需要注意需要打开兼容模式,或者使用2.5GHZ,ESP8266不支持5GHz。

AT+MQTTUSERCFG=0,1,"DHT11","6KQ4d4ociD","version=2018-10-31&res=products%2F6KQ4d4ociD%2Fdevices%2FDHT11&et=1895232083&method=md5&sign=GsAEZlkj8FuUBfDnOqllZA%3D%3D"

//配置 MQTT 用户属性,DHT11是设备ID(前面平台创建的设备ID),6KQ4d4ociD是产品ID(前面平台创建的产品ID),后续参数为OneNet平台生成的鉴权信息token(由专用软件生成),返回OK代表用户信息配置成功。

AT+MQTTCONN=0,"mqtts.heclouds.com",1883,1//连接到OneNet服务器。

AT+MQTTSUB=0,"$sys/6KQ4d4ociD/DHT11/thing/property/post/reply",1

//订阅OneNet平台下发属性指令的主题,1为QoS等级(确保消息可靠接收),返回OK代表订阅成功,之后平台下发指令可被模块接收。 其中DHT11是设备ID(前面平台创建的设备ID),6KQ4d4ociD是产品ID(前面平台创建的产品ID)。

AT+MQTTPUB=0,"$sys/6KQ4d4ociD/DHT11/thing/property/post","{"id":"133","params":{"humi":{"value":55},"temp":{"value":12}}}",0,0

//上报设备数据到平台,DHT11是设备ID(前面平台创建的设备ID),6KQ4d4ociD是产品ID(前面平台创建的产品ID),示例中上报humi(湿度)值为55%,temp(温度)值为12度,0,0代表 QoS 等级与保留消息标志,返回OK代表数据上报触发成功,平台可查收数据。

八.STM32单片机与ESP8266WIFI模块通讯实验

1.硬件准备

开发板插上ESP8266 WIFI模块,

主要信号:

板子PC13<--->WIFI模块RST脚

板子PA2<------>WIFI模块RX

板子PA3<------>WIFI模块TX

板子3.3V<----->WIFI模块3V3

板子GND<---->WIFIGND

2.软件主要代码

主函数

c 复制代码
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&UartRxData, 1);//接收中断使能
	ESP8266_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		ESP8266_STA_TCPClient_Test();//测试MQTT通讯
  }
  /* USER CODE END 3 */
}

串口中断接收

c 复制代码
volatile uint8_t UartRxData;
uint8_t UartTxbuf[1000]={1,2,3,4,5,6,7,8,9,10};
uint8_t UartRxbuf[1024],UartIntRxbuf[1024];
uint16_t UartRxIndex=0,UartRxFlag,UartRxLen=0,UartRxTimer,UartRxOKFlag,UartIntRxLen;

//串口清除
uint8_t UartRecv_Clear(void)
{
	UartRxOKFlag=0;
	UartRxLen=0;
	UartIntRxLen=0;
	UartRxIndex=0;
	return 1;
}

//接收标志函数,返回0说明没收据接收,返回1说明有数据收到
uint8_t Uart_RecvFlag(void)
{
		if(UartRxOKFlag==0x55)
		{
			UartRxOKFlag=0;
			UartRxLen=UartIntRxLen;
			memcpy(UartRxbuf,UartIntRxbuf,UartIntRxLen);//把缓冲区的数据,放入需要解析的数组
			UartIntRxLen=0;
			TcpClosedFlag = strstr (UartRxbuf, "CLOSED\r\n" ) ? 1 : 0;
			return 1;
		}
		return 0;
}
//串口2在1字节接收完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	if(huart==&huart2)//判断是否串口2
	{
		UartRxFlag=0x55;//接收标志置位
		UartIntRxbuf[UartRxIndex]=UartRxData;//数据写入缓冲区
		UartRxIndex++;//记载数目加1
		if(UartRxIndex>=1024)//缓冲区是1024字节,如果存满,归零
		{
			UartRxIndex=0;
		}
		HAL_UART_Receive_IT(&huart2,(unsigned char*)&UartRxData,1);//继续接收下一字节
 }

}

//1ms调用一次,用来判断是否收完一帧
void UART_RecvDealwith(void)
{
	if(UartRxFlag==0x55)
	{
		if(UartIntRxLen<UartRxIndex)//UartIntRxLen小于UartRxIndex,说明有收到新的数据,把接收长度增加
		{
		UartIntRxLen=UartRxIndex;
		}else
		{
			UartRxTimer++;
			if(UartRxTimer>=50)//50ms,等待,没收到新数据,说明已经收完一帧
			{
				UartRxTimer=0;
				UartRxFlag=0;
				UartRxOKFlag=0x55;
				UartRxIndex=0;
			}
		}
	}
}
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
	UART_RecvDealwith();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

AT指令相关

c 复制代码
void ESP8266_STA_TCPClient_Test(void)
{

    ESP8266_AT_Test();
		printf("正在配置ESP8266\r\n");
    ESP8266_Net_Mode_Choose(STA);//设置Wi-Fi工作模式为Station模式
    while(!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD));//登录WIFI 用户名,密码
    ESP8266_Enable_MultipleId ( DISABLE );//单连接模式
		HAL_Delay(1000);
		while(! ESP8266_MQTTUSERCFG(PROID,DEVID,AUTH_INFO));//配置 MQTT 用户属性
		HAL_Delay(1000);
		while(!ESP8266_MQTTCONN("mqtts.heclouds.com",1883))//连接到OneNet服务器
		{
			  HAL_Delay(5000);
		}
	 while(!ESP8266_MQTTSUB())//订阅OneNet平台下发属性指令的主题
		{
			  HAL_Delay(5000);
		}
    while ( 1 )
    {       

			  ESP8266_MQTTPUB();//上报设备数据到平台
         HAL_Delay(2000);
			  Uart_RecvFlag();//接收数据
       
    }   
}
/*
*MQTT配置用户属性
pClient_Id:产品ID
pUserName:设备ID
产品ID:6KQ4d4ociD
设备ID:DHT11
设置成功返回true 反之false
*/
   
bool ESP8266_MQTTUSERCFG( char * pClient_Id, char * pUserName,char * PassWord)
{

    sprintf ( cCmd, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"",pUserName, pClient_Id,PassWord );//设备ID在前,产品ID在后
    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 );
}


/*
*连接指定的MQTT服务器
*IP:MQTT服务器上对应的IP地址
*ComNum MQTT服务器上对应的端口号,一般为1883
*设置成功返回true 反之false
*/
bool ESP8266_MQTTCONN( char * Ip, int  Num)
{
    sprintf ( cCmd,"AT+MQTTCONN=0,\"%s\",%d,1", Ip,Num);
    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 );
}

/*
*订阅指定连接的 MQTT 主题, 可重复多次订阅不同 topic
*设置成功返回true 反之false
*/
bool ESP8266_MQTTSUB(void)
{
		char topic_buf[56];
  	const char *topic = topic_buf;
		sprintf(topic_buf,  "$sys/%s/%s/thing/property/set", PROID, DEVID);
    sprintf ( cCmd, "AT+MQTTSUB=0,\"%s\",1",topic_buf );
    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 );
}


/*
onenet json数据格式
{
  "id": "123",
  "params": {
    "temperature": {
      "value": 25
    },
    "humidity": {
      "value": 50
    }
  }
}
*设置成功返回true 反之false
*/

bool ESP8266_MQTTPUB( void)
{

	sprintf(cCmd, "AT+MQTTPUB=0,\"$sys/%s/%s/thing/property/post\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"humi\\\":{\\\"value\\\":79}\\,\\\"temp\\\":{\\\"value\\\":20}}}\",0,0", 
        PROID, DEVID);//20度,湿度79%
	
    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 1000);
}

3.实验效果

如下图所示,打开OneNET平台,一开始看到离线状态

执行完ESP8266_MQTTCONN("mqtts.heclouds.com",1883),就能看到设备处于在线状态,如下图所示。

执行完ESP8266_MQTTPUB()函数,就能在OneNET平台看到上报上来的温湿度数据,还有数据更新的时间,温湿度数值跟程序里的,湿度值是79%,温度是20度,内容一致。

九.小结

使用ESP8266的MQTT协议连接OneNET,主要的工作点主要是:固件烧录,Token生成,MQTT相关的AT指令移植这几点,只有自己把这些都跑通了,才会更熟悉ESP8266模块。

相关推荐
Deitymoon2 小时前
STM32——蜂鸣器
stm32·单片机·嵌入式硬件
BT-BOX2 小时前
STM32物联网云监控智能报警器(MQ-2烟雾/火焰/DHT11温湿度/红外)
stm32·嵌入式硬件·物联网
项目題供诗2 小时前
STM32-EXIT外部中断(七)
stm32·单片机·嵌入式硬件
Lazionr2 小时前
数据结构队列详解:从概念到代码实现
c语言·数据结构
三品吉他手会点灯2 小时前
STM32F103 学习笔记-21-串口通信(第4节)—串口发送和接收代码讲解(下)
笔记·stm32·单片机·嵌入式硬件·学习
时空自由民.2 小时前
嵌入式-CI(Continuous Integration)介绍
linux·单片机·ci/cd
流年如夢2 小时前
编译前奏:预处理全面梳理
c语言
LingLong_roar12 小时前
STM32 启动流程
stm32·单片机·嵌入式硬件
weixin_5206498712 小时前
短距离硬件通信
单片机·嵌入式硬件