物联网LoRa系列-30:LoRaWAN A类/C类终端的载波信道资源与时间资源上下行调度算法

2023-11-13

前言:

本文将从频率、时间这两个资源的角度,来剖析LoRaWAN A类/C类终端的信道选择算法与代码实现示例。

不同的地区的频段,有不同的规范要求,算法有所差异,本文将以中国区的470M频段为例进行拆解,其他区域的频段以此类推。

不同的终端类型,算法也算法有所差异,本文将以ClassA与Class C为例,而Class B相对比较复杂,将单独讨论。


Table of Contents

前言:

第一章 频谱资源与载波信道

1.1 电磁频谱

1.2 LoRa WAN频段:

1.3 载波信道

1. 4 RegionCN470载波信道的划分与定义

1.5  RegionCN470信道号与频率的映射关系

第二章  RegionCN470上行发送的信道/频率资源调度算法

第三章 RegionCN470下行接收的信道/频率资源调度算法

3.1 接收窗口Rx1

3.2 接收窗口Rx2

第四章 RegionCN470上下发送的时间资源调度算法

4.1 非Join消息上行调度算法--占空比未使能

4.2 非Join消息上行调度算法--占空比使能

4.3 Join消息上行调度算法--自带占空比使能

第五章 RegionCN470下行接收的时间资源调度算法

5.1 Class A类型终端

5.2 Class C类型终端

5.3 时间资源调度算法代码示例


第一章 频谱资源与载波信道

1.1 电磁频谱

是指按电磁波波长(或频率)连续排列的整个电磁波族。


1.2 LoRa WAN频段:

频段:无线通信中使用的频段只是电磁波频段中很小的一部分,定义了无线电波的频率范围。

LoRaWAN代码目前支持的频段  
 *              - #define REGION_EU433
 *              - #define REGION_CN470
 *              - #define REGION_CN779
 *              - #define REGION_IN865
 *              - #define REGION_EU868
 *              - #define REGION_AU915
 *              - #define REGION_US915
 *              - #define REGION_US915_HYBRID
 *              - #define REGION_KR920
 *              - #define REGION_AS923

EU: 欧洲; CN: 中国;IN:印度;AU:澳大利亚;US: 美国;

1.3 载波信道

频段是一段频率范围,跨越的范围有几十兆,甚至上百兆。对于LoRa而言,一次数据传输通常只需要125K或250K或500K的频谱带宽。因此需要把整个频段的频谱进一步的平均切分。有点类似整个马路的车道:

每个切分的一小段称为载波带宽

在LTE里面,每个切分的一小段载波带宽,又称为子载波;

在LoRa里,没有子载波的概念,每个切分的一小段载波带宽,被称为一个独立的信道(channel)

LoRa的调制解调,就是对125K或250K或500K这么一小段的载波带宽进行的。

1. 4 RegionCN470载波信道的划分与定义

上行发送信道:96个信道,信道带宽:200K, 总带宽=96*0.2K = 19.2M

下行接收信道:48个信道,信道带宽:200K,   总带宽=48*0.2K = 9.6M

接收窗口Rx1和RX2的信道都来下行接收信道。

至于Rx1和Rx2窗口选择哪个具体的信道,由下行信道的算法所决定。

代码实现参考:

/*!
 * Defines the first channel for RX window 1 for CN470 band
 */
#define CN470_FIRST_RX1_CHANNEL                     ( (uint32_t) 500300000 )

/*!
 * Defines the last channel for RX window 1 for CN470 band
 */
#define CN470_LAST_RX1_CHANNEL                      ( (uint32_t) 509700000 )

/*!
 * Defines the step width of the channels for RX window 1
 */
#define CN470_STEPWIDTH_RX1_CHANNEL                 ( (uint32_t) 200000 )

/*!
 * Second reception window channel frequency definition.
 */
#define CN470_RX_WND_2_FREQ                         ( (uint32_t)505300000 )


/*!
 * LoRaMac maximum number of channels
 */
#define CN470_MAX_NB_CHANNELS                        96


/*!
 * LoRaMAC channel definition
 */
typedef struct sChannelParams
{
    /*!
     * Frequency in Hz
     */
    uint32_t Frequency;
    /*!
     * Alternative frequency for RX window 1
     */
    uint32_t Rx1Frequency;
    /*!
     * Data rate definition
     */
    DrRange_t DrRange;
    /*!
     * Band index
     */
    uint8_t Band;
}ChannelParams_t;

/*!
 * LoRaMAC receive window 2 channel parameters
 */
typedef struct sRx2ChannelParams
{
    /*!
     * Frequency in Hz
     */
    uint32_t Frequency;
    /*!
     * Data rate
     *
     * LoRaWAN Regional Parameters V1.0.2rB
     *
     * The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
     */
    uint8_t  Datarate;
}Rx2ChannelParams_t;




// Global attributes
/*!
 * LoRaMAC channels
 */
static ChannelParams_t Channels[CN470_MAX_NB_CHANNELS];

/*!
 * LoRaMac bands
 */
static Band_t Bands[CN470_MAX_NB_BANDS] =
{
    CN470_BAND0
};

/*!
 * LoRaMac channels mask
 */
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];  //通过mask,可以中96个信道中选择部分信道

/*!
 * LoRaMac channels default mask
 */
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];


//上行信道号与上行发送频率之间的映射关系:按顺序一一映射
void RegionCN470InitDefaults( InitType_t type )
{
//.........................................
	// 125 kHz channels
	for( i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
	{
		Channels[i].Frequency = 470300000 + i * 200000;
                Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
                Channels[i].Band = 0;
	}      
	
	// Initialize the channels default mask
        // 使用所有的96个信道
	ChannelsDefaultMask[0] = 0xFFFF;
	ChannelsDefaultMask[1] = 0xFFFF;
	ChannelsDefaultMask[2] = 0xFFFF;
	ChannelsDefaultMask[3] = 0xFFFF;
	ChannelsDefaultMask[4] = 0xFFFF;
	ChannelsDefaultMask[5] = 0xFFFF;
}

//下行信道号与下行发送频率之间的映射关系:按顺序一一映射
//这里采用的是动态计算还是一次性初始化
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{

    if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
    {
        // Apply window 1 frequency
        frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
    }
}

1.5  RegionCN470信道号与频率的映射关系

对上述代码需要进一步解读的是:信道号与频率的映射关系

(1)发送信道号与频率的映射关系:是在程序初始时,进行映射的。

(2)接收信道号与频率的映射关系:

接收窗口Rx1:是在每次RxConfg的时候,进行映射的。

bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
}

接收窗口Rx2:是动态参数配置

static void OnRxWindow2TimerEvent( void )
{

    RxWindow2Config.Channel = Channel;
    RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;  //读取参数设置。

   RegionRxConfig( LoRaMacRegion, &RxWindow2Config, ....)

}


第二章  RegionCN470上行发送的信道/频率资源调度算法

每一次数据发送,LoWAN MAC都会从96个最大信道数,随机的选择一个可用的信道,而不是采用固定信道:

代码示例:

LoRaMacStatus_t RegionCN470NextChannel(...)
{

        // We found a valid channel
        *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];

}

nbEnabledChannels:是支持的最大时机channel数目

randr( 0, nbEnabledChannels - 1):在0和nbEnabledChannels - 1产生一个随机数,通过该随机数的下标,从enabledChannels【】数组中获取实际的信道号 。


第三章 RegionCN470下行接收的信道/频率资源调度算法

RegionCN470 FDD模式,上下行的频率是分开的。

3.1 接收窗口Rx1

由于上行发送最大支持96个信道,下行接收只支持48个信道,因此无法采用1对1的映射。

RegionCN470采用的是多对1的映射关系:接收信号号=发送信道号%48.

当LoRa的网关接收到终端的数据,并获取该数据对应的信道后,通过上述同样的映射关系,选择下行的发送信道。

确保终端的接收与网关的发送是在相同的信道上。

bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
    //...................................

    if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
    {
        // Apply window 1 frequency
        rx_channel = rxConfig->Channel % 48;
        frequency = CN470_FIRST_RX1_CHANNEL + rx_channel * CN470_STEPWIDTH_RX1_CHANNEL;
    }
}

注意:

多对一的映射关系不会引发错乱,只有一对多的关系,才会导致错乱,才会导致终端接收与网关发送的信道不一致。

3.2 接收窗口Rx2

终端的接收窗口Rx2的接收信道与发送信道号无关。采用两种机制

  • 终端与网关预先约定好
  • 网关通过接收窗口Rx1的信道,下发配置命令,通知终端接收窗口Rx2信道号,实际上是接收频率。

代码示例:

static void OnRxWindow2TimerEvent( void )
{
    RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;
}

上述参数LoRaMacParams.Rx2Channel.Frequency是实现线下预约好的,作为默认值,也可以通过下发配置命令修改该默认值。


至此:探讨了LoRa终端在接收和发送数据时,发送和接收信道的选择,即发送和接收数据时,载波频率的选择。

但每个LoRa终端,并非在任何时间,都可以占用信道发送数据,这里受限于发送占空比(消息类型、占空比 duty cycle的设定)

也并非在任何时候,都可以通过信道接收数据,这里这里所限于终端的工作模式(种类类型、接收窗口)



第四章 RegionCN470上下发送的时间资源调度算法

4.1 非Join消息上行调度算法--占空比未使能

在这种情况下,不受空口占用信道占空比的限制,可以在任意时刻发送数据。

发送数据的周期只收到如下参数的影响:

#define CN470_DUTY_CYCLE_ENABLED                    0


/*!
 * Defines the application data transmission duty cycle. 5s, value in [ms].
 */
#define APP_TX_DUTYCYCLE                            5000

/*!
 * Defines a random delay for application data transmission duty cycle. 1s,
 * value in [ms].
 */
#define APP_TX_DUTYCYCLE_RND                        1000


// Schedule next packet transmission
TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( 0, APP_TX_DUTYCYCLE_RND );

TxDutyCycleTime定义了下次发送数据的时间,叠加了周期性与随机性双重特征。

4.2 非Join消息上行调度算法--占空比使能

当应用层有数据发送时,LoRaWAN的发送调度器必须确保:发送数据占用空口信道的时间满足占空比的要求。

在上图中,在T0和T2之间的任何时间是不允许发送数据的,比如T1,因为这段时间,不满足发送占空比的要求。

只有当前时间大于T2, 比如T3, 才能允许发送下一个数据。

这里的关键是如何求发送间隔周期?

发送间隔周期T =  数据帧在空口发送时间 /占空比。

举例:

空口发送时间1.2s, 占空比100%(或者变成1), 最短发送周期=1.2s

空口发送时间1.2s, 占空比1%(或者表达成100), 最短发送周期=1.2s * 100 =》120s =》2分钟。

空口发送时间1.2s, 占空比0.1%(或者表达成1000), 最短发送周期=1.2s * 1000 =》1200s =》20分钟。

代码示例:

#define CN470_DUTY_CYCLE_ENABLED                    1


/*!
 * Band 0 definition
 * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
 */
#define CN470_BAND0   { 1, CN470_MAX_TX_POWER, 0, 0, 0 } //  占空比:1/1 = 100.0 %


void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
{

    if( calcBackOffParams->DutyCycleEnabled == true ) //发送占空比使能
    {
        //计算还剩多少时间,允许下次发送数据
        calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
    }
    else //发送占空比没有使能
    {    
        //立即发送数据,无时间延时:TimeOff = 0
        calcBackOffParams->Bands[bandIdx].TimeOff = 0; 
    }

}

4.3 Join消息上行调度算法--自带占空比使能

(1)Join消息的可变占空比

为了防止join request失败或无响应后,终端无休止的发送Jion request。

针对request成功之前的Join消息请求,LoRaWAN MAC设计了强制性的占空比使能机制。

且随着时间的推移,占空比的比值不是固定的,需要分等级性的变化,时间越长,占空比的比值越小。

定义可变占空比的代码案例:


#define BACKOFF_DC_1_HOUR       100     //占空比=1%
#define BACKOFF_DC_10_HOURS     1000    //占空比=0.1%
#define BACKOFF_DC_24_HOURS     10000   //占空比=0.01%

uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime )
{
    uint16_t dutyCycle = 0;

    if( elapsedTime < 3600000 )
    {
        dutyCycle = BACKOFF_DC_1_HOUR;
    }
    else if( elapsedTime < ( 3600000 + 36000000 ) )
    {
        dutyCycle = BACKOFF_DC_10_HOURS;
    }
    else
    {
        dutyCycle = BACKOFF_DC_24_HOURS;
    }
    return dutyCycle;
}

(2)通过占空比和join消息空口的发送时间求下次发送的剩余时间time_off

void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
{

    if( calcBackOffParams->Joined == false )
    {
        // Get the join duty cycle: 100, 1000, 10000
        joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime );

        // Apply band time-off.
        calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * (dutyCycle - 1);

    }

}

因此,如果Join request消息的空口发送时间是1.5s,

则Join request失败或超时重新请求的最小周期为:1.5s * 100 = 1500s => 2.5分钟。


第五章 RegionCN470下行接收的时间资源调度算法

5.1 Class A类型终端

(1)Join accept之前

(2)Join accept之后:

5.2 Class C类型终端

(1)Join accept之前

(2)Join accept之后:

5.3 时间资源调度算法代码示例

static void OnRadioTxDone( void )
{
    GetPhyParams_t getPhy;
    PhyParam_t phyParam;
    SetBandTxDoneParams_t txDone;
    TimerTime_t curTime = TimerGetCurrentTime( );

    if( LoRaMacDeviceClass != CLASS_C )
    {
        Radio.Sleep( );   //Class A终端,发送完成后,直接进入休眠状态
    }
    else
    {
        OpenContinuousRx2Window( ); //Class A终端,发送完成后, 带宽Rx2接收窗口
    }
	
    // Setup timers
    if( IsRxWindowsEnabled == true )
    {
        TimerSetValue( &RxWindowTimer1, RxWindow1Delay );  //1s或5s之后打开Rx1窗口
        TimerStart( &RxWindowTimer1 ); 
		
        if( LoRaMacDeviceClass != CLASS_C )
        {
            TimerSetValue( &RxWindowTimer2, RxWindow2Delay ); //2s或6s之后打开Rx2窗口
            TimerStart( &RxWindowTimer2 );
        }
		
        if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
        {
            getPhy.Attribute = PHY_ACK_TIMEOUT;
            phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
            TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + phyParam.Value );
            TimerStart( &AckTimeoutTimer );               //对于需要应答的消息,额外等待2s
        }
    }
//...................
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

物联网LoRa系列-30:LoRaWAN A类/C类终端的载波信道资源与时间资源上下行调度算法 的相关文章

  • Python 中的引导采样

    这是关于 Python 中的 Bootstrap 采样的教程 在本教程中 我们将了解什么是引导 然后了解如何实现它 让我们开始吧 什么是引导抽样 引导抽样的定义如下 在统计学中 引导抽样是一种方法 涉及从数据源中重复抽取样本数据并进行替换
  • 如何在 Ubuntu 14.04 上为多个 Apache 虚拟主机设置 Let's Encrypt 证书

    介绍 SSL 证书在 Web 服务器内用于加密服务器和客户端之间的流量 为访问您的应用程序的用户提供额外的安全性 Let s Encrypt 提供了一种免费获取和安装受信任证书的简单方法 本教程将向您展示如何设置 TLS SSL 证书让我们

随机推荐

  • 如何在 Ubuntu 18.04 上安装 Go

    介绍 Go是 Google 开发的一种现代编程语言 它在许多应用程序和许多公司中越来越受欢迎 并提供了一组强大的库 本教程将引导您下载和安装最新版本的 Go 本文发布时为 Go 1 10 以及构建一个简单的 Hello World 应用程序
  • 使用 C++ 的分数背包

    在本文中 我们将学习使用 C 解决分数背包问题 我们将从查看问题陈述开始 然后转向解决方案 该问题是许多流行的经典问题之一 它与它的兄弟 0 1 背包有很大不同0 N背包 这是一种贪心算法 另外两种是动态规划算法 什么是分数背包 您将获得某
  • 2023年03月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试

    C C 编程 1 8级 全部真题 点这里 第1题 最短路径问题 平面上有n个点 n lt 100 每个点的坐标均在 10000 10000之间 其中的一些点之间有连线 若有连线 则表示可从一个点到达另一个点 即两点间有通路 通路的距离为两点
  • Downie4.6.4视频下载工具

    前言 Downie是Mac下一个简单的下载管理器 可以让您快速将不同的视频网站上的视频下载并保存到电脑磁盘里然后使用您的默认媒体播放器观看它们 下载 Downie 解压后直接安装 主要特点 支持许多网站目前支持超过1 000个不同的网站 包
  • SVN基本操作之新手上路

    SVN是什么Svn是一个离线的代码管理 可以多个人一起修改 然后再将修改的内容提交到Svn中 每一个svn服务器中的数据存储单位叫做存储 但是你不仅仅可以把整个存储当作你维护的内容 也可以将其中的某个分支目录像根存储一样的使用 Svn是严格
  • url相对路径

    一 url相对路径 无需协议名 ip 端口 项目名等 只需请求的路径 例如 项目路径 http localhost 8080 projectName 页面路径 projectName index html 请求路径 api getdetai
  • 几个比较好用的Node.js插件

    一 Nodejs 下安装scss npm i sass g npm i scss g 在静态文件中创建scss目录和css目录 进入到项目目录下执行 sass watch scss css 二 moment 时间格式化 npm i mome
  • luci的国际化(多语言)

    语言的选择在dispatch函数入口出完成 如果配置文件 etc config luci中配置的lang为auto 则根据浏览器所带的信息选择一个合适的语言 否则就使用lang定义的语言 然后使用i18n lua中的setlanguage设
  • 小程序-1-1 富文本的内容查看

    主要通过小程序原生组件rich text进行展示 将获取到的富文本内容传给nodes属性 话不多说 直接放代码
  • 【QT】ubuntu环境qt交叉编译环境的配置

    1 安装qt creater工具 默认安装在 opt 路径下 可参考如下文章 qt安装包http download qt io archive qt 如何在linux上安装qt while 1 的博客 CSDN博客 linux安装qt 2
  • linux支持usb打印机

    配置CONFIG USB PRINTER y inux内核默认运行打印机 核 驱动 直接在配置上CONFIG USB PRINTER y添加上去就好了 make menuconfig 选上USB打印机选项 Device Drivers gt
  • ue4中导入substance designer sbsar格式材质

    文章末尾更新离线导入方式 ue4 16 3 首先在商城下插件 下载后 打开任意工程勾上 如果你在Launcher里面看会有下面情况 看起来没有4 16版本 实际上是可以的 不要用上图方式添加 直接在plugin里面加就可以了 然后就可以把s
  • 基于 Knative 低成本部署在线应用,灵活自动伸缩

    作者 冬岛 阿里巴巴高级技术专家 导读 Serverless 如今已是万众期待未来可期的状态 但一个系统到底具备怎样的能力才能更好地支撑 Serverless 应用 随着 Kubernetes 和云原生概念的崛起 Serverless 在
  • [原]红帽 Red Hat Linux相关产品iso镜像下载

    不为什么 就为了方便搜索 特把红帽EL 5 EL6 EL7 的各版本整理一下 共享出来 RedHat Enterprise Server 7 3 for x86 64 rhel server 7 3 x86 64 dvd iso SHA 2
  • git 远程删除不需要的文件

    git clone git 192 168 2 246 dev ncrm git 23 find name target 24 find name target xargs rm rf 25 find name target 26 git
  • Java集合的lastlastIndexOfSubList()方法具有什么功能呢?

    转自 Java集合的lastlastIndexOfSubList 方法具有什么功能呢 下文笔者将讲述lastlastIndexOfSubList 方法的功能简介说明 如下所示 lastlastIndexOfSubList 方法的功能 返回一
  • 【python基础知识】16.文件读写基础及操作

    文章目录 前言 读取文件 第1步 开 第2步 读 第3步 关 写入文件 第1步 开 第2步 写 第3步 关 练习时间来咯 小技巧 小练习 前言 文件读写 是Python代码调用电脑文件的主要功能 能被用于读取和写入文本记录 音频片段 Exc
  • 臻识车牌识别摄像头对接

    一 臻识车牌识别摄像头 1 非常有用的官方代码 内部有TCP HTTP等协议 2 官方常见问题 3 官方下载专区 二 http对接例子 1 自己使用java mock 模拟后台服务 你会用到的配置文件 java jar moco runne
  • 目标检测和跟踪小结

    一 目标检测 目标检测即为从序列图像中将变化区域从背景图像中提取出来 运动目标检测的算法依照目标与摄像机之间的关系可以分为静态背景下运动检测和动态背景下运动检测 1 静态背景 背景差分法 帧间差分法 光流法 2 动态背景 需要进行图像的全局
  • 物联网LoRa系列-30:LoRaWAN A类/C类终端的载波信道资源与时间资源上下行调度算法

    前言 本文将从频率 时间这两个资源的角度 来剖析LoRaWAN A类 C类终端的信道选择算法与代码实现示例 不同的地区的频段 有不同的规范要求 算法有所差异 本文将以中国区的470M频段为例进行拆解 其他区域的频段以此类推 不同的终端类型