[RISC-V MCU 创新应用比赛] CH32V103驱动ESP8266连接阿里云物联网平台

[复制链接]
 楼主| gaochy1126 发表于 2021-8-22 22:13 | 显示全部楼层 |阅读模式
#申请原创#
这次要做的项目就是要通过CH32V103驱动ESP8266芯片,通过MQTT协议连接阿里云的物联网平台,并把温湿度数据和火警信息传递到阿里云的物联网平台。
此次用到的硬件CH32V103 ESP8266模块 DHT11芯片 火焰传感器。
怎么读取ESP8266和火焰传感器就见上一个贴子https://bbs.21ic.com/icview-3156850-1-1.html
购买一个esp8266模块首先是需要对ESP8266的AT固件进行升级,使用的工具为flash_download_tool_v3.8.5

这个文件太大了,不能上传过来,给一个链接把。https://www.espressif.com/zh-han ... d_type_tid%5B%5D=14
使用的固件版本是Ai-Thinker_ESP8266_DOUT_8Mbit_v1.5.4.1-a_20171130。这个在官网也有下载的。
这个可以放在这里 Ai-Thinker_ESP8266_DOUT_8Mbit_v1.5.4.1-a_20171130.rar (291.3 KB, 下载次数: 9)
程序下载的配置方式为
0.jpg

硬件第一步的问题解决了。下载开始在阿里云物联网平台搭建一个设备平台。
1 搭建阿里云物联网平台
注册好了阿里云以后,就是怎么搭建环境了。
1.jpg
进入物联网平台以后,首先需要创建产品。如上图所示
2.jpg
输入产品名称以后,选择自定义类型,这个不是必须的,点击确认。
3.jpg
点击查看设备,需要对设备的功能自定义进行配置。
4.jpg
找到功能自定义一栏,编辑草稿。需要添加自己定义的功能。

5.jpg
点击自定义功能,弹出下面的菜单。


对照下图添加功能名称和标识符,这个标识符是唯一的,不能重复。

6.jpg
然后发布就可以了,这个就完成了功能设计的最要的一些步骤了。

7.jpg

点击添加设备,弹出如下的菜单。需要选择产品,并输入设备名称,这个只能为英文。

8.jpg
添加设备成功以后,点击查看设备,进入需要用的三元素


9.jpg
这个就是连接阿里云物联网平台的三元素。后面需要用到的。若使用一机一密认证方式,设备上需要烧写product_key、device_name和device_secret
10.jpg
当设备平台搭建好以后,需要在iot studio 搭建显示界面。

11.jpg
点击新建web应用,并输入下面的设备名称。如果没有绑定设备,需要在iot studio里面绑定之前建好的产品和设备。
12.jpg
这些内容随便输入了。

13.jpg
点击编辑,进入编辑界面,对相关的界面进行配置。

14.jpg
从右侧控件栏中,添加仪表 和指示灯 曲线图等三个空间。

15.jpg
选中空间,在右侧属性一栏对相关数据进行配置。

16.jpg
这里仅仅展示一个温度显示的控件和数据的绑定过程。

17.jpg
搭建好后,点击预览就可在网页端查看相关的数据了。
2、搭建硬件平台。
外设和硬件对应的IO。
  1. ESP8266:串口2
  2. TX-----------PA3
  3. RX------------PA2

  4. 火焰传感器:
  5. IO----------PA1

  6. DHT11:
  7. IO----------PB10
至于MQTT是怎么通信的这里就不再赘述了,还是去百度一下吧。当然了不懂里面的规则也是无所谓的。流程都是一样的。
初始化ESP8266
首先需要配置ESP8266为AP模式,连接上家里的路由器,才能与外部网络进行通信。 ssid,  pswd分别为路由器的名称和密码。后面才能开始进行阿里云的连接通信了,使用的TCP的通信模式。
  1. uint8_t ESP8266_ConnectAP(char* ssid,char* pswd)
  2. {
  3.     uint8_t cnt=5;
  4.     while(cnt--)
  5.     {
  6.         memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));
  7.         ESP8266_ATSendString("AT+CWMODE_CUR=1\r\n");              //设置为STATION模式
  8.         if(FindStr((char*)usart2_rxbuf,"OK",200) != 0)
  9.         {
  10.             break;
  11.         }
  12.     }
  13.     if(cnt == 0)
  14.         return 0;

  15.     cnt=2;
  16.     while(cnt--)
  17.     {
  18.         memset(usart2_txbuf,0,sizeof(usart2_txbuf));//清空发送缓冲
  19.         memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));//清空接收缓冲
  20.         sprintf((char*)usart2_txbuf,"AT+CWJAP_CUR="%s","%s"\r\n",ssid,pswd);//连接目标AP
  21.         ESP8266_ATSendString((char*)usart2_txbuf);
  22.         if(FindStr((char*)usart2_rxbuf,"OK",8000)!=0)                      //连接成功且分配到IP
  23.         {
  24.             return 1;
  25.         }
  26.     }
  27.     return 0;
  28. }


MQTT通信阿里云需要明确是阿里云的三元素,就是加密的部分。
  1. char ClientID[128];
  2. char Username[128];  
  3. char Passward[128];     
密码就是用户名和产品,加上DeviceSecret的组合。
接入域名为 ${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com,端口固定为1883

ClientId由客户端ID(clientId)、安全模式(securemode)、签名算法类型(signmethod)和时间戳(timestamp)拼接而成。
例如${YourProductKey}|securemode=3,signmethod=hmacmd5|
来看个列表
01.jpg
在这里进行http://encode.chahuo.com/加密的过程。
02.jpg
获得的ID 用户名称和密码都填写到 ClientID  Username  Passward三个里面
使用的ESP8266的AT进行TCP的连接
  1. ESP8266_ConnectServer("TCP",ServerIP,1883)

具体AT的操作代码如下所示,使用的透传方式,就是需要在发送send指令了。
  1. uint8_t ESP8266_ConnectServer(char* mode,char* ip,uint16_t port)
  2. {
  3.     uint8_t cnt;

  4.     ESP8266_ExitUnvarnishedTrans();                   //多次连接需退出透传
  5.     Delay_Ms(500);

  6.     //连接服务器
  7.     cnt=2;
  8.     while(cnt--)
  9.     {
  10.         memset(usart2_txbuf,0,sizeof(usart2_txbuf));//清空发送缓冲
  11.         memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));//清空接收缓冲
  12.         sprintf((char*)usart2_txbuf,"AT+CIPSTART="%s","%s",%d\r\n",mode,ip,port);
  13.         ESP8266_ATSendString((char*)usart2_txbuf);
  14.         if(FindStr((char*)usart2_rxbuf,"CONNECT",8000) !=0 )
  15.         {
  16.                                         printf("%s",(char*)usart2_rxbuf);
  17.             break;
  18.         }
  19.     }
  20.     if(cnt == 0)
  21.         return 0;
  22.     //设置透传模式
  23.     if(ESP8266_OpenTransmission()==0) return 0;
  24.     //开启发送状态
  25.     cnt=2;
  26.     while(cnt--)
  27.     {
  28.         memset(usart2_rxbuf,0,sizeof(usart2_rxbuf)); //清空接收缓冲
  29.         ESP8266_ATSendString("AT+CIPSEND\r\n");//开始处于透传发送状态
  30.         if(FindStr((char*)usart2_rxbuf,">",200)!=0)
  31.         {
  32.             return 1;
  33.         }
  34.     }
  35.     return 0;
  36. }


TCP通信以后,需要进行MQTT通信录。
  1. MQTT_Connect(ClientID, Username, Passward)


MQTT的连接代码
  1. //MQTT连接服务器的打包函数
  2. uint8_t MQTT_Connect(char *ClientID,char *Username,char *Password)
  3. {
  4.         //char temp[200];
  5.         int ClientIDLen = strlen(ClientID);
  6.         int UsernameLen = strlen(Username);
  7.         int PasswordLen = strlen(Password);
  8.         int DataLen;
  9.         MQTT_TxLen=0;
  10.         //可变报头+Payload  每个字段包含两个字节的长度标识
  11.   DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
  12.         //固定报头
  13.         //控制报文类型
  14.   usart2_txbuf[MQTT_TxLen++] = 0x10;                //MQTT Message Type CONNECT
  15.         //剩余长度(不包括固定头部)
  16.         do{
  17.                 uint8_t encodedByte = DataLen % 128;
  18.                 DataLen = DataLen / 128;
  19.                 // if there are more data to encode, set the top bit of this byte
  20.                 if ( DataLen > 0 )
  21.                         encodedByte = encodedByte | 128;
  22.                 usart2_txbuf[MQTT_TxLen++] = encodedByte;
  23.         }while ( DataLen > 0 );
  24.         //可变报头
  25.         //协议名
  26.         usart2_txbuf[MQTT_TxLen++] = 0;                        // Protocol Name Length MSB
  27.         usart2_txbuf[MQTT_TxLen++] = 4;                        // Protocol Name Length LSB
  28.         usart2_txbuf[MQTT_TxLen++] = 'M';                // ASCII Code for M
  29.         usart2_txbuf[MQTT_TxLen++] = 'Q';                // ASCII Code for Q
  30.         usart2_txbuf[MQTT_TxLen++] = 'T';                // ASCII Code for T
  31.         usart2_txbuf[MQTT_TxLen++] = 'T';                // ASCII Code for T
  32.         //协议级别
  33.         usart2_txbuf[MQTT_TxLen++] = 4;                        // MQTT Protocol version = 4
  34.         //连接标志
  35.         usart2_txbuf[MQTT_TxLen++] = 0xc2;                // conn flags
  36.         usart2_txbuf[MQTT_TxLen++] = 0;                        // Keep-alive Time Length MSB
  37.         usart2_txbuf[MQTT_TxLen++] = 60;                // Keep-alive Time Length LSB  60S心跳包
  38.         usart2_txbuf[MQTT_TxLen++] = BYTE1(ClientIDLen);// Client ID length MSB
  39.         usart2_txbuf[MQTT_TxLen++] = BYTE0(ClientIDLen);// Client ID length LSB
  40.         memcpy(&usart2_txbuf[MQTT_TxLen],ClientID,ClientIDLen);
  41.         MQTT_TxLen += ClientIDLen;
  42.         if(UsernameLen > 0)
  43.         {   
  44.                 usart2_txbuf[MQTT_TxLen++] = BYTE1(UsernameLen);                //username length MSB
  45.                 usart2_txbuf[MQTT_TxLen++] = BYTE0(UsernameLen);            //username length LSB
  46.                 memcpy(&usart2_txbuf[MQTT_TxLen],Username,UsernameLen);
  47.                 MQTT_TxLen += UsernameLen;
  48.         }
  49.         if(PasswordLen > 0){   
  50.                 usart2_txbuf[MQTT_TxLen++] = BYTE1(PasswordLen);                //password length MSB
  51.                 usart2_txbuf[MQTT_TxLen++] = BYTE0(PasswordLen);            //password length LSB
  52.                 memcpy(&usart2_txbuf[MQTT_TxLen],Password,PasswordLen);
  53.                 MQTT_TxLen += PasswordLen;
  54.         }
  55.         uint8_t cnt=2;
  56.         uint8_t wait;
  57.         while(cnt--){
  58.                 memset(usart2_rxbuf,0,sizeof(usart2_rxbuf));
  59.                 MQTT_SendBuf(usart2_txbuf,MQTT_TxLen);
  60.                 wait=30;//等待3s时间
  61.                 while(wait--){
  62.                         //CONNECT
  63.                         if(usart2_rxbuf[0]==parket_connetAck[0] && usart2_rxbuf[1]==parket_connetAck[1]) //连接成功
建立连接以后,就是需要发布话题了。发布话题的代码如下所示:
  1. uint8_t MQTT_PublishData(char *topic, char *message, uint8_t qos)
  2. {  
  3.         int topicLength = strlen(topic);   
  4.         int messageLength = strlen(message);     
  5.         static uint16_t id=0;
  6.         int DataLen;
  7.         MQTT_TxLen=0;
  8.         //有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度
  9.         //QOS为0时没有标识符
  10.         //数据长度             主题名   报文标识符   有效载荷
  11.         if(qos)        DataLen = (2+topicLength) + 2 + messageLength;      
  12.         else        DataLen = (2+topicLength) + messageLength;   

  13.     //固定报头
  14.         //控制报文类型
  15.         usart2_txbuf[MQTT_TxLen++] = 0x30;    // MQTT Message Type PUBLISH

  16.         //剩余长度
  17.         do
  18.         {
  19.                 uint8_t encodedByte = DataLen % 128;
  20.                 DataLen = DataLen / 128;
  21.                 // if there are more data to encode, set the top bit of this byte
  22.                 if ( DataLen > 0 )
  23.                         encodedByte = encodedByte | 128;
  24.                 usart2_txbuf[MQTT_TxLen++] = encodedByte;
  25.         }while ( DataLen > 0 );       
  26.        
  27.         usart2_txbuf[MQTT_TxLen++] = BYTE1(topicLength);//主题长度MSB
  28.         usart2_txbuf[MQTT_TxLen++] = BYTE0(topicLength);//主题长度LSB
  29.         memcpy(&usart2_txbuf[MQTT_TxLen],topic,topicLength);//拷贝主题
  30.         MQTT_TxLen += topicLength;
  31.         
  32.         //报文标识符
  33.         if(qos)
  34.         {
  35.                         usart2_txbuf[MQTT_TxLen++] = BYTE1(id);
  36.                         usart2_txbuf[MQTT_TxLen++] = BYTE0(id);
  37.                         id++;
  38.         }
  39.         memcpy(&usart2_txbuf[MQTT_TxLen],message,messageLength);
  40.   MQTT_TxLen += messageLength;
  41.         
  42.         MQTT_SendBuf(usart2_txbuf,MQTT_TxLen);
  43.   return MQTT_TxLen;
  44. }
这个就是整个的操作过程。
最后需要在代码里面进行发布的操作。使用一个sprintf函数,把所有的代码转换到字符串中,然后发送出去。
  1.             sprintf(s_temp,"{"id":1,"params":{"CurrentTemperature":%d,"CurrentHumidity":%d,"warning":%d},"version":"1.0","method":"thing.event.property.post"}",
  2.                     temperature,humidity,cnt>0?1:0);
  3.             MQTT_PublishData(P_TOPIC_NAME, s_temp, 0);// 发送数据到服务器



最终的显示效果如图所示。
00.jpg

最后附上源代码

游客,如果您要查看本帖隐藏内容请回复


xdqfc 发表于 2021-8-23 11:01 | 显示全部楼层
请问阿里云平台是免费接入,还是需要每年每个终端都要付费啊?、
 楼主| gaochy1126 发表于 2021-8-23 14:39 | 显示全部楼层
xdqfc 发表于 2021-8-23 11:01
请问阿里云平台是免费接入,还是需要每年每个终端都要付费啊?、

现在来看是一定数量是免费的,一般没有问题。把发送时间间隔调的长一点。   
wangcf20006 发表于 2021-8-24 10:30 | 显示全部楼层
讲的不错,比较详细!!!!!!!!!!!!!
uiint 发表于 2021-9-2 20:28 | 显示全部楼层
有onenet的驱动代码吗?         
hellosdc 发表于 2021-9-2 20:30 | 显示全部楼层
ESP8266怎么下载固件?   
mituzu 发表于 2021-9-2 20:30 | 显示全部楼层
这个比较牛,物联网通信。   
suzhanhua 发表于 2021-9-2 20:31 | 显示全部楼层
esp8266如何怎样连接公网外网设置
xietingfeng 发表于 2021-9-2 20:31 | 显示全部楼层
可以不通过云服务器连接互联网吗?
isseed 发表于 2021-9-2 20:32 | 显示全部楼层
怎么接入物联网云服务平台
wangdezhi 发表于 2021-9-2 20:32 | 显示全部楼层

如何单片机通过wifi模块ESP8266连接外网web网页
biechedan 发表于 2021-9-2 20:33 | 显示全部楼层
esp8266怎么连接到wifi  
chenci2013 发表于 2021-9-2 20:33 | 显示全部楼层
有阿里云的AT固件吗   
gygp 发表于 2021-9-2 20:33 | 显示全部楼层
esp8266怎么将数据传给云平台
xietingfeng 发表于 2021-9-2 20:34 | 显示全部楼层
esp8266 想要通过mqtt协议连接华为云
suzhanhua 发表于 2021-9-2 20:34 | 显示全部楼层
作为客户端去tcp连接一个服务器?   
uiint 发表于 2021-9-2 20:34 | 显示全部楼层
onenet的http的上传方式。        
isseed 发表于 2021-9-2 20:34 | 显示全部楼层
如何固定接收数据的端口  
mituzu 发表于 2021-9-2 20:34 | 显示全部楼层
传输数据的最大速度是多少呢   
chenci2013 发表于 2021-9-2 20:34 | 显示全部楼层
ESP8266如何实现与服务器的TCP通讯
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:这个社会混好的两种人:一是有权有势,二是没脸没皮的。

1148

主题

11651

帖子

26

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:这个社会混好的两种人:一是有权有势,二是没脸没皮的。

1148

主题

11651

帖子

26

粉丝
快速回复 在线客服 返回列表 返回顶部