专栏首页物联网思考LoRa节点开发——代码详解如何修改发射和接收信道(频率)

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——————

转发分享、点在看,就是对作者最大的支持,谢谢哦

本文分享自微信公众号 - 物联网思考(everythinglink),作者:everythinglink

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ASR6505 LoRaWAN通信(二)

    前言:在ASR6505 LoRaWAN通信(一)中谈到了设备入网、ClassA、C,本节聊聊设备的信道、发送、接收数据。

    ManInRoad
  • 遇见野牛,重新定义开发板

    一直在群里面看野牛开发板的炫酷GUI演示,有幸终于拿到了跳兔科技出品的野牛开发板(Bison-Board),我们一起来探个究竟。

    ManInRoad
  • LoRaNode开发——初识SDK

    从github获取节点源码https://github.com/Lora-net/LoRaMac-node/tree/develop,可以看到最新的源码是v4....

    ManInRoad
  • 不要离我太近!疫情下估计人群传染风险 ,ECCV Demo 奖大显身手!

    在新冠疫情在全球持续蔓延的背景下,来自意大利摩德纳大学的研究者们结合计算机视觉技术以及传染病预测模型设计了一种可以实时运行的多场景人员感染风险估计系统。

    AI科技评论
  • 从数据库巨人身上撕开一道口子

    | 大咖介绍 苏强,腾讯云数据库资深产品经理,拥有多年ToB产品策划、产品运维经验。曾在多个知名企业任职产品经理,主导或参与多款业内知名的B端产品从0到1过程...

    腾讯云数据库 TencentDB
  • 精通MVC3摘译(4)-使用Area

    MVC Framework支持将一个web application放入一个area,每个area表示一个特殊功能的应用程序片段,比如管理,账单,客户支持等等。这...

    py3study
  • 如何在Ubuntu 16.04上使用dry管理和监控Docker容器

    dry是一个简单但广泛的终端应用程序,用于与Docker容器及其映像交互。使用dry会删除执行常规Docker Engine命令时所涉及的重复,并且还提供了更原...

    谢鸢
  • 复杂和变态的环境下jsp连接数据库

    1、jsp网站没有写入权限,有执行命令的时候,低权限,为了可以方便快速的读取文件。并且建立数据库连接可以使用小技巧在目标服务器上,搭建一个WEB服务。此WEB服...

    周俊辉
  • Kubernetes角度解读:CoreOS与Docker分手事件

    Kubernetes这个名字起源于古希腊,是舵手的意思,所以它的Logo既像一张渔网,又像一个罗盘。谷歌采用这个名字的一层深意就是:既然Docker把自己定位为...

    博文视点Broadview
  • SQL Server 每日一题--产品

    某公司生产U盘多年,一天老板来到财务部要求财务人员统计出产品的上市年份和单价。于是财务部主管找到了程序员S,让他帮忙统计一下。

    喵叔

扫码关注云+社区

领取腾讯云代金券