智能创客,中国最大的极客空间,智能平台,免费教学,视频教程,手把手教你创造儿时梦想!

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 55569|回复: 200
打印 上一主题 下一主题

Arduino开源智能家居《认识Zigbee》zigbee功能和自组网介绍

  [复制链接]

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
跳转到指定楼层
楼主
发表于 2014-6-8 15:00:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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 )
[C] 纯文本查看 复制代码
/*********************************************************************
 * 函数名称: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进入函数里。
[C] 纯文本查看 复制代码
/* 初始化操作系统 */
osal_init_system();



三、这里就是系统初始化,我们要看的是,我们的任务如何建立!双击osalInitTasks(),再按F12进入函数里。





四、看到了吗?串口通信被分配任务了。SerialApp_Init( taskID );这个可以是我们自己写的任务。双击,再按F12进入函数里。




五、在这里我们可以自己定义自己的东东了,初始化!
[C] 纯文本查看 复制代码
/*********************************************************************
 * 函数名称: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系统有事件(消息),你可以认为是有动作,就会激活这里。
[C] 纯文本查看 复制代码
/*********************************************************************
 * 函数名称: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 ); 
}





七、实例,我们在电脑用串口如何发送信息给它,它在哪里收到!
[C] 纯文本查看 复制代码
/*********************************************************************
 * 函数名称: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家居-性价比高
Arduino开源智能家居04《插座开关》手机控制:网扇、空调...
Arduino开源智能家居05《红外线》手机红外线控制电器


《百元智能家居DIY教程系列》
《智能家居网关》DIY制作图文教程01-百元智能家居系列
《智能温湿度》DIY制作图文教程02-百元智能家居系列
《智能插座》DIY制作图文教程03-百元智能家居系列
《智能电灯开关》DIY制作图文教程04-百元智能家居系列
《手机红外线》DIY制作图文教程05-百元智能家居系列
关注@智能创客  微信:znck007(打造DIY创客平台)





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 支持支持 反对反对
回复

使用道具 举报

0

主题

6

帖子

85

积分

注册会员

Rank: 2

积分
85
沙发
发表于 2014-6-8 23:44:51 | 只看该作者
不明觉厉啊
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
板凳
 楼主| 发表于 2014-6-9 00:40:03 | 只看该作者

哈哈,大家一起追求不明觉历吧……
回复 支持 反对

使用道具 举报

0

主题

1

帖子

4

积分

新手上路

Rank: 1

积分
4
地板
发表于 2014-6-9 08:14:55 | 只看该作者
GOOD~~~~~~~~~~~~~~~~~~~
回复

使用道具 举报

0

主题

1

帖子

4

积分

新手上路

Rank: 1

积分
4
5#
发表于 2014-6-9 08:52:45 | 只看该作者
学习 一定要学习,这个不能不学
回复 支持 反对

使用道具 举报

0

主题

9

帖子

116

积分

注册会员

Rank: 2

积分
116
6#
发表于 2014-6-9 09:34:02 | 只看该作者
学习学习!!!!!!!!!!!!
回复

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
7#
 楼主| 发表于 2014-6-9 20:05:25 | 只看该作者

哈哈哈……
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
8#
 楼主| 发表于 2014-6-9 20:05:36 | 只看该作者
eveloves 发表于 2014-6-9 08:52
学习 一定要学习,这个不能不学

嗯嗯嗯,加油吧……
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
9#
 楼主| 发表于 2014-6-9 20:05:46 | 只看该作者
tomko 发表于 2014-6-9 09:34
学习学习!!!!!!!!!!!!

回复 支持 反对

使用道具 举报

0

主题

3

帖子

114

积分

禁止发言

积分
114
10#
发表于 2014-6-9 23:30:46 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|小黑屋|手机版|智能创客 ( 桂ICP备14000828号

GMT+8, 2024-11-30 14:01 , Processed in 0.140789 second(s), 35 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表