迪加 发表于 2012-9-22 10:34:39

迪加Zigbee学习历程九 ZigBee信号传输质量检测

本帖最后由 迪加 于 2012-9-22 14:37 编辑

前言:PER(误包率检测)实验是BasicRF的第二个实验,和无线点灯一样是没有使用协议栈的点对点通讯。通过无线点灯大家应该对zigbee的发射和接收有个感性的认识,本次实验讲解不会像无线点灯一样讲得那么详细,因为接收发射的过程基本上是一样的,但也希望初学者能自己认真学习一下这个实验,相信会对无线传输会有一个更清晰的认识。
实现平台:两块WeBee base_board及两块WeBee无线模块


                              图1 网蜂ZigBee开发平台

实验现象:两块WeBee模块通信,一个模块作发射,另外一个模块接收,接收模块通过串口不在PC机上显示当前的误包率、RSSI值和接收到数据包的个数。

实验详解:例程的源代码CC2530 BasicRF.rar是TI官网上下载的,打开\CC2530 BasicRF\ide\srf05_cc2530\iar里面的per_test.eww工程,由于我们的硬件平台不同于TI的开发板,所以我们需要在per_test中加入串口发送函数,才能在串口调试助手上看到我们的实验现象。

打开工程,在application文件夹点per_test.c我们的主要功能函数都在这里

                                             图2

在这个.c文件中添加串口发送函数
INCLUDES中添加:#include "string.h"

                              图3

然后继续添加串口初始化和发送函数:

                              图4

很简单地就把串口搞定了,因为只有接收模块才会用到串口,所以串口的初始化只需要放在appReceiver ( )函数中

下面分析整个工程的发送和接收过程
首先还是要先找到main.c
/******************************************************************************
* @fn          main
*
* @brief       This is the main entry of the "PERtest" application.
*
* @param       basicRfConfig - file scope variable.Basic RF configuration data
*            appState - file scope variable.Holds application state
*            appStarted - file scope variable.Used to control start and stop of
*            transmitter application.
*
* @return      none
*/
1.       voidmain (void)2.       {3.       uint8appMode;4.       appState= IDLE;5.       appStarted= TRUE;6.       // Config basicRF   配置Basic RF7.       basicRfConfig.panId= PAN_ID;8.       basicRfConfig.ackRequest= FALSE;
9.       // Initialise board peripherals 初始化外围硬件10.   halBoardInit();
11.   // Initalise hal_rf   初始化hal_rf12.   if(halRfInit()==FAILED){13.   HAL_ASSERT(FALSE);14.   }
15.   // Indicate that device is powered16.   halLedSet(1);17.   // Print Logo and splash screen on LCD18.   utilPrintLogo("PERTester");
19.   // Wait for user to press S1 to enter menu20.   halMcuWaitMs(350);21.   // Set channel22.   //设置信道,规范要求信道只能为为11——25。这里选择信道11 23.   basicRfConfig.channel= 0x0B;
//设置模块的模式,一个作为发射,另一个为接收,看是否define MODE_SEND
24.   #ifdefMODE_SEND25.   appMode= MODE_TX;26.   #else27.   appMode= MODE_RX;28.   #endif29.   // Transmitter application30.   if(appMode== MODE_TX) {// No return from here    如果define MODE_SEND则进入appTransmitter();发射模式
31.   appTransmitter();32.   }33.   // Receiver application34.   else if(appMode== MODE_RX) {35.   // No return from here如果没有define MODE_SEND则进入appReceiver ();接收模式36.   appReceiver();37.   }
38.   // Role is undefined. This code should not be reached39.   HAL_ASSERT(FALSE);40.   }
大家看注释也应该知道main.c做了哪些事情:
1、 一大堆的初始化(都是必须的)2、 设置信道,发射和接收模块的信道必须一致3、 选择为发射或者接收模式

发射函数define MODE_SEND则进入appTransmitter();
/*********************************************************
* @fn         appTransmitter
*
* @brief       Applicationcode for the transmitter mode. Puts MCU in endless
*            loop
*
* @param      basicRfConfig - file scope variable. Basic RF configuration data
*            txPacket -file scope variable of type perTestPacket_t
*            appState -file scope variable. Holds application state
*            appStarted- file scope variable. Controls start and stop of
*                        transmission
*
* @return      none
*/
1.       static void appTransmitter()2.       {3.       uint32 burstSize=0;4.       uint32 pktsSent=0;5.       uint8 appTxPower;6.       uint8 n;7.       // Initialize BasicRF               /* 初始化Basic RF */8.       basicRfConfig.myAddr = TX_ADDR;9.       if(basicRfInit(&basicRfConfig)==FAILED) 10.    {
11.    HAL_ASSERT(FALSE);
12.    }

13.    // Set TX outputpower                      /* 设置输出功率 */14.    halRfSetTxPower(2);            //HAL_RF_TXPOWER_4_DBM

15.    // Set burstsize         /* 设置进行一次测试所发送的数据包数量 */16.    burstSize = 1000;

17.    // Basic RF puts onreceiver before transmission of packet, and turns off after packet is sent18.    basicRfReceiveOff();

19.    /*************************************************************/
20.    Config timer andIO   配置定时器和IO21.    *************************************************************/22.    appConfigTimer(0xC8);

23.    // Initalise packetpayload            /* 初始化数据包载荷 */24.    txPacket.seqNumber = 0;
25.    for(n = 0; n <sizeof(txPacket.padding); n++) 26.    {
27.    txPacket.padding = n;
28.    }
//************************进入循环*******************//
29.    while (TRUE)
30.    {
31.    while(appStarted)
32.    {
33.    if (pktsSent < burstSize)
34.    {
35.    // Make suresequence number has network byte order36.    UINT32_HTON(txPacket.seqNumber);// 改变发送序号的字节顺序
37.    basicRfSendPacket(RX_ADDR,(uint8*)&txPacket, PACKET_SIZE);
38.    // Change byte orderback to host order before increment /* 在增加序号前将字节顺序改回为主机顺序 */39.    UINT32_NTOH(txPacket.seqNumber);
40.    txPacket.seqNumber++;    //数据包序列号自加1

41.    pktsSent++;
42.    appState = IDLE;
43.    halLedToggle(1);   //改变LED1的亮灭状态
44.    halMcuWaitMs(500);
45.    }
46.    else
47.    appStarted = !appStarted;
48.    // Reset statisticsand sequence number/* 复位统计和序号 */49.    pktsSent = 0;
50.    }
51.    }
52.    }

总结appTransmitter函数完成的任务:
1、初始化BasicRF
2、设置发射功率
3、设定测试的数据包量
4、配置定时器和IO
5、初始化数据包载荷
6、进行循环函数,不断地发送数据包,每发送完一次,下一个数据包的序列号自加1再发送;

接收函数没有define MODE_SEND则进入appReceiver ()
接收函数比较长,担心大家看到会反感,而且查看不方便,此处只把有必要说明的地方才贴出来,具体的全部代码内容肯定是打开工程看最好啦。。。

/***********************************************************************************
*@fn          appReceiver*
*@brief       Application code for thereceiver mode. Puts MCU in endless loop*
*@param       basicRfConfig - file scopevariable. Basic RF configuration data*            rxPacket - file scope variable oftype perTestPacket_t*
* @return      none
*/
1.       staticvoid appReceiver()2.       {3.       initUART();                  // 初始化串口   4.       basicRfConfig.myAddr= RX_ADDR;5.       if(basicRfInit(&basicRfConfig)==FAILED)Initialize BasicRF //初始化Basic RF6.       {7.       HAL_ASSERT(FALSE);8.       }9.       basicRfReceiveOn();10.   while(TRUE) 11.   {12.   while(!basicRfPacketIsReady()); // 等待新的数据包13.   if(basicRfReceive((uint8*)&rxPacket,MAX_PAYLOAD_LENGTH, &rssi)>0) {14.   halLedSet(3);//*************P1_415.   UINT32_NTOH(rxPacket.seqNumber);// 改变接收序号的字节顺序16.   segNumber= rxPacket.seqNumber   17.   //若统计被复位,设置期望收到的数据包序号为已经收到的数据包序号   18.   if(resetStats)19.   {20.   rxStats.expectedSeqNum= segNumber;21.   resetStats=FALSE;22.   }      23.   // Subtract old RSSI value from sum24.   rxStats.rssiSum-= perRssiBuf;// 从sum中减去旧的RSSI值25.   // Store new RSSI value in ring buffer, will add it to sum later26.   perRssiBuf=rssi;// 存储新的RSSI值到环形缓冲区,之后它将被加入sum27.   rxStats.rssiSum+= perRssiBuf;// 增加新的RSSI值到sum28.   if(++perRssiBufCounter== RSSI_AVG_WINDOW_SIZE) {29.   perRssiBufCounter= 0;      // Wrap ring buffer counter 30.   }31.   // Check if received packet is the expected packet   检查接收到的数据包是否是所期望收到的数据包32.   if(rxStats.expectedSeqNum== segNumber)//是所期望收到的数据包 33.   {34.   rxStats.expectedSeqNum++;35.   }36.   // If there is a jump in the sequence numbering this means somepackets inbetween has been lost.37.   elseif(rxStats.expectedSeqNum < segNumber) //大于期望收到的数据包的序号38.   {                                     // 认为丢包39.   rxStats.lostPkts+= segNumber - rxStats.expectedSeqNum;40.   rxStats.expectedSeqNum= segNumber + 1;41.   }42.   else // 小于期望收到的数据包的序号43.   {      44.   rxStats.expectedSeqNum= segNumber + 1;45.   rxStats.rcvdPkts= 0;46.   rxStats.lostPkts= 0;47.   }48.   rxStats.rcvdPkts++;49.   /*******************以下为串口打印部分的函数*********************/50.   temp_receive=(int32)rxStats.rcvdPkts;51.   if(temp_receive>1000)52.   {53.   if(halButtonPushed()==HAL_BUTTON_1){54.   resetStats= TRUE;55.   rxStats.rcvdPkts= 1;56.   rxStats.lostPkts= 0;57.   }58.   }59.   Myreceive=temp_receive/100+'0';    //打印接收到数据包的个数60.   Myreceive=temp_receive%100/10+'0';61.   Myreceive=temp_receive%10+'0';62.   Myreceive='\0';63.   UartTX_Send_String("RECE:",strlen("RECE:"));64.   UartTX_Send_String(Myreceive,4);65.   UartTX_Send_String("    ",strlen("    "));       66.   temp_per=(int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts));67.   Myper=temp_per/100+'0';             //打印当前计算出来的误包率68.   Myper=temp_per%100/10+'0';69.   Myper='.';70.   Myper=temp_per%10+'0';71.   Myper='%';72.   UartTX_Send_String("PER:",strlen("PER:"));73.   UartTX_Send_String(Myper,5);74.   UartTX_Send_String("    ",strlen("    "));75.   temp_rssi=(0-(int32)rxStats.rssiSum/32);//打印上32个数据包的RSSI值的平均值76.   Myrssi=temp_rssi/10+'0';77.   Myrssi=temp_rssi%10+'0';78.   UartTX_Send_String("RSSI:-",strlen("RSSI:-"));79.   UartTX_Send_String(Myrssi,2);      80.   UartTX_Send_String("\n",strlen("\n"));81.   halLedClear(3);82.   halMcuWaitMs(300);83.   }               84.   }85.   }那么长,有点头晕是吧。不用一句句地看,撒几眼你就知道这个函数干了什么事了…但还是建议直接打开工程学习。
接收函数的作用:
1、   串口在此初始化2、   初始化BasicRF3、   不断地接收数据包,并检查数据包序号是否为期望值,作出相应处理4、   串口打印出,接收包的个数\误包率及上32个数据包的RSSI值的平均值

有几个比较重要的数据作个简要的说明一下:
为了获取传输的性能参数,接收器中包含了如下几个数据(包含在rxStats 变量中,其类型为perRxStats_t)rxStats.expectedSeqNum   预计下一个数据包的序号,其值等于“成功接收的数据包”+“丢失的数据包”+1 rxStats.rssiSum          上32 个数据包的 RSSI 值的和
rxStats.rcvdPkts          每次PER 测试中,成功接收到的数据包的个数
rxStats.lostPkts          丢失数据包的个数
这些数据具体是怎么得来,我们没有必要具体去分析,直接读取我们感兴趣的数据就可以了。
误包率又是怎么计数的呢?TI公司的使用文档有说明的

如果大家想了解具体的话就可以去\CC2530 BasicRF\docs 文件夹中找到CC2530_Software_Examples.pdf 文档4.2章节有详细介绍的

实验操作:1、下载发射模块,在per_test.c中,找到:/********************important select or shelt****************************/#defineMODE_SEND            //屏蔽时:appReceiver                               //不屏蔽时:appTransmitter/******************************************************************/不要屏蔽#define MODE_SEND    编译下载到发射模块 2、下载接收模块,同样的找到/********************important select or shelt****************************///#define MODE_SEND            //屏蔽时:appReceiver                               //不屏蔽时:appTransmitter/******************************************************************/要屏蔽#define MODE_SEND编译下载到接收模块 3、 接收模块USB连接PC机并给发射模块供电,打开串口调试助手,并设置好相应的COM口和波特率,先开接收模块,再开发送模块。然后就可以看到我们的实验现象了。如图5所示。 由于距离比较近,所以掉包不明显的,有兴趣的可以把发送节点拿到较远的地方,然后观察掉包率。或者先打开发送模块,再打开接收模块来测试掉包,会显示出掉包情况。

                  图5 实验现象(包数量-掉包率-RSS)

至此,信号传输质量检测结束。和历程八一样,这次也是没用到协议栈的内容。在下一次教程中,我们正式进入协议栈内容。

附网蜂开源程序:

(有莫友提及到,这些内容在网蜂《zigbee实战演练》已经提及了,为什么还要再花时间发帖出来。迪加在这里需要说明一下,我们在学习每个内容过程中总遇到问题,这也很可能是后来者将会遇到的问题,我们把问题记录在帖子里,那么以后的人就能看到或者搜索到相关内容,从而节省解决问题的时间。这对他们是有很大帮助的。群讨论能解决当前问题,而帖子的魅力却能解决以后的问题,感谢大家对网蜂的支持。)

rei1984 发表于 2012-9-22 10:40:14

请问 lz 目前zigbee点对点 传输的话, 距离 最远可以做到 多少?

zegbee 的 强项是不是在自动组网,而不是在 单点传输上 比 距离上?

zigbee的 速率可以做到 多大,是实时传 640*48030fps的 视频?

Flyback 发表于 2012-9-22 10:52:37

rei1984 发表于 2012-9-22 10:40 static/image/common/back.gif
请问 lz 目前zigbee点对点 传输的话, 距离 最远可以做到 多少?

zegbee 的 强项是不是在自动组网,而 ...

要是zigbee也能传视频,让wifi情何以堪

hongshuang 发表于 2012-9-22 13:01:46

Zigbee的优势在于自组网,但是不支持休眠唤醒,所以功耗一直降不下来,实际应用不知道怎么样了?
TI的协议栈代码看着好乱,以前在学校的时候看着那些变量定义啊,函数什么的感觉好晦涩,不知道现在是不是这样?
协议栈封装了网络层,开发主要是在应用层,我一直认为网络层才是重中之重,所有的应用都是基于网络的基础才实现的,始终感觉TI的Zigbee协议栈适合于学习不适合商用.
以上个人观点,有不对的地方请指教!
PS:TI的协议栈已经几年没有更新了,

迪加 发表于 2012-9-22 14:27:12

rei1984 发表于 2012-9-22 10:40 static/image/common/back.gif
请问 lz 目前zigbee点对点 传输的话, 距离 最远可以做到 多少?

zegbee 的 强项是不是在自动组网,而 ...

1.距离需要看你模块的性能。
2.basicRF能给你们对组网一个提前的感知认识。
3.理论250KB/S。不能传输视频和音频。优势是适合做无线传感网。

迪加 发表于 2012-9-22 14:28:08

hongshuang 发表于 2012-9-22 13:01 static/image/common/back.gif
Zigbee的优势在于自组网,但是不支持休眠唤醒,所以功耗一直降不下来,实际应用不知道怎么样了?
TI的协议 ...

协议栈还是使用 2007 pro . 另外zigbee是支持定时唤醒和无线唤醒的。

helongfu 发表于 2012-9-23 19:59:08

{:victory:}

dingshidong214 发表于 2012-9-23 20:56:31

好贴支持下先

dingshidong214 发表于 2012-9-23 20:56:48

好贴支持下先{:smile:}

hongshuang 发表于 2012-9-26 22:46:15

迪加 发表于 2012-9-22 14:28 static/image/common/back.gif
协议栈还是使用 2007 pro . 另外zigbee是支持定时唤醒和无线唤醒的。

定时唤醒可以由MCU去实现,但是休眠的时候路由应该会受到很大影响,请教一下Zigbee在这方面是怎么处理的?
无线唤醒我只知道TI的CC1101这类支持,下一步准备用它去组网,CC2520/2530也支持吗?能够做休眠的点我觉得只适合做END而不适合做Router,这样一样功耗还是降不下去!

52robot 发表于 2012-9-26 23:00:04

楼主开源精神值得学习,马克备用

迪加 发表于 2012-9-27 13:01:17

hongshuang 发表于 2012-9-26 22:46 static/image/common/back.gif
定时唤醒可以由MCU去实现,但是休眠的时候路由应该会受到很大影响,请教一下Zigbee在这方面是怎么处理的 ...

官方也是了。 协调器和路由器需要组网和中继,不推荐睡眠的。

fx568000 发表于 2012-10-11 18:11:31

楼主,我应用CC2530做了一款普通功率的ZIGBEE产品,实际通讯距离是130米左右,我想从硬件上修改一下,来使传输距离加大;
我想用巴伦器件接RF_P与RF_N端的形式(以前是用TI给的原理图做的),如下图所示:的方式改进天线部分的电路,不知道这样改进怎么样,楼主有这方面的经验吗?

345161974 发表于 2013-1-23 12:59:02

很有道理,有必要把实践教程里面的各个章节拿出来发帖,这样大家更容易交流了,具有问题的针对性.

Sc0pin 发表于 2013-7-23 16:48:07

iar是什么版本的啊?

supermantv 发表于 2014-4-9 17:37:50

mark{:smile:}{:smile:}

ywq 发表于 2014-8-15 13:34:57

谢谢分享,除了通过串口,可以用单片机显示出来吗?
页: [1]
查看完整版本: 迪加Zigbee学习历程九 ZigBee信号传输质量检测