查看: 134940|回复: 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
    您需要登录后才可以回帖 登录 | 立即注册 ?

    本版积分规则

    热门推荐

    关于温湿度传感器在LCD显示上的问题
    关于温湿度传感器在LCD显
    我建立了一个程序,想要将dht11传感器得到的数据显示在LCD1602上,但是LCD显的都是乱
    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    【Arduino】108种传感器模块系列实验(74)--- 4位LED数码管模块
    【Arduino】108种传感器模
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
    (开源)ESP8266改装小风扇,app远程控制+天猫精灵控制
    (开源)ESP8266改装小风
    材料准备 [*]USB风扇一个 [*]ESP8266一块 [*]3.3继电器一块 拆解风扇 第一次,没有
    基于机器视觉的智能分拣机械臂
    基于机器视觉的智能分拣机
    本作品是一个基于机器视觉的智能机械臂操作平台,其采用atmega32单片机作为主控制系统
    Copyright ???2015-2016??Arduino中文社区??Powered by?Discuz! ??( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表