LoRa开发7: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回应帧完毕;

说明:LPWA物联网应用站(LPWAP.com)通过公开互联网收集、整理并转载有关LPWA物联网应用解决方案,以供广大LPWA应用开发者和爱好者共同学习交流和参考运用到实际生产生活中。本站所有转载的文章、图片、音频、视频等资料的版权归版权所有人所有并衷心感谢您的付出,由于本站采纳的非本站原创文章及图片等内容无法一一联系确认版权者,如果本网所选内容的文章原创作者认为其作品不宜放在本站,请及时通过以下留言功能通知我们采取适当措施,避免给双方造成不必要的经济损失。如果您希望保留文章在本站,但希望文章末尾提供对作者的致谢或者产品、网站交换链接的,也请将需求写入以下留言栏中,谢谢您的支持。让我们共同努力,打造万物互联的未来美好生活!

您的留言或需求: