野生程序员
发布于 2022-11-06 / 180 阅读 / 1 评论 / 0 点赞

使用Arduino Nano驱动Lora模块

为什么选用Lora

射频通信芯片有很多种,但是一般在同样功耗下,距离没有Lora远;同等范围下,没有Lora节能。
Lora通信只适用于低速率,高延时的场合,与WiFi正好相反。

考虑在野外,没有移动通信网络覆盖的环境下,收集传感器数据,适合使用。
在设密度大,使用移动通信网络成本过高,使用Lora来统一收集数据,例如远程抄表。
Lora作为物联网的一种通信技术选型,正好是移动通信网络,WiFi的补充。

完整项目

我使用一个Arduino Nano 来驱动Lora模块,另外加了一个BMP085(I2C接口)气压传感器,一个光敏电阻,一个按钮。

使用PlantformIO平台开发。(比Arduino IDE好用很多)

实现功能有:

参考arduino-LoRa双向通行的自有简单协议;
获取传感器的温度,气压数据,光亮度;
获取供电电池电压;
定时通过Lora发送数据,按键强制发送一条数据;
使用链表缓存需要发送的内容,避免频繁发送时候影响数据接收;
接收Lora数据:
指令led点亮灯2秒;
指令ping,返回pong;
项目地址: https://github.com/formatkm/lora_node

Lora模块

串口模块
SPI接口模块
一般串口模块连接相对简单,与其他无线模块AT指令不同(例如:蓝牙模块、GPRS模块),还需要对GPIO口连接控制引脚完成状态配置操作,我想这个是因为需要比达到比较快的切换速度。

SPI口接口直接操作寄存器完成对芯片的操作和数据的发送接收。优点是可以自定义自己的通信协议,而且是要使用的是同种sx127X系列的芯片的模块都可以相互通信。

串口模块内部实际是有一个单片机控制Lora芯片,实现的自己的一套通信协议,一般同一个厂家的模块才可以互相通信。

基本概念

RSSI:信号强度指示,用来判定链接质量,数字越大通信效果越好。

SNR:信噪比,电平与噪声电平之比。数字越大通信效果越好。

Preamble
前导码用于保持接收机与输入的数据流同步。作用是提醒接收芯片,即将发送的是有效信号。

Header
可以通过操作模式,选择显示/隐式两种Header类型:在RegModemConfig1寄存器上,通过设定ImplicitHeaderModeOn选择

显式报头模式
LoRa默认都为显式Header模式,在这种模式下,Header会包含Payload的相关信息,包括:

Payload长度(byte)
前向纠错编码率
是否使用CRC(16位)
隐式报头模式
在特定情况下,如果Payload长度、编码率以及CRC为固定值或已知,则可以通过隐式Header模式来缩短发送时间。。该情况下 ,需要手动设置无线链路两端的Payload长度、错误编码率以及CRC。。。

IQ signal:极性信号反转,用于标识上行,下行,避免多个节点间互相冲突,节点间不能互相通信

接线

按钮接到D3,使用中断引脚

SPI接口

SCK  <----> D13
MISO <----> D12
MOSI <----> D11
NSS  <----> D10
REST <----> D09
DIO0 <----> D02 (中断)
I2C
SDA  <----> A4
SCL  <----> A5
其他
LED  <----> D06
KEY  <----> D03
光敏  <----> A2

驱动程序代码
基于Arduino的Sx1278驱动有(测试使用顺序):

LoRaLib (已不在维护,使用RadioLib替代)
RadioLib (支持多种无线芯片,更专业)
arduino-LoRaarduino-LoRa (简单好用,封装配置)
最终选用的是arduino-LoRa,使用RadioLib 在实现双向通行上遇到问题(C++功力不够)。

arduino-LoRa最大的好处就是简化了很多芯片参数的配置,如果业余选手要配置好参数能够实现两个模块通信是个艰巨的挑战,这也是串口Lora模块的优势,不用去关心复杂的通信参数配置。

阅读arduino-LoRa代码,你会发现很多参数都有范围判断的默认值,如果设置超出范围也不会出错。

要实现模块连通,SPI接线基本不会有问题。最重要的是NSS、REST、DIO0这三个不能接错,对于Arduino板DIO0一定要接在有中断的引脚上。

DIO0也称IRQ引脚,在模块有数据接收,发送完毕后会有一个电平指示(高度单片机,要接受数据或者数据发送完毕),所以必须接到中断引脚,普通GPIO脚速度达不到。

const int csPin = 7;          // 也就是NSS接口
const int resetPin = 6;       // reset引脚 
const int irqPin = 2;         // 必须是中断引脚,Arduino Nano只有2、3脚为中断

初始化模块

LoRa.setPins(csPin, resetPin, irqPin);// set NSS, reset, DIO0 pin

if (!LoRa.begin(433E6)) {             // 初始化使用频率 433 MHz
    Serial.println("LoRa init failed. Check your connections.");
    while (true);                       // 失败后停止执行
}

测试
使用arduino-LoRa的例子程序,如果接线正确,那么Arduino中烧入程序,会打赢出Sx1278的寄存器信息。

https://github.com/sandeepmistry/arduino-LoRa/blob/master/examples/LoRaDumpRegisters/LoRaDumpRegisters.ino


评论