查看: 56378|回復: 275
打印 上一主題 下一主題

Arduino開源智能家居01《網關》升級版網關正式教程(zigbee)

  [復制鏈接]
  • TA的每日心情

    2015-9-22 09:41
  • 簽到天數: 9 天

    [LV.3]偶爾看看II

    跳轉到指定樓層
    樓主
    發表于 2014-7-2 23:36 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
    本帖最后由 智能創客 于 2014-10-11 16:31 編輯

    這篇開始,我們就真正做《網關》升級版教程了,采用arduino+zigbee哦。
    arduino簡單易學,zigbee自組網(如果不懂c語言,直接用就好,我們已經刷好自組網代碼)!

    這次我們的教程是通過以下配件實現《網關》功能,并在手機端點擊按鈕,使zigbee模塊上的燈閃亮(實現是發送真正的命令了{ckxxxxxxxxx}的格式)!
    通過不同的格式命令就可以操作開、關、接收、發送數據!之后《溫濕傳感器》《zigbee插座》等就可以直接連上了!


    上面就是arduino開源網關的配件。

    1、SMARTRF04EB(ZIGBEE下載器)35元
    2、CP2102(arduino下載器)15元
    3、電源供電 10元
    4、arduino板(含w5100、zigbee插槽、SD卡座)100元
    5、zigbee開發板 30元 (如果只想學zigbee只需要兩塊開發板和zigbee模塊,自組網學習哦)
    6、zigbee模塊 45元
    游客,如果您要查看本帖隱藏內容請回復




    第一部份:arduino板刷上代碼。

    一、安裝CP2102驅動(USB驅動)
    http://pan.baidu.com/s/1o6iDLcm(下載后直接安裝或發現有新硬件就更新驅動)。


    二、將CP2102連上arduino板底下的插槽的一定要一一對應哦。
    DTR->DTR
    GND->GND
    TX->RXI
    RX->TXO
    VDD3.3->VCC









    三、刷arduino代碼
    大家可以直接在這里下載源代碼:
    http://pan.baidu.com/s/1i386zPV(包含arduino軟件和所有的庫)


    [size=0.83em]
    [color=rgb(153, 153, 153) !important]





    下面我們就貼上代碼(都有注釋哦)

    kittenblock中小學創客名師推薦的圖形化編程軟件

    #include <iBoardRF24Network.h>
    #include <iBoardRF24.h>
    #include <digitalWriteFast.h>
    #include <SPI.h>
    #include <Ethernet.h>
      
       
      
    //請到m.znck007.com申請登陸-》家中環境-》網關,里可以看到!
    #define APIKEY "xxxxxxxxxxxxxxxx" //設置apikey 
     
    uint16_t sid=001;//設置sid(設備號)
      
      
     
    //NRF24l01發送接收節點
    const uint16_t this_node = 0; 
    const uint16_t other_node = 1;
      
    //NRF24l01收發數據
    struct payload_t
    {
      uint32_t ms;
      uint32_t data;
      char sendchar[20];
    };
     
    //NRF24l01腳針設置
    iBoardRF24 radioSend(3,8,5,6,7,2);
    iBoardRF24Network networkSend(radioSend);
     
    bool ispayload=false;//NRF24l01收發判斷
    uint16_t sendChannel=1;//NRF24l01發送頻道
    uint32_t sendCount=0;//NRF24l01發送次數
     
    char incomingData[20]={0};//NRF24l01接收到的字符(其它設置發過來)
     
     
     
     
     
    //設置MAC地址,如果有二個請改為不同(隨意)
    static byte mymac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
       
    EthernetClient client;//聲明網關類
     
    char server[] = "api.znck007.com";//聲明API網址
    //char urlBuf[] = "/index.php";
     
    static long timer;//用于規定時間間隔
    unsigned long last_http;//記錄http時間,用于http超時判斷,目前20秒無響應則重新GET。
    bool ishttpget=false;//標示http是否已經結束
     
     
     
    bool isUpdate=false;//成功則更新服務器數據為正常
    char updateData[20]={0};//更新的字符(服務器通過字符分析指定某個設備)
     
    //串口通信處理(主要用于zigbee通信)
    unsigned long serialnowlast;
    char serialbuff[80]={0};
    char serialData;
    int seriali=0;
     
     
      
    void setup(void)
    {
      //設置串口波特率
      Serial.begin(115200);
      Serial.println("IBOARD_GATEWAY_ZIGBEE/RF24Network");
       
      //NRF24l01初始化
      SPI.begin();
      radioSend.begin();
       
      //獲取IP DNS等
      Serial.println("\n[getDHCPandDNS]"); 
      if (Ethernet.begin(mymac) == 0)
      {
            Serial.print(F("Failed to configure Ethernet using DHCP\n"));
            while(1);
       }
       else
       {
            Serial.print("My IP address: ");
            for (byte thisByte = 0; thisByte < 4; thisByte++) {
           // print the value of each byte of the IP address:
            Serial.print(Ethernet.localIP()[thisByte], DEC);
            Serial.print("."); }
            Serial.println("Ethernet configuration OK");
      }
      
      //連接web服務器
      // if you get a connection, report back via serial:
      if (client.connect(server, 80)) {
        Serial.println("connected");    
        client.println("GET /index.php HTTP/1.1");
        client.println("Host: api.znck007.com");
        client.println("Connection: close");          
        client.println();
      } 
      else {
        // kf you didn't get a connection to the server:
        Serial.println("connection failed");
        client.stop();
      }
       
      //判斷web服務器是否正常
      timer=millis();
      while ((!client.available()) && (millis()-timer)<2000);
     
      if (client.available()) {
        char c = client.read();
        Serial.print(c);
        client.stop();
      }
      timer = millis();  
      
      //完成setup
      Serial.println("setup success");    
       
    }
     
     
    void loop(void)
    {
    //  //NRF24l01檢測接收數處理
    //  //如果使用NRF24l01,請啟動這里(并刪除ZIGBEE檢測接收數據處理)
    //  networkSend.begin(/*channel*/ sid, /*node address*/ this_node);
    //  // Pump the network regularly
    //  networkSend.update();
    //
    //  // Is there anything ready for us?
    //  timer=millis();
    //  //while ((!networkSend.available())  && (millis()-timer)<2000);
    //  while(networkSend.available())
    //  {
    //    // If so, grab it and print it out
    //    RF24NetworkHeader header;
    //    payload_t payload;
    //    memset(payload.sendchar, 0, 20);
    //    networkSend.read(header,&payload,sizeof(payload));
    //    Serial.print("Received packet #");
    //    Serial.print(payload.data);
    //    Serial.print(" at ");
    //    Serial.print(payload.ms);
    //    Serial.print(" getchar ");
    //    Serial.println(payload.sendchar); 
    //
    //    ispayload = true;
    //    
    //    get_html_body(payload.sendchar,incomingData);
    //    Serial.println(incomingData);
    //  }
    //  
    //  if(!ishttpget)
    //  {
    //        if(ispayload)
    //        {
    //          ispayload = false;
    //
    //      if(strstr(incomingData,"{ck") && strstr(incomingData,"}") )
    //        {
    //          last_http = millis();          
    //          ishttpget=true;  
    //                    
    //          Serial.println("\n>>> POST");
    //          static char buf[20]={0};
    //          sprintf(buf,"%s",incomingData);
    //
    //          client_post(server,APIKEY,buf);
    //          my_result_cb();
    //                
    //          return;
    //        }                
    //        
    //        }
    //  
    //  
    //  }
     
     
      //ZIGBEE檢測接收數據處理
      if(!ishttpget)
      {   
           
          unsigned long serialnow = millis();//獲取現在的時間
          if(serialnow - serialnowlast >= 5000)//如果數據間隔超過5秒而清空字符(為了防止數據錯亂)
          { 
            serialnowlast = millis(); 
            memset(serialbuff, 0, 80);
            seriali=0;
          } 
           
          bool isSerial=false;
          while( Serial.available() )//如果串口有數據(ZIGBEE或電腦發過來的)
          {
            if(seriali==0)
            {
              Serial.println("Serial->");//打印出來方便調試
            }       
            serialData=(char)Serial.read();//讀取串口數據
            //Serial.print(serialData);////這里不打印,否則ZIGBEE檢測到{ckxxxx}就認為是命令
            serialbuff[seriali]=serialData;////保存到數組
            seriali++;////數組長度+1
            if(serialData=='}' || seriali>=80)//如果發現}而說明命令結束(并少于80個字符,太長會出錯)
            {
              isSerial=true;
              break;
            }
          }
           
          //開始處理{ckxxxxx}字符,如POST上傳到web服務器
          if(isSerial)
          {
            serialnowlast = millis(); //更新當前時間,不然5秒就超時了
             
            //Serial.println(serialbuff);
            char body[81]={0};
            get_html_body(serialbuff,body);//獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式 
            //Serial.println(body);    
            
            Serial.println("-------------------");
            
           //如果命令格式真確則POST到web服務器了
            if(strstr(body,"{ck") && strstr(body,"}") )
            {          
              last_http = millis();
              ishttpget=true;
              timer = millis();
               
              Serial.println("\n>>> POST");
              //static char buf[81]={0};
              //sprintf(buf,"%s",body);
               
              client_post(server,APIKEY,body);//POST到網址,APIKEY,字符
              my_result_cb();//接收web服務器返回的字符
               
            }
            
            memset(serialbuff, 0, 80);//清空字符
            seriali=0;//字符長度為0
             
            return;
          }
      }
      //delay(200);
     
      //更新web服務器命令的狀態(比如發送成功還是失敗還是異常等,NRF24l01用到,ZIGBEE不用這里而是直接發送{ck00xxxxxxupdate}命令就行)
      if( isUpdate )
      {
          isUpdate=false;
         
          last_http = millis(); 
          ishttpget=true;      
           
          Serial.println("\n>>> UPDATE");
     
          static char buf[20]={0};
          sprintf(buf,"%s",updateData); 
          //Serial.println(buf);  
        
          client_post(server,APIKEY,buf);//POST到網址,APIKEY,字符
          my_result_cb();//接收web服務器返回的字符        
          isUpdate=false;
           
          return;
      }
     
      //每2秒鐘查看web服務器是有命令數據
      unsigned long now = millis();   
      if(now - last_http >= 2000)
      { 
        if(!ishttpget || (now - last_http) >= 20000)//20秒超時會執行,為了防卡死問題
        {
           last_http = millis(); 
           ishttpget=true;      
                 
             
          Serial.println("\n>>> REQ");
          static char buf[20]={0};
          sprintf(buf,"{ck001000000000}"); //這個字符串代表獲取新命令數據
          client_post(server,APIKEY,buf);//POST到網址,APIKEY,字符
          my_result_cb();//接收web服務器返回的字符        
           
          timer = millis();
     
        } 
        
      }   
       
     
    }
     
    //接收web服務器返回的字符        
    static void my_result_cb(){
      char eth_buffer[350];
      timer=millis();
      while ((!client.available()) && (millis()-timer)<1000);
     
      if (client.available()) {
       
       for(int j=0;client.available()>0;j++)
       {
        char c = client.read();
        eth_buffer[j]=c;
        Serial.print(c);
       }
       client.stop(); 
      }
      Serial.println();
       
        char body[81]={0};
        get_html_body(eth_buffer,body);//獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式 
        //Serial.println(body);
             
        sendChannel=get_channel(body);//獲取是哪個sid,這是m.znck007.com手機客服端里的sid
     
    //  //如果使用NRF24l01,請啟動這里
    //   if(  sendChannel>0 )
    //   {
    //      networkSend.begin(/*channel*/ sendChannel, /*node address*/ other_node);
    //         
    //      networkSend.update();
    //      Serial.println("");
    //      Serial.print("Sending...");
    //      if(sendCount>1000000) sendCount=0;
    //      payload_t payload = { sendChannel, sendCount++, "{ck000000000000}" };//millis()    
    //      sprintf(payload.sendchar,"%s",body);
    //      RF24NetworkHeader header(/*to node*/ this_node);
    //      bool ok = networkSend.write(header,&payload,sizeof(payload));
    //      if (ok)
    //      {
    //        Serial.println("ok.");  
    //        
    //        isUpdate=true;        
    //        char front[10]={0};
    //        memcpy(front,body,9);       
    //        sprintf(updateData,"%supdate}",front);
    //        Serial.println(updateData);
    //       
    //      }
    //      else
    //      {
    //        Serial.println("failed."); 
    //      }
    //    }  
         
        ishttpget=false;    
        last_http = millis();
           
     
        networkSend.begin(/*channel*/ sid, /*node address*/ this_node);         
        networkSend.update();        
             
    }
     
     
    //獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式 
    void get_html_body(char *p,char *s){
       
      char rechar[81]={0};
      int bufi=0;
       
      bool isend=false;
      int charnum=0;    
       
      for(bufi=0;bufi<strlen(p);bufi++){
        //Serial.print(p[bufi]);
         
        if(p[bufi]=='{'){
          isend=true;
        }
        if(p[bufi]=='}' && isend==true){
          isend=false;
          rechar[charnum]=p[bufi];
          break;
        }
        if(isend){
          if(charnum<80)
          {
            rechar[charnum]=p[bufi];//Serial.print(rechar[charnum]);
            charnum++;        
          }
        }
         
      }
      Serial.println(""); 
      //memcpy(s,rechar,17);
      sprintf(s,"%s",rechar);
    }
     
    //獲取是哪個sid,這是m.znck007.com手機客服端里的sid
    int get_channel(char *buff){
         
      if( strstr(buff,"{ck") && strstr(buff,"}") && strlen(buff)>10)
        {
          char charChannel[4]={0};
          memcpy(charChannel,buff+3,3);
          Serial.println(charChannel);
          int intChannel=atoi(charChannel);
          Serial.println(intChannel);
          return intChannel;      
        }
        else
        {
          return 0;
        }
       
    }
     
    //W5100芯片POST字符數據到web服務器
    int client_post(char *server, char *apikey, char *buf){
     
      if (client.connect(server, 80)) 
      {
          Serial.println("connecting...");
          // send the HTTP PUT request:
          client.print("POST /index.php");
          client.println(" HTTP/1.1");
          client.println("Host: api.znck007.com");
          client.print("apikey: ");
          client.println(APIKEY);
          client.print("Accept: *");
          client.print("/");
          client.println("*");
          client.print("Content-Length: ");
          // calculate the length of the sensor reading in bytes:
          // 8 bytes for {"value":} + number of digits of the data:
          size_t thisLength = strlen(buf);
          client.println(thisLength);
           
          client.println("Content-Type: application/x-www-form-urlencoded");
          client.println("Connection: close");
          client.println();
           
          client.println(buf);
          client.println();
      } 
      else
      {
          // kf you didn't get a connection to the server:
          Serial.println("connection failed");
          Serial.println();
          Serial.println("disconnecting.");
          client.stop();
      }
     
    }











    四、插上網線,打開串口就可以測試聯網是否成功了!






    第二部份:刷zigbee模塊代碼


    一、將zigbee模塊插到zigbee開發板上





    二、連上SMARTRF04EB下載器。
    將一邊有凸出來的一端與(VDD、RES、NC、DC、GND的NC對應就正確了!


    三、安裝SMARTRF04EB驅動
    http://pan.baidu.com/s/1dDH1ZX3(安裝SmartRFStudio后里面包含有驅動)
    提示:如果刷不成功,點擊一下SMARTRF04EB上的RESET(凹進去就用筆撮)。


    四、安裝IAR 8.1,軟件比較大,安裝后看說明破解就好。
    http://pan.baidu.com/s/1c0b69Ra(下載解壓里面有安裝說明)

    五、下載zigbee自組網代碼。
    http://pan.baidu.com/s/1COxT8(最新ZStack-CC2530-2.5.1自組網代碼,已經寫好了按鍵、LED燈功能)

    六、點擊編譯并下載。

    七、插個LED到zigbee開發板的P1.0和-。

    八、安到arduino板上。






    第三步:使用手機測試



    一、手機打開m.znck007.com手機控制端。



    二、新建一個開關。


    三、點擊開關,如果發現LED燈閃,說明《網關工作正常了》!



    OK,《網關》部份已經搞定了,下期我們就來上《溫濕傳感器》《Zigbee插座》《紅外控制》!
    因為我們還未使用Wifi,所以都需要與《網關》交互數據哦!
    等我們Wifi產品出來就可以單獨使用了!



    《WIFI作品DIY教程》
    WIFI作品DIY教程01-《Z WIFI開發板》介紹和聯網等配置教程


    《Arduino開源智能家居DIY教程系列》
    Arduino開源智能家居《花絮1》zigbee小底板DIY成功
    Arduino開源智能家居《認識Zigbee》zigbee功能和自組網介紹
    Arduino開源智能家居《zigbee開發板》手機/按鍵點亮LED
    Arduino開源智能家居01《網關》升級版網關正式教程(zigbee)
    Arduino開源智能家居02《溫濕傳感器》什么樣溫濕度才適居
    Arduino開源智能家居03《開發板套件》學習zigbee家居-性價比高
    Arduino開源智能家居04《插座開關》手機控制:網扇、空調...
    Arduino開源智能家居05《紅外線》手機紅外線控制電器


    《百元智能家居DIY教程系列》
    arduino教程【實戰篇】01《家居網關》DIY圖文視頻教程
    arduino教程【實戰篇】02《溫濕度》DIY圖文視頻教程
    arduino教程【實戰篇】03《智能插座》DIY圖文視頻教程
    arduino教程【實戰篇】04《電燈開關》DIY圖文視頻教程
    arduino教程【實戰篇】05《手機紅外線》DIY圖文視頻教程
    關注@智能創客http://www.znck007.com(打造DIY創客平臺)

  • TA的每日心情
    奮斗
    2019-10-15 09:51
  • 簽到天數: 1670 天

    [LV.Master]伴壇終老

    推薦
    發表于 2014-7-3 15:01 | 只看該作者
    我要好好學習!

    該用戶從未簽到

    板凳
    發表于 2014-7-3 09:22 | 只看該作者
    不錯,真是需要的
  • TA的每日心情
    慵懶
    2019-6-11 14:24
  • 簽到天數: 101 天

    [LV.6]常住居民II

    5#
    發表于 2014-7-3 16:11 | 只看該作者

    不錯,真是需要的
  • TA的每日心情
    開心
    2015-5-25 09:37
  • 簽到天數: 2 天

    [LV.1]初來乍到

    6#
    發表于 2014-7-3 17:26 | 只看該作者
    看看怎么樣.

    該用戶從未簽到

    7#
    發表于 2014-7-7 17:18 | 只看該作者
    想學學突然看到了這么好的貼
  • TA的每日心情

    2015-9-22 09:41
  • 簽到天數: 9 天

    [LV.3]偶爾看看II

    8#
     樓主| 發表于 2014-7-7 20:15 | 只看該作者
    fever1985 發表于 2014-7-7 17:18
    想學學突然看到了這么好的貼

    哈哈,一起加油……

    該用戶從未簽到

    9#
    發表于 2014-7-8 09:24 | 只看該作者
    灰常酷 喜歡額
  • TA的每日心情
    開心
    2016-1-27 11:13
  • 簽到天數: 1 天

    [LV.1]初來乍到

    10#
    發表于 2014-7-8 09:53 | 只看該作者
    恭喜升級!IBoard+zigbee真心不錯!{:soso_e179:}
    您需要登錄后才可以回帖 登錄 | 立即注冊  

    本版積分規則

    熱門推薦

    【原創】全球最小口袋3D打印機mini one直播教程貼
    【原創】全球最小口袋3D打
    最近閑得蛋疼,沒事搞個掌上3D打印機,先放效果圖吧。 搞了半天,終于能正常打印,
    Blink——Arduino的Hello World!
    Blink——Arduino的Hello
    本教程節選自《Arduino程序設計基礎》 Arduino編程基礎(零)——Blink,Arduino的He
    ATmega2560-16AU刷BootLoader好慢
    ATmega2560-16AU刷BootLoa
    各位朋友,ATmega2560-16AU刷BootLoader好慢,有沒有比較快的辦法,一塊板子要5分鐘左
    【Arduino】108種傳感器模塊系列實驗(104)---MAX30102手腕心率
    【Arduino】108種傳感器模
    37款傳感器與模塊的提法,在網絡上廣泛流傳,其實Arduino能夠兼容的傳感器模塊肯定是
    Arduino MEGA 與UNO 通過nRF24L模塊通訊
    Arduino MEGA 與UNO 通過n
    之前在深水寶很“實惠”的店鋪買了一些原件,隨手砍了esp8266以及nRF24L*3 因為缺
    Copyright   ©2015-2016  Arduino中文社區  Powered by©Discuz!   ( 蜀ICP備14017632號-3 )
    快速回復 返回頂部 返回列表
    六肖六码中特