星星博客 »  > 

2-STM32+ESP8266连接onenet并上传数据(HTTP)

上一篇文章内容链接为下
1-ESP8266-AT指令初试化及部分基础知识
2-STM32+ESP8266连接onenet并上传数据(HTTP)

一、预备知识小插曲

ESP8266,onenet云平台,STM32三部分在结合使用前最好还是分别学习了解一下,效率更高,在开发过程中哪里有问题就有针对性了。

1、了解8266的基础知识(模式、初始化、操作过程,并用串口助手测试)–上一篇博客,下为链接
ESP8266-AT指令初试化及部分基础知识-点我
2、了解了onenet云平台(翻翻官方文档看一看)
onenet云平台开发文档–点我

3、串口助手发送AT指令控制ESP8266连接onenet云平台,并上传数据(主要了解8266整个初始化及连接云端传输数据的过程及数据格式)–下文第三部分已经涉及

4、在原来已有的基础上(STM32控制OLED上显示温湿度)尝试添加ESP8266部分代码进行合并并修改,实现连接onenet云平台并上传温湿度–下面链接是之前程序移植部分
博客跳转链接-STM32串口实验基础上移植oled和dht11

5、由于HTTP协议适合于简单数据上报场景,所以又尝试使用MQTT协议上传数据的同时实现云端对开关的远程控制–下一篇博客

6、在这两天使用onenet的过程中发现web可视化有旋转的那种开关,但不知道下发的数据能不能充分利用一下,突然想着过几天能不能尝试做一个远程调节灯光亮度的功能(PWM控制灯光)–整理完这几天的学习后会尝试一做一下

批注:其实在真正接触8266和onenet前还在B站跟着原子哥的STM32视频课程学习了一段时间的STM32基础知识,感觉还是非常有必要的

二、onenet云平台新建产品和设备

在准备工作做好之后,便开始了新的学习之旅,首先在onenet云平台创建产品和设备

1、在控制台首页切换至旧版本
01-ONENET控制台首页-请点我
在这里插入图片描述
2、选择全部产品-多协议接入,
在这里插入图片描述
3、创建http协议下的产品和设备
在HTTP协议下自己创建产品,在产品之下再对应创建一个设备即可(下方为官方文档)-也可以自行百度新建产品和设备的博客

02-onenet创建产品
03-创建设备
在这里插入图片描述

4、查看密钥和设备ID
产品和设备创建完毕后,保存我们需要的密钥和设备id

在这里插入图片描述
在这里插入图片描述
04-协议使用场景–请点我

5、素材获取
自己根据下方提供的素材进行整合到自己程序中去就可以,素材内容为下,点击连接获取:
在这里插入图片描述
onenet.c和ESP8266.c素材连接提取码:aavj

6、修改参数信息
在onenet.c文件的代码中要进行修改为自己的设备ID和密钥
在这里插入图片描述
7、修改wifi名和密码
在esp8266.c文件的代码中修改要连接的wifi名和wifi密码
在这里插入图片描述

三、使用串口助手连接onenet并且传输数据

1、ESP8266初始化
连接onenet云平台的IP地址:183.230.40.33,端口号:80

1.AT+CWMODE=1   设置为STA模式
2.AT+CWJAP_DEF="study_test1","esp8266test"   连接 WIFI(串口助手)
3.AT+CIPMUX=0   设置单连接
4AT+CIPSTART="TCP","183.230.40.33",80  输入服务器地址+端口号连接tcp服务器
5.AT+CIPMODE=1    进入透传模式
6.AT+CIPSEND      准备发送数据(发送此指令收到ok和>后即可发送数据)

在这里插入图片描述
2、发送数据

上一步已经连接云端并开启了数据透传模式,接下来即可通过串口助手发送数据,type=3的话下面发送的数据格式就比较简单了
在这里插入图片描述

POST /devices/7058xxx72/datapoints?type=3 HTTP/1.1
api-key:XNmVBSWyYSxxxxxxxxxxxLXA3KM=
Host:api.heclouds.com
Connection:close
Content-Length:59

{"hum":25,"temp":65}

3、数据上传成功
出现下面这样就是上传消息成功(由于串口助手只能发一行数据就换了一个)
在这里插入图片描述
4、云端查看数据
onenet云平台具体设备的数据流展示处即可看到上传的数据
在这里插入图片描述
5、相对于阿里云的一个好处

发现onenet的物模型有一个好处,不需要手动创建物模型,在上传数据时可以随意添加新的变量,你只要上传新的属性和数值就会自动创建对应的物模型,如果是阿里云的话是不行的,只要属性名称,数据类型有一个对应不起来,都不会正常显示数据,此处随意添加了一个烟雾浓度属性

在这里插入图片描述

通过以上方法即可实现使用串口助手发送AT指令控制8266上传数据

四、STM32+ESP8266+onenet使用方法

(一)、博君一笑

在正文开始之前先说一下我最才开始遇到的问题:STM32串口2接收不到8266反馈信息

我在刚开始便遇到了问题,在程序整合逻辑代码均没错误之后,使用串口2给ESP8266发送控制指令进行初始化,结果永远收不到反馈消息,也就一直没有初始化成功,还没开始,就这样结束了?

怎么可能放弃呢,于是就一点一点的排除,先单独用USB调试ESP8266完全没问题,再使用串口2发送和接收数据测试也没问题,然后又借助逻辑分析仪分析出每次串口都发送出了AT指令,的确是没有返回数据,或者只反馈回一小部分错误信息,调了得一个小时吧。

在快要放弃的时候突然看到8266的红色指示灯很暗,突然想到会不会是供电不稳定啊,结果真的是杜邦线连接导致电压不稳,后来直接用USB供电就完全没问题了。希望遇到同样电压不稳问题的朋友,不要再把宝贵的时间浪费在这里了。

下面是我的开发板,接线比较多,杜邦线接来接去可能也就导致接触不良才出现以上电压不稳的问题,有点惨,供大家一笑。
在这里插入图片描述

(二)、正文开始

上面已经说过使用串口助手模拟设备给8266发送指令连接云平台并发送数据的方法,接下来只需要把串口助手发送数据换为STM32发送即可。

STM32两个串口的功能:
串口1的功能:负责打印信息(可以看到程序执行到了什么地方,主要用于观察程序执行过程即调试过程中修改错误使用)。
串口2功能:主要用于实现和8266的数据交互过程,发送数据和接收数据。

函数小鬼还有五秒到达战场…

1、ESP8266的初始化函数:
使能引脚,设置工作模式,连接路由器,设置单连接,连接TCP服务器等

void ESP8266_Init(void)
{

GPIO_InitTypeDef GPIO_Initure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

//ESP8266复位引脚
GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Initure.GPIO_Pin = GPIO_Pin_13;					//GPIOC13-复位
GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_Initure);

GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET);
delay_ms(250);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
delay_ms(500);

ESP8266_Clear();

printf("1. AT\r\n");
while(ESP8266_SendCmd("AT\r\n", "OK"))//AT测试
	delay_ms(500);

printf("2. CWMODE\r\n");
while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))//设置为STA模式
	delay_ms(500);

printf( "3. AT+CWDHCP\r\n");
while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))//开启DHCP
	delay_ms(500);

printf("4. CWJAP\r\n");
while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))//链接路由器
	delay_ms(500);

printf( "5. CIPSTART\r\n");
while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))//连接TCP服务器
	delay_ms(500);

printf("6. ESP8266 Init OK\r\n");//打印一下信息表明8266初试化成功

 }

2、上传数据到平台
从此函数开始下一个函数是前一个函数中调用过的函数

(小插曲)函数使用1-C语言中清空数组的办法

void OneNet_SendData(void)
{
char buf[256];
memset(buf, 0, sizeof(buf));//清空数组内容
OneNet_FillBuf(buf);	//封装数据流(把需要上传的数据封装到里面)
ESP8266_SendData((unsigned char *)buf, strlen(buf));	//上传已经封装好的数据

 }

3、封装数据函数
把需要上传的数据整合到一个数组里

(小插曲)函数使用2-sprintf格式化函数

(小插曲)函数使用3-strcat拼接函数

void OneNet_FillBuf(char *buf)
{
	char text[24];//存放临时数据
	char buf1[128];//最终的数据
	
	memset(text, 0, sizeof(text));
	memset(buf1, 0, sizeof(buf1));
	
	//要开始构造json格式了
	
	strcpy(buf1, "{");
	//buf1={
	
	memset(text, 0, sizeof(text));
	sprintf(text, "\"temp\":%d.%d,",temperatureH,temperatureL);//格式化温度
	strcat(buf1, text);
	//buf1={ \"Temperature\":20.3,
	
	memset(text, 0, sizeof(text));
	sprintf(text, "\"hum\":%d.%d", humidityH,humidityL);//格式化湿度
	strcat(buf1, text);
	//buf1={ \"Temperature\":20.3 , \"Humidity\":65.0
	
	strcat(buf1, "}");
	//buf1={ \"Temperature\":20.3 , \"Humidity\":65.0}
	
	//格式化数据
	sprintf(buf, "POST /devices/%s/datapoints?type=3 HTTP/1.1\r\napi-key:%s\r\nHost:api.heclouds.com\r\n"
					"Content-Length:%d\r\n\r\n",
	
					DEVID, APIKEY, strlen(buf1));			
	strcat(buf, buf1);//把要发送的数据拼接到buf发送数据的后面

	//此时buf含有所有需要上传的数据(设备id,apikey,数据长度,采集的数据)
	printf("pub_buf=%s\r\n",buf);

}

4、发送数据
在允许发送数据后,开始发送上一步封装好的数据

void ESP8266_SendData(unsigned char *data, unsigned short len)
{
char cmdBuf[32];
ESP8266_Clear();								//清空接收缓存
//先发送要发送数据的指令做准备
sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//发送命令
if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据
{
	//既然准备完毕即可开始发送数据
	Usart_SendString(USART2, data, len);		//发送设备连接请求数据
}
}

5、平台返回数据检测
检测反馈会的数据是发送成功还是失败

(小插曲)函数使用4-strstr字符串匹配函数

void OneNet_RevPro(unsigned char *dataPtr)
{

if(strstr((char *)dataPtr, "CLOSED"))
{
	printf("TCP CLOSED\r\n");
}
else
{
	//这里用来检测是否发送成功
	if(strstr((char *)dataPtr, "succ"))
	{
		printf("Tips:	Send OK\r\n");
	}
	else
	{
		printf("Tips:	Send Err\r\n");
	}
}

ESP8266_Clear();

}

6、主函数的内容

int main(void)
 {	

unsigned char *dataPtr = NULL;
unsigned short timeCount = 0;	//发送间隔变量
 
delay_init();	    	 //延时函数初始化	  
NVIC_Configuration(); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init();			     //LED端口初始化
OLED_Init();			//初始化OLED   
OLED_Clear();    
 
uart_init(115200);//串口1初始化
uart2_init(115200);//串口2初始化
DHT11_Init();//DHT11初始化
 
ESP8266_Init();					//初始化ESP8266
printf("8266_INIT_END\n");//初始化结束
while(1) 
{		
	if(++timeCount >= 500)		//间隔5s
	{
			
		if( Read_DHT11(&DHT11_Data)==SUCCESS)	//获取温湿度数据(温湿度均有整数位,小数位--湿度小数位忽略)
		{
			//printf("temp %d hum %d",DHT11_Data.temp_int,DHT11_Data.humi_int);
			OLED_ShowString(8,4,"TEMP:"); //显示温度
			OLED_ShowNum(48,4,DHT11_Data.temp_int,2,16);
			OLED_ShowChar(70,4,'.');
			OLED_ShowNum(85,4,DHT11_Data.temp_deci,1,16);
			
			//printf("temp=%d.%d\n",DHT11_Data.temp_int,DHT11_Data.temp_deci);
			
			printf("hum=%d.%d\n",DHT11_Data.humi_int,DHT11_Data.humi_deci);
			
			OLED_ShowString(8,2,"HUM:"); //显示湿度
			OLED_ShowNum(48,2,DHT11_Data.humi_int,2,16);
			OLED_ShowChar(70,2,'%'); 
			delay_ms(100);
		
			//将温湿度的各位赋值给对应的参数,上传云端时使用
			humidityH=DHT11_Data.humi_int;	  //湿度整数部分
			humidityL=DHT11_Data.humi_deci;	  //湿度小数部分
			temperatureH=DHT11_Data.temp_int;   //温度整数部分
			temperatureL=DHT11_Data.temp_deci;   //温度小数部分
			printf("hum temp=%d .%d %d .%d\r\n",humidityH,humidityL,temperatureH,temperatureL);
			
		}
		  printf( "OneNet_SendData\r\n");//通过串口1发送数据(表示下一步要发送数据了)
				
			OneNet_SendData();//发送数据给onenet
			
			printf("PUB_data_end\n");
		
			timeCount = 0;
			
			ESP8266_Clear();
	}
	//ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度,yyy是数据内容
	dataPtr = ESP8266_GetIPD(0);//获取平台返回的数据
	if(dataPtr != NULL)//如果返回数据不为空
		OneNet_RevPro(dataPtr);//平台返回数据检测
	
	delay_ms(10);
	
}

}

五、接下来将整理以下内容

1、STM32+ESP8266将本地采集的温湿度上传云端(MQTT)

2、STM32+ESP8266实现本地温湿度的上传和云端对开关的远程控制(MQTT)

如若发现错误或者不对的地方,还望评论指正,我会及时修改,谢谢。

相关文章