?一、環(huán)境介紹
上網(wǎng)方式:采用ESP8266,也可以使用其他設備代替,只要支持TCP協(xié)議即可。比如:GSM模塊、有線網(wǎng)卡等。
云平臺: 采用中國移動OneNet. 也可以采用騰訊、阿里云、華為云、百度天工物接入、機智云等等。 前面文章有講解。
協(xié)議: 采用MQTT協(xié)議
開發(fā)軟件:keil5
二、包含的硬件與實物圖介紹
2. 一個DHT11溫濕度傳感器
3. 一個MQ-5 液化氣/天然氣/煤氣監(jiān)測傳感器
4. 一個MQ-2 煙霧傳感器
5. 3盞LED燈表示窗簾開關、空調(diào)開關、電視開關
6. 聯(lián)網(wǎng)WIFI采用: ESP8266
7. 最小系統(tǒng)板: STM32F103C8T6
8. 物聯(lián)網(wǎng)服務器: OneNet平臺
9. 物聯(lián)網(wǎng)手機APP: 設備云
設備云APP下載地址(Android): onenet設備云.zip-桌面系統(tǒng)文檔類資源-CSDN下載
?
?
?
三、功能介紹
這是基于STM32設計的智能家居控制系統(tǒng),采用ESP8266連接OneNet云平臺。
設備端可以實時采集煙霧濃度、溫濕度、煤氣天然氣濃度到云平臺,在云平臺網(wǎng)頁端或者手機APP上可以遠程查看數(shù)據(jù),還可以點擊云平臺界面上的按鈕,完成對家里的電器設備控制:窗簾開關、空調(diào)開關、電視開關(采用LED燈模擬)等。
?
?
?
?
?
四、OneNet創(chuàng)建設備
從0開始創(chuàng)建OneNet設備,參考這里:STM32+ESP8266+MQTT協(xié)議連接OneNet物聯(lián)網(wǎng)平臺_DS小龍哥的專欄-CSDN博客_esp8266mqtt協(xié)議
首地址:OneNET - 中國移動物聯(lián)網(wǎng)開放平臺
?
?
?
?
?
這是STM32設備端連接OneNet串口打印的提示信息:
?
登錄成功的效果:
?
?
數(shù)據(jù)流收到物聯(lián)網(wǎng)終端上傳的信息。
?
查看設計的網(wǎng)頁界面:
?
?
?
五、程序下載介紹
?
點擊開始編程之后,按下開發(fā)板上的RST按鈕,即可啟動下載。
六、STM32設備端代碼
?
6.1 esp8266.c
#include "esp8266.h"
struct ESP8266_WIFI esp8266_wifi;
/*
函數(shù)功能: 配置ESP8266WIFI為AP模式+TCP服務器模式
函數(shù)參數(shù):
char *ssid :將要創(chuàng)建的WIFI熱點名稱(英文字母)
char *password :將要創(chuàng)建的WIFI熱點密碼(最短長度8位)
u16 port :TCP服務器的端口號(0~65535)
返 回 值:0表示成功,其他值表示失敗
*/
u8 ESP8266_AP_TCP_ServerMode(const char *ssid,const char *password,u16 port)
{
u8 i;
char *find_str=NULL;
char cmd_buffer[100];
/*1. 發(fā)送測試指令,檢測WIFI是否正常*/
printf("發(fā)送測試指令,檢測WIFI是否正常...\n");
if(ESP8266_SendCmd("AT\r\n"))return 1;
/*2. 關閉回顯*/
printf("關閉回顯...\n");
if(ESP8266_SendCmd("ATE0\r\n"))return 2;
/*3. 設置當前WIFI的模式為AP模式*/
printf("設置當前WIFI的模式為AP模式...\n");
if(ESP8266_SendCmd("AT+CWMODE=2\r\n"))return 3;
/*4. 復位模塊,設置的模式必須復位之后才會生效*/
printf("復位模塊...\n");
if(ESP8266_SendCmd("AT+RST\r\n"))return 4;
DelayMs_72M(1000);
DelayMs_72M(1000);
DelayMs_72M(1000);
DelayMs_72M(1000);
/*5. 關閉回顯*/
printf("關閉回顯...\n");
if(ESP8266_SendCmd("ATE0\r\n"))return 5;
/*6. 設置創(chuàng)建的熱點信息*/
printf("設置創(chuàng)建的熱點信息...\n");
snprintf(cmd_buffer,100,"AT+CWSAP="%s","%s",1,4\r\n",ssid,password);
if(ESP8266_SendCmd(cmd_buffer))return 6;
/*7. 開啟多連接,在服務器模式下才可開啟*/
printf("開啟多連接...\n");
if(ESP8266_SendCmd("AT+CIPMUX=1\r\n"))return 7;
/*8. 設置端口號(0~65535)*/
printf("設置端口號...\n");
snprintf(cmd_buffer,100,"AT+CIPSERVER=1,%d\r\n",port);
if(ESP8266_SendCmd(cmd_buffer))return 8;
/*9.查詢本地IP地址*/
printf("查詢本地IP地址...\n");
if(ESP8266_SendCmd("AT+CIFSR\r\n"))return 9;
/*10. 保存WIFI的信息*/
esp8266_wifi.port=port;
strcpy(esp8266_wifi.mode,"AP");
//提取IP地址
/*
IP地址=+CIFSR:APIP,"192.168.4.1"
+CIFSR:APMAC,"86:f3:eb:17:e6:86"
*/
find_str=strstr((char*)USART3_RX_BUFF,"APIP");
if(find_str) //判斷是否查找成功
{
find_str+=6;
for(i=0;*find_str!='"';i++)
{
esp8266_wifi.ip[i]=*find_str;
find_str++;
}
esp8266_wifi.ip[i]='\0';
}
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
printf("當前WIFI模式:%s\n",esp8266_wifi.mode);
printf("當前網(wǎng)絡協(xié)議類型:%s\n","TCP");
printf("當前網(wǎng)絡通信模式:%s\n","server");
printf("當前網(wǎng)絡端口號:%d\n",esp8266_wifi.port);
printf("本地網(wǎng)絡IP地址:%s\n",esp8266_wifi.ip);
return 0;
}
/*
函數(shù)功能:向ESP8266wifi發(fā)送指令
說明:該函數(shù)只是適用于成功后返回OK的指令
返回值: 0表示成功 1表示失敗
*/
u8 ESP8266_SendCmd(char *cmd)
{
u8 i,j;
for(i=0;i<5;i++) //測試的總次數(shù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
USART_X_SendString(USART3,cmd);
for(j=0;j<200;j++) //等待的時間(ms單位)
{
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
printf("USART3_RX_BUFF=%s\r\n",USART3_RX_BUFF);
if(strstr((char*)USART3_RX_BUFF,"OK\r\n"))
{
return 0;
}
else break;
}
DelayMs_72M(2); //一次的時間
}
}
return 1;
}
/*
函數(shù)功能:ESP8266wifi處于TCP服務器模式下的數(shù)據(jù)發(fā)送函數(shù)
函數(shù)參數(shù):
u8 id :已經(jīng)連接服務器的客戶端ID號
char *data :將要發(fā)送數(shù)據(jù)(字符串)
返回值: 0表示成功 1表示失敗
說明:只有在TCP服務器模式下才可使用該函數(shù)
OK
>
Recv 12 bytes
SEND OK
*/
u8 ESP8266_ServerSendData(u8 id,char *data)
{
u32 i,j,n;
char cmd[100];
snprintf(cmd,1024,"AT+CIPSEND=%d,%d\r\n",id,strlen(data));
for(i=0;i<5;i++) //測試的總次數(shù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
USART_X_SendString(USART3,cmd);
for(j=0;j<200;j++) //等待的時間(ms單位)
{
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
if(strstr((char*)USART3_RX_BUFF,">")) //開始發(fā)送數(shù)據(jù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
USART_X_SendString(USART3,data); //發(fā)送數(shù)據(jù)
for(n=0;n<10000;n++)
{
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
if(strstr((char*)USART3_RX_BUFF,"SEND OK")) //開始發(fā)送數(shù)據(jù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
return 0;
}
else return 1;
}
DelayMs_72M(1); //一次的時間
}
}
else break;
}
DelayMs_72M(5); //一次的時間
}
}
return 1;
}
/*
函數(shù)功能: 設置STA模式下連接的熱點信息
返 回 值: 0表示成功,1表示失敗
連接成功的提示符:
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IP
OK
*/
u8 ESP8266_STA_ModeConnectWIFI(char *cmd)
{
u32 i,j;
for(i=0;i<3;i++) //測試的總次數(shù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
USART_X_SendString(USART3,cmd);
for(j=0;j<30000;j++) //等待的時間(ms單位)
{
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
if(strstr((char*)USART3_RX_BUFF,"OK"))
{
return 0;
}
else
{
memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
}
}
DelayMs_72M(1); //一次的時間
}
}
return 1;
}
/*
函數(shù)功能: 用于在客戶端模式下,連接服務器
返 回 值: 0表示成功,1表示失敗
連接成功的提示符:CONNECT
*/
u8 ESP8266_ConnectServer(char *cmd)
{
u32 i,j;
for(i=0;i<5;i++) //測試的總次數(shù)
{
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
USART_X_SendString(USART3,cmd);
for(j=0;j<10000;j++) //等待的時間(ms單位)
{
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
if(strstr((char*)USART3_RX_BUFF,"CONNECT"))
{
return 0;
}
else
{
memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
USART3_RX_FLAG=0;
USART3_RX_CNT=0;
}
}
DelayMs_72M(1); //一次的時間
}
}
return 1;
}
/*
函數(shù)功能: 配置ESP8266WIFI為STA模式+TCP客戶端模式
函數(shù)參數(shù):
char *ssid :將要連接的WIFI熱點名稱(英文字母)
char *password :將要連接的WIFI熱點密碼(最短長度8位)
u16 port :TCP服務器的端口號(0~65535)
返 回 值:0表示成功,其他值表示失敗
*/
u8 ESP8266_STA_TCP_ClientMode(const char *ssid,const char *password,char *server_ip,u16 port)
{
u8 i;
char *find_str=NULL;
char cmd_buffer[100];
/*1. 發(fā)送測試指令,檢測WIFI是否正常*/
printf("發(fā)送測試指令,檢測WIFI是否正常...\n");
for(i=0;i<10;i++)
{
if(ESP8266_SendCmd("AT\r\n")) //可能WIFI正處于透傳模式,無法接收指令
{
USART_X_SendString(USART3,"+++"); //退出透傳模式
DelayMs_72M(80); //等待退出透傳模式
}
else break;
}
if(i==10)return 1; //檢測失敗
/*2. 關閉回顯*/
printf("關閉回顯...\n");
if(ESP8266_SendCmd("ATE0\r\n"))return 2;
/*3. 設置當前WIFI的模式為STA模式*/
printf("設置當前WIFI的模式為STA模式...\n");
if(ESP8266_SendCmd("AT+CWMODE=1\r\n"))return 3;
/*4. 復位模塊,設置的模式必須復位之后才會生效*/
printf("復位模塊...\n");
if(ESP8266_SendCmd("AT+RST\r\n"))return 4;
DelayMs_72M(1000);
DelayMs_72M(1000);
DelayMs_72M(1000);
DelayMs_72M(1000);
/*5. 關閉回顯*/
printf("關閉回顯...\n");
if(ESP8266_SendCmd("ATE0\r\n"))return 5;
/*6. 設置連接的熱點信息*/
printf("設置連接的熱點信息...\r\n");
snprintf(cmd_buffer,100,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,password);
printf("cmd_buffer=%s",cmd_buffer);
if(ESP8266_STA_ModeConnectWIFI(cmd_buffer))return 6;
/*7. 開啟單連接,在客戶端模式下才可開啟*/
printf("開啟單連接...\n");
if(ESP8266_SendCmd("AT+CIPMUX=0\r\n"))return 8;
/*8.查詢本地IP地址*/
printf("查詢本地IP地址...\n");
if(ESP8266_SendCmd("AT+CIFSR\r\n"))return 7;
/*9. 保存WIFI的信息*/
esp8266_wifi.port=port;
strcpy(esp8266_wifi.mode,"STA");
//提取IP地址
/*
+CIFSR:STAIP,"192.168.1.115"
+CIFSR:STAMAC,"84:f3:eb:17:e6:86"
*/
find_str=strstr((char*)USART3_RX_BUFF,"STAIP");
if(find_str) //判斷是否查找成功
{
find_str+=7;
for(i=0;*find_str!='"';i++)
{
esp8266_wifi.ip[i]=*find_str;
find_str++;
}
esp8266_wifi.ip[i]='\0';
}
/*10. 連接服務器*/
printf("開始連接服務器...\n");
snprintf(cmd_buffer,100,"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",server_ip,port);
if(ESP8266_ConnectServer(cmd_buffer))return 9;
/*11. 開啟透傳模式*/
printf("開啟透傳模式...\n");
if(ESP8266_SendCmd("AT+CIPMODE=1\r\n"))return 10;
/*12. 開始透傳*/
printf("開始透傳...\n");
if(ESP8266_SendCmd("AT+CIPSEND\r\n"))return 11;
printf("當前WIFI模式:%s\r\n",esp8266_wifi.mode);
printf("當前網(wǎng)絡協(xié)議類型:%s\r\n","TCP");
printf("當前網(wǎng)絡通信模式:%s\r\n","Client");
printf("連接的服務器端口號:%d\r\n",esp8266_wifi.port);
printf("連接的服務器IP地址:%s\r\n",server_ip);
printf("本地的IP地址:%s\r\n",esp8266_wifi.ip);
return 0;
}
6.2 esp8266.h
#ifndef ESP8266_H
#define ESP8266_H
#include "stm32f10x.h"
#include "usart.h"
#include "key.h"
#include "led.h"
#include
#include
u8 ESP8266_SendCmd(char *cmd);
u8 ESP8266_AP_TCP_ServerMode(const char *ssid,const char *password,u16 port);
u8 ESP8266_ServerSendData(u8 id,char *data);
u8 ESP8266_STA_TCP_ClientMode(const char *ssid,const char *password,char *server_ip,u16 port);
struct ESP8266_WIFI
{
u16 port;
char mode[10]; //sta/ap
char ip[10]; //ip地址
};
extern struct ESP8266_WIFI esp8266_wifi;
#endif
6.3 main.c
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include
#include "adc.h"
#include "esp8266.h"
#include "timer.h"
#include "rtc.h"
#include "dht11.h"
//網(wǎng)絡協(xié)議層
#include "onenet.h"
//協(xié)議封裝文件
#include "dStream.h"
/*WIFI信息配置---將要連接的WIFI信息*/
#define WIFI_NAME "Xiaomi_meizi6"
#define WIFI_PASSWORD "12170307yu"
/*Onenet服務器地址:固定的*/
#define SERVER_IP "183.230.40.39"
#define SERVER_PORT 6002
//產(chǎn)品ID
const char OneNetPROID[]="332761";
//鑒權信息 access_key
const char OneNetAUTH_INFO[]="1234567890";
//設備ID
char OneNetDEVID[]="590592359";
//ApiKey
char OneNetAPI_KEY[]="fTgT3L9k3gyalPDMeojEEPrwzlo=";
//onenet數(shù)據(jù)點定義
DATA_STREAM data_stream[]=
{
{"DHT11_T","66",TYPE_STRING,1}, //溫度
{"DHT11","66",TYPE_STRING,1}, //濕度
{"Light","66",TYPE_STRING,1}, //光照強度
{"MQ2","66",TYPE_STRING,1}, //煙霧濃度
{"MQ5","66",TYPE_STRING,1}, //液化氣濃度
};
char *WIFI_STAT; //WIFI狀態(tài)指針
//u8 temp,humi;
char DisplayDataBuffer[20];
u8 GL5637_Info[10]; //光敏傳感器信息
u8 TEMP_Info[10];
u8 HUMI_Info[10];
u8 MQ2_Info[10];
u8 MQ5_Info[10];
/*
工程內(nèi)容介紹: 物聯(lián)網(wǎng)開發(fā)平臺全功能測試代碼! 支持上位機控制
編寫日期 : 20200403
版本 : v4.0
*/
int main(void)
{
int cnt_OneNet_time=0;
u32 time_cnt=0; //記錄時間
u16 GL5637_temp=0; //光敏信息
u8 ESP8266_Stat;
u8 temp,humi;
u16 mq2_temp,mq5_temp;
LedInit();
KeyInit();
USART_X_Init(USART1,72,115200);
USART_X_Init(USART3,36,115200); //WIFI的波特率為115200
ADC1_Init(); //ADC初始化
Timer2Init(72,10000); //10ms中斷一次,輔助串口3接收數(shù)據(jù)--WIFI數(shù)據(jù)
printf("DHT11=%d\r\n",DHT11_Init());
//連接至指定的WIFI
ESP8266_Stat=ESP8266_STA_TCP_ClientMode(WIFI_NAME,WIFI_PASSWORD,SERVER_IP,SERVER_PORT);
if(ESP8266_Stat)
{
printf("ESP8266_Stat=%d\r\n",ESP8266_Stat);
WIFI_STAT="WIFIConnectERROR";
}
else
{
WIFI_STAT="WIFI Connect OK";
//接入OneNET
while(OneNet_DevLink())
{
printf("Connect OneNet..\r\n");
DelayMs_72M(500);
LED=!LED;
}
}
while(1)
{
cnt_OneNet_time++;//用于控制向服務器上傳數(shù)據(jù)點的頻率
/*輪詢掃描數(shù)據(jù)*/
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
//解析平臺返回的數(shù)據(jù)
OneNet_RevPro(USART3_RX_BUFF);
USART3_RX_CNT=0;
USART3_RX_FLAG=0;
memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
}
/*獲取光敏數(shù)據(jù)*/
GL5637_temp=ADC1_GetCHxVal(8);
sprintf((char*)GL5637_Info,"%d",GL5637_temp); //保存光敏傳感器信息,上傳給上位機
/*獲取煙霧濃度數(shù)據(jù)*/
mq2_temp=ADC1_GetCHxVal(1);
sprintf((char*)MQ2_Info,"%d",mq2_temp); //保存MQ2傳感器信息,上傳給上位機
/*獲取液化氣濃度數(shù)據(jù)*/
mq5_temp=ADC1_GetCHxVal(2);
sprintf((char*)MQ5_Info,"%d",mq5_temp); //保存MQ5傳感器信息,上傳給上位機
/*獲取溫濕度*/
if(DHT11_Read_Data(&temp,&humi)==0)
{
sprintf((char*)TEMP_Info,"%d",temp); //保存溫度傳感器信息,上傳給上位機
sprintf((char*)HUMI_Info,"%d",humi); //保存溫度傳感器信息,上傳給上位機
}
DelayMs_72M(1); //延時1ms
time_cnt++;
if(cnt_OneNet_time>=200 &&ESP8266_Stat==0)
{
cnt_OneNet_time=0; //清0
data_stream[0].dataPoint=TEMP_Info;
data_stream[1].dataPoint=HUMI_Info;
data_stream[2].dataPoint=GL5637_Info;
data_stream[3].dataPoint=MQ2_Info;
data_stream[4].dataPoint=MQ5_Info;
printf("GL5637_Info=%s\r\n",GL5637_Info);
printf("temp=%s,humi=%s\r\n",TEMP_Info,HUMI_Info);
printf("MQ2_Info=%s\r\n",MQ2_Info);
printf("MQ5_Info=%s\r\n",MQ5_Info);
//向OneNet云端服務器上傳數(shù)據(jù)點
OneNet_SendData(FORMAT_TYPE1,OneNetDEVID,OneNetAPI_KEY,data_stream,5);
printf("發(fā)送成功\r\n");
}
/*輪詢掃描數(shù)據(jù)*/
if(USART3_RX_FLAG)
{
USART3_RX_BUFF[USART3_RX_CNT]='\0';
//解析平臺返回的數(shù)據(jù)
OneNet_RevPro(USART3_RX_BUFF);
USART3_RX_CNT=0;
USART3_RX_FLAG=0;
memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
}
}
}
審核編輯:湯梓紅
?
-
STM32
+關注
關注
2264文章
10854瀏覽量
354304 -
智能家居
+關注
關注
1926文章
9472瀏覽量
183889
發(fā)布評論請先 登錄
相關推薦
評論