From 03cf7dc460195f0525f001cbaf8ad4cf2c7739b4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:02:44 +0100 Subject: [PATCH] Fix ESP32 LoRaWanBridge OTAA --- .../xdrv_73_3_lora_sx126x.ino | 68 +++++++++++++++---- .../xdrv_73_3_lora_sx127x.ino | 16 ++--- .../xdrv_73_8_lorawan_bridge.ino | 11 ++- .../tasmota_xdrv_driver/xdrv_73_9_lora.ino | 21 +++--- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx126x.ino b/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx126x.ino index a7419884e..14c0e1842 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx126x.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx126x.ino @@ -26,10 +26,24 @@ * - Lora_DI1 \*********************************************************************************************/ +//#define USE_LORA_SX126X_DEBUG + #include SX1262 LoRaRadio = nullptr; // Select LoRa support -void LoraOnReceiveSx126x(void) { +bool LoraSx126xBusy(void) { + // This is not consistently implemented in the used library + uint32_t timeout; + SetNextTimeInterval(timeout, 100); + while ((1 == digitalRead(Pin(GPIO_LORA_BUSY))) && !TimeReached(timeout)) { + delay(0); + } + return TimeReached(timeout); +} + +/*********************************************************************************************/ + +void LoraSx126xOnInterrupt(void) { // This is called after EVERY type of enabled interrupt so chk for valid receivedFlag in LoraAvailableSx126x() if (!Lora.sendFlag && !Lora.receivedFlag && !Lora.receive_time) { Lora.receive_time = millis(); @@ -37,17 +51,34 @@ void LoraOnReceiveSx126x(void) { Lora.receivedFlag = true; // we got a packet, set the flag } -bool LoraAvailableSx126x(void) { - if (Lora.receivedFlag && Lora.sendFlag) { +bool LoraSx126xAvailable(void) { + if (Lora.sendFlag) { Lora.receivedFlag = false; // Reset receive flag as it was caused by send interrupt + + uint32_t time = millis(); + int state = LoRaRadio.startReceive(); // Put module back to listen mode Lora.sendFlag = false; - LoRaRadio.startReceive(); // Put module back to listen mode - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("S6X: Receive restarted")); + if (state != RADIOLIB_ERR_NONE) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("S6X: Rcvd (%d) restarted (%d)"), time, state); + } + } + else if (Lora.receivedFlag) { + uint32_t irq_stat = LoRaRadio.getIrqStatus(); + +#ifdef USE_LORA_SX126X_DEBUG + if (irq_stat != 0) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("S6X: Flag (%d) irq %04X"), millis(), irq_stat); + } +#endif // USE_LORA_SX126X_DEBUG + + if (0 == (irq_stat & RADIOLIB_SX126X_IRQ_RX_DONE)) { + Lora.receivedFlag = false; // Reset receive flag + } } return (Lora.receivedFlag); // Check if the receive flag is set } -int LoraReceiveSx126x(char* data) { +int LoraSx126xReceive(char* data) { Lora.receivedFlag = false; // Reset flag int packet_size = LoRaRadio.getPacketLength(); int state = LoRaRadio.readData((uint8_t*)data, TAS_LORA_MAX_PACKET_LENGTH -1); @@ -66,19 +97,28 @@ int LoraReceiveSx126x(char* data) { return packet_size; } -bool LoraSendSx126x(uint8_t* data, uint32_t len, bool invert) { - Lora.sendFlag = true; // Use this flag as LoRaRadio.transmit enable send interrupt +bool LoraSx126xSend(uint8_t* data, uint32_t len, bool invert) { + int state1 = RADIOLIB_ERR_NONE; + int state2 = RADIOLIB_ERR_NONE; if (invert) { - LoRaRadio.invertIQ(true); + LoRaRadio.standby(); + state1 = LoRaRadio.invertIQ(true); + LoraSx126xBusy(); } int state = LoRaRadio.transmit(data, len); + Lora.sendFlag = true; // Use this flag as LoRaRadio.transmit enable send interrupt if (invert) { - LoRaRadio.invertIQ(false); + LoraSx126xBusy(); + state2 = LoRaRadio.invertIQ(false); + LoRaRadio.standby(); + } + if (state != RADIOLIB_ERR_NONE || state1 != RADIOLIB_ERR_NONE || state2 != RADIOLIB_ERR_NONE) { + AddLog(LOG_LEVEL_DEBUG, PSTR("S6X: Send error %d %d %d"), state1, state, state2); } return (RADIOLIB_ERR_NONE == state); } -bool LoraConfigSx126x(void) { +bool LoraSx126xConfig(void) { LoRaRadio.setCodingRate(LoraSettings.coding_rate); LoRaRadio.setSyncWord(LoraSettings.sync_word); LoRaRadio.setPreambleLength(LoraSettings.preamble_length); @@ -97,11 +137,11 @@ bool LoraConfigSx126x(void) { return true; } -bool LoraInitSx126x(void) { +bool LoraSx126xInit(void) { 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(LoraSettings.frequency)) { - LoraConfigSx126x(); - LoRaRadio.setDio1Action(LoraOnReceiveSx126x); + LoraSx126xConfig(); + LoRaRadio.setDio1Action(LoraSx126xOnInterrupt); if (RADIOLIB_ERR_NONE == LoRaRadio.startReceive()) { return true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx127x.ino b/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx127x.ino index ce86c7e5f..f34a1d609 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx127x.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_73_3_lora_sx127x.ino @@ -29,7 +29,7 @@ #include // extern LoRaClass LoRa; -void LoraOnReceiveSx127x(int packet_size) { +void LoraSx127xOnReceive(int packet_size) { // This function is called when a complete packet is received by the module #ifdef USE_LORA_DEBUG // AddLog(LOG_LEVEL_DEBUG, PSTR("S7X: Packet size %d"), packet_size); @@ -41,11 +41,11 @@ void LoraOnReceiveSx127x(int packet_size) { Lora.packet_size = packet_size; // we got a packet, set the flag } -bool LoraAvailableSx127x(void) { +bool LoraSx127xAvailable(void) { return (Lora.packet_size > 0); // check if the flag is set } -int LoraReceiveSx127x(char* data) { +int LoraSx127xReceive(char* data) { int packet_size = 0; while (LoRa.available()) { // read packet up to LORA_MAX_PACKET_LENGTH char sdata = LoRa.read(); @@ -59,7 +59,7 @@ int LoraReceiveSx127x(char* data) { return packet_size; } -bool LoraSendSx127x(uint8_t* data, uint32_t len, bool invert) { +bool LoraSx127xSend(uint8_t* data, uint32_t len, bool invert) { if (invert) { LoRa.enableInvertIQ(); // active invert I and Q signals } @@ -73,7 +73,7 @@ bool LoraSendSx127x(uint8_t* data, uint32_t len, bool invert) { return true; } -bool LoraConfigSx127x(void) { +bool LoraSx127xConfig(void) { LoRa.setFrequency(LoraSettings.frequency * 1000 * 1000); LoRa.setSignalBandwidth(LoraSettings.bandwidth * 1000); LoRa.setSpreadingFactor(LoraSettings.spreading_factor); @@ -98,11 +98,11 @@ bool LoraConfigSx127x(void) { return true; } -bool LoraInitSx127x(void) { +bool LoraSx127xInit(void) { LoRa.setPins(Pin(GPIO_LORA_CS), Pin(GPIO_LORA_RST), Pin(GPIO_LORA_DI0)); if (LoRa.begin(LoraSettings.frequency * 1000 * 1000)) { - LoraConfigSx127x(); - LoRa.onReceive(LoraOnReceiveSx127x); + LoraSx127xConfig(); + LoRa.onReceive(LoraSx127xOnReceive); LoRa.receive(); return true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_73_8_lorawan_bridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_73_8_lorawan_bridge.ino index e00fac085..2177b43e3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_73_8_lorawan_bridge.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_73_8_lorawan_bridge.ino @@ -18,8 +18,8 @@ * which makes the use of single fixed frequency and spreadingfactor hardware like * SX127x (LiliGo T3, M5 LoRa868 or RFM95W) or SX126x (LiLiGo T3S3) a challenge. * This driver uses one fixed frequency and spreadingfactor trying to tell the End-Device to do - * the same. In some cases the End-Device needs to be (serial) configured to use a single - * channel and fixed datarate. + * the same using Over The Air Activation (OTAA). In some cases the End-Device needs to be + * (serial) configured to use a single channel and fixed datarate. * * To be able to do this: * - Tasmota needs a filesystem to store persistent data (#define USE_UFILESYS) @@ -152,21 +152,18 @@ void LoraWanTickerSend(void) { if (1 == Lorawan.send_buffer_step) { Lorawan.rx = true; // Always send during RX1 Lora.receive_time = 0; // Reset receive timer - LoraWan_Send.attach_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms + LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms } if (Lorawan.rx) { // If received in RX1 do not resend in RX2 LoraSend(Lorawan.send_buffer, Lorawan.send_buffer_len, true); } - if (Lorawan.send_buffer_step <= 0) { - LoraWan_Send.detach(); - } } void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) { memcpy(Lorawan.send_buffer, buffer, sizeof(Lorawan.send_buffer)); Lorawan.send_buffer_len = len; Lorawan.send_buffer_step = 2; - LoraWan_Send.attach_ms(lorawan_delay - TimePassedSince(Lora.receive_time), LoraWanTickerSend); + LoraWan_Send.once_ms(lorawan_delay - TimePassedSince(Lora.receive_time), LoraWanTickerSend); } /*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/tasmota_xdrv_driver/xdrv_73_9_lora.ino b/tasmota/tasmota_xdrv_driver/xdrv_73_9_lora.ino index d0b483b70..effe5e739 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_73_9_lora.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_73_9_lora.ino @@ -252,6 +252,7 @@ void LoraInit(void) { #endif // ESP8266 #ifdef ESP32 SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1); +// SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); #endif // ESP32 #ifdef USE_LORAWAN_BRIDGE @@ -266,11 +267,11 @@ void LoraInit(void) { #ifdef USE_LORA_SX127X else if (PinUsed(GPIO_LORA_DI0)) { // SX1276, RFM95W - if (LoraInitSx127x()) { - Lora.Config = &LoraConfigSx127x; - Lora.Available = &LoraAvailableSx127x; - Lora.Receive = &LoraReceiveSx127x; - Lora.Send = &LoraSendSx127x; + if (LoraSx127xInit()) { + Lora.Config = &LoraSx127xConfig; + Lora.Available = &LoraSx127xAvailable; + Lora.Receive = &LoraSx127xReceive; + Lora.Send = &LoraSx127xSend; strcpy_P(hardware, PSTR("SX127x")); Lora.present = true; } @@ -279,11 +280,11 @@ void LoraInit(void) { #ifdef USE_LORA_SX126X else if (PinUsed(GPIO_LORA_DI1) && PinUsed(GPIO_LORA_BUSY)) { // SX1262, LilyGoT3S3 - if (LoraInitSx126x()) { - Lora.Config = &LoraConfigSx126x; - Lora.Available = &LoraAvailableSx126x; - Lora.Receive = &LoraReceiveSx126x; - Lora.Send = &LoraSendSx126x; + if (LoraSx126xInit()) { + Lora.Config = &LoraSx126xConfig; + Lora.Available = &LoraSx126xAvailable; + Lora.Receive = &LoraSx126xReceive; + Lora.Send = &LoraSx126xSend; strcpy_P(hardware, PSTR("SX126x")); Lora.present = true; }