LoRa节点开发——代码详解如何修改发射和接收信道(频率)
本文主要结合LoRaNode SDK v4.4.2和LoRaWAN规范1.0.3来展开。
查看《lorawan_regional_parameters_v1.0.3reva_0.pdf》文档,每个地区对应的信道都不一样;同样的,在SDK中,不同的地区以不同的文件实现:
查看文档,CN470频段,支持96个上行通道,48个下行通道。
国内主要是CN470,因此主要看RegionCN470这个文件。
发送频率设置
SDK在函数voidRegionCN470InitDefaults(InitDefaultsParams_t* params )中初始化信道参数:
void RegionCN470InitDefaults( InitDefaultsParams_t* params )
{
Band_t bands[CN470_MAX_NB_BANDS] =
{
CN470_BAND0
};
switch( params->Type )
{
case INIT_TYPE_INIT:
{
// Initialize bands
memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )//CN470_MAX_NB_CHANNELS是一个宏定义,取值是96
{
NvmCtx.Channels[i].Frequency = 470300000 + i * 200000;
NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
NvmCtx.Channels[i].Band = 0;
}
// Initialize the channels default mask
NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
NvmCtx.ChannelsDefaultMask[5] = 0xFFFF;
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
case INIT_TYPE_RESTORE_CTX:
{
if( params->NvmCtx != 0 )
{
memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
}
break;
}
case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
default:
{
break;
}
}
}
可以看到,通过for循环给96个信道赋值,从470.3M开始,以200K的步长增加,并且把信道掩码全部赋值为0xffff。
其中NvmCtx是一个结构体变量,查看其定义如下:
// Definitions
#define CHANNELS_MASK_SIZE 6
/*!
* Region specific context
*/
typedef struct sRegionCN470NvmCtx
{
/*!
* LoRaMAC channels
*/
ChannelParams_t Channels[ CN470_MAX_NB_CHANNELS ];
/*!
* LoRaMac bands
*/
Band_t Bands[ CN470_MAX_NB_BANDS ];
/*!
* LoRaMac channels mask
*/
uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
/*!
* LoRaMac channels default mask
*/
uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
}RegionCN470NvmCtx_t;
可以看到,CN470信道掩码是一个uint16_t的数组,数组有6个元素,16*6=96bit刚好对应96个上行信道,既就是每个信道对应一个bit。在上面初始化的时候,信道通过for循环遍历,信道掩码全部设置为了0xffff,既SDK中默认开启了所有的信道。
通常情况下LoRaWAN网关(sx1301/2/8)只支持8个上行通道1个下行通道,既只可以同时接收8路数据。因此我们需要修改让节点只用8个信道上报数据,这8个信道与网关保持一致。
我们参考上面的把不需要的信道频率设置为0,或对应的掩码位置设为0,剩下的就是我们需要的信道。
假设,我们要设置的8个频点为:
uint32_t UserFreq[8]={471900000,472100000,472300000,472500000,
472700000,472900000,473100000,473300000};
那么只需在void RegionCN470InitDefaults(InitDefaultsParams_t* params )函数默认的信道初始化后加入如下代码:
NvmCtx.ChannelsDefaultMask[0] = 0x0000;
NvmCtx.ChannelsDefaultMask[1] = 0x0000;
NvmCtx.ChannelsDefaultMask[2] = 0x0000;
NvmCtx.ChannelsDefaultMask[3] = 0x0000;
NvmCtx.ChannelsDefaultMask[4] = 0x0000;
NvmCtx.ChannelsDefaultMask[5] = 0x0000;
for( uint8_t i = 0,j=0; i < 8; i++ )
{
j=(UserFreq[i].Frequency-470300000 )/200000;//计算信道号
NvmCtx.Channels[j].Frequency = UserFreq[i].Frequency ;
NvmCtx.Channels[j].DrRange.Value=( DR_5 << 4 ) | DR_0;
NvmCtx.Channels[j].Band = 0;
NvmCtx.ChannelsDefaultMask[j/16]|=1<<(j%16);//相应的信道掩码位设置为1
}
// Update the channels mask
RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
上面代码中,最关键的两句话,计算信道号和相应的信道掩码位设置为1。
接收频率设置
可以看出,下行通道rx1等于上行通道号与48取余,rx2是固定的,默认为505.3MHZ。
SDK中在函数bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )实现了接收频率的设置:
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
//计算rx1的频率
}
// Read the physical datarate from the datarates table
phyDr = DataratesCN470[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
*datarate = (uint8_t) dr;
return true;
}
其中,最重要的一句代码:
// Apply window 1 frequency
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
//计算rx1的频率
通过发射信道号,计算rx1的接收信道。可见,如果发射信道固定了,那么rx1(接收1)的信道也就固定了。
因此,我们在CN470频段,只需要修改发射信道即可完成发射和接收的设置。
——————END——————
转发分享、点在看,就是对作者最大的支持,谢谢哦
。
- PySpark数据类型转换异常分析
- SQLI-LABS 更新帖(二)
- 如何重置Hue用户密码
- 如何使用R连接Hive与Impala
- Equation Group泄露工具之vBulletin无文件后门分析
- 如何使用CDSW在CDH集群通过sparklyr提交R的Spark作业
- 如何使用Beeline连接Impala
- 微软公式编辑器系列漏洞分析(一):CVE-2017-11882
- 预警揭秘:倒计时炸弹11.2.0.4前版本DB Link必须在2019年4月升级真相
- RPO攻击技术浅析
- 渗透技巧 | Windows上传并执行恶意代码的N种姿势
- 如何通过Cloudera Manager配置Spark1和Spark2的运行环境
- 从CPU漏洞Meltdown&Spectre看侧信道攻击
- 如何使用Java连接Kerberos的Kafka
- 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 数组属性和方法
- SpringMVC数据类型转换器与国际化配置
- 分布式资源调度——YARN框架
- 在SpringMVC中使用数据验证组件——hibernate-validator
- 我的 2020 iOS BAT 面试心得
- Java操作HDFS开发环境搭建以及HDFS的读写流程
- HDFS伪分布式环境搭建
- 初识Hadoop
- SpringMVC返回JSON数据以及文件上传、过滤静态资源
- SpringMVC返回数据到视图
- 初识SpringBoot Web开发
- Nginx+Tomcat搭建集群环境
- Maven环境隔离
- Lombok快速入门
- Apache Curator操作zookeeper的API使用
- 微信公众号开发-自定义菜单接口