Fix LoRa Config

This commit is contained in:
Theo Arends 2024-02-27 17:09:50 +01:00
parent 77cba87994
commit 24b59376bb
4 changed files with 132 additions and 76 deletions

View File

@ -8,8 +8,44 @@
#ifdef USE_SPI
#ifdef USE_SPI_LORA
/*********************************************************************************************\
* LoRa defines and global struct
\*********************************************************************************************/
#define LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (defined by RadioLib driver)
//#define USE_LORA_DEBUG
#define LORA_MAX_PACKET_LENGTH 252 // Max packet length allowed (keeping room for control bytes)
#ifndef TAS_LORA_FREQUENCY
#define TAS_LORA_FREQUENCY 868.0 // Allowed values range from 150.0 to 960.0 MHz
#endif
#ifndef TAS_LORA_BANDWIDTH
#define TAS_LORA_BANDWIDTH 125.0 // Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz
#endif
#ifndef TAS_LORA_SPREADING_FACTOR
#define TAS_LORA_SPREADING_FACTOR 9 // Allowed values range from 5 to 12
#endif
#ifndef TAS_LORA_CODING_RATE
#define TAS_LORA_CODING_RATE 7 // Allowed values range from 5 to 8
#endif
#ifndef TAS_LORA_SYNC_WORD
#define TAS_LORA_SYNC_WORD 0x12 // Allowed values range from 1 to 255
#endif
#ifndef TAS_LORA_OUTPUT_POWER
#define TAS_LORA_OUTPUT_POWER 10 // Allowed values range from 1 to 20
#endif
#ifndef TAS_LORA_PREAMBLE_LENGTH
#define TAS_LORA_PREAMBLE_LENGTH 8 // Allowed values range from 1 to 65535
#endif
#ifndef TAS_LORA_CURRENT_LIMIT
#define TAS_LORA_CURRENT_LIMIT 60.0 // Overcurrent Protection - OCP in mA
#endif
#ifndef TAS_LORA_HEADER
#define TAS_LORA_HEADER 0 // Explicit (0) or Implicit (1 to 4) Header
#endif
#ifndef TAS_LORA_CRC_BYTES
#define TAS_LORA_CRC_BYTES 2 // No (0) or Number (1 to 4) of CRC bytes
#endif
struct {
bool (* Config)(void);
@ -18,18 +54,17 @@ struct {
bool (* Send)(char*, uint32_t);
float rssi;
float snr;
int packet_size;
float frequency; // 868.0 MHz
float bandwidth; // 125.0 kHz
int spreading_factor; // 9
int coding_rate; // 7
int sync_word; // 0x12
int output_power; // 10 dBm
long preamble_length; // 8 symbols
float current_limit; // 60.0 mA (Overcurrent Protection (OCP))
int implicit_header; // 0
bool crc_bytes; // 2 bytes
uint8_t gain;
uint16_t preamble_length; // 8 symbols
uint8_t sync_word; // 0x12
uint8_t spreading_factor; // 9
uint8_t coding_rate; // 7
uint8_t output_power; // 10 dBm
uint8_t implicit_header; // 0
uint8_t crc_bytes; // 2 bytes
uint8_t packet_size; // Max is 255 (LORA_MAX_PACKET_LENGTH)
volatile bool receivedFlag; // flag to indicate that a packet was received
volatile bool enableInterrupt; // disable interrupt when it's not needed
bool sendFlag;

View File

@ -22,8 +22,8 @@
* - SPI_MOSI
* - LoRa_CS
* - LoRa_Rst
* - Lora_Busy (Tasmota currently does not support user config of GPIO34 on ESP32S3
* - Lora_DI1 (Tasmota currently does not support user config of GPIO33 on ESP32S3
* - Lora_Busy
* - Lora_DI1
\*********************************************************************************************/
#include <RadioLib.h>
@ -46,10 +46,10 @@ int LoraReceiveSx126x(char* data) {
int state = LoRaRadio.readData((uint8_t*)data, LORA_MAX_PACKET_LENGTH -1);
if (RADIOLIB_ERR_NONE == state) {
if (!Lora.sendFlag) {
// Find end of raw data being non-zero (No way to know raw data length)
packet_size = LORA_MAX_PACKET_LENGTH;
while (packet_size-- && (0 == data[packet_size]));
if (0 != data[packet_size]) { packet_size++; }
packet_size = LoRaRadio.getPacketLength();
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Packet %d, Rcvd %32_H"), packet_size, data);
#endif
}
}
else if (RADIOLIB_ERR_CRC_MISMATCH == state) {
@ -72,36 +72,45 @@ int LoraReceiveSx126x(char* data) {
bool LoraSendSx126x(char* data, uint32_t len) {
Lora.sendFlag = true;
// int state = LoRaRadio.startTransmit(data, len);
// return (RADIOLIB_ERR_NONE == state);
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Len %d, Send %*_H"), len, len + 2, data);
#endif
/*
int state = LoRaRadio.startTransmit(data, len);
return (RADIOLIB_ERR_NONE == state);
*/
// https://learn.circuit.rocks/battery-powered-lora-sensor-node
uint32_t retry_CAD = 0;
uint32_t retry_send = 0;
bool send_success = false;
while (!send_success) {
// time_t lora_time = millis();
#ifdef USE_LORA_DEBUG
time_t lora_time = millis();
#endif
// Check 200ms for an opportunity to send
while (LoRaRadio.scanChannel() != RADIOLIB_CHANNEL_FREE) {
retry_CAD++;
if (retry_CAD == 20) {
// LoRa channel is busy too long, give up
// AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Channel is too busy, give up"));
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Channel is too busy, give up"));
#endif
retry_send++;
break;
}
}
// AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: CAD finished after %ldms tried %d times"), (millis() - loraTime), retryCAD);
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: CAD finished after %ldms tried %d times"), (millis() - lora_time), retry_CAD);
#endif
if (retry_CAD < 20) {
// Channel is free, start sending
// lora_time = millis();
#ifdef USE_LORA_DEBUG
lora_time = millis();
#endif
int status = LoRaRadio.transmit(data, len);
// AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Transmit finished after %ldms with status %d"), (millis() - loraTime), status);
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Transmit finished after %ldms with status %d"), (millis() - lora_time), status);
#endif
if (status == RADIOLIB_ERR_NONE) {
send_success = true;
}
@ -110,9 +119,9 @@ bool LoraSendSx126x(char* data, uint32_t len) {
}
}
if (retry_send == 3) {
// AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Failed 3 times to send data, giving up"));
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Failed 3 times to send data, giving up"));
#endif
send_success = true;
}
}
@ -120,15 +129,15 @@ bool LoraSendSx126x(char* data, uint32_t len) {
}
bool LoraConfigSx126x(void) {
LoRaRadio.setFrequency(Lora.frequency);
LoRaRadio.setBandwidth(Lora.bandwidth);
LoRaRadio.setSpreadingFactor(Lora.spreading_factor);
LoRaRadio.setCodingRate(Lora.coding_rate);
LoRaRadio.setSyncWord(Lora.sync_word);
LoRaRadio.setOutputPower(Lora.output_power);
LoRaRadio.setPreambleLength(Lora.preamble_length);
LoRaRadio.setCurrentLimit(Lora.current_limit);
LoRaRadio.setCRC(Lora.crc_bytes);
LoRaRadio.setSpreadingFactor(Lora.spreading_factor);
LoRaRadio.setBandwidth(Lora.bandwidth);
LoRaRadio.setFrequency(Lora.frequency);
LoRaRadio.setOutputPower(Lora.output_power);
if (Lora.implicit_header) {
LoRaRadio.implicitHeader(Lora.implicit_header);
} else {
@ -138,11 +147,7 @@ bool LoraConfigSx126x(void) {
}
bool LoraInitSx126x(void) {
int lora_di1 = Pin(GPIO_LORA_DI1);
if (lora_di1 == -1) { lora_di1 = 33; } // Workaround support user config of GPIO33 on ESP32S3 for LilyGo T3S3
int lora_busy = Pin(GPIO_LORA_BUSY);
if (lora_busy == -1) { lora_busy = 34; } // Workaround support user config of GPIO34 on ESP32S3 for LilyGo T3S3
LoRaRadio = new Module(Pin(GPIO_LORA_CS), lora_di1, Pin(GPIO_LORA_RST), lora_busy);
LoRaRadio = new Module(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_DI1), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_BUSY));
if (RADIOLIB_ERR_NONE == LoRaRadio.begin(Lora.frequency)) {
LoraConfigSx126x();
LoRaRadio.setDio1Action(LoraOnReceiveSx126x);

View File

@ -31,9 +31,9 @@
void LoraOnCadDoneSx127x(boolean signalDetected) {
if (signalDetected) { // detect preamble
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("LOR: Signal detected"));
#endif
LoRa.receive(); // put the radio into continuous receive mode
} else {
LoRa.channelActivityDetection(); // try next activity dectection

View File

@ -49,6 +49,19 @@ void LoraInput(void) {
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR("LoRaReceived"));
}
void LoraDefaults(void) {
Lora.frequency = TAS_LORA_FREQUENCY;
Lora.bandwidth = TAS_LORA_BANDWIDTH;
Lora.spreading_factor = TAS_LORA_SPREADING_FACTOR;
Lora.coding_rate = TAS_LORA_CODING_RATE;
Lora.sync_word = TAS_LORA_SYNC_WORD;
Lora.output_power = TAS_LORA_OUTPUT_POWER;
Lora.preamble_length = TAS_LORA_PREAMBLE_LENGTH;
Lora.current_limit = TAS_LORA_CURRENT_LIMIT;
Lora.implicit_header = TAS_LORA_HEADER;
Lora.crc_bytes = TAS_LORA_CRC_BYTES;
}
void LoraInit(void) {
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
(PinUsed(GPIO_LORA_CS)) && (PinUsed(GPIO_LORA_RST))) {
@ -59,18 +72,8 @@ void LoraInit(void) {
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
#endif // ESP32
Lora.frequency = 868.0; // MHz
Lora.bandwidth = 125.0; // kHz
Lora.spreading_factor = 9;
Lora.coding_rate = 7;
Lora.sync_word = 0x12;
Lora.output_power = 10; // dBm
Lora.preamble_length = 8; // symbols
Lora.current_limit = 60.0; // mA (Overcurrent Protection (OCP))
Lora.implicit_header = 0; // explicit
Lora.crc_bytes = 2; // bytes
Lora.enableInterrupt = true;
LoraDefaults();
char hardware[20];
if (false) {
@ -89,8 +92,9 @@ void LoraInit(void) {
}
#endif // USE_LORA_SX127X
#ifdef USE_LORA_SX126X
else if (LoraInitSx126x()) {
else if (PinUsed(GPIO_LORA_DI1) && PinUsed(GPIO_LORA_BUSY)) {
// SX1262, LilyGoT3S3
if (LoraInitSx126x()) {
Lora.Config = &LoraConfigSx126x;
Lora.Available = &LoraAvailableSx126x;
Lora.Receive = &LoraReceiveSx126x;
@ -98,6 +102,7 @@ void LoraInit(void) {
strcpy_P(hardware, PSTR("SX126x"));
Lora.present = true;
}
}
#endif // USE_LORA_SX126X
else {
strcpy_P(hardware, PSTR("Not"));
@ -121,18 +126,23 @@ void (* const LoraCommand[])(void) PROGMEM = {
void CmndLoraSend(void) {
// LoRaSend "Hello Tiger" - Send "Hello Tiger\n"
// LoRaSend - Set to text decoding
// LoRaSend1 "Hello Tiger" - Send "Hello Tiger\n"
// LoRaSend2 "Hello Tiger" - Send "Hello Tiger"
// LoRaSend3 "Hello Tiger" - Send "Hello Tiger\f"
// LoRaSend4 = LoraSend2
// LoRaSend4 - Set to binary decoding
// LoRaSend4 "Hello Tiger" - Send "Hello Tiger" and set to binary decoding
// LoRaSend5 "AA004566" - Send "AA004566" as hex values
// LoRaSend6 "72,101,108,108" - Send decimals as hex values
// if (XdrvMailbox.index > 9) { XdrvMailbox.index -= 10; } // Allows leading spaces (not supported - See support_command/CommandHandler)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) {
Lora.raw = (XdrvMailbox.index > 3); // Global flag set even without data
if (XdrvMailbox.data_len > 0) {
char data[LORA_MAX_PACKET_LENGTH];
char data[LORA_MAX_PACKET_LENGTH] = { 0 };
uint32_t len = (XdrvMailbox.data_len < LORA_MAX_PACKET_LENGTH -1) ? XdrvMailbox.data_len : LORA_MAX_PACKET_LENGTH -2;
#ifdef USE_LORA_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Len %d, Send %*_H"), len, len + 2, XdrvMailbox.data);
#endif
if (1 == XdrvMailbox.index) { // "Hello Tiger\n"
memcpy(data, XdrvMailbox.data, len);
data[len++] = '\n';
@ -183,9 +193,14 @@ void CmndLoraSend(void) {
void CmndLoraConfig(void) {
// LoRaConfig - Show all parameters
// LoRaConfig 1 - Set default parameters
// LoRaConfig {"Frequency":868.0,"Bandwidth":125.0} - Enter float parameters
// LoRaConfig {"SyncWord":18} - Enter decimal parameter (=0x12)
if (XdrvMailbox.data_len > 0) {
if (XdrvMailbox.payload == 1) {
LoraDefaults();
Lora.Config();
} else {
JsonParser parser(XdrvMailbox.data);
JsonParserObject root = parser.getRootObject();
if (root) {
@ -202,6 +217,7 @@ void CmndLoraConfig(void) {
Lora.Config();
}
}
}
ResponseCmnd(); // {"LoRaConfig":
ResponseAppend_P(PSTR("{\"" D_JSON_FREQUENCY "\":%1_f"), &Lora.frequency); // xxx.x MHz
ResponseAppend_P(PSTR(",\"" D_JSON_BANDWIDTH "\":%1_f"), &Lora.bandwidth); // xxx.x kHz