ZigBee学习(7)————Zigbee无线传感器网络远程数据采集

目录

在开发ZigBee无线传感器网络过程中,需解决以下几个问题:

网络拓扑结构

传感器数据采集

网络节点能量供应问题

数据传输距离


设计原理图如下:

ZigBee学习(7)————Zigbee无线传感器网络远程数据采集_第1张图片

ZigBee学习(7)————Zigbee无线传感器网络远程数据采集_第2张图片

 

协调器编程:

//Coordinator.h

typedef union h
{
  unsigned char databuf[18];
  struct RFRXBUF
  {
    unsigned char head[2];                     //命令头
    unsigned char type[3];
    unsigned char myNWK[4];
    unsigned char pNWK[4];
    unsigned char value[4];                 //温度数据
    unsigned char tail;                     //命令尾
  }BUF;
}RFTX;   

该联合体包括一个数组databuf和一个结构体BUF

 

//Coordinator.c
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
  afIncomingMSGPacket_t *MSGpkt;
  if ( events & SYS_EVENT_MSG )
  {
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    while ( MSGpkt )
    {
      switch ( MSGpkt->hdr.event )
      {
        case AF_INCOMING_MSG_CMD:
          GenericApp_MessageMSGCB( MSGpkt );
          break;

        default:
          break;
      }

      osal_msg_deallocate( (uint8 *)MSGpkt );
      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
    }
    return (events ^ SYS_EVENT_MSG);
  }
  return 0;
}

void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
  RFTX rftx;
  unsigned char changeline[2]={0x0A , 0x0D};     //定义温度的位数字节,回车换行符的ASCII码
  switch ( pkt->clusterId )
  {
    case GENERICAPP_CLUSTERID:
      osal_memcpy( &rftx,pkt->cmd.Data,sizeof(rftx));
      HalUARTWrite(0,rftx.databuf,sizeof(rftx));
      HalUARTWrite(0,changeline,2);              //输出回车换行符
      break;
  }
}

对收到的消息进行处理和发送到串口

 

终端节点和路由器编程:

//Sensor.c
int8 readTemp(void)
{
   static uint16 reference_voltage;
   static uint8 bCalibrate = TRUE;
   unsigned char tmpADCCON3=ADCCON3;
   uint16 value;
   int8 temp;
   
   ATEST = 0x01;     //使能温度传感器
   TR0 |= 0x01;      //连接温度传感器
   ADCIF=0;
   ADCCON3 = (ADC_REF_115V | ADC_DEC_256 | ADC_CHN_TEMP);
   while(!ADCIF);
   ADCIF=0;
   value=ADCL;
   value |= ((uint16) ADCH) << 8;
   value >>=4;
   ADCCON3=tmpADCCON3;
   if(bCalibrate)       //记录第一次读取的温度值,用于校正温度数据
   {
      reference_voltage=value;
      bCalibrate=FALSE;
   }
   temp = 22+((value-reference_voltage)/4);     //温度校正函数
   return temp;
}

unsigned int getVddvalue(void)
{
    unsigned int value;
    unsigned char tmpADCCON3=ADCCON3;
    
    ADCIF=0;
    ADCCON3=(ADC_REF_115V | ADC_DEC_064 | ADC_CHN_VDD3);
    while(!ADCIF);
    value=ADCH;
    ADCCON3=tmpADCCON3;
    return (value);
}

分别是温度检测函数和电压检测函数,使用CC2530单片机内部自带的温度传感器进行温度检测,内部ADC对电压进行检测,VDD/3作为一个ADC输入通道,对通道进行检测

ZigBee学习(7)————Zigbee无线传感器网络远程数据采集_第3张图片

 

//Enddevice.c
void sendTemp( void )
{
  //unsigned char theMessageData[10] = "EndDevice";
  uint16 tempvalue;
  uint16 nwk;
  RFTX rftx;
  tempvalue = readTemp();
  rftx.BUF.value[0] = 'W';
  rftx.BUF.value[1] = tempvalue / 10 + '0';
  rftx.BUF.value[2] = tempvalue % 10 + '0';
  rftx.BUF.value[3] = '*';
  
  osal_memcpy(rftx.BUF.head,"&&",2);
  if(GenericApp_NwkState == DEV_ROUTER)
  {
    osal_memcpy(rftx.BUF.type,"ROU",3);
  }
  if(GenericApp_NwkState == DEV_END_DEVICE)
  {
    osal_memcpy(rftx.BUF.type,"END",3);
  }
  nwk=NLME_GetShortAddr();
  To_string(rftx.BUF.myNWK,(uint8 *)&nwk,2);
  nwk=NLME_GetCoordShortAddr();
  To_string(rftx.BUF.pNWK,(uint8 *)&nwk,2);
  rftx.BUF.tail='&';
  
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t) Addr16Bit;            //单播发送
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;                 //目的端口号
  my_DstAddr.addr.shortAddr= 0x0000;                        //协调器网络地址
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       18,
                       (uint8 *)&rftx,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
}

void sendVdd( void )
{
  uint16 vddvalue;
  uint16 nwk;
  RFTX rftx;
  
  vddvalue=69*getVddvalue()/256;
  rftx.BUF.value[0] = 'V';
  rftx.BUF.value[1] = vddvalue / 10 + '0';
  rftx.BUF.value[2] = '.';
  rftx.BUF.value[3] = vddvalue % 10 + '0';
  
  if(GenericApp_NwkState == DEV_ROUTER)
  {
    osal_memcpy(rftx.BUF.type,"ROU",3);
  }
  if(GenericApp_NwkState == DEV_END_DEVICE)
  {
    osal_memcpy(rftx.BUF.type,"END",3);
  }
  nwk=NLME_GetShortAddr();
  To_string(rftx.BUF.myNWK,(uint8 *)&nwk,2);
  nwk=NLME_GetCoordShortAddr();
  To_string(rftx.BUF.pNWK,(uint8 *)&nwk,2);
  rftx.BUF.tail='&';
  
  afAddrType_t my_DstAddr;
  my_DstAddr.addrMode= (afAddrMode_t) Addr16Bit;            //单播发送
  my_DstAddr.endPoint= GENERICAPP_ENDPOINT;                 //目的端口号
  my_DstAddr.addr.shortAddr= 0x0000;                        //协调器网络地址
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       18,
                       (uint8 *)&rftx,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, 
                       AF_DEFAULT_RADIUS ) ;
}

对于温度检测函数,调用readTem()函数,读取温度传感器数据,将网络地址,父节点网络地址以及数据头和数据尾信息填充到rftx相应的数据域,最后调用数据发送函数AF_DataRequest();对于电压检测函数,调用getVddvalue()函数,读取电压数据,将网络地址,父节点网络地址以及数据头和数据尾信息填充到rftx相应的数据域。

测试如下:

ZigBee学习(7)————Zigbee无线传感器网络远程数据采集_第4张图片

 

你可能感兴趣的:(ZigBee)