查看: 135367|回復: 942
打印 上一主題 下一主題

Arduino開源智能家居《認識Zigbee》zigbee功能和自組網介紹

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

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

    [LV.3]偶爾看看II

    跳轉到指定樓層
    樓主
    發表于 2014-6-9 20:08 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
    本帖最后由 智能創客 于 2014-7-17 20:37 編輯

    HI創友們,這周工廠已經在打板了,下周就能看到《Arduino開源智能家居》的網關作品了!

    這次我們采用Arduino+Zigbee模式,也就是真正意思個的智能家居系統哦親!

    Zigbee是什么,有很多人可能只是知道有這么個東西,但不明白具體是什么,有什么作用!
    以下我們用通俗易懂(以比喻為主)的方式來講一下ZIGBEE。

    游客,如果您要查看本帖隱藏內容請回復



    《功能說明》
    一、51單片機
    簡單的說,他就是一塊51單片機(含無線傳輸功能),用IAR 8.10軟件可以直接對他編程,比如點亮LED、收發數據、點擊按鍵(IO)、輸入數據(傳感器)等。
    很多arduino的同學就可以用他來學51單片機啦,一通百通嘛。51單片機其實就這樣……

    二、無線傳輸(遠)
    之前我們用NRF24l01,他的距離比較近,我們用zigbee代替它(這時zigbee等于Nrf24l01),加上天線后可以達上千米。這樣的傳輸距離夠用了吧!

    三、用最多的智能家居協議
    Zigbee是目前來說,全球智能家居用最多的協議之一(國際上是有統一協議規范的,但要按協議寫代碼然后還要認證)。
    這個怎么理解呢?打個比方:如果以后你買個電視,他就能自動連入的你家居網關(zigbee協議一樣)。用個詞:萬能家居網關,控制所有家居!

    四、兩兩通信
    一般一個智能家居系統有個網關,和很多傳感器、設備(電器),zigbee可以不通過網關,就是(兩個傳感器)、(傳感器和設備)、(設備和設備)之間可以互通信,可以不用通網關。比如:5樓的設備只和5樓的通信,不用經過1樓的總網關。這樣就更方便快捷了嘛……

    五、自網組(牛b、專業了)

    簡單的說,他就是小型的3G或CDMA或GSM網絡。每個zigbee類式于一個基站,他們可以自己組成一個網。然后你在一個zigbee說話,任何一個點都可以收到(可以加密防竊聽)。
    舉例子了:
    你家是一棟別墅有3棟樓,每棟3層。
    你想在某個室間控制整個別野,好辦了就用zigbee,棟和棟之間的zigbee用天線,他們會自組網,斷線自離網,上線自恢復。
    只要你在一點操作,哪里都能收得到(也就是你打電話給你妹,你妹如果手機有信號,在哪都可以收得到!)

    六、支持65000個節點
    ZigBee大規模的組網能力——每個網絡65000個節點,而每個藍牙網絡只有8個節點。


    不想說了不想說了,反應已經夠我們用了!


    接下來說一下cdoe,我是個程序員嘛,這段日子都在研究自組網。自組網是最難的,你聽我的解說就不會難了!
    讓我來說說zigbee自組網,殺上代碼:


    小菜,你只要關心圖上的二個文件就好,其它你也不懂的,以后慢慢來!

    一、我們雙擊ZMain.c,找到main( void )

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

    /*********************************************************************
    * 函數名稱:main
    * 功    能:主函數。
    * 入口參數:無
    * 出口參數:無
    * 返 回 值:無
    ********************************************************************/
    int main( void )
    {
      /* 關閉中斷 */
      osal_int_disable( INTS_ALL );
    
      /* 初始化系統時鐘及LED等 */
      HAL_BOARD_INIT();
    
      /* 檢測供電電壓 */ 
      zmain_vdd_check();
    
      /* 初始化堆棧 */
      zmain_ram_init();
    
      /* 初始化主板外圍I/O */
      InitBoard( OB_COLD );
    
      /* 初始化硬件抽象層驅動 */
      HalDriverInit();
    
      /* 初始化系統NV非易失性存儲 */
      osal_nv_init( NULL );
    
      /* 初始化基礎NV項 */
      zgInit();
    
      /* 初始化MAC */ 
      ZMacInit();
    
      /* 確定擴展地址 */
      zmain_ext_addr();
    
      /* 初始化應用框架 */
    #ifndef NONWK
      afInit(); // AF應用框架不是系統的任務,因此調用它的初始化程序
    #endif
    
      /* 初始化操作系統 */
      osal_init_system();
    
      /* 允許中斷 */
      osal_int_enable( INTS_ALL );
    
      /* 最終板級初始化 */
      InitBoard( OB_READY );
    
      /* 顯示該設備信息 */
      zmain_dev_info();
    
      /* 如果定義了LCD,則在LCD上顯示設備信息 */
    #ifdef LCD_SUPPORTED
      zmain_lcd_init();
    #endif
    
    #ifdef WDT_IN_PM1
      /* 如果看門狗被使用,此處使能 */
      WatchDogEnable( WDTIMX );
    #endif
      //printf("osal_start_system");
      osal_start_system(); // 進入系統調度,無返回
    
      return ( 0 );
    }
    



    二、只關注這個,然后雙擊它,再按F12進入函數里。

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

    /* 初始化操作系統 */
    osal_init_system();



    三、這里就是系統初始化,我們要看的是,我們的任務如何建立!雙擊osalInitTasks(),再按F12進入函數里。





    四、看到了嗎?串口通信被分配任務了。SerialApp_Init( taskID );這個可以是我們自己寫的任務。雙擊,再按F12進入函數里。



    五、在這里我們可以自己定義自己的東東了,初始化!

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

    /*********************************************************************
    * 函數名稱:SerialApp_Init
    * 功    能:SerialApp的初始化函數。
    * 入口參數:task_id  由OSAL分配的任務ID。該ID被用來發送消息和設定定時
    *           器。
    * 出口參數:無
    * 返 回 值:無
    ********************************************************************/
    void SerialApp_Init( uint8 task_id )
    {
      halUARTCfg_t uartConfig;     // 定義串口配置結構體變量
    
      SerialApp_MsgID = 0x00;      // 初始化傳輸序號
      SerialApp_SeqRx = 0xC3;      // 初始化接收序號為十進制195
      SerialApp_TaskID = task_id;  // 獲取應用任務ID
    
      /* 初始化發送信息目的地址 */
      SerialApp_DstAddr.endPoint = 0;
      SerialApp_DstAddr.addr.shortAddr = 0;
      SerialApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
      
      /* 初始化響應信息的目的地址 */
      SerialApp_RspDstAddr.endPoint = 0;
      SerialApp_RspDstAddr.addr.shortAddr = 0;
      SerialApp_RspDstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
    
      /* 注冊端點描述符 */
      afRegister( (endPointDesc_t *)&SerialApp_epDesc );
    
      /* 注冊按鍵事件,將所有按鍵事件發送給本應用任務SerialApp_TaskID */
      RegisterForKeys( task_id );
    
      /* 串口初始化 */
      uartConfig.configured           = TRUE;              
      uartConfig.baudRate             = SERIAL_APP_BAUD;   // 波特率
      uartConfig.flowControl          = TRUE;              // 流控使能
      uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 流控閾值
      uartConfig.rx.maxBufSize        = SERIAL_APP_RX_MAX; // 最大接收量
      uartConfig.tx.maxBufSize        = SERIAL_APP_TX_MAX; // 最大發送量
      uartConfig.idleTimeout          = SERIAL_APP_IDLE;   // 空閑時間
      uartConfig.intEnable            = TRUE;              // 中斷使能
    /* 若使能了環回測試功能 */
    #if SERIAL_APP_LOOPBACK
      uartConfig.callBackFunc         = rxCB_Loopback;     // 回調函數
    /* 若未使能環回測試功能 */
    #else
      uartConfig.callBackFunc         = rxCB;              // 回調函數
    #endif
      HalUARTOpen (SERIAL_APP_PORT, &uartConfig);          // 打開串口
    
       
      /* 若包含了LCD_SUPPORTED編譯選項,則在LCD上進行相應的顯示 */
    #if defined ( LCD_SUPPORTED )
    #if defined ( ZIGBEEPRO )
      HalLcdWriteString( "SerialApp(ZigBeePRO)", HAL_LCD_LINE_2 );
    #else
      HalLcdWriteString( "SerialApp(ZigBee2007)", HAL_LCD_LINE_2 );
    #endif
    #endif
    
      /* ZDO信息注冊 */
      /* 注冊ZDO的簇End_Device_Bind_rsp,將收到的End_Device_Bind_rsp事件
         發送給本應用任務SerialApp_TaskID
       */    
      ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );
      
      /* ZDO信息注冊 */
      /* 注冊ZDO的簇Match_Desc_rsp,將收到的Match_Desc_rsp事件發送給本應
         用任務SerialApp_TaskID
       */  
      ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );
    }






    六、zigbee系統有事件(消息),你可以認為是有動作,就會激活這里。

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

    /*********************************************************************
    * 函數名稱:SerialApp_ProcessEvent
    * 功    能:SerialApp的任務事件處理函數。
    * 入口參數:task_id  由OSAL分配的任務ID。
    *           events   準備處理的事件。該變量是一個位圖,可包含多個事件。
    * 出口參數:無
    * 返 回 值:尚未處理的事件。
    ********************************************************************/
    UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
    {
      /* 系統消息事件 */
      if ( events & SYS_EVENT_MSG )
      {
        afIncomingMSGPacket_t *MSGpkt;
    
        while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(
                                                              SerialApp_TaskID )))
        {
          switch ( MSGpkt->hdr.event )
          {
            /* ZDO信息輸入事件 */
            case ZDO_CB_MSG:
              // 調用ZDO信息輸入事件處理函數
              SerialApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
              break;
            
            /* 按鍵事件 */  
            case KEY_CHANGE:
              HalUARTWrite(0,"KEY_CHANGE",4);
              // 調用按鍵事件處理函數
              SerialApp_HandleKeys( ((keyChange_t *)MSGpkt)->state,
                                    ((keyChange_t *)MSGpkt)->keys );
              break;
            
            /* AF輸入信息事件 */
            case AF_INCOMING_MSG_CMD:
              // 調用輸入信息事件處理函數
              SerialApp_ProcessMSGCmd( MSGpkt );
              break;
      
            default:
              break;
          }
    
          osal_msg_deallocate( (uint8 *)MSGpkt );  // 釋放存儲器
        }
    
        return ( events ^ SYS_EVENT_MSG );  // 返回未處理的事件
      }
    
      /* 發送數據事件 */
      if ( events & SERIALAPP_MSG_SEND_EVT )
      {
        SerialApp_SendData( otaBuf, otaLen );  // 調用發送數據處理函數
    
        return ( events ^ SERIALAPP_MSG_SEND_EVT );
      }
    
      /* 發送數據重傳事件 */
      if ( events & SERIALAPP_MSG_RTRY_EVT )
      {
        /* 若重傳計數不為0 */
        if ( --rtryCnt )
        {
          /* 發送OTA信息(需要重傳的發送數據) */
          AF_DataRequest( &SerialApp_DstAddr,
                          (endPointDesc_t *)&SerialApp_epDesc,
                           SERIALAPP_CLUSTERID1, otaLen, otaBuf,
                          &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );
          
          /* 在指定時間SERIALAPP_MSG_RTRY_TIMEOUT到時后觸發發送數據重傳事件 */
          osal_start_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT,
                                                SERIALAPP_MSG_RTRY_TIMEOUT );
        }
        else
        {
          FREE_OTABUF();  // 處理緩沖區
        }
    
        return ( events ^ SERIALAPP_MSG_RTRY_EVT );
      }
    
      /* 響應信息重傳事件 */
      if ( events & SERIALAPP_RSP_RTRY_EVT )
      {
        /* 發送OTA信息(需要重傳的響應信息)*/
        afStatus_t stat = AF_DataRequest( &SerialApp_RspDstAddr,
                                          (endPointDesc_t *)&SerialApp_epDesc,
                                           SERIALAPP_CLUSTERID2,
                                           SERIAL_APP_RSP_CNT, rspBuf,
                                          &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );
    
        /* 若發送OTA信息(需要重傳的響應信息)不成功*/
        if ( stat != afStatus_SUCCESS )
        {
          /* 在指定時間SERIALAPP_RSP_RTRY_TIMEOUT到時后觸發響應信息重傳事件 */
          osal_start_timerEx( SerialApp_TaskID, SERIALAPP_RSP_RTRY_EVT,
                                                SERIALAPP_RSP_RTRY_TIMEOUT );
        }
    
        return ( events ^ SERIALAPP_RSP_RTRY_EVT );
      }
    
      /* 若使能了環回測試 */
    #if SERIAL_APP_LOOPBACK
      /* 串口重發送事件 */
      if ( events & SERIALAPP_TX_RTRY_EVT )
      { /* 若接收緩沖區中有數據 */
        if ( rxLen )
        { /* 若將接收緩沖區中的數據寫入到串口不成功 */
          if ( !HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
          { /* 在指定時間SERIALAPP_TX_RTRY_TIMEOUT后觸發串口重發送事件 */
            osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                                  SERIALAPP_TX_RTRY_TIMEOUT );
          }
          /* 若將接收緩沖區中的數據寫入到串口成功 */
          else
          {
            rxLen = 0;  // 清零接收緩沖區中數據長度變量
          }
        }
    
        return ( events ^ SERIALAPP_TX_RTRY_EVT );
      }
    #endif
    
      /* 丟棄未知事件 */ 
      return ( 0 ); 
    }





    七、實例,我們在電腦用串口如何發送信息給它,它在哪里收到!

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

    /*********************************************************************
    * 函數名稱:rxCB_Loopback
    * 功    能:串口接收回調函數(環回測試時使用)
    * 入口參數:port   串口號
    *           event  串口事件
    * 出口參數:無
    * 返 回 值:無
    ********************************************************************/
    static void rxCB_Loopback( uint8 port, uint8 event )
    {
      /* 若接收緩沖區中有數據 */
      if ( rxLen )
      {
        /* 若將接收緩沖區中的數據寫入到串口不成功 */
        if ( !HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
        {
          /* 在指定時間SERIALAPP_TX_RTRY_TIMEOUT后觸發串口重發送事件 */
          osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                                SERIALAPP_TX_RTRY_TIMEOUT );
          return;  // 返回
        }
        /* 若將接收緩沖區中的數據寫入到串口成功 */
        else
        { /* 停止串口重發送事件 */
          osal_stop_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT );
        }
      }
    
      /* 若從串口讀取數據不成功(讀出的數據長度為0) */
      if ( !(rxLen = HalUARTRead( port, rxBuf, SERIAL_APP_RX_CNT )) )
      {
        return;  // 返回
      }
    
      /* 若將已從串口讀取的數據回寫到串口成功 */
      if ( HalUARTWrite( SERIAL_APP_PORT, rxBuf, rxLen ) )
      {
        rxLen = 0;  // 清零接收緩沖區中數據長度變量
      }
      /* 若將已從串口讀取的數據回寫到串口不成功 */
      else
      { /* 在指定時間SERIALAPP_TX_RTRY_TIMEOUT后觸發串口重發送事件 */ 
        osal_start_timerEx( SerialApp_TaskID, SERIALAPP_TX_RTRY_EVT,
                                              SERIALAPP_TX_RTRY_TIMEOUT );
      }



    這個就是我們的串口數據了rxBuf,接到后判斷是什么字符,然后做相應的處理吧(操控你的世界吧),親!

    8、好了,第一篇zigbee就先寫到這里。
    讓住,很多東西我們可以不用去理解(除非你有能力),就在SerialApp.c寫上自己要實現的代碼就OK了。
    難嗎?難嗎?難嗎?不啊小菜……


    當然現在還沒有發正式教程,沒有IAR 8.10軟件下載沒有源代碼(你沒有硬件也沒有),所以等期我們的《Arduino開源智能家居》吧。親……



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


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



  • TA的每日心情
    開心
    2015-7-26 09:38
  • 簽到天數: 7 天

    [LV.3]偶爾看看II

    推薦
    發表于 2015-7-27 22:33 | 只看該作者
    不錯,學習了!

    該用戶從未簽到

    沙發
    發表于 2014-6-9 22:44 | 只看該作者
    為了看得隱藏的內容

    該用戶從未簽到

    板凳
    發表于 2014-6-10 09:34 | 只看該作者
    huifu kankan

    該用戶從未簽到

    地板
    發表于 2014-6-10 10:21 | 只看該作者
    11111111111111111111
  • TA的每日心情

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

    [LV.3]偶爾看看II

    5#
     樓主| 發表于 2014-6-10 11:12 | 只看該作者

    互粉……
  • TA的每日心情

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

    [LV.3]偶爾看看II

    6#
     樓主| 發表于 2014-6-10 11:12 | 只看該作者

    22222222222222222
  • TA的每日心情

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

    [LV.3]偶爾看看II

    8#
     樓主| 發表于 2014-6-10 13:22 | 只看該作者

    該用戶從未簽到

    10#
    發表于 2014-6-11 02:05 | 只看該作者
    之前項目用過zigbee,就是帶自組網太貴了,還不如433
    您需要登錄后才可以回帖 登錄 | 立即注冊  

    本版積分規則

    熱門推薦

    arduino實現L298N控制工業步進電機
    arduino實現L298N控制工業
    求助 L298N是ST公司生產的一種高電壓、大電流電機驅動芯片。該芯片采用15腳封裝。主
    arduino IDE錯誤,有點崩潰了,要搞作業!
    arduino IDE錯誤,有點崩
    無論編譯什么程序文件都是這個錯誤!程序自帶例程,最簡單的點亮led燈也是 這個 問題
    【項目】基于Arduino Nano的多功能桌面感應垃圾桶
    【項目】基于Arduino Nano
    基于Arduino Nano的多功能桌面感應垃圾桶隨著大學生活不斷往前邁進,宿舍桌面上的雜物
    在芯間投資成立的零知實驗室發布國內的STM32開源開發板
    在芯間投資成立的零知實驗
    在芯間電子元器件商城成立于2016年,是集電子元器件采購、SMT貼片、PCB打樣、于一
    【原創】全球最小口袋3D打印機mini one直播教程貼
    【原創】全球最小口袋3D打
    最近閑得蛋疼,沒事搞個掌上3D打印機,先放效果圖吧。 搞了半天,終于能正常打印,
    Copyright   ©2015-2016  Arduino中文社區  Powered by©Discuz!   ( 蜀ICP備14017632號-3 )
    快速回復 返回頂部 返回列表
    七星彩综合基本走势图