简介
如果你已经实现了lora的简单收发,我认为你应该考虑一下,当lora处于一对多(一主机、多从机)的收发环境时,怎么样才能避免从机在发送数据时产生的碰撞导致的丢包问题。聪明的你肯定想到了如果我能在发送之前先检查一下有没有其他的从机在发送,从而等待一段时间再发送来避免产生碰撞。没错,在实际的项目运用中,我们也是采用了这种方法。它就叫做信道活动检测。
事实上,我们有两种办法来检测,一种是CAD,还有另外一种是RSSI。先说一下RSSI,RSSI能够测量无线信号的强度,我么可以设置一个合适的阈值,当信号强度高于这个阈值时,代表当前信道中有其他的从机在发送数据。当低于这个阈值时,代表信道空闲,此时就可以发送数据了。此种方法虽然简单,但是我们无法确认信道被占有,是由于低噪声影响,还是真的数据来到,在这种情况下,使用RSSI无疑是行不通的。所以为了解决这个问题,我么使用CAD来检测信道。
- CAD是什么呢?
CAD就是已尽可能高的功耗效率检测无线信道上的LORA前导码。在CAD模式下,lora模块快速的扫描频段。来检测LORA数据包前导码。举个例子来说,从机就像教室里的学生一样,当老师提了一个问题后,学生回答问题时要看一下有没有其他人在发言,这个看的过程就是我们要说的CAD过程。
这个时候我们要看一下lora的数据包格式:
lora的数据包由三个部分组成:前导码,可选报头和有效负载。
- 前导码:前导码用于保持接收机与输入的数据流同步,默认是12个符号长度,我个人建议使用默认的长度就可以,如果你是接受密集型应用,你可以通过往前导码寄存器写值来更改前导码长度。
- 可选报头:两种,显示报头和隐式报头。如果你的扩频因子设置成了6,你就只能使用隐式报头了哦!默认是选用显示报头的。
- 有效负载:这一部分就因人而异了,因为这是你定义的数据部分,长度不固定。
CAD的流程
大家注意的是,无论是否有信号到来,都会产生CADDone中断),当有匹配(相同的频率和扩频因子)的信号到来时,才会产生CADDetect中断。
上图就是一个典型的接收机做CAD检测的流程,我们来看一下,开始时处于待机模式,设置CAD模式后调制解调器会产生CADDone中断,如果这时候有其他从机在发数据,代表关联成功,就会产生一个CADDetected中断。模式自动转变为待机模式,这个时候如果是接收机的话就可以转变为接收模式接收数据了。如果是发送机的话,代表这个时候信道被占用了,需要等待一段时间在发送。(这里插一个:这个等待时间大家如果要写的可以选用生成随机数的方式,网上应该有很多的例程可以供大家参考)
给大家一个网址参考:http://c.biancheng.net/view/2043.html
我们使用CAD功能时,需要用到lora的DIO口,之前收发数据用到的DIO0引脚,我们再来回顾一下DIO映射表
通过上表我们可以看到DIO1可以被映射为CadDetected功能,DIO3可以被映射为CadDone功能。所以在软件方面我们需要配置一下这两个引脚。
CAD代码实现
嘻嘻,相信大家最关心的就是代码方面如何实现了。其实非常简单,我们一起来学习一下。首先,大家需要确保自己的lora模块能实现简单的收发。我们的步骤是当从机定时到了的时候做一下CAD检测,如果信道忙碌我们就生成随机事件来延时发送。
1. 先来配置一下DIO3和DIO1引脚
//配置DIO3中断
Gpio_InitIOExt(3, 3, GpioDirIn, FALSE, TRUE, FALSE, FALSE);//下拉
Gpio_ClearIrq(3, 3);
Gpio_EnableIrq(3, 3, GpioIrqRising);
//配置DIO1中断
Gpio_InitIOExt(3, 2, GpioDirIn, FALSE, TRUE, FALSE, FALSE); //下拉
Gpio_ClearIrq(3, 2);
Gpio_EnableIrq(3, 2, GpioIrqRising);
EnableNvic(PORT3_IRQn, DDL_IRQ_LEVEL_DEFAULT, TRUE);
将DIO3和DIO1都配置成中断模式,这里我们设置了下拉,是因为考虑了低功耗的问题,大家只是测试CAD功能的话不需要特别设置的
2. CAD检测函数
当大家的数据帧组装完成后,不要着急发出去,先写一个CAD检测函数
//CAD检测
int SX1278_LoRaCadPacket(SX1278_t * module,uint32_t timeout)
{
SX1278_standby(module); //Entry standby mode
SX1278_SPIWrite(LR_RegIrqFlagsMask, 0xFA);
SX1278_clearLoRaIrq();
SX1278_SPIWrite(REG_LR_DIOMAPPING1, 0x20);//DIO0=00,DIO1=10,DIO2=00, DIO3=00
SX1278_SPIWrite(LR_RegOpMode, 0x8F); //CAD模式
while(1)
{
if(DIO3flag) //DIO3
{
DIO3flag = 0;
//SX1278_clearLoRaIrq(module);
SX1278_SPIWrite(LR_RegIrqFlags, 0x04);
// SX1278_standby(module); //Entry standby mode
if(DIO1flag) //DIO1
{
DIO1flag =0;
//SX1278_clearLoRaIrq(module);
SX1278_SPIWrite(LR_RegIrqFlags, 0x01);
return 0;
}else{
return 1;
}
}
if(--timeout == 0)
{
SX1278_hw_Reset();
SX1278_defaultConfig(module);
return 0;
}
delay1ms(1);
}
}
将RegIrqFlagsMask寄存器设置成0xFA,用来检测CadDone和CadDeceted中断(注意:数据手册上对该寄存器设置了代表是屏蔽中断服务的意思),大家自行参考数据手册。之后我们将DIO口映射到对应的功能,再将模式设置成CAD模式。此时就可以产生CadDone中断了,如果继续产生CadDetected中断,就返回0,代表信道忙碌。超时也会返回0。只有返回1时才代表信道空闲。
3. CAD处理函数
CADresult = SX1278_LoRaCadPacket(&SX1278,100);
if(CADresult)
{
//发送数据
}else{
//随机延时函数(等待随机事件后再发送)
}
总结
CAD 信道活动检测在实际项目中的运用非常广泛,尤其是在发射密集型的应用中,希望你能根据这篇文章来熟悉信道活动检测的流程。