LoRa开发7:PingPong系统

来源:互联网 发布:安卓按键软件 编辑:程序博客网 时间:2024/06/03 14:20

PingPong系统

1 引言

前2章介绍了SX1278的发送和接收,在此基础上,我们设计一个有趣的PingPong系统,更好地理解LoRa终端的收发逻辑。

该系统将LoRa终端自动定义成2种角色:master和slave。master主动发送ping数据帧,接收pong数据帧;slave如果接收到ping数据帧,回应pong数据帧。

2 整体逻辑流程


如上图所示,当LoRa终端上电后,在(2 * PingPongPeriod)周期内没有接收到ping数据帧,它就认为自己是master。Master节点每隔(1 * PingPongPeriod)周期主动发送ping数据帧,然后启动RF接收,可能接收到pong回应帧(正常通信),也可能接收超时(slave没有上电或通信失败)。


同理,当LoRa终端上电后,在(2 * PingPongPeriod)周期内接收到ping数据帧,它就认为自己是slave。Slave节点启动RF接收,如果接收到ping数据帧,它将发送pong回应帧。

一个节点从上电,判断自身角色,根据角色处理逻辑,如下流程图所示。


3 代码剖析

PROCESS_THREAD(PingPong, ev, data)

{

  #definePING    "ping, this is MASTER ofrime node."

  #definePONG    "pong, this is SLAVE of rimenode."

  #definePING_SIZE    34

  #definePONG_SIZE    33

 

  staticbool    s_bIsMaster;

  staticuint16_t    s_wPingPongPeriod;

  staticint32_t    s_lTxCnt = 0;

  staticint32_t    s_lRxCnt = 0;

  

  PROCESS_BEGIN();

 

  InitSetLoRa();

  s_wPingPongPeriod =

  SX1278GetTimeOnAir(4) + SX1278GetTimeOnAir(4) + 15;                   1

 

  /*Determine MASTER or SLAVE by RX "ping". */

  SX1278Receive(2 * s_wPingPongPeriod);                                              2

  PROCESS_YIELD(); /* Yield until receive or timeout. */                          3

  SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */       4

 

  if(GetCompareRxFrame(PING, PING_SIZE))                                           5

  {

    s_bIsMaster = FALSE;

  }

  else

  {

    s_bIsMaster = TRUE;

  }

 

  if(s_bIsMaster) /* Is MASTER */

  {

    while (1)

    {

      /* TX "ping" */

      ++s_lTxCnt;

      SX1278Send(PING, PING_SIZE);                                                          6

      PROCESS_YIELD_UNTIL( (RF_Tx_Done == s_tRFResult) || 

                                                   (RF_Tx_Timeout ==s_tRFResult) );          7

 

      /* RX "pong" */

      SX1278Receive(s_wPingPongPeriod);                                                  8

      PROCESS_YIELD(); /* Yield until receive a frame or timeout. */

      SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */

 

      if (GetCompareRxFrame(PONG, PONG_SIZE))                                    9

      {

        ++s_lRxCnt;

        RIME_DBG( RIME_DBG_ON,  

                             "TxCnt=%ld, Rx Cnt=%ld, SNR=%d, RSSI=%d.\r\n",

                             s_lTxCnt, s_lRxCnt, s_chPacketSnr,s_nPacketRssi );   10

      }

    }

  }

 else /* Is SLAVE */

  {

    while (1)

    {

      /* RX "ping" */

      SX1278Receive(0);                                                                                  11

      PROCESS_YIELD(); /* Yield until receive a frame or rx error. */

      SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */

      if (GetCompareRxFrame(PING, PING_SIZE))                                          12

      {

        /* TX "pong" */

        ++s_lTxCnt;

        SX1278Send(PONG, PONG_SIZE);                                                      13

        PROCESS_YIELD_UNTIL( (RF_Tx_Done ==s_tRFResult) || 

                                                     (RF_Tx_Timeout == s_tRFResult) );         14

 

        ++s_lRxCnt;

        RIME_DBG( RIME_DBG_ON,

                             "Tx Cnt=%ld, RxCnt=%ld, SNR=%d, RSSI=%d.\r\n",

                             s_lTxCnt, s_lRxCnt,s_chPacketSnr, s_nPacketRssi ); 

      }

    }

  }

  PROCESS_END();

}

Line#1:计算PingPong通信空中时间,添加15ms做为收发准备时间;

Line#2:启动接收功能,超时时长为2倍PingPong通信空中时间;

Line#3:阻塞进程,直到接收数据帧或超时;

Line#4:设置SX1278为休眠,否则它将处于持续接收状态(那怕超时亦如此);

Line#5:GetCompareRxFrame()复制数据帧到解析工作区,比较是否为ping帧;

 

Master节点逻辑

Line#6:master节点发送ping数据帧;

Line#7:阻塞进程,直到发送ping数据帧完毕;

Line#8:启动接收功能,超时时长为PingPong通信空中时间;

Line#9:比较是否为pong回应帧;

Line#10:打印发送和接收数据帧个数,SNR和RSSI值;

 

Slave节点逻辑

Line#11:启动持续接收功能,为0表明关闭超时功能;

Line#12:比较是否为ping数据帧;

Line#13:slave节点发送pong回应帧;

Line#14:阻塞进程,直到发送pong回应帧完毕;


1 1
原创粉丝点击