Arduino使用CubeCell开发板进行LORA无线通信

HSM
HSM
2021-12-06 / 0 评论 / 3,852 阅读 / 正在检测是否收录...

什么是LoRa

  • LoRa是semtech公司创建的低功耗局域网无线标准,低功耗一般很难覆盖远距离,远距离一般功耗高,要想马儿不吃草还要跑得远,好像难以办到。
  • LoRa的名字就是远距离无线电(Long Range Radio),它最大特点就是在同样的功耗条件下比其他无线方式传播的距离更远,实现了低功耗和远距离的统一,它在同样的功耗下比传统的无线射频通信距离扩大3-5倍。

LoRa的特性

  • 传输距离:城镇可达2-5 Km , 郊区可达15 Km 。
  • 工作频率:ISM 频段 包括433、868、915 MH等。
  • 标准:IEEE 802.15.4g。
  • 调制方式:基于扩频技术,线性调制扩频(CSS)的一个变种,具有前向纠错(FEC)能力,semtech公司私有专利技术。
  • 容量:一个LoRa网关可以连接上千上万个LoRa节点。
  • 电池寿命:长达10年。
  • 安全:AES128加密。
  • 传输速率:几百到几十Kbps,速率越低传输距离越长,这很像一个人挑东西,挑的多走不太远,少了可以走远。

LoRa和LoRaWan

  • LoRa和LoRaWan很容易混淆。下图可以看出,LoRa是LoRaWan的一个子集,LoRa仅仅包括物理层定义,LoRaWan还包括了链路层。
    lora_1.png
    lora_2.png
  • 这张图片是LoRaWan的网络架构图,左边是各种应用传感器,包括智能水表,智能垃圾桶,物流跟踪,自动贩卖机等,它右边是LoRaWan网关,网关转换协议,把LoRa传感器的数据转换为TCP/IP的格式发送到Internet上。
  • LoRa网关用于远距离星型架构,是多信道、多调制收发、可多信道同时解调。由于LoRa的特性可以同一信道上同时多信号解调。
  • 网关使用不同于终端节点的RF器件,具有更高的容量,作为一个透明网桥在终端设备和中心网络服务器间中继消息。
  • 网关通过标准IP连接连接到网络服务器,终端设备使用单播的无线通信报文到一个或多个网关。
  • 其实LoRaWan并不是一个完整的通信协议,因为它只定义了物理层和链路层,网络层和传输层没有,功能也并不完善,没有漫游,没有组网管理等通信协议的主要功能。

LORA 的Class ABC三个模式

  • Class A 上下行的时序图,目前接收窗口RX1一般是在上行后1秒开始,接收窗口RX2是在上行后2秒开始。(终端有数据了,就上报,顺便收一下服务器下发的指令。终端没数据的时候,服务器下发不了指令。适合用在智能井盖、智能垃圾桶、传感器等场景,你可以几天才发一个数据上去,省电的很。)
    class1.jpeg
  • Class B 的时隙则复杂一些,它有一个同步时隙beacon,还有一个固定周期的接收窗口ping时隙。如这个示例中,beacon周期为128秒,ping周期为32秒。(看起来复杂,实际上就跟NB-IoT的eDRX模式差不多,隔几十秒收一个数据。其他时候都在休眠。功耗低、服务器下发数据延时也不大。适合定位器、开关等场景。既不用接电,也能够“还算及时”的控制设备。)
    class3.jpeg
  • Class C 和 A 基本是相同的,只是在 Class A 休眠的期间,它都打开了接收窗口RX2。(几乎随时都可以接收数据。只干活不睡觉,功耗自然就高了。考虑到10mA级别的接收电流,不是长供电的设备最好别用这个模式。)
    class2.jpeg

LoRa关键参数(扩频因子,编码率,带宽)的设定及解释

1. 扩频因子(SF)

  • LoRa采用多个信息码片来代表有效负载信息的每个位,扩频信息的发送速度称为符号速率(Rs),而码片速率与标称的Rs比值即为扩频因子(SF,SpreadingFactor),表示了每个信息位发送的符号数量。
  • LoRa扩频因子取值范围:
    LoRa扩频因子取值范围.jpeg
注意:因为不同的SF之间为正交关系,因此必须提前获知链路发送端和接收端的SF。另外,还必须获知接受机输入端的信噪比。。在负信噪比条件下信号也能正常接收,这改善了LoRa接受机的林敏度,链路预算及覆盖范围。

理解扩频因子的概念:

  • 通俗的说 扩频时你的数据每一位都和扩频因子相乘,例如有一个1 bit需要传送,当扩频因子为1时,传输的时候数据1就用一个1来表示,扩频因子为6时(有6位)111111,这111111就来表示1,这样乘出来每一位都由一个6位的数据来表示,也就是说需要传输总的数据量增大了6倍。
  • 这样扩频后传输可以降低误码率也就是信噪比,但是在同样数据量条件下却减少了可以传输的实际数据,所以,扩频因子越大,传输的数据数率(比特率)就越小。

Lora扩频因子的使用:

  • 当扩频因子SF为6时,LoRa的数据传输速率最快,因此这一扩频因子仅在特定情况下使用。使用时需要配置LoRa芯片SX127x:

    • 在RegModemConfig2,将SpreadingFactor设为6
    • 将报头设置为隐式模式
    • 在寄存器地址(0x31)的2至0位写入0b101
    • 在寄存器地址(0x37)写入0x0C

2. 编码率(CR)

  • 编码率,是数据流中有用部分的比例。
  • 编码率(或信息率)是数据流中有用部分(非冗余)的比例。也就是说,如果编码率是k/n,则对每k位有用信息,编码器总共产生n位的数据,其中n-k是多余的。
  • LoRa采用循环纠错编码进行前向错误检测与纠错。。使用该方式会产生传输开销。
  • 每次传输产生的数据开销如下:
    每次传输产生的数据开销.png
  • 在存在干扰的情况下,前向纠错能有效提高链路的可靠性。由此,编码率(抗干扰性能)可以随着信道条件的变化而变化,可以选择在报头加入编码率以便接收端能够解析。

    3. 信号带宽(BW)

  • 增加BW,可以提高有效数据速率以缩短传输时间,但是 以牺牲部分接受灵敏度为代价。对于LoRa芯片SX127x,LoRa带宽为双边带宽(全信道带宽),而FSK调制方式的BW是指单边带宽。
  • LoRa带宽选项:
    LoRa带宽选项.jpeg

    注意:较低频段(169MHz)不支持250K和500KHz的BW

4. LoRa信号带宽BW、符号速率Rs和数据速率DR的关系

  • LoRa符号速率Rs可以通过以下公式计算:

    $$ Rs\ =\ \frac{BW}{2^{SF}} $$

  • 每Hz每秒发送一个码片。
  • LoRa数据速率DR可以通过以下公式计算:

    $$ DR\ =\ \ SF\frac{BW}{2^{SF}}CR $$

Lora的使用

1. CubeCell开发版

2. 配置开发cubecell的arduino IDE环境

远程通信的实现

1. 环境

  • 本次使用LORA开发版型号 CubeCell AB01
  • 本次使用的频段833MHZ

2. 发送端程序

#include "LoRaWan_APP.h"
#include "Arduino.h"
#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

#define RF_FREQUENCY                                868000000 // Hz

#define TX_OUTPUT_POWER                             22        // dBm

#define LORA_BANDWIDTH                              2         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         0         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false


#define RX_TIMEOUT_VALUE                            1000
#define BUFFER_SIZE                                 512 // Define the payload size here

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;

double txNumber;

int16_t rssi,rxSize;
#define TIMEOUT 10//time in ms

uint8_t serialBuffer[BUFFER_SIZE];
int size;


void setup() {
    boardInitMcu( );
    Serial.begin(115200);
    txNumber=0;
    rssi=0;
    RadioEvents.RxDone = OnRxDone;
    Radio.Init( &RadioEvents );
    Radio.SetChannel( RF_FREQUENCY );
    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 );
                   
    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 ); 
   turnOnRGB(1,0); //change rgb color
   Serial.println("into RX mode");
   }
   


void loop()
{ 
//   发送数据
  size = Serial.read(serialBuffer,TIMEOUT);
  if(size && size <= BUFFER_SIZE/2)
  {
    Serial.printf("send data size %d : ",size);
    Serial.write(serialBuffer,size);
    Radio.Send( serialBuffer,size ); //send the package out  
    turnOnRGB(COLOR_SEND,0);
    Serial.printf("\nsend success\n");
  }
}

3. 接收端程序

/* Heltec Automation Receive communication test example
 *
 * Function:
 * 1. Receive the same frequency band lora signal program
 * 
 * 
 * this project also realess in GitHub:
 * https://github.com/HelTecAutomation/ASR650x-Arduino
 * */

#include "LoRaWan_APP.h"
#include "Arduino.h"

/*
 * set LoraWan_RGB to 1,the RGB active in loraWan
 * RGB red means sending;
 * RGB green means received done;
 */
#ifndef LoraWan_RGB
#define LoraWan_RGB 0
#endif

#define RF_FREQUENCY                                868000000 // Hz

#define TX_OUTPUT_POWER                             22        // dBm

#define LORA_BANDWIDTH                              2         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         0         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false


#define RX_TIMEOUT_VALUE                            1000
#define BUFFER_SIZE                                 30 // Define the payload size here

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;

int16_t txNumber;

int16_t rssi,rxSize;
#define TIMEOUT 10//time in ms

uint8_t serialBuffer[256];
int size;

void setup() {
    boardInitMcu( );
    Serial.begin(115200);

    txNumber=0;
    rssi=0;
    
      RadioEvents.RxDone = OnRxDone;
    Radio.Init( &RadioEvents );
    Radio.SetChannel( RF_FREQUENCY );
    
     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 );
   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 ); 
   turnOnRGB(COLOR_SEND,0); //change rgb color
   Serial.println("into RX mode");
   }



void loop()
{
    Radio.Rx( 0 );
//  delay(500);
  Radio.IrqProcess( );
  // 发送数据
  size = Serial.read(serialBuffer,TIMEOUT);
  if(size)
  {
    Serial.printf("send data size %d : ",size);
    Serial.write(serialBuffer,size);
    Radio.Send( serialBuffer,size ); //send the package out  
    turnOnRGB(COLOR_SEND,0);
    Serial.printf("\nsend success\n");
  }
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    rssi=rssi;
    rxSize=size;
    memcpy(rxpacket, payload, size );
    rxpacket[size]='\0';
    turnOnRGB(COLOR_RECEIVED,0);
    Radio.Sleep( );
    Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxpacket,rssi,rxSize);

}
1

评论 (0)

取消