1. 功能介紹
現(xiàn)在物聯(lián)網(wǎng)已經(jīng)遍布生活每個角落,幾乎哪里都能看到物聯(lián)網(wǎng)的應(yīng)用。物聯(lián)網(wǎng)就是物物相連的互聯(lián)網(wǎng),可以將之前單機設(shè)備全部接入互聯(lián)網(wǎng),完成數(shù)據(jù)交互,遠(yuǎn)程控制。 比如: 智能電表(遠(yuǎn)程抄表),智能水表,智能天然氣表,智能井蓋(遠(yuǎn)程向市政機關(guān)上包污水污染程度、水深程度),智慧路燈,智慧停車場(APP上遠(yuǎn)程查看是否有空余車位)等等,都是物聯(lián)網(wǎng)成功應(yīng)用的例子。
現(xiàn)在各大平臺都提供了物聯(lián)網(wǎng)服務(wù)器,比如:OneNet(中國移動)、阿里云物聯(lián)網(wǎng)、百度天工物接入、華為云物聯(lián)網(wǎng)、機智云物聯(lián)網(wǎng)、騰訊云物聯(lián)網(wǎng)(支持自定義小程序,效果非常nice)等。
前面幾篇文章已經(jīng)分別介紹了,OneNet(中國移動)、阿里云物聯(lián)網(wǎng)、騰訊云物聯(lián)網(wǎng) 平臺的接入案例。
OneNet(中國移動): https://xiaolong.blog.csdn.net/article/details/107385118
騰訊云物聯(lián)網(wǎng): https://xiaolong.blog.csdn.net/article/details/117167261
阿里云物聯(lián)網(wǎng): https://xiaolong.blog.csdn.net/article/details/107311897
這篇文章就介紹如何使用STM32接入華為云物聯(lián)網(wǎng)平臺,完成數(shù)據(jù)交互,設(shè)計案例是基于華為云物聯(lián)網(wǎng)平臺設(shè)計智能家居控制系統(tǒng)(模型),硬件采用STM32+ESP8266完成上云組合;通過云平臺可以遠(yuǎn)程控制家里的各種電器開關(guān),并且可以遠(yuǎn)程收集家里煤氣、天然氣、煙霧、光照度、溫度濕度等信息。
硬件介紹:
主控MCU: STM32F103ZET6
天然氣檢測傳感:MQ5
溫度濕度檢測傳感器: DHT11
光照強度檢測傳感器: BH1750
物聯(lián)網(wǎng)云平臺: 華為云物聯(lián)網(wǎng)平臺
電器開關(guān)模擬采用板載的LED燈、繼電器。
WIFI: ESP8266
這是支持串口AT指令控制的WIFI模塊,聯(lián)網(wǎng)比較方便。
與華為云物聯(lián)網(wǎng)平臺通信的協(xié)議: MQTT
說明: 當(dāng)前程序里的MQTT協(xié)議代碼是參考MQTT官方文檔編寫的,不是使用ESP8266內(nèi)置的,所以程序并不依賴ESP8266專用或者指定的SDK,使用任意可以上網(wǎng)的網(wǎng)卡都可以套用,并不是一定非要使用ESP8266。
2. 登錄華為云創(chuàng)建云端設(shè)備
2.1 創(chuàng)建產(chǎn)品
華為運官網(wǎng): https://www.huaweicloud.com/
在這里可以查看接入的協(xié)議的端口號和地址。
我們設(shè)備接入的協(xié)議選擇MQTT,端口對應(yīng)是1883
接下來繼續(xù)創(chuàng)建產(chǎn)品,點擊產(chǎn)品頁面,點擊右上角創(chuàng)建產(chǎn)品:
2.2 創(chuàng)建設(shè)備
設(shè)備ID
61a580fad28ce3028832c2d8_esp8266_iot
設(shè)備密鑰
1126626497
{
"device_id": "61a580fad28ce3028832c2d8_esp8266_iot",
"secret": "1126626497"
}
2.3 產(chǎn)品模型定義
這一步就是設(shè)置上報設(shè)備的屬性,也就是設(shè)備的數(shù)據(jù)類型定義。
2.4 生成MQTT登錄密匙
創(chuàng)建完產(chǎn)品、設(shè)備之后,接下來就需要知道如何通過MQTT協(xié)議登陸華為云服務(wù)器。
官方的詳細(xì)介紹在這里: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html#ZH-CN_TOPIC_0240834853__zh-cn_topic_0251997880_li365284516112
MQTT設(shè)備登陸密匙生成地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
下面就得到了MQTT協(xié)議設(shè)備登錄的參數(shù)。
2.5 使用MQTT客戶端軟件登錄
所有的參數(shù)已經(jīng)得到,接下來采用MQTT客戶端登錄華為云進(jìn)行測試。
下面這個軟件是自己開發(fā)的,為了方便測試MQTT協(xié)議登錄。
華為云物聯(lián)網(wǎng)平臺的域名是: a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
華為云物聯(lián)網(wǎng)平臺的IP地址是: 121.36.42.100
在軟件里參數(shù)填充正確之后,就看到設(shè)備已經(jīng)連接成功了。
接下來打開設(shè)備頁面,可以看到設(shè)備已經(jīng)在線了。
2.6 上報數(shù)據(jù)
官方文檔: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html#ZH-CN_TOPIC_0240834853__zh-cn_topic_0251997880_li365284516112
在這個文檔里介紹了MQTT上報數(shù)據(jù)的格式。
總結(jié)的格式:
//訂閱主題: 平臺下發(fā)消息給設(shè)備
$oc/devices/61a580fad28ce3028832c2d8_esp8266_iot/sys/messages/down
//設(shè)備上報數(shù)據(jù)
$oc/devices/61a580fad28ce3028832c2d8_esp8266_iot/sys/properties/report
//上報的屬性消息 (一次可以上報多個屬性,在json里增加就行了)
{"services": [{"service_id": "dht11","properties":{"DHT11-C":50}}]}
下面采用MQTT軟件上報數(shù)據(jù):
到此,設(shè)備數(shù)據(jù)已經(jīng)上報成功,如果需要增加更多的屬性,按照流程繼續(xù)增加即可。
3. STM32+ESP8266上報數(shù)據(jù)到華為云
3.1 硬件設(shè)備效果圖
3.2 BH1750.c 光照度傳感器
#include "bh1750.h"
float Read_BH1750_Data()
{
unsigned char t0;
unsigned char t1;
float t;
u8 r_s=0;
IIC_Start(); //發(fā)送起始信號
IIC_WriteOneByteData(0x46);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:1\r\n");
IIC_WriteOneByteData(0x01);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:2\r\n");
IIC_Stop(); //停止信號
IIC_Start(); //發(fā)送起始信號
IIC_WriteOneByteData(0x46);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:3\r\n");
IIC_WriteOneByteData(0x01);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:4\r\n");
IIC_Stop(); //停止信號
IIC_Start(); //發(fā)送起始信號
IIC_WriteOneByteData(0x46);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:5\r\n");
IIC_WriteOneByteData(0x10);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:6\r\n");
IIC_Stop(); //停止信號
DelayMs(300); //等待
IIC_Start(); //發(fā)送起始信號
IIC_WriteOneByteData(0x47);
r_s=IIC_GetACK();//獲取應(yīng)答
if(r_s)printf("error:7\r\n");
t0=IIC_ReadOneByteData(); //接收數(shù)據(jù)
IIC_SendACK(0); //發(fā)送應(yīng)答信號
t1=IIC_ReadOneByteData(); //接收數(shù)據(jù)
IIC_SendACK(1); //發(fā)送非應(yīng)答信號
IIC_Stop(); //停止信號
t=(((t0<<8)|t1)/1.2);
return t;
}
3.3 ESP8266.c WIFI代碼
#include "esp8266.h"
u8 ESP8266_IP_ADDR[16]; //255.255.255.255
u8 ESP8266_MAC_ADDR[18]; //硬件地址
/*
函數(shù)功能: ESP8266命令發(fā)送函數(shù)
函數(shù)返回值:0表示成功 1表示失敗
*/
u8 ESP8266_SendCmd(char *cmd)
{
u8 i,j;
for(i=0;i<10;i++) //檢測的次數(shù)--發(fā)送指令的次數(shù)
{
USARTx_StringSend(USART3,cmd);
for(j=0;j<100;j++) //等待的時間
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
if(strstr((char*)USART3_RX_BUFFER,"OK"))
{
return 0;
}
}
}
}
return 1;
}
/*
函數(shù)功能: ESP8266硬件初始化檢測函數(shù)
函數(shù)返回值:0表示成功 1表示失敗
*/
u8 ESP8266_Init(void)
{
//退出透傳模式
USARTx_StringSend(USART3,"+++");
delay_ms(50);
return ESP8266_SendCmd("AT\r\n");
}
/*
函數(shù)功能: TCP服務(wù)器模式下的發(fā)送函數(shù)
發(fā)送指令:
*/
u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len)
{
u8 i,j,n;
char ESP8266_SendCMD[100]; //組合發(fā)送過程中的命令
for(i=0;i<10;i++)
{
sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d,%d\r\n",id,len);
USARTx_StringSend(USART3,ESP8266_SendCMD);
for(j=0;j<10;j++)
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
if(strstr((char*)USART3_RX_BUFFER,">"))
{
//繼續(xù)發(fā)送數(shù)據(jù)
USARTx_DataSend(USART3,data,len);
//等待數(shù)據(jù)發(fā)送成功
for(n=0;n<200;n++)
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
{
return 0;
}
}
}
}
}
}
}
return 1;
}
/*
函數(shù)功能: 配置WIFI為STA模式+TCP客戶端模式
函數(shù)參數(shù):
char *ssid 創(chuàng)建的熱點名稱
char *pass 創(chuàng)建的熱點密碼 (最少8位)
char *p 將要連接的服務(wù)器IP地址
u16 port 將要連接的服務(wù)器端口號
u8 flag 1表示開啟透傳模式 0表示關(guān)閉透傳模式
函數(shù)返回值:0表示成功 其他值表示對應(yīng)的錯誤
*/
u8 ESP8266_STA_TCP_Client_Mode(char *ssid,char *pass,char *ip,u16 port,u8 flag)
{
char ESP8266_SendCMD[100]; //組合發(fā)送過程中的命令
//退出透傳模式
//USARTx_StringSend(USART3,"+++");
//delay_ms(50);
/*1. 測試硬件*/
if(ESP8266_SendCmd("AT\r\n"))return 1;
/*2. 關(guān)閉回顯*/
if(ESP8266_SendCmd("ATE0\r\n"))return 2;
/*3. 設(shè)置WIFI模式*/
if(ESP8266_SendCmd("AT+CWMODE=1\r\n"))return 3;
/*4. 復(fù)位*/
ESP8266_SendCmd("AT+RST\r\n");
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
/*5. 關(guān)閉回顯*/
if(ESP8266_SendCmd("ATE0\r\n"))return 5;
/*6. 配置將要連接的WIFI熱點信息*/
sprintf(ESP8266_SendCMD,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pass);
if(ESP8266_SendCmd(ESP8266_SendCMD))return 6;
/*7. 設(shè)置單連接*/
if(ESP8266_SendCmd("AT+CIPMUX=0\r\n"))return 7;
/*8. 配置要連接的TCP服務(wù)器信息*/
sprintf(ESP8266_SendCMD,"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",ip,port);
if(ESP8266_SendCmd(ESP8266_SendCMD))return 8;
/*9. 開啟透傳模式*/
if(flag)
{
if(ESP8266_SendCmd("AT+CIPMODE=1\r\n"))return 9; //開啟
if(ESP8266_SendCmd("AT+CIPSEND\r\n"))return 10; //開始透傳
if(!(strstr((char*)USART3_RX_BUFFER,">")))
{
return 11;
}
//如果想要退出發(fā)送: "+++"
}
//打印總體信息
USART1_Printf("WIFI模式:STA+TCP客戶端\n");
USART1_Printf("Connect_WIFI熱點名稱:%s\n",ssid);
USART1_Printf("Connect_WIFI熱點密碼:%s\n",pass);
USART1_Printf("TCP服務(wù)器端口號:%d\n",port);
USART1_Printf("TCP服務(wù)器IP地址:%s\n",ip);
return 0;
}
/*
函數(shù)功能: TCP客戶端模式下的發(fā)送函數(shù)
發(fā)送指令:
*/
u8 ESP8266_ClientSendData(u8 *data,u16 len)
{
u8 i,j,n;
char ESP8266_SendCMD[100]; //組合發(fā)送過程中的命令
for(i=0;i<10;i++)
{
sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d\r\n",len);
USARTx_StringSend(USART3,ESP8266_SendCMD);
for(j=0;j<10;j++)
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
if(strstr((char*)USART3_RX_BUFFER,">"))
{
//繼續(xù)發(fā)送數(shù)據(jù)
USARTx_DataSend(USART3,data,len);
//等待數(shù)據(jù)發(fā)送成功
for(n=0;n<200;n++)
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
{
return 0;
}
}
}
}
}
}
}
return 1;
}
3.4 main.c 主函數(shù)
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include
#include "timer.h"
#include "esp8266.h"
#include "mqtt.h"
#include "oled.h"
#include "fontdata.h"
#include "bh1750.h"
#include "iic.h"
#include "sht3x.h"
#define ESP8266_WIFI_AP_SSID "CMCC-Cqvn" //將要連接的路由器名稱 --不要出現(xiàn)中文、空格等特殊字符
#define ESP8266_AP_PASSWORD "99pu58cb" //將要連接的路由器密碼
//華為云服務(wù)器的設(shè)備信息
#define MQTT_ClientID "61a580fad28ce3028832c2d8_esp8266_iot_0_0_2021113002"
#define MQTT_UserName "61a580fad28ce3028832c2d8_esp8266_iot"
#define MQTT_PassWord "74af3bf3024cf9c41b13d6c63fc86e25012b54141ecfcdff3516f08665140e6f"
//訂閱與發(fā)布的主題
#define SET_TOPIC "$oc/devices/61a580fad28ce3028832c2d8_esp8266_iot/sys/messages/down" //訂閱
#define POST_TOPIC "$oc/devices/61a580fad28ce3028832c2d8_esp8266_iot/sys/properties/report" //發(fā)布
char mqtt_message[200];//上報數(shù)據(jù)緩存區(qū)
char OLED_ShowBuff[100];
u8 ESP8266_Stat=0;
/*
函數(shù)功能: 溫濕度\光強度顯示
*/
void ShowTemperatureAndHumidity(float temp,float humi,float light)
{
sprintf(OLED_ShowBuff,"T: %.2f",temp);
OLED_ShowString(40,16*0,16,OLED_ShowBuff);
sprintf(OLED_ShowBuff,"H: %.2f%%",humi);
OLED_ShowString(40,16*1,16,OLED_ShowBuff);
sprintf(OLED_ShowBuff,"L: %.2f%%",light);
OLED_ShowString(40,16*2,16,OLED_ShowBuff);
}
/*
函數(shù)功能: ESP8266顯示頁面
*/
void ESP8266_ShowPageTable(void)
{
if(ESP8266_Stat)OLED_ShowString(0,16*0,16,"WIFI STAT:ERROR");
else OLED_ShowString(0,16*0,16,"WIFI STAT:OK");
//顯示字符串
sprintf((char*)OLED_ShowBuff,"%s",ESP8266_WIFI_AP_SSID);
OLED_ShowString(0,16*1,16,OLED_ShowBuff);
sprintf((char*)OLED_ShowBuff,"%s",ESP8266_AP_PASSWORD);
OLED_ShowString(0,16*2,16,OLED_ShowBuff);
}
int main()
{
u32 time_cnt=0;
u32 i;
u8 key;
u8 page=0;
float temp=0;
float humi=0;
float light=0;
u8 motor_state=0;
float Humidity;
float Temperature;
delay_ms(1000);
delay_ms(1000);
LED_Init();
KEY_Init();
IIC_Init();
//OLED初始化
OLED_Init(0xc8,0xa1); //OLED顯示屏初始化--正常顯示;
//清屏
OLED_Clear(0);
USART1_Init(115200);
TIMER1_Init(72,20000); //超時時間20ms
USART3_Init(115200);//串口-WIFI
TIMER3_Init(72,20000); //超時時間20ms
Init_SHT30();
USART1_Printf("正在初始化WIFI請稍等.\n");
if(ESP8266_Init())
{
ESP8266_Stat=1;
USART1_Printf("ESP8266硬件檢測錯誤.\n");
}
else
{
//非加密端口
USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode(ESP8266_WIFI_AP_SSID,ESP8266_AP_PASSWORD,"121.36.42.100",1883,1));
}
//2. MQTT協(xié)議初始化
MQTT_Init();
//3. 連接華為云IOT服務(wù)器
while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
{
USART1_Printf("服務(wù)器連接失敗,正在重試...\n");
delay_ms(500);
}
USART1_Printf("服務(wù)器連接成功.\n");
//3. 訂閱主題
if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
{
USART1_Printf("主題訂閱失敗.\n");
}
else
{
USART1_Printf("主題訂閱成功.\n");
}
while(1)
{
//按鍵可以測試
key=KEY_Scan(0);
if(key==1)
{
//清屏
OLED_Clear(0);
//翻頁
if(page>=1)
{
page=0;
}
else
{
page++;
}
LED1=!LED1; //LEd狀態(tài)燈
}
else if(key==2)
{
LED1=!LED1; //LEd狀態(tài)燈
time_cnt=0;
//電機狀態(tài)改變
MOTOR_DEV=!MOTOR_DEV;
//電機狀態(tài)
motor_state=MOTOR_DEV;
//補光燈
LIGHT_DEV=!LIGHT_DEV;
}
//接收WIFI返回的數(shù)據(jù)
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='\0';
//向串口打印返回的數(shù)據(jù)
for(i=0;i;i++)>
審核編輯:湯梓紅
-
控制系統(tǒng)
+關(guān)注
關(guān)注
41文章
6604瀏覽量
110576 -
物聯(lián)網(wǎng)
+關(guān)注
關(guān)注
2909文章
44557瀏覽量
372780 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355743 -
智能家居
+關(guān)注
關(guān)注
1928文章
9553瀏覽量
184937 -
華為云
+關(guān)注
關(guān)注
3文章
2445瀏覽量
17409
發(fā)布評論請先 登錄
相關(guān)推薦
評論