我有 SX1262 868M LoRa 帽子,附带测试代码。这总结了初始化设备的函数调用。
node = sx126x.sx126x(serial_num = "/dev/ttyS0", freq=868, addr=0, power=22, rssi=True, air_speed=2400, relay=False)
现在,我尝试将这顶帽子设置为接收器(代码已经做到了),并将 ESP32(也配备了 SX1262)设置为具有以下代码的发送器:
LoRa发射器.h
#include "LoRaWan_APP.h"
#include "Arduino.h"
class LoRaTransmitter {
private:
RadioEvents_t RadioEvents;
static LoRaTransmitter* instance;
bool txDone;
LoRaTransmitter();
public:
static LoRaTransmitter* getInstance();
void send(const char *message);
void send(const String &message);
static void OnTxDone(void);
static void OnTxTimeout(void);
};
LoRa发射器.cpp
#include "LoRaTransmitter.h"
#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 4 // 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 BUFFER_SIZE 512
LoRaTransmitter* LoRaTransmitter::instance;
LoRaTransmitter::LoRaTransmitter() {
Mcu.begin();
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
Radio.Init(&RadioEvents);
Radio.SetChannel(RF_FREQUENCY);
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);
txDone = true;
}
LoRaTransmitter* LoRaTransmitter::getInstance() {
if (instance == nullptr)
instance = new LoRaTransmitter();
return instance;
}
void LoRaTransmitter::send(const char *message) {
if (txDone) {
txDone = false;
Serial.println("Sending message: " + String(message) + ", Length: " + String(strlen(message)));
char packet[BUFFER_SIZE];
strncpy(packet, message, BUFFER_SIZE);
Radio.Send((uint8_t *)packet, strlen(packet));
}
Radio.IrqProcess();
}
void LoRaTransmitter::send(const String &message) {
send(message.c_str());
}
void LoRaTransmitter::OnTxDone(void) {
Serial.print("TX done......");
instance->txDone = true;
}
void LoRaTransmitter::OnTxTimeout(void) {
Radio.Sleep();
Serial.print("TX Timeout......");
}
现在,我还将复制用于帽子的设置类:
import RPi.GPIO as GPIO
import serial
import time
class sx126x:
M0 = 22
M1 = 27
# if the header is 0xC0, then the LoRa register settings don't get lost when it powers off, and 0xC2 will be lost.
# cfg_reg = [0xC0, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x17, 0x43, 0x00, 0x00]
cfg_reg = [0xC2, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x12, 0x43, 0x00, 0x00]
get_reg = bytes(12)
rssi = False
addr = 65535
serial_n = ""
addr_temp = 0
# start frequency of the two LoRa modules
# E22-400T22S E22-900T22S
# 410~493MHz or 850~930MHz
start_freq = 850
# offset between start and end frequency of the two LoRa modules
# E22-400T22S E22-900T22S
# 410~493MHz or 850~930MHz
offset_freq = 18
# power = 22
# air_speed =2400
SX126X_UART_BAUDRATE_1200 = 0x00
SX126X_UART_BAUDRATE_2400 = 0x20
SX126X_UART_BAUDRATE_4800 = 0x40
SX126X_UART_BAUDRATE_9600 = 0x60
SX126X_UART_BAUDRATE_19200 = 0x80
SX126X_UART_BAUDRATE_38400 = 0xA0
SX126X_UART_BAUDRATE_57600 = 0xC0
SX126X_UART_BAUDRATE_115200 = 0xE0
SX126X_PACKAGE_SIZE_240_BYTE = 0x00
SX126X_PACKAGE_SIZE_128_BYTE = 0x40
SX126X_PACKAGE_SIZE_64_BYTE = 0x80
SX126X_PACKAGE_SIZE_32_BYTE = 0xC0
SX126X_Power_22dBm = 0x00
SX126X_Power_17dBm = 0x01
SX126X_Power_13dBm = 0x02
SX126X_Power_10dBm = 0x03
lora_air_speed_dic = {
1200:0x01,
2400:0x02,
4800:0x03,
9600:0x04,
19200:0x05,
38400:0x06,
62500:0x07
}
lora_power_dic = {
22:0x00,
17:0x01,
13:0x02,
10:0x03
}
lora_buffer_size_dic = {
240:SX126X_PACKAGE_SIZE_240_BYTE,
128:SX126X_PACKAGE_SIZE_128_BYTE,
64:SX126X_PACKAGE_SIZE_64_BYTE,
32:SX126X_PACKAGE_SIZE_32_BYTE
}
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)
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 setting 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 printing rssi value
rssi_temp = 0x80
else:
# disable printing 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_tempreadingto read noise rssi value when add 0x20 as follows
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 enabling the 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 enabling the
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)
def get_settings(self):
# the pin M1 of lora HAT must be high when entering setting mode and getting parameters
GPIO.output(M1, GPIO.HIGH)
time.sleep(0.1)
# send command to get setting parameters
self.ser.write(bytes([0xC1, 0x00, 0x09]))
if self.ser.inWaiting() > 0:
time.sleep(0.1)
self.get_reg = self.ser.read(self.ser.inWaiting())
# check the return characters from hat and print the setting parameters
if self.get_reg[0] == 0xC1 and self.get_reg[2] == 0x09:
fre_temp = self.get_reg[8]
addr_temp = self.get_reg[3] + self.get_reg[4]
air_speed_temp = self.get_reg[6] & 0x03
power_temp = self.get_reg[7] & 0x03
print("Frequence is {0}.125MHz.", fre_temp)
print("Node address is {0}.", addr_temp)
print("Air speed is {0} bps"+ lora_air_speed_dic.get(None, air_speed_temp))
print("Power is {0} dBm" + lora_power_dic.get(None, power_temp))
GPIO.output(M1, GPIO.LOW)
# the data format is as follows
# "node address, frequency, 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)
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')
def get_channel_rssi(self):
GPIO.output(self.M1, GPIO.LOW)
GPIO.output(self.M0, GPIO.LOW)
time.sleep(0.1)
self.ser.flushInput()
self.ser.write(bytes([0xC0, 0xC1, 0xC2, 0xC3, 0x00, 0x02]))
time.sleep(0.5)
re_temp = bytes(5)
if self.ser.inWaiting() > 0:
time.sleep(0.1)
re_temp = self.ser.read(self.ser.inWaiting())
if re_temp[0] == 0xC1 and re_temp[1] == 0x00 and re_temp[2] == 0x02:
print("the current noise rssi value: -{0}dBm".format(256-re_temp[3]))
# print("the last receive packet rssi value: -{0}dBm".format(256-re_temp[4]))
else:
# pass
print("receive rssi value fail")
# print("receive rssi value fail: ", re_temp)
我想这两个设备应该能够通信,因为最终它们是相同的。有人知道为什么接收器 HAT 没有收到来自 ESP32 LoRa 发送器的任何消息吗?
我想这两个设备应该能够通信,因为最终它们是相同的。
但这就是问题所在。虽然它们的核心是相同的(两个 SX1262),但它们根本不同。其中一个是 ebyte 垃圾,是一个托管 LoRa 模块,您可以通过 UART 访问它,并且几乎无法控制。另一种是“真正的”SX1262,您可以通过 SPI 自行管理和控制。
您应该注意到的一件事是两者之间的设置非常不同。亿佰特与普通SX1262模块的主要区别是:
addr
地址设置?那是什么?我认为相关的前两点使得 ebyte 模块几乎不可能与普通 LoRa 模块一起工作。他们的固件似乎从“空气速度”的东西中得出了 SF 值。我无法将这些空速与 BW / SF / CR 值相匹配。例如,查看LoRa计算器,非常常见的SF 10、BW 7、CR 4/5设置为您提供每秒977波特的数据速率。无法将这些设置扭曲到接近 2,400。
我在某处读到一个人设法使 ebyte 与 SX1276 进行通信。不记得在哪里或如何,但听起来很复杂。你最好的猜测是要么留在 ebyte 生态系统中(无论如何这都是垃圾),要么使用像样的产品,无论是 SPI 还是 UART 管理的产品。那里有很多,我最喜欢的是 RAKwireless(为了质量)和 Heltec(为了更便宜的东西)。