SX1268 433M LoRa HAT
| ||||||||||||||||
| ||||||||||||||||
产品概述
- 本产品是基于SX1268/SX1262芯片,具有LoRa调制功能无线串口模块的树莓派扩展板
- 具有多级中继实现超远距离通信,低功耗唤醒通信、加密传输等优点
- 本产品不支持LoRaWAN
产品特点
- 支持全球免许可ISM 433/470/868/915MHz频段频段
- 支持空中唤醒,即超低功耗功能,适用于电池供电的应用方案
- 支持定点传输、广播传输、信道监听,多级中继用于超远距离通信
- 支持 RSSI 信号强度指示功能,用于评估信号质量、改善通信网络
- 支持 LBT 功能,在发送前监听信道环境噪声,可极大提高模块在恶劣环境下的通信成功率
- LoRa扩频技术,多达84信道/81信道(SX1268,SX1262)可选
- 支持空中唤醒,在线配置,载波监听,自动中继,通信密钥,低功耗休眠
- 理想环境下通信距离可达5KM
产品参数
功耗 | 发射电流 | 100mA(瞬时功耗) |
接收电流 | 11mA | |
休眠电流 | 2uA(LoRa模组深度休眠) | |
最大发射功率 | 22.0dBm(10、13、17、22dBm软件选择) | |
发射长度 | 240Byte(32、64、128、240Byte软件选择) | |
缓存容量 | 1000Byte | |
工作频段 | 410.125~493.125MHz或850.125~930.125MHz | |
接收灵敏度 | -147dBm@0.3Kbps空中速率 | |
空中速率 | 0.3K~62.5Kbps(可软件选择) | |
通信接口 | UART | |
参考距离 | 5KM(晴朗空旷,天线增益5dBi,天线高度2.5米,空中速率2.4kbps) | |
供电电压 | 5V | |
逻辑电平 | 3.3V | |
工作温度 | -40~85℃ |
硬件介绍
序号 | 描述 | |
---|---|---|
1 | SX1268/SX1262模组 | |
2 | 74HC125V电平转换芯片 | |
3 | CP2102 USB转UART芯片 | |
4 | RPi接口 | |
5 | USB TO UART接口 | |
6 | UART接口方便外接其它MCU | |
7 | SMA天线接口 | |
8 | IPEX天线接口 | |
9 | 指示灯 | RXD/TXD:串口指示灯 |
AUX:辅助指示灯 | ||
PWR:电源指示灯 | ||
10 | UART选择跳帽 | A:USB转串口控制LoRa |
B:树莓派控制LoRa | ||
C:USB转串口访问树莓派 | ||
11 | LoRa模式选择跳线 | 模式0: M0短接,M1短接:传输模式 |
模式1:M0不接,M1短接:WOR模式 | ||
模式2:M0短接,M1不接:配置模式 | ||
模式3:M0不接,M1不接:深度休眠模式 |
1、将M1、M0进行高低电平组合,确定工作模式,其中M1、M0不接跳帽时为高电平,切换工作模式后,若模块空闲,则进入新的工作模式,否则将处理完当前发射接收后再进入新工作模式
2、模式0,用户串口输入数据后,模块启动无线发射,空闲时,无线接收功能打开,接收到数据串口TXD输出
3、模式1,当定义为发射时,发射前自动增加一定时间唤醒码,接收等同于模式0
4、模式2,无线收发功能关闭,用户可以参造寄存器配置设置寄存器
5、模式3,无线收发关闭,进入深度休眠模式,当进入其他工作模式,模块重新配置参数
LoRa和LoRaWAN
什么是LoRa?
Semtech 的 LoRa 是一种长距离、低功耗的物联网 (IoT) 无线平台,一般情况下泛指使用LoRa技术的射频芯片.主要特点如下
- LoRa(long range 的缩写)采用的扩频调制技术源于啁啾扩频 (CSS) 技术,是远距离无线传输技术和LPWAN通信技术中的一种.目前,LoRa 主要在ISM频段运行主要包括433、868、915 MHz等
- LoRa技术融合了数字扩频、数字信号处理和前向纠错编码等技术使得在长距离通信性能层面大幅度提高,LoRa的链路预算优于其他任何标准化的通信技术,链路预算是指给定的环境中决定距离的主要因素
- LoRa射频芯片主要有 SX127X系列,SX126X系列,SX130X系列,其中SX127X,SX126X系列用于LoRa节点,SX130X用于LoRa网关,详情可参考Semtech的产品列表
什么是LoRaWAN?
- LoRaWAN 是一种建立在 LoRa 无线电调制技术之上的低功耗广域网开放协议。旨在将电池供电的“事物”无线连接到区域、国家或全球网络中的互联网,并针对关键的物联网 (IoT) 要求,例如双向定向通信、端到端安全、移动性和本地化服务。其中节点无线连接到互联网有入网认证,相当于建立节点和服务器间的加密通信信道,入网详情参考[ 文档]和源码,LoRaWAN协议层次下图所示。
- MAC层中的Class A/B/C 三类节点设备基本覆盖了物联网所有的应用场景,三者之间不同点在于节点收发的时隙不同
- Modulation层中EU868,AS430等表明不同国家使用频段参数不同,地区参数请点击参考链接
- 实现LoRaWAN网络覆盖城市或其它区域需要由节点(LoRa节点射频芯片)、网关(或称基站,LoRa网关射频芯片)、Server和云四部分组成,如下图所示
- DEVICE(节点设备)需先发起入网请求数据包到GATEWAY(网关)再到服务器,认证通过后才可以正常和服务器收发应用数据
- GATEWAY(网关)可通过有线网络,3/4/5G无线网络与服务器进行通信
- 服务器端主要运营商有TTN等,自行搭建云端服务请参考lorawan-stack,chirpstack
应用
LoRa 器件和网络(如 LoRaWAN)使得智能物联网应用能够帮助解决地球面临的能源管理、自然资源减少、污染控制、基础设施效率、防灾等艰巨挑战。Semtech 的 LoRa 器件已在智慧城市、家居和建筑、社区、计量、供应链和物流、农业等领域实现了数百个成功应用案例。LoRa 网络已覆盖 100 多个国家/地区的数亿台器件,致力于打造一个更智慧的地球。
Windows
硬件连接和测试
- 准备两个SX126x LoRa HAT 模块(以下统称Lora模块),两根Micro USB线,装配SMA天线,跳帽置于A上,M0和M1连接GND
- WINDOWS PC上安装CP2102驱动,两个Lora模块使用Micro USB连接至PC
- 打开PC设备管理器,查找CP2102对应的两个COM口,使用SSCOM串口软件分别连接两个Lora模块,波特率都设置为9600
- 其中一个SSCOM串口软件的输入栏输入数据,点击发送按钮,在另一个SSCOM串口软件显示栏可以看到LoRa模块收到的数据。
PC终端
本测试使用Windows PC连接LoRa HAT,跳冒设置按出厂位置不改变
1. Windows安装python3,然后在启动栏输入cmd搜索并打开Windows终端
2. 把python3的路径输入终端,一般默认地址如下图所示,注意检查用户自己的python3路径,安装pyserial
path=%path%;C:\Users\zhongshaohua\AppData\Local\Programs\Python\Python37\Scripts\ path=%path%;C:\Users\zhongshaohua\AppData\Local\Programs\Python\Python37\ pip3 install pyserial
3. 使用上位机软件设置LoRa HAT,设置时拔掉M1跳冒,设置完成后接入M1跳冒并关闭上位机串口,设置参数如下
4. 把示例程序解压到桌面,打开main.py文件修改COM口,然后再运行
Raspberry Pi
本章节示例演示1使用两个LoRa HAT分别接入两个树莓派进行收发测试,示例演示2使用3个LoRa HAT进行中继通信收发测试
硬件连接,安装库,使能树莓派串口,下载示例程序
等待树莓派开机后再接入LoRa HAT,跳冒按照如下设置
逐条输入下面命令,第一条指令使能树莓派串口
#2021.10.30后的系统不再需要安装serial库 #sudo apt install python-serial sudo raspi-config cd Documents wget https://www.waveshare.net/w/upload/6/68/SX126X_LoRa_HAT_Code.zip unzip SX126X_LoRa_HAT_Code.zip
打开树莓派SERIAL串口
若用户使用SSH登录树莓派终端,请点击我参阅使能树莓派SERIAL串口
例程演示1
- 执行下面命令后,节点接收其它节点发送的数据时自动打印到终端,当节点需要发送数据给其它节点时候,按下键盘i,然后按提示输入输入即可,如下图所示
cd ~/Documents/sx126x_lora_hat/RaspberryPi/python/ sudo python3 main.py
例程演示2
中继通信是为实现超远距离通信一种方法,将LoRa模块设置成中继模式,中继模式的LoRa模块地址寄存器只作为NETID转发配对,不再有主动收发功能,也无法低功耗操作
注意:实现中继功能至少需要三个LoRa模块
- 将三个LoRa模块假设为LoRa模块A,LoRa模块B,LoRa模块C。
- LoRa模块A直接接入树莓派, LoR模块B和LoRa模块C使用Windows端上位机设置
- LoRa模块A接入树莓派后打开main.py文件,更改66行,把realy=False改成realy=True,执行下面命令,LoRa模块C收到数据会从串口打印数据,而中继LoRa模块B不会从串口打印任何数据,输入下面命令:
cd ~/Documents/SX126X_LoRa_HAT_Code/RaspberryPi/python/ # node = sx126x.sx126x(serial_num = "/dev/ttyS0",freq=868,addr=0,power=22,rssi=True,air_speed=2400,relay=True) sudo python3 main.py
STM32
本例程使用STM32F103CBT6,程序是基于HAL库
硬件连接
跳帽连接B,M0、M1跳帽移除改用STM32F103C的GPIO使用
SX1268 LoRa HAT | STM32F103C |
---|---|
5V | 5V |
GND | GND |
RXD | PA10 |
TXD | PA9 |
M1 | PB15 |
M0 | PB14 |
例程演示
- 连接电脑USB的LoRa模块的设置同以上三个例程相同。
- 打开Keil工程文档,在main.c文件第75行到77行使用不同的定义使用不同的通信方式
#define TRASNSPARENT //#define RELAY //#define WOR
- 选择好上面的通讯方式按F7编译,按F8下载到STM32。
代码简析
本小节简述本产品的工作过程和python程序
- 上电后设置/dev/ttyS0串口及9600波特率,模组的M0(BCM22)引脚低电平,M1(BCM27)引脚高电平,模组进入配置模式
def __init__(self,serial_num,freq,addr,power,rssi,air_speed=2400,\ net_id=0,buffer_size = 240,crypt=0,\ relay=False,lbt=False,wor=False): self.rssi = rssi self.addr = addr self.freq = freq self.serial_n = serial_num self.power = power # Initial the GPIO for M0 and M1 Pin GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(self.M0,GPIO.OUT) GPIO.setup(self.M1,GPIO.OUT) GPIO.output(self.M0,GPIO.LOW) GPIO.output(self.M1,GPIO.HIGH) # The hardware UART of Pi3B+,Pi4B is /dev/ttyS0 self.ser = serial.Serial(serial_num,9600) self.ser.flushInput() self.set(freq,addr,power,rssi,air_speed,net_id,buffer_size,crypt,relay,lbt,wor)
- 下面代码中第11行至第77行设置LoRa模组的低地址,高地址,网络ID,自身频率,空速大小,缓存大小,功率大小,RSSI输入使能,加密密钥和是否使能中继模式参数,LoRa模组的寄存器点击查看寄存器描述和寄存器配置方法,第79行至第113行是串口发送配置指令给LoRa模组,如果配置正确则拉低M1引脚进入收发模式
def set(self,freq,addr,power,rssi,air_speed=2400,\ net_id=0,buffer_size = 240,crypt=0,\ relay=False,lbt=False,wor=False): self.send_to = addr self.addr = addr # We should pull up the M1 pin when sets the module GPIO.output(self.M0,GPIO.LOW) GPIO.output(self.M1,GPIO.HIGH) time.sleep(0.1) low_addr = addr & 0xff high_addr = addr >> 8 & 0xff net_id_temp = net_id & 0xff if freq > 850: freq_temp = freq - 850 self.start_freq = 850 self.offset_freq = freq_temp elif freq >410: freq_temp = freq - 410 self.start_freq = 410 self.offset_freq = freq_temp air_speed_temp = self.lora_air_speed_dic.get(air_speed,None) # if air_speed_temp != None buffer_size_temp = self.lora_buffer_size_dic.get(buffer_size,None) # if air_speed_temp != None: power_temp = self.lora_power_dic.get(power,None) #if power_temp != None: if rssi: # enable print rssi value rssi_temp = 0x80 else: # disable print rssi value rssi_temp = 0x00 # get crypt l_crypt = crypt & 0xff h_crypt = crypt >> 8 & 0xff if relay==False: self.cfg_reg[3] = high_addr self.cfg_reg[4] = low_addr self.cfg_reg[5] = net_id_temp self.cfg_reg[6] = self.SX126X_UART_BAUDRATE_9600 + air_speed_temp # # it will enable to read noise rssi value when add 0x20 as follow # self.cfg_reg[7] = buffer_size_temp + power_temp + 0x20 self.cfg_reg[8] = freq_temp # # it will output a packet rssi value following received message # when enable eighth bit with 06H register(rssi_temp = 0x80) # self.cfg_reg[9] = 0x43 + rssi_temp self.cfg_reg[10] = h_crypt self.cfg_reg[11] = l_crypt else: self.cfg_reg[3] = 0x01 self.cfg_reg[4] = 0x02 self.cfg_reg[5] = 0x03 self.cfg_reg[6] = self.SX126X_UART_BAUDRATE_9600 + air_speed_temp # # it will enable to read noise rssi value when add 0x20 as follow # self.cfg_reg[7] = buffer_size_temp + power_temp + 0x20 self.cfg_reg[8] = freq_temp # # it will output a packet rssi value following received message # when enable eighth bit with 06H register(rssi_temp = 0x80) # self.cfg_reg[9] = 0x03 + rssi_temp self.cfg_reg[10] = h_crypt self.cfg_reg[11] = l_crypt self.ser.flushInput() for i in range(2): self.ser.write(bytes(self.cfg_reg)) r_buff = 0 time.sleep(0.2) if self.ser.inWaiting() > 0: time.sleep(0.1) r_buff = self.ser.read(self.ser.inWaiting()) if r_buff[0] == 0xC1: pass # print("parameters setting is :",end='') # for i in self.cfg_reg: # print(hex(i),end=' ') # print('\r\n') # print("parameters return is :",end='') # for i in r_buff: # print(hex(i),end=' ') # print('\r\n') else: pass #print("parameters setting fail :",r_buff) break else: print("setting fail,setting again") self.ser.flushInput() time.sleep(0.2) print('\x1b[1A',end='\r') if i == 1: print("setting fail,Press Esc to Exit and run again") # time.sleep(2) # print('\x1b[1A',end='\r') GPIO.output(self.M0,GPIO.LOW) GPIO.output(self.M1,GPIO.LOW) time.sleep(0.1)
- 串口发送应用数据到LoRa模组通过无线发送其它LoRa节点
# the data format like as following # "node address,frequence,payload" # "20,868,Hello World" def send(self,data): GPIO.output(self.M1,GPIO.LOW) GPIO.output(self.M0,GPIO.LOW) time.sleep(0.1) self.ser.write(data) # if self.rssi == True: # self.get_channel_rssi() time.sleep(0.1)
- 接收端接收到数据后从串口输出给控制器,注意第三行代码,如果接收数据量过大,请相应增加延时等待全部数据接收完毕再读取,第10行至第15行是根据RSSI使能与否打印RSSI值
def receive(self): if self.ser.inWaiting() > 0: time.sleep(0.5) r_buff = self.ser.read(self.ser.inWaiting()) print("receive message from node address with frequence\033[1;32m %d,%d.125MHz\033[0m"%((r_buff[0]<<8)+r_buff[1],r_buff[2]+self.start_freq),end='\r\n',flush = True) print("message is "+str(r_buff[3:-1]),end='\r\n') # print the rssi if self.rssi: # print('\x1b[3A',end='\r') print("the packet rssi value: -{0}dBm".format(256-r_buff[-1:][0])) self.get_channel_rssi() else: pass #print('\x1b[2A',end='\r')
- main.py文件中,在程序运行后,等待用户按下键盘执行对应操作,输入Esc退出循环,输入i则为输入要发送的应用信息,输入s则为每间隔10秒广播一次cpu温度
try: time.sleep(1) print("Press \033[1;32mEsc\033[0m to exit") print("Press \033[1;32mi\033[0m to send") print("Press \033[1;32ms\033[0m to send cpu temperature every 10 seconds") # it will send rpi cpu temperature every 10 seconds seconds = 10 while True: if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): c = sys.stdin.read(1) # dectect key Esc if c == '\x1b': break # dectect key i if c == '\x69': send_deal() # dectect key s if c == '\x73': print("Press \033[1;32mc\033[0m to exit the send task") timer_task = Timer(seconds,send_cpu_continue) timer_task.start() while True: if sys.stdin.read(1) == '\x63': timer_task.cancel() print('\x1b[1A',end='\r') print(" "*100) print('\x1b[1A',end='\r') break sys.stdout.flush() node.receive() # timer,send messages automatically except: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
FAQ
- 串口问题,程序默认用的串口是ttyS0,树莓派串口可能不是,可以用以下指令确认(serial0 对应的是选用串口):
ls -l /dev/serial*
- 470M和433M的模块程序是一样的,默认用433M 的程序;915M 和 868M用的都是868M程序,程序默认用的是433M,改下注释即可:
- 可能是系统问题,请用这边验证过可以稳定使用的树莓派Buster系统
- 不可以的,Lora是私有协议,由于LoRa模块的射频参数不一致,内部实现、通信协议、数据编码等方面的差异
- 比方说,需要两个或以上的SX1262 433M LoRa HAT才能实现通信,成对使用,不能和别的系列Lora通信
- 因此请选择同款的LoRa模块,以确保硬件和协议的一致性;或者改用开放协议的Lorawan模块
- 地面吸收、反射无线电波,靠近地面测试效果较差;当存在直线通信障碍时,通信距离会相应的衰减;
- 天线附近有金属物体,或放置于金属壳内,信号衰减会非常严重;海水具有极强的吸收无线电波能力,故海边测试效果差;
- 温度、湿度,同频干扰,会导致通信丢包率提高;室温下电源低压低于推荐值,电压越低发功率越小;
- 功率寄存器设置错误、空中速率设置过高(空中速率越高,距离越近);
不支持
需要支持LoRaWAN网络协议的话选购这个Pico-LoRa-SX1262-868M ,可以搭配LoRaWAN网关SX1302 LoRaWAN Gateway HAT:
补充说明: 在计算机网络OSI模型中,LoRa位于最底部的物理层中,一般情况下泛指使用LoRa技术的射频芯片; LoRaWAN是在LoRa传输技术 基础之上的以MAC层为主的一套协议标准。有了这个标准之后,LoRaWAN的就变成一种网络技术。 仅支持Lora而不支持Lorawan的话,可以进行点对点通信,但无法建立更高级别的网络连接,如LoRaWAN网络。如果需要建立更大规模的LoRa网络,建议使用LoRaWAN协议。
- 流模式(非确认模式):
在流模式下,LoRa设备发送数据后不会等待接收方的确认。这种模式适用于对实时性要求较高或对数据完整性要求不高的应用。
- 数据包模式(确认模式):