天天看點

基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)

一、環境介紹

單片機采用:STM32F103C8T6

上網方式:采用ESP8266,也可以使用其他裝置代替,隻要支援TCP協定即可。比如:GSM子產品、有線網卡等。

雲平台: 采用中國移動OneNet.  也可以采用騰訊、阿裡雲、華為雲、百度天工物接入、機智雲等等。 前面文章有講解。

協定: 采用MQTT協定

開發軟體:keil5

完整項目源碼下載下傳:  

https://download.csdn.net/download/xiaolong1126626497/19766925

二、包含的硬體與實物圖介紹

1. 一個光敏電阻傳感器

2. 一個DHT11溫濕度傳感器

3. 一個MQ-5 液化氣/天然氣/瓦斯監測傳感器

4. 一個MQ-2 煙霧傳感器

5. 3盞LED燈表示窗簾開關、空調開關、電視開關

6. 聯網WIFI采用: ESP8266

7. 最小系統闆: STM32F103C8T6

8. 物聯網伺服器: OneNet平台

9. 物聯網手機APP: 裝置雲

裝置雲APP下載下傳位址(Android):  

https://download.csdn.net/download/xiaolong1126626497/18697132
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)

三、功能介紹

這是基于STM32設計的智能家居控制系統,采用ESP8266連接配接OneNet雲平台。

裝置端可以實時采集煙霧濃度、溫濕度、瓦斯天然氣濃度到雲平台,在雲平台網頁端或者手機APP上可以遠端檢視資料,還可以點選雲平台界面上的按鈕,完成對家裡的電器裝置控制:窗簾開關、空調開關、電視開關(采用LED燈模拟)等。

基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)

四、OneNet建立裝置

從0開始建立OneNet裝置,參考這裡:

https://xiaolong.blog.csdn.net/article/details/107385118 首位址: https://open.iot.10086.cn/
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
這是STM32裝置端連接配接OneNet序列槽列印的提示資訊:
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
登入成功的效果:
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
資料流收到物聯網終端上傳的資訊。
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
檢視設計的網頁界面:
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
五、程式下載下傳介紹
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
點選開始程式設計之後,按下開發闆上的RST按鈕,即可啟動下載下傳。 六、STM32裝置端代碼
基于STM32設計的智能家居系統(采用ESP8266+OneNet雲平台)
6.1 esp8266.c

#include "esp8266.h"
 
struct ESP8266_WIFI esp8266_wifi;
 
 
/*
函數功能: 配置ESP8266WIFI為AP模式+TCP伺服器模式
函數參數:
        char *ssid  :将要建立的WIFI熱點名稱(英文字母)
        char *password :将要建立的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. 發送測試指令,檢測WIFI是否正常*/
    printf("發送測試指令,檢測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. 設定建立的熱點資訊*/
    printf("設定建立的熱點資訊...\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("目前網絡協定類型:%s\n","TCP");
    printf("目前網絡通信模式:%s\n","server");
    printf("目前網絡端口号:%d\n",esp8266_wifi.port);
    printf("本地網絡IP位址:%s\n",esp8266_wifi.ip);
    return 0;
}
 
/*
函數功能:向ESP8266wifi發送指令
說明:該函數隻是适用于成功後傳回OK的指令
傳回值: 0表示成功 1表示失敗
*/
u8 ESP8266_SendCmd(char *cmd)
{
   u8 i,j;
   for(i=0;i<5;i++) //測試的總次數
   {
      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;
}
 
/*
函數功能:ESP8266wifi處于TCP伺服器模式下的資料發送函數
函數參數:
        u8 id      :已經連接配接伺服器的用戶端ID号
        char *data :将要發送資料(字元串)
傳回值: 0表示成功 1表示失敗
說明:隻有在TCP伺服器模式下才可使用該函數
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++) //測試的總次數
   {
      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,">")) //開始發送資料
              {
                  USART3_RX_FLAG=0;
                  USART3_RX_CNT=0;
                  USART_X_SendString(USART3,data); //發送資料
                  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")) //開始發送資料
                          {
                              USART3_RX_FLAG=0;
                              USART3_RX_CNT=0;
                              return 0;
                          }
                          else return 1;
                      }
                      DelayMs_72M(1); //一次的時間 
                  }
              }
              else break;
          }
          DelayMs_72M(5); //一次的時間
      }
   }
   return 1;
}
 
/*
函數功能: 設定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++) //測試的總次數
   {
      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;
}
 
 
/*
函數功能: 用于在用戶端模式下,連接配接伺服器
返 回 值: 0表示成功,1表示失敗
連接配接成功的提示符:CONNECT
*/
u8 ESP8266_ConnectServer(char *cmd)
{
   u32 i,j;
   for(i=0;i<5;i++) //測試的總次數
   {
      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;
}
 
 
/*
函數功能: 配置ESP8266WIFI為STA模式+TCP用戶端模式
函數參數:
        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. 發送測試指令,檢測WIFI是否正常*/
    printf("發送測試指令,檢測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("目前網絡協定類型:%s\r\n","TCP");
    printf("目前網絡通信模式:%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 <string.h>
#include <stdlib.h>
 
 
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      

3.3 main.c

#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "adc.h"
#include "esp8266.h"
#include "timer.h"
#include "rtc.h"
#include "dht11.h"
//網絡協定層
#include "onenet.h"
//協定封裝檔案
#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
 
//産品ID
const char OneNetPROID[]="332761";
//鑒權資訊 access_key
const char OneNetAUTH_INFO[]="1234567890";
//裝置ID
char OneNetDEVID[]="590592359";
//ApiKey
char OneNetAPI_KEY[]="fTgT3L9k3gyalPDMeojEEPrwzlo=";
 
//onenet資料點定義
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狀态指針
//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];
 
/*
工程内容介紹: 物聯網開發平台全功能測試代碼! 支援上位機控制
編寫日期    : 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接收資料--WIFI資料
    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++;//用于控制向伺服器上傳資料點的頻率            
        /*輪詢掃描資料*/
        if(USART3_RX_FLAG)
        {
            USART3_RX_BUFF[USART3_RX_CNT]='\0';
            //解析平台傳回的資料
            OneNet_RevPro(USART3_RX_BUFF);
            USART3_RX_CNT=0;
            USART3_RX_FLAG=0;
            memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
        }
        
            /*擷取光敏資料*/
            GL5637_temp=ADC1_GetCHxVal(8);
            sprintf((char*)GL5637_Info,"%d",GL5637_temp); //儲存光敏傳感器資訊,上傳給上位機
          /*擷取煙霧濃度資料*/
            mq2_temp=ADC1_GetCHxVal(1);
            sprintf((char*)MQ2_Info,"%d",mq2_temp); //儲存MQ2傳感器資訊,上傳給上位機
          /*擷取液化氣濃度資料*/
            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雲端伺服器上傳資料點
                OneNet_SendData(FORMAT_TYPE1,OneNetDEVID,OneNetAPI_KEY,data_stream,5);
                printf("發送成功\r\n"); 
            }
            /*輪詢掃描資料*/
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFF[USART3_RX_CNT]='\0';
                //解析平台傳回的資料
                OneNet_RevPro(USART3_RX_BUFF);
                USART3_RX_CNT=0;
                USART3_RX_FLAG=0;
                memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));
            }
    }
}
       

繼續閱讀