LoRa点对点通信,OLED显示(内附代码)
时间:2022-07-25
本文章向大家介绍LoRa点对点通信,OLED显示(内附代码),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
前言:在上一节的基础上,为了方便测试,对PingPong通信进行改造,加入OLED显示,显示接收、发送数据包的个数和显示接收数据包的RSSI和SNR,一目了然。(视频演示:LoRa点对点通信演示)
1、关于RSSI和SNR
RSSI:是Received Signal Strength Indication的缩写,中文含义是接收的信号强度指示,RSSI越大,表明信号越好。
SNR:是Signal Noise Ratio的缩写,中文含义是信噪比,是信号电平与噪声电平之比,SNR越大,表明信号越好。
2、实验设计
标定一个主机(M)一个从机(S),上电后主机主动发起通讯(发送“ping”),从机处于接收状态,从机接收到主机的信号后,回复信号(pong),完成一次正常通讯。在下一个发送点到来之前,主机都会一直等待从机的回复。下一个发送点到达之后发起下一次通讯。在整个通讯过程中从机不会主动发起通讯,只会在收到主机的信号后,回复主机信号。主从机的OLED会相应显示各自发送和接收到的包的个数和接收信号的RSSI和SNR。
3、代码实现
void MasterCycleSendTimerEvent()
{
TimerStop(&MasterCycleSendTimer);
Buffer[0] = 'P';
Buffer[1] = 'I';
Buffer[2] = 'N';
Buffer[3] = 'G';
for( i = 4; i < BufferSize; i++ )
{
Buffer[i] = i - 4;
}
DelayMs( 1 );
printf("Send: PINGrn");
Radio.Send( Buffer, BufferSize );
TimerStart(&MasterCycleSendTimer);
}
//回调函数
void OnTxDone( void )
{
Radio.Sleep( );
TxCnt++;
printf("Tx=%drn",TxCnt);
memset(OLED_BUF,0,sizeof(OLED_BUF));
if(isMaster)
{
sprintf(OLED_BUF,"M TX:%d ",TxCnt);
}
else
{
sprintf(OLED_BUF,"S TX:%d ",TxCnt);
}
OLED_ShowString(8,0,OLED_BUF,16);
Radio.Rx( 0 );
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
Radio.Sleep( );
BufferSize = size;
memcpy( Buffer, payload, BufferSize );
RssiValue = rssi;
SnrValue = snr;
if( isMaster == true )
{
if( BufferSize > 0 )
{
if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
{
RxCnt++;
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"RX:%d",RxCnt);
OLED_ShowString(24,2,OLED_BUF,16);
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"Rssi:%d ",RssiValue);
OLED_ShowString(24,4,OLED_BUF,16);
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"Snr:%d ",SnrValue);
OLED_ShowString(24,6,OLED_BUF,16);
printf("Received: PONG,rssi=%d,snr=%drn",RssiValue,SnrValue);
}
else
{
Radio.Rx( 0 );
}
}
}
else
{
if( BufferSize > 0 )
{
if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
{
RxCnt++;
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"RX:%d",RxCnt);
OLED_ShowString(24,2,OLED_BUF,16);
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"Rssi:%d ",RssiValue);
OLED_ShowString(24,4,OLED_BUF,16);
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"Snr:%d ",SnrValue);
OLED_ShowString(24,6,OLED_BUF,16);
printf("Received: PING,rssi=%d,snr=%drn",RssiValue,SnrValue);
Buffer[0] = 'P';
Buffer[1] = 'O';
Buffer[2] = 'N';
Buffer[3] = 'G';
for( i = 4; i < BufferSize; i++ )
{
Buffer[i] = i - 4;
}
DelayMs( 1 );
Radio.Send( Buffer, BufferSize );
printf("Send: PONGrn");
}
else
{
Radio.Rx( 0 );
}
}
}
}
void OnTxTimeout( void )
{
Radio.Sleep( );
Radio.Rx( 0 );
}
void OnRxTimeout( void )
{
printf("OnRxTimeoutrn");
Radio.Sleep( );
memset(OLED_BUF,0,sizeof(OLED_BUF));
sprintf(OLED_BUF,"RX:%d",RxCnt);
OLED_ShowString(24,2,OLED_BUF,16);
Radio.Rx( 0 );
}
void OnRxError( void )
{
Radio.Sleep( );
Radio.Rx( 0 );
}
int main( void )
{
BoardInitMcu( );
printf("ASR6505 PingPong test !rn");
I2C_PeriphInit();
BoardInitPeriph( );
OLED_Init();
OLED_Clear();
OLED_ShowString(16,1,(char *)("LoRa"),16);
OLED_ShowCN(48,1,0);
OLED_ShowCN(64,1,1);
OLED_ShowCN(80,1,2);
OLED_ShowString(24,4,(char *)("ASR6505"),16);
OLED_ShowString(8,6,(char *)("PingPong test"),16);
Delay(3);
OLED_Clear();
memset(OLED_BUF,0,sizeof(OLED_BUF));
// Radio initialization
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
if(isMaster)
{
TimerInit(&MasterCycleSendTimer,MasterCycleSendTimerEvent);
TimerSetValue( &MasterCycleSendTimer, 5000 );
TimerStart(&MasterCycleSendTimer);
Buffer[0] = 'P';
Buffer[1] = 'I';
Buffer[2] = 'N';
Buffer[3] = 'G';
for( i = 4; i < BufferSize; i++ )
{
Buffer[i] = i - 4;
}
DelayMs( 1 );
printf("Send: PINGrn");
Radio.Send( Buffer, BufferSize );
OLED_ShowString(8,0,"M",16);
}
else
{
Radio.Rx( 0 );
OLED_ShowString(8,0,"S",16);
}
while( 1 )
{
Radio.IrqProcess( );
}
}
4、实验现象
从图片中也可以清楚的看出,发送、接收、RSSI、SNR等重要参数,这些对于实际布网有重要意义。
- LINUX中常用操作命令
- Java异常抛出及try,catch应用实例
- GitHub实战系列~2.把本地项目提交到github中 2015-12-10
- 前20名Python机器学习开源项目
- 接口测试 | 24 requests + unittest集成你的接口测试
- [快学Python3]数据结构与算法-二分查找
- 基于Excel参数化你的Selenium2测试
- 【LeetCode】关关刷题日记24-Leetcode 121. Best Time to Buy and Sell Stock
- 线性表的链式存储结构的实现及其应用(C/C++实现)
- [接口测试 - 基础篇] 01 你应该了解的协议基础
- 使用TensorFlow实现神经网络的介绍
- HTTP协议报文结构及抓包报文分析示例
- 必备 .NET - C# 异常处理
- Java Socket获取本机的InetAddress实例
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java基础【冒泡、选择排序、二分查找】
- Java基础 【Arrays 类的使用】
- i++ 是线程安全的吗?一脸蒙逼
- Java程序员必备基础:JDK 5-15都有哪些经典新特性
- Java开发中如何自动填充SQL语句中的公共字段
- 打卡群刷题总结0918——乘积最大子数组
- 打卡群刷题总结0919——打家劫舍
- 打卡群刷题总结0920——打家劫舍 II
- 打卡群刷题总结0921——最大正方形
- 打卡群刷题总结0922——丑数 II
- 打卡群刷题总结0923——完全平方数
- 打卡群刷题总结0924——最长上升子序列
- VS2017中使用QT Chart图表
- C++核心准则T.81:不要混用继承层级和数组
- C++核心准则T.83:不要将成员函数定义为模板虚函数