上一篇文章内容链接为下
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云平台创建产品和设备
1、在控制台首页切换至旧版本
01-ONENET控制台首页-请点我
2、选择全部产品-多协议接入,
3、创建http协议下的产品和设备
在HTTP协议下自己创建产品,在产品之下再对应创建一个设备即可(下方为官方文档)-也可以自行百度新建产品和设备的博客
4、查看密钥和设备ID
产品和设备创建完毕后,保存我们需要的密钥和设备id
5、素材获取
自己根据下方提供的素材进行整合到自己程序中去就可以,素材内容为下,点击连接获取:
onenet.c和ESP8266.c素材连接提取码:aavj
6、修改参数信息
在onenet.c文件的代码中要进行修改为自己的设备ID和密钥
7、修改wifi名和密码
在esp8266.c文件的代码中修改要连接的wifi名和wifi密码
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和>后即可发送数据)
上一步已经连接云端并开启了数据透传模式,接下来即可通过串口助手发送数据,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串口2接收不到8266反馈信息
我在刚开始便遇到了问题,在程序整合逻辑代码均没错误之后,使用串口2给ESP8266发送控制指令进行初始化,结果永远收不到反馈消息,也就一直没有初始化成功,还没开始,就这样结束了?
怎么可能放弃呢,于是就一点一点的排除,先单独用USB调试ESP8266完全没问题,再使用串口2发送和接收数据测试也没问题,然后又借助逻辑分析仪分析出每次串口都发送出了AT指令,的确是没有返回数据,或者只反馈回一小部分错误信息,调了得一个小时吧。
在快要放弃的时候突然看到8266的红色指示灯很暗,突然想到会不会是供电不稳定啊,结果真的是杜邦线连接导致电压不稳,后来直接用USB供电就完全没问题了。希望遇到同样电压不稳问题的朋友,不要再把宝贵的时间浪费在这里了。
下面是我的开发板,接线比较多,杜邦线接来接去可能也就导致接触不良才出现以上电压不稳的问题,有点惨,供大家一笑。
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);
}
}
最终代码整合下载链接
3-STM32+ESP8266连接onenet上传数据+远程控制(MQTT)链接