STM32W108无线传感器网络节点自组织与移动智能体导航技术

原创 2015年07月08日 11:10:13

 

使用STM32W108无线开发板及节点完成大规模网络的自组建,网络模型选择树型,网络组建完成之后,使用基于接收信号强度指示RSSI(ReceivedSignal Strength Indication)N次三边质心加权定位法进行节点定位及智能车导航。

 

 

节点自组织及移动智能体导航实际场景

 

程序设计与实现

基于SimpleMac协议栈sample实例及第15章给出的N次三边质心加权定位算法程序,进行本章程序的设计,对于本章使用的N次三边质心加权定位算法及三边质心定位算法的实现在此就不再说明,主要给出自组网及智能车导航程序的设计实现。

数据包类型定义:

//负载类型定义

//已知位置的节点进行广播信息,用于移动位置节点的定位

#define PT_FIXED_NODE_SEND_SITE (0x07)

 

/*用于移动节点广播搜索信道,当已知位置节点收到此类型信息时回复PT_CHANNEL_AVAILABLE类型信息*/

#define PT_CHANNEL_SEARCH (0x08)

 

/*已知位置节点回复移动节点信息类型,当移动节点收到此信息说明网络当前信道即为其当前信道*/

#define PT_CHANNEL_AVAILABLE (0x09)

 

//移动节点广播信息,请求已知位置节点广播其位置信息,以用于移动节点的定位

#define PT_POSITIONING_REQUEST (0x0A)

#define PT_DATA_TO_ROOT   (0x0B) //定位传送数据到根节点类型的数据包

 

//移动智能体进行广播询问定位

#define PT_MOBILE_NODE_POSITIONING_REQUEST  (0x0C)

//移动智能体发送数据到网络,传送至根节点

#define PT_DATA_FROM_MOBILE_NODE (0x0D)

#define PT_DATA_TO_MOBILE_NODE (0x0E) //网络发送数据给移动智能体

 

/*网络广播数据给移动智能体,和PT_DATA_TO_MOBILE_NODE相区别,当来自汇聚节点的数据到达最后一个与移动智能体通信的节点时此节点进行广播,而此广播信息只有移动节点会接收处理*/

#define PT_DATA_BROADCAST_TO_MOBILE_NODE  (0x0F)

 

//数据包类型定义

#define POSITIONING_REQUEST_PACKET ((FT_DATA  << 4)

| (PT_POSITIONING_REQUEST <<0)) //0x1A

#define DATA_TO_ROOT_PACKET ((FT_DATA  <<4)

| (PT_DATA_TO_ROOT <<0)) //0x1B

#define  MOBILE_NODE_POSITIONING_REQUEST_PACKET ((FT_DATA <<4)

|(PT_MOBILE_NODE_POSITIONING_REQUEST <<0)) //0x1C

#define DATA_FROM_MOBILE_NODE_PACKET ((FT_DATA  <<4)

| (PT_DATA_FROM_MOBILE_NODE <<0))//0x1D

#define DATA_TO_MOBILE_NODE_PACKET  ((FT_DATA <<4)

| (PT_DATA_TO_MOBILE_NODE <<0))//0x1E

#define DATA_BROADCAST_TO_MOBILE_NODE_PACKET  ((FT_DATA <<4)

| (PT_DATA_BROADCAST_TO_MOBILE_NODE <<0))//0x1F

 

本文的实验采用的是大边飞翔科技有限公司的STM32W108无线射频开发板及节点完成大规模物联网网络的组建。

函数processRxPacket()

/**************************************************************************

功能描述:对接收的数据包进行解析,并执行相应的操作

输入参数:无

输出参数:无

*************************************************************************/

void processRxPacket(void)

{

   u8 i;

   boolean pktHasSrcPanId = FALSE;

   u8 srcAddrOffset = 0;

   u16 srcPanId=0xFFFF;

   u16 shortSrcAddr=0;

   u8 longSrcAddr[8]={0,};//64位数据源地址

  u8 pt = PT_JOIN_DENIED; //负载类型

   u8 assignedShortId[2] = {0xFE, 0xFF};

#ifdef ROOT_ROLE

   u8 fatherLongAddr[8]={0,},childLongAddr[8]={0,}; //记录64位长地址

#endif

   u8 payloadStart; //负载的起始位置

   u8 packetType; //数据包类型

   u8 packet[128]; //用于记录将发送的数据包内容

   int x,y;//用于记录节点的坐标 

   if(!rxData.packetBeingProcessed) {

     return;

  }

    

   //数据包的长度不能小于10

   if(rxData.packet[0]<10) {

     RX_DETAILS(printf("Length byte too short\r\n");)

     goto stopProcessing;

  }

 

   //判断帧类型

   switch(rxData.packet[1]&0x7) {

     case FT_DATA:

       RX_DETAILS(printf("FT_DATA\r\n");)

       packetType = (FT_DATA<<4);

       RX_DETAILS(printf("the packet type is:%X\r\n",packetType);)

       break;

     case FT_MAC_COMMAND:

       RX_DETAILS(printf("FT_MAC_COMMAND\r\n");)

       packetType = (FT_MAC_COMMAND<<4);

       break;

     default:

       RX_DETAILS(printf("Unknown frame type\r\n");)

       goto stopProcessing;

  };

 

   //判断是否有PAN ID

   if((rxData.packet[1]&0x40)!=0x40) {

     pktHasSrcPanId=TRUE;

     srcAddrOffset = 2;

  }

 

   //判断地址类型

   switch(rxData.packet[2]) {   

     case FCF_SHORTDST + FCF_SHORTSRC:

       RX_DETAILS(printf("short dst, short src\r\n");)

       shortSrcAddr = (rxData.packet[8+srcAddrOffset+1]<<8)|

                      (rxData.packet[8+srcAddrOffset+0]<<0);

       payloadStart = 10+srcAddrOffset;

       if(pktHasSrcPanId) {

         srcPanId = (rxData.packet[9]<<8)|(rxData.packet[8]<<0);

       }

       break;

     case FCF_SHORTDST + FCF_LONGSRC:

       RX_DETAILS(printf("short dst, long src\r\n");)

       memcpy(longSrcAddr, (rxData.packet+8+srcAddrOffset), 8);

       payloadStart = 16+srcAddrOffset;

       if(pktHasSrcPanId) {

         srcPanId = (rxData.packet[9]<<8)|(rxData.packet[8]<<0);

       }

       break; 

     case FCF_LONGDST + FCF_SHORTSRC:

       RX_DETAILS(printf("long dst, short src\r\n");)

       shortSrcAddr = (rxData.packet[14+srcAddrOffset+1]<<8)|

                      (rxData.packet[14+srcAddrOffset+0]<<0);

       payloadStart = 16+srcAddrOffset;

       if(pktHasSrcPanId) {

         srcPanId = (rxData.packet[15]<<8)|(rxData.packet[14]<<0);

       }

       break;

     case FCF_LONGDST + FCF_LONGSRC:

       RX_DETAILS(printf("long dst, long src\r\n");)

       memcpy(longSrcAddr, (rxData.packet+14+srcAddrOffset), 8);

       payloadStart = 22+srcAddrOffset;

       if(pktHasSrcPanId) {

         srcPanId = (rxData.packet[15]<<8)|(rxData.packet[14]<<0);

       }

       break;

     default:

       RX_DETAILS(printf("Unknown addressing mode\r\n");)

       goto stopProcessing;

   } 

   RX_DETAILS(

     if(pktHasSrcPanId) {

       RX_DETAILS(printf("src pan = 0x%04X\r\n", srcPanId);)

     }

  )

 

   //确保数据包的长度足够包含负载类型数据

   if(rxData.packet[0]<payloadStart) {

     RX_DETAILS(printf("Length byte too short\r\n");)

     goto stopProcessing;

  }

 

   //获取数据包的负载类型   

   packetType |= (rxData.packet[payloadStart]<<0);

   RX_DETAILS(printf("packet type = 0x%02X\r\n", packetType);

printf("the longAddr is:");printLongAddr(longSrcAddr);)

 

   //根据负载类型,处理数据包

   switch(packetType) { 

     case (GENERIC_DATA_PACKET): //普通类型数据包,用于更新最新通信时间  

       RX_DETAILS(printf("GENERIC_DATA_PACKET\r\n");)

       rxData.lqi = calculateLqi(rxData.errors, (rxData.packet[0]+3));  //计算通信联络质量

 

       //节点坐标

       x=((rxData.packet[payloadStart+3]&0xFF)

          |((rxData.packet[payloadStart+4]&0xFF)<<8)

          |((rxData.packet[payloadStart+5]&0xFF)<<16)

          |((rxData.packet[payloadStart+6]&0xFF)<<24));

       y=((rxData.packet[payloadStart+7]&0xFF)

          |((rxData.packet[payloadStart+8]&0xFF)<<8)

          |((rxData.packet[payloadStart+9]&0xFF)<<16)

          |((rxData.packet[payloadStart+10]&0xFF)<<24));

       printLongAddr(longSrcAddr);

       RX_DETAIL(printf("RSSI=%d,X=%d,Y=%d\n",rxData.rssi,x,y);)

 

       //更新父节点与子节点之间的通信时间

       for(i=0;i<CHILD_TABLE_SIZE;i++)

       {

         if(childTable[i].active&&whetherEqual(longSrcAddr,childTable[i].longAddr))//子节点

         {       

           //更新子节点记录信息

           childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick();

           childTable[i].nodeSite.x=x;

           childTable[i].nodeSite.y=y;

           break;

         }

       }

       break;  

      

/*当节点收到加入请求数据包时,首先判断自己是否是根节点,如果是则回复数据包,

如果不是则判断自己是否已加入网络,如果已加入网络则可作为路由节点使用,如果

没有加入网络则忽略此数据包*/

     case (FATHER_SEARCH_PACKET):

       if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

       {    

         goto stopProcessing;

       }

       if(father.active&&childAvailable) //判断是否具有作为父节点的条件

       {             

           //数据包封装

           packet[0] = (25+2); //数据包长度

           packet[1] = FCF_DATA; //帧类型

           packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型

           currSeqNum++; //数据包序列号

           packet[3]=currSeqNum;

           packet[4] = (0xFFFF>>0)&0xFF; //目标PAN ID

           packet[5] = (0xFFFF>>8)&0xFF;

           memcpy((packet+6), longSrcAddr, 8); //64位长目标地址

           packet[14] = (ST_RadioGetPanId()>>0)&0xFF; //PAN ID

           packet[15] = (ST_RadioGetPanId()>>8)&0xFF;

           memcpy((packet+16), ST_RadioGetEui64(), 8); //64位长目标地址

           packet[24] = PT_FATHER_AVAILABLE; //负载类型,父节点可用数据包

           packet[25]=currentHopCount;  //传递当前节点的跳数

           enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播通信

       }

       break;

      

       /*当节点搜索父节点加入网络时,收到回复的数据,此前是广播所以可能会有多个节

点进行回复,此时需要延时,等待收到所有的回复,然后从回复的数据中选择跳数

最少,如果跳数最少的有多个节点,则选择RSSI最大的节点作为父节点进行加入

网络*/

   case (FATHER_AVAILABLE_PACKET): //父节点可用数据包

       if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

       {    

         goto stopProcessing;

       }

       if(!father.active) //如果当前没有加入网络,进入如下操作 

       {   

         for(i=0;i<current_optional_father_num;i++) //扫描当前可用父节点数组

         {

//判断数组中是否包含此父节点的信息

           if(whetherEqual(longSrcAddr,optionalFather[i].longAddr))

           {                            

            optionalFather[i].rssi +=  rxData.rssi; //RSSI值累加

            optionalFather[i].packetNum++; //记录接收数据包次数

 

            //判断数据包次数是否满足成为有效父节点的最小次数

             if(optionalFather[i].packetNum==MIN_PACKET_NUM)

              optionalFather[i].active=TRUE;

            break;

           }    

         }       

         if(i==current_optional_father_num) //数组中不包含此数据包信息

         {   

           //记录跳数信息

           optionalFather[current_optional_father_num].hop=rxData.packet[payloadStart+1];

 

           //数据包源地址

           memcpy(optionalFather[current_optional_father_num].longAddr,longSrcAddr,8);

           optionalFather[current_optional_father_num].panId=srcPanId; //PAN ID

           optionalFather[current_optional_father_num].rssi=rxData.rssi; //RSSI

           optionalFather[current_optional_father_num].packetNum=1; //数据包个数

           optionalFather[current_optional_father_num].active=FALSE; //不可以

           current_optional_father_num++; //可用父节点数增加

         }

     }

     break;

      

     case (JOIN_REQUEST_PACKET): //加入网络请求数据包

       if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

       {

         goto stopProcessing;

       }

       RX_DETAIL(printf("JOIN_REQUEST_PACKET\r\n");)

      

//数据包封装

       packet[0] = (24+2); //数据包长度

       packet[1] = FCF_DATA + FCF_ACKREQ + FCF_INTRAPAN; //帧类型

       packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型

       currSeqNum++; //数据包序列号

       packet[3]=currSeqNum;

       packet[4] = (ST_RadioGetPanId()>>0)&0xFF; //目标PAN ID

       packet[5] = (ST_RadioGetPanId()>>8)&0xFF;

       memcpy((packet+6), longSrcAddr, 8); //64位长目标地址

       memcpy((packet+14), ST_RadioGetEui64(), 8);//64位长源地址

 

       //扫描子节点数组,判断是否有可用空间添加新的子节点

       for(i=0;i<CHILD_TABLE_SIZE;i++)

       {

         //判断数组中是否已包含此子节点

         if(whetherEqual(childTable[i].longAddr,longSrcAddr))

         {

           //记录子节点坐标信息

           childTable[i].nodeSite.x=(rxData.packet[payloadStart+1]&0xFF

                                     |(rxData.packet[payloadStart+2]&0xFF)<<8

                                       |(rxData.packet[payloadStart+3]&0xFF)<<16

                                        |(rxData.packet[payloadStart+4]&0xFF)<<24);

           childTable[i].nodeSite.y=(rxData.packet[payloadStart+5]&0xFF

                                     |(rxData.packet[payloadStart+6]&0xFF)<<8

                                       |(rxData.packet[payloadStart+7]&0xFF)<<16

                                         |(rxData.packet[payloadStart+8]&0xFF)<<24);

 

           //记录最新通信时间

           childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick();

           if(!childTable[i].active) //更新该数组位置信息

           {

            childNum++; //子节点数增加

            childTable[i].active=TRUE; //此子节点位置占用

            if(childNum==CHILD_TABLE_SIZE) //判断子节点数是否等于最大子节点数

              childAvailable=FALSE; //如果是,则此节点不能再作为其他节点的父节点

           }

           pt = PT_JOIN_ACCEPTED; //发送加入网络允许数据包

           assignedShortId[0] = (shortAddrCounter>>0)&0xFF;

           assignedShortId[1] = (shortAddrCounter>>8)&0xFF;

           RX_DETAIL(printf("Join: the child in the childtable Planet 0x%04X  (index %d)

has joined the network\r\n", shortAddrCounter, i);)

           break;

         }

         else if(!childTable[i].active) //如果数组空间没有被占用,占用该位置空间

         {

           childTable[i].active = TRUE; //占用该位置空间

           childNum++; //子节点数增加

           if(childNum==CHILD_TABLE_SIZE) //判断子节点数是否等于最大子节点数

            childAvailable=FALSE; //如果是,则此节点不能再作为其他节点的父节点

           shortAddrCounter++; //短地址增加

           childTable[i].shortAddr = shortAddrCounter; //短地址

           memcpy(childTable[i].longAddr,longSrcAddr, 8); //64位长地址

 

           //子节点坐标

           childTable[i].nodeSite.x=(rxData.packet[payloadStart+1]&0xFF

                                     |(rxData.packet[payloadStart+2]&0xFF)<<8

                                       |(rxData.packet[payloadStart+3]&0xFF)<<16

                                        |(rxData.packet[payloadStart+4]&0xFF)<<24);

           childTable[i].nodeSite.y=(rxData.packet[payloadStart+5]&0xFF

                                     |(rxData.packet[payloadStart+6]&0xFF)<<8

                                       |(rxData.packet[payloadStart+7]&0xFF)<<16

                                         |(rxData.packet[payloadStart+8]&0xFF)<<24);

 

           //最新通信时间

           childTable[i].lastDataTransmitTick=halCommonGetInt16uQuarterSecondTick();

           pt = PT_JOIN_ACCEPTED; //负载类型

           assignedShortId[0] =  (shortAddrCounter>>0)&0xFF;

           assignedShortId[1] = (shortAddrCounter>>8)&0xFF;

           RX_DETAIL(printf("Join: the child is a new child Planet 0x%04X  (index %d)

has joined the network\r\n", shortAddrCounter, i);)

#ifndef ROOT_ROLE

#ifndef MOBILE_NODE

             //将子节点信息发送到汇聚节点

             sendNewNodeSiteToRoot(longSrcAddr,childTable[i].nodeSite);

#endif

#endif

           break;

         }

       }

       packet[22] = pt; //负载类型

       packet[23] = assignedShortId[0]; //节点Node ID

       packet[24] = assignedShortId[1];

       enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播回复

       break;

      

     case (JOIN_ACCEPTED_PACKET): //允许加入网络数据包

       if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

       { 

         goto stopProcessing;

       }

       RX_DETAIL(printf("JOIN_ACCEPTED_PACKET\r\n");)

 

//设置Node ID

ST_RadioSetNodeId((rxData.packet[payloadStart+1]<<0)

|(rxData.packet[payloadStart+2]<<8));

       networkJoinedStopSearching = TRUE; //加入网络成功,停止搜索

       break;

      

     case (JOIN_DENIED_PACKET): //加入网络拒绝数据包

       RX_DETAIL(printf("JOIN_DENIED_PACKET\r\n");)

       ST_RadioSetPanId(0xFFFF); //重置PAN ID

       break;

      

     case (LEAVING_PACKET): //离开网络数据包

       RX_DETAIL(printf("LEAVING_PACKET\r\n");)

 

       //将节点信息从子节点表中删除

       for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描子节点表,查找子节点

{

         if(childTable[i].active &&  whetherEqual(childTable[i].longAddr,longSrcAddr))

{   

           RX_DETAIL(printLongAddr(longSrcAddr);printf("the node leave the  network\n");)

           childTable[i].active = FALSE; //将该子节点设置为无效

           childNum--; //子节点数减少

           childAvailable=TRUE; //并且设置该节点可继续作为父节点,运行子节点的加入

           break;

         }

       }

       break;

 

   //信标节点发送的位置信息数据包,用于移动节点的定位 

   case (FIXED_NODE_SEND_SITE_PACKET):

     if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

     {

       goto stopProcessing;

     }

     if(!siteIsFixed) //如果位置为固定,则处理此数据包 

     {

       for(i=0;i<current_node_num;i++) //扫描信标节点数组

       {

         //判断是否有此节点的信息

         if(whetherEqual(longSrcAddr,receivePacketRecord[i].longAddr))

         {

           receivePacketRecord[i].totalRssi+=rxData.rssi; //RSSI值累加

           receivePacketRecord[i].current_num++; //数据包数增加

           break;

         }

       }

       if(i==current_node_num) //如果数组中无此节点的记录信息

       {

         //获取信标节点的坐标

         x=(rxData.packet[payloadStart+1]&0xFF

                |(rxData.packet[payloadStart+2]&0xFF)<<8

                |(rxData.packet[payloadStart+3]&0xFF)<<16

                |(rxData.packet[payloadStart+4]&0xFF)<<24);

         y=(rxData.packet[payloadStart+5]&0xFF

               |(rxData.packet[payloadStart+6]&0xFF)<<8

                |(rxData.packet[payloadStart+7]&0xFF)<<16

                |(rxData.packet[payloadStart+8]&0xFF)<<24);

         RX_DETAIL(printf("the node site x is:%d, y is:%d\n",x,y);)

         receivePacketRecord[current_node_num].nodeSite.x=x; //记录坐标

         receivePacketRecord[current_node_num].nodeSite.y=y;

         receivePacketRecord[current_node_num].current_num=1;//第一个数据包

         receivePacketRecord[current_node_num].totalRssi=rxData.rssi;//RSSI

         memcpy(receivePacketRecord[i].longAddr,longSrcAddr,8); //64位长地址

         current_node_num++; //当前可用定位节点个数

       }       

     }     

     break;

 

     case (CHANNEL_SEARCH_PACKET): //信道搜索数据包   

       if(channelSearched)

       {

          RX_DETAIL(printf("CHANNEL_SEARCH_PACKET\r\n");)

         

          //数据包封装

          packet[0] = (24+2);  //数据包长度

          packet[1] = FCF_DATA; //帧类型

          packet[2] = FCF_LONGDST + FCF_LONGSRC; //地址类型

          currSeqNum++; //数据包序列号

          packet[3]=currSeqNum;

          packet[4] = (0xFFFF>>0)&0xFF; //目标PAN ID

          packet[5] = (0xFFFF>>8)&0xFF;

          memcpy((packet+6), longSrcAddr, 8); //长目标地址

          packet[14] = (ST_RadioGetPanId()>>0)&0xFF; //PAN ID

          packet[15] = (ST_RadioGetPanId()>>8)&0xFF;

          memcpy((packet+16), ST_RadioGetEui64(), 8); //长源地址

          packet[24] = PT_CHANNEL_AVAILABLE; //负载类型,信道可用数据包

          enqueueTxPacket(TRUE, 0xFFFF, packet, 0); //广播回复

       }    

       break;

 

       case (CHANNEL_AVAILABLE_PACKET): //信道可用数据包

         RX_DETAIL(printf("CHANNEL_AVAILABLE_PACKET\r\n");)

         channelStopSearching=TRUE;

         break;

      

       //移动节点请求定位数据包,当信标节点接收到此数据包时广播其位置信息

      case (POSITIONING_REQUEST_PACKET):  

         if(rxData.rssi<RELIABLE_RSSI)  //根据数据包RSSI进行数据包的过滤

         {

           goto stopProcessing;

         }

#ifndef ROOT_ROLE

#ifndef MOBILE_NODE

         if(siteIsFixed) //如果为信标节点

         {

             fixedNodeBroadcast(longSrcAddr,FALSE);  //广播其位置信息

         }

#endif

#endif

       break;

 

   //移动智能体请求定位数据包,当信标节点接收到此数据包时广播其位置信息

   case (MOBILE_NODE_POSITIONING_REQUEST_PACKET):

     if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

     {    

       goto stopProcessing;

     }

#ifndef ROOT_ROLE

#ifndef MOBILE_NODE

     if(siteIsFixed)

     {     

       fixedNodeBroadcast(longSrcAddr,TRUE); //信标节点广播,用于移动智能体定位

     }

#endif

#endif

     break;

    

   case (DATA_FROM_MOBILE_NODE_PACKET): //移动智能体发送的数据包

     if(rxData.rssi<RELIABLE_RSSI) //根据数据包RSSI进行数据包的过滤

     {

       goto stopProcessing;

     }

#ifdef ROOT_ROLE //如果为汇聚节点

 

       //获取移动智能体的坐标信息

       x=((rxData.packet[payloadStart+1]&0xFF)

          |((rxData.packet[payloadStart+2]&0xFF)<<8)

          |((rxData.packet[payloadStart+3]&0xFF)<<16)

          |((rxData.packet[payloadStart+4]&0xFF)<<24));

       y=((rxData.packet[payloadStart+5]&0xFF)

          |((rxData.packet[payloadStart+6]&0xFF)<<8)

          |((rxData.packet[payloadStart+7]&0xFF)<<16)

          |((rxData.packet[payloadStart+8]&0xFF)<<24));

       memcpy(childLongAddr,(rxData.packet+payloadStart+9),8); //64位长地址

       RX_DETAIL(printf("%d %d\n",x,y);)   

       for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描其子节点表  

       {

         if(whetherEqual(longSrcAddr,childTable[i].longAddr)) //查找数据包来自哪个子节点

         {

           //TRUE表示能够在移动智能体和汇聚节点之间建立通信路由

           inDirectDataOfMobileNode=TRUE;

 

           //表示此子节点能够和移动智能体之间建立通信路由

           childTable[i].transDataFromMobileNode=TRUE;

childTable[i].pathStartTime=((rxData.packet[payloadStart+9])

|((rxData.packet[payloadStart+10]&0xFF)<<8)); //记录通信路由的建立时间

           break;

         }

       }

#else

#ifndef MOBILE_NODE //非汇聚节点和非移动智能体

/*间节点收到来自移动智能体的数据包进行转发,发送给其父节点,

父节点继续向其父节点转发,直到到达汇聚节点*/

     transmitDataFromMobileNode(payloadStart+1,rxData.packet[0]-payloadStart);  //转发数据

     for(i=0;i<CHILD_TABLE_SIZE;i++) //扫描其子节点表

     {

       if(whetherEqual(longSrcAddr,childTable[i].longAddr)) //查找数据包来自哪个子节点

       {

         inDirectDataOfMobileNode=TRUE; //表示此节点与移动智能体之间建立通信路径

         childTable[i].transDataFromMobileNode=TRUE; //通信路径的下一跳为此子节点

         if(rxData.packet[0]-payloadStart==8) //判断数据包中是否包含时间信息

           childTable[i].pathStartTime=halCommonGetInt16uQuarterSecondTick(); //当前时间

        else

childTable[i].pathStartTime=((rxData.packet[payloadStart+9])

|((rxData.packet[payloadStart+10]&0xFF)<<8));  //数据包中的时间

         break;

       }

     }

#endif

#endif

     break;

    

   case (DATA_TO_MOBILE_NODE_PACKET): //发往移动智能体的数据包

#ifndef MOBILE_NODE

#ifndef ROOT_ROLE

     //非移动智能体节点收到来自汇聚节点发送给移动智能体的数据,进行转发

     dataTransmitToMobileNode(payloadStart+1,rxData.packet[0]-payloadStart);

#endif   

#endif

     break;

    

   //广播发送给移动智能体的数据包

   case (DATA_BROADCAST_TO_MOBILE_NODE_PACKET):

#ifdef MOBILE_NODE

/*移动智能体根据收到来自汇聚节点的信息,调整自己的移动

汇聚节点发送给移动智能体的数据可能是控制命令,可能是新的目标坐标*/

     if(rxData.packet[0]-payloadStart > 1)//发送的是目标坐标

     {

       x=((rxData.packet[payloadStart+1]&0xFF)

          |((rxData.packet[payloadStart+2]&0xFF)<<8)

          |((rxData.packet[payloadStart+3]&0xFF)<<16)

          |((rxData.packet[payloadStart+4]&0xFF)<<24));

       y=((rxData.packet[payloadStart+5]&0xFF)

          |((rxData.packet[payloadStart+6]&0xFF)<<8)

          |((rxData.packet[payloadStart+7]&0xFF)<<16)

          |((rxData.packet[payloadStart+8]&0xFF)<<24));

       RX_DETAIL(printf("mobile node receive new  site:x=%d,y=%d\n",x,y);)

       if(x!=targetSite.x||y!=targetSite.y)

       {

        targetSite.x=x; //设置新的移动坐标

        targetSite.y=y;

        isArriveTargetSite=FALSE; //表示没有达到指定位置

        arriveTargetSiteTimes=0; //清空达到指定位置次数

      }      

    }

    else //发送的是控制命令

    {

      u8 data;

      data=rxData.packet[payloadStart+1];

      switch (data)

      {

      case 's': //停止移动命令    

        isArriveTargetSite=TRUE;

        STOP(); //执行STOP()函数,停止移动智能体的移动

        break;

      case 'm': //移动命令          

        isArriveTargetSite=FALSE;

        adjustAngle(nodeSite,targetSite); //根据当前位置和目标位置调整移动方向及角度

        break;

      default://不可识别的信息,不进行任何操作

        break;

      }

    }

#endif

    break;

   

  case (DATA_TO_ROOT_PACKET): //收到发送到根节点的数据

//如果汇聚节点接收到此信息,通过串口显示信息

#ifdef ROOT_ROLE

       //获取坐标信息

       x=((rxData.packet[payloadStart+17]&0xFF)

          |((rxData.packet[payloadStart+18]&0xFF)<<8)

          |((rxData.packet[payloadStart+19]&0xFF)<<16)

          |((rxData.packet[payloadStart+20]&0xFF)<<24));

       y=((rxData.packet[payloadStart+21]&0xFF)

          |((rxData.packet[payloadStart+22]&0xFF)<<8)

          |((rxData.packet[payloadStart+23]&0xFF)<<16)

          |((rxData.packet[payloadStart+24]&0xFF)<<24));

       memcpy(fatherLongAddr,(rxData.packet+payloadStart+1),8); //父节点64位长地址

       memcpy(childLongAddr,(rxData.packet+payloadStart+9),8); //子节点64为长地址

 

       //输出64位长地址信息

       printFatherLongAddr(fatherLongAddr);

       printChildLongAddr(childLongAddr);

       RX_DETAIL(printf("RSSI=%d,",rxData.rssi);)

       RX_DETAIL(printf("X=%d,Y=%d\n",x,y);)

#else //不是汇聚节点而是中间路由节点

#ifndef MOBILE_NODE

     dataTransmitToRoot(payloadStart+1,rxData.packet[0]-payloadStart); //转发数据

#endif

#endif

       break;

   default:

       RX_DETAIL(printf("Unknown payload type\r\n");)

       goto stopProcessing;

  }

stopProcessing:

   rxData.packetBeingProcessed = FALSE;

}

 

 

 

本文出自《STM32W108嵌入式无线传感器网络》邱铁,夏锋,周玉编著.清华大学出版社,20145

版权声明:

相关文章推荐

STM32W108无线传感器网络节点定位技术

使用STM32W108无线节点完成基于接收信号强度指示(RSSI:Received SignalStrength Indication)的N次三边质心加权定位,对移动中的节点实时进行定位,并将定位结果...

STM32W108无线射频模块两节点之间通信实例

本文基于802.15.4/ZigBee的SimpleMac协议栈编写程序,实现两个STM32W108无线节点之间的通信。节点分为SUN节点和PLANET节点,SUN节点使用STM32W108无线开发板...

无线传感器网络节点连通率

前段时间忙学业,现在来总结学习中遇到的问题及解决方法。 第一个问题是这样的: 在1x1的单位矩形中随机部署传感器节点,而且假设每个节点的通信半径一样,要求利用蒙特卡洛算法进行1000次试验分别模拟...

水下无线传感器网络节点定位算法

目前存在着大量的基于水下的无线传感器网络节点定位算法,根据采集或处理数据方式的不同,可将这些定位算法划分为以下几种类型:       (1)根据位置计算过程中是否测量节点间的角度或距离信息,可将...

STM32W108无线ZigBee射频模块复位模块原理

STM32W108具有丰富的功能模块,包括电源、复位、时钟、系统定时器、电源管理和加密引擎等。

STM32W108无线ZigBee射频芯片引脚说明(上篇)

STM32W108是一个集成的片上系统,将一个2.4GHz的IEEE802.15.4标准的收发器、32位的ARM Cortex-M3微处理器、Flash和RAM存储器融合,添加相应的外设,设计成基于8...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)