我正在尝试通过 LoRa 将数据从 Arduino 发送到 ESP32。我正在使用 2 个带有天线的相同 Ra-02 Aithinker 模块。我为 Arduino “LoRa”使用常用库,为 ESP32移植相同的库。我没有实现所有功能,因为我只需要最简单的设置。
这是移植库的代码:
罗拉.h:
#ifndef LORA_H
#define LORA_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#define PIN_NUM_MISO 25
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK 19
#define PIN_NUM_CS 22
#define PIN_NUM_RST 18
#define LORA_DEFAULT_DIO0_PIN 2
#define PA_OUTPUT_RFO_PIN 0
#define PA_OUTPUT_PA_BOOST_PIN 1
// registers
#define REG_FIFO 0x00
#define REG_OP_MODE 0x01
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define REG_PA_CONFIG 0x09
#define REG_LNA 0x0c
#define REG_FIFO_ADDR_PTR 0x0d
#define REG_FIFO_TX_BASE_ADDR 0x0e
#define REG_FIFO_RX_BASE_ADDR 0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_RX_NB_BYTES 0x13
#define REG_PKT_RSSI_VALUE 0x1a
#define REG_PKT_SNR_VALUE 0x1b
#define REG_MODEM_CONFIG_1 0x1d
#define REG_MODEM_CONFIG_2 0x1e
#define REG_PREAMBLE_MSB 0x20
#define REG_PREAMBLE_LSB 0x21
#define REG_PAYLOAD_LENGTH 0x22
#define REG_MODEM_CONFIG_3 0x26
#define REG_RSSI_WIDEBAND 0x2c
#define REG_DETECTION_OPTIMIZE 0x31
#define REG_DETECTION_THRESHOLD 0x37
#define REG_SYNC_WORD 0x39
#define REG_DIO_MAPPING_1 0x40
#define REG_VERSION 0x42
// modes
#define MODE_LONG_RANGE_MODE 0x80
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_TX 0x03
#define MODE_RX_CONTINUOUS 0x05
#define MODE_RX_SINGLE 0x06
// PA config
#define PA_BOOST 0x80
// IRQ masks
#define IRQ_TX_DONE_MASK 0x08
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
#define IRQ_RX_DONE_MASK 0x40
#define MAX_PKT_LENGTH 255
class LoRaClass{
public:
LoRaClass();
uint8_t begin(long frequency=0);
void sleep();
void setFrequency(long frequency);
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
void idle();
int parsePacket(int size = 0);
virtual int available();
virtual int read();
int packetRssi();
uint8_t beginPacket(uint8_t implicitHeader = false);
uint8_t endPacket();
size_t write(const uint8_t *buffer, size_t size);
void setSpreadingFactor(int sf);
void dumpRegisters();
private:
uint8_t singleTransfer(uint8_t data);
uint8_t readRegister(uint8_t address);
void writeRegister(uint8_t address, uint8_t value);
void explicitHeaderMode();
void implicitHeaderMode();
private:
//SPISettings _spiSettings;
spi_device_handle_t _spi;
int _ss;
int _reset;
int _dio0;
int _frequency;
int _packetIndex;
int _implicitHeaderMode;
void (*_onReceive)(int);
};
extern LoRaClass LoRa;
#endif
洛拉.c:
#include "LoRa.h"
// registers
#define REG_FIFO 0x00
#define REG_OP_MODE 0x01
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define REG_PA_CONFIG 0x09
#define REG_LNA 0x0c
#define REG_FIFO_ADDR_PTR 0x0d
#define REG_FIFO_TX_BASE_ADDR 0x0e
#define REG_FIFO_RX_BASE_ADDR 0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_RX_NB_BYTES 0x13
#define REG_PKT_RSSI_VALUE 0x1a
#define REG_PKT_SNR_VALUE 0x1b
#define REG_MODEM_CONFIG_1 0x1d
#define REG_MODEM_CONFIG_2 0x1e
#define REG_PREAMBLE_MSB 0x20
#define REG_PREAMBLE_LSB 0x21
#define REG_PAYLOAD_LENGTH 0x22
#define REG_MODEM_CONFIG_3 0x26
#define REG_RSSI_WIDEBAND 0x2c
#define REG_DETECTION_OPTIMIZE 0x31
#define REG_DETECTION_THRESHOLD 0x37
#define REG_SYNC_WORD 0x39
#define REG_DIO_MAPPING_1 0x40
#define REG_VERSION 0x42
// modes
#define MODE_LONG_RANGE_MODE 0x80
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_TX 0x03
#define MODE_RX_CONTINUOUS 0x05
#define MODE_RX_SINGLE 0x06
// PA config
#define PA_BOOST 0x80
// IRQ masks
#define IRQ_TX_DONE_MASK 0x08
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
#define IRQ_RX_DONE_MASK 0x40
#define MAX_PKT_LENGTH 255
LoRaClass::LoRaClass() {
//_spiSettings(8E6, MSBFIRST, SPI_MODE0),
_ss = PIN_NUM_CS;
_reset = PIN_NUM_RST;
_dio0 = LORA_DEFAULT_DIO0_PIN;
_frequency = 0;
_packetIndex = 0;
_implicitHeaderMode = 0;
//_onReceive(NULL)
// setup pins
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE ;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (uint64_t)(((uint64_t)(((uint64_t)1)<<_ss)) | ((uint64_t)(((uint64_t)1)<<_reset)));
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE ;
gpio_config(&io_conf);
// perform reset
gpio_set_level((gpio_num_t)_reset, 0);
vTaskDelay(10 / portTICK_RATE_MS);
gpio_set_level((gpio_num_t)_reset, 1);
vTaskDelay(10 / portTICK_RATE_MS);
// set SS high
gpio_set_level((gpio_num_t)_ss, 1);
esp_err_t ret;
//memset(_spi,0,sizeof(spi_device_handle_t));
spi_bus_config_t buscfg;
memset(&buscfg,0,sizeof(buscfg));
buscfg.miso_io_num=PIN_NUM_MISO;
buscfg.mosi_io_num=PIN_NUM_MOSI;
buscfg.sclk_io_num=PIN_NUM_CLK;
buscfg.quadwp_io_num=-1;
buscfg.quadhd_io_num=-1;
spi_device_interface_config_t devcfg;
memset(&devcfg,0,sizeof(devcfg));
devcfg.clock_speed_hz=2*1000*1000; //Clock out at 10 MHz
devcfg.mode=0;
devcfg.spics_io_num=-1; //CS pin
devcfg.queue_size=7; //We want to be able to queue 7 transactions at a time
ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
if (ret != ESP_OK) {
printf("Error: spi_bus_initialize: %0d",ret);
}
ret=spi_bus_add_device(HSPI_HOST, &devcfg, &_spi);
if (ret != ESP_OK) {
printf("Error: spi_bus_add_device: %0d",ret);
}
printf("\n\nLoRa Initialized\n");
}
uint8_t LoRaClass::begin(long frequency) {
uint8_t version = readRegister(REG_VERSION);
if (version != 0x12) {
return version;
}
sleep();
if (frequency>0) setFrequency(frequency);
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
writeRegister(REG_MODEM_CONFIG_3, 0x04);
setTxPower(17);
idle();
printf("\n\nLoRa started\n");
return 1;
}
uint8_t LoRaClass::singleTransfer(uint8_t data)
{
uint32_t resp=0;
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); //Zero out the transaction
t.length=8; //Command is 8 bits
t.tx_buffer=&data; //The data is the cmd itself
t.rx_buffer=&resp;
ret = spi_device_transmit(_spi, &t); //Transmit!
if (ret != ESP_OK) printf("spi_device_transmit error: 0x%0x\n",ret);
return resp;
}
uint8_t LoRaClass::readRegister(uint8_t address)
{
gpio_set_level((gpio_num_t)_ss, 0);
vTaskDelay(1 / portTICK_RATE_MS);
singleTransfer(address & 0x7f);
//printf(".");
uint8_t resp = singleTransfer(0x00);
vTaskDelay(1 / portTICK_RATE_MS);
gpio_set_level((gpio_num_t)_ss, 1);
return resp;
}
void LoRaClass::writeRegister(uint8_t address, uint8_t value)
{
gpio_set_level((gpio_num_t)_ss, 0);
vTaskDelay(1 / portTICK_RATE_MS);
singleTransfer(address | 0x80);
singleTransfer(value);
vTaskDelay(1 / portTICK_RATE_MS);
gpio_set_level((gpio_num_t)_ss, 1);
}
void LoRaClass::sleep()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
}
void LoRaClass::setFrequency(long frequency)
{
_frequency = frequency;
long fstep = 61.03515625;
long frfl = frequency/fstep;
uint64_t frf = ((uint64_t)frfl);
writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
}
void LoRaClass::setTxPower(int level, int outputPin)
{
if (PA_OUTPUT_RFO_PIN == outputPin) {
// RFO
if (level < 0) {
level = 0;
} else if (level > 14) {
level = 14;
}
writeRegister(REG_PA_CONFIG, 0x70 | level);
} else {
// PA BOOST
if (level < 2) {
level = 2;
} else if (level > 17) {
level = 17;
}
writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
}
}
void LoRaClass::idle()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
}
int LoRaClass::parsePacket(int size)
{
int packetLength = 0;
int irqFlags = readRegister(REG_IRQ_FLAGS);
if (size > 0) {
implicitHeaderMode();
writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
} else {
explicitHeaderMode();
}
writeRegister(REG_IRQ_FLAGS, irqFlags);
if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
_packetIndex = 0;
if (_implicitHeaderMode) {
packetLength = readRegister(REG_PAYLOAD_LENGTH);
} else {
packetLength = readRegister(REG_RX_NB_BYTES);
}
writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
idle();
} else
if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
writeRegister(REG_FIFO_ADDR_PTR, 0);
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
}
return packetLength;
}
void LoRaClass::explicitHeaderMode()
{
_implicitHeaderMode = 0;
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
}
void LoRaClass::implicitHeaderMode()
{
_implicitHeaderMode = 1;
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
}
int LoRaClass::available()
{
return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
}
int LoRaClass::read()
{
_packetIndex++;
return readRegister(REG_FIFO);
}
int LoRaClass::packetRssi()
{
return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868000000 ? 164 : 157));
}
uint8_t LoRaClass::beginPacket(uint8_t implicitHeader)
{
idle();
if (implicitHeader) {
implicitHeaderMode();
} else {
explicitHeaderMode();
}
writeRegister(REG_FIFO_ADDR_PTR, 0);
writeRegister(REG_PAYLOAD_LENGTH, 0);
return 1;
}
uint8_t LoRaClass::endPacket()
{
// put in TX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
// wait for TX done
while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
return 1;
}
size_t LoRaClass::write(const uint8_t *buffer, size_t size)
{
int currentLength = readRegister(REG_PAYLOAD_LENGTH);
// check size
if ((currentLength + size) > MAX_PKT_LENGTH) {
size = MAX_PKT_LENGTH - currentLength;
}
// write data
for (size_t i = 0; i < size; i++) {
writeRegister(REG_FIFO, buffer[i]);
}
// update length
writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
return size;
}
void LoRaClass::setSpreadingFactor(int sf)
{
if (sf < 6) {
sf = 6;
} else if (sf > 12) {
sf = 12;
}
if (sf == 6) {
writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
} else {
writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
}
writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
}
void LoRaClass::dumpRegisters()
{
for (int i = 0; i < 128; i++) {
printf("0x%02X=0x%02X\n",i,readRegister(i));
}
}
在 Arduino 上,我这样发送:
LoRa.beginPacket();
LoRa.write(0);
LoRa.write(1);
LoRa.write(2);
LoRa.write(3);
LoRa.endPacket();
delay(3000);
在 ESP32 上,我收到这样的信息:
while (1) {
packetSize = LoRa.parsePacket();
if (packetSize>0) {
printf("\nReceived: ");
while (LoRa.available()) {
printf("%02X ",LoRa.read());
}
printf(" (RSSI: %0d)\n", LoRa.packetRssi());
}
}
但问题是我收到了这个:
Received: 99 CB 2B 0F (RSSI: -89)
Received: 90 0D 2B 1F (RSSI: -90)
Received: 9A 9D 2B 0F (RSSI: -94)
Received: 00 01 2B 07 (RSSI: -87)
Received: 00 0D 2B 0F (RSSI: -89)
Received: 9A 0B 2B 0F (RSSI: -94)
Received: A8 C1 2B 0F (RSSI: -90)
Received: 00 01 A3 03 (RSSI: -88)
Received: 00 07 2B 0F (RSSI: -87)
Received: 00 0D 2B 0F (RSSI: -89)
Received: 09 08 2B 5F (RSSI: -89)
Received: 99 08 02 0A (RSSI: -95)
Received: A9 0B 2B 0F (RSSI: -95)
有人可以建议修复以正确接收数据吗?
顺便说一句,从 ESP32 到 ESP32 的数据正确。我还在两边都转储了 SX1278 寄存器——它们是相同的。