The LoRa Developer Forum is now in read-only mode and new content will not be added.
Semtech, in its commitment to enhance user experience and streamline content, has successfully integrated the LoRa Developer Portal content into Semtech.com. As a result of this consolidation effort, the LoRa® Developer Portal Forum will be discontinued on May 1st. After this date, you will be automatically redirected to Semtech.com.
For any technical support related to LoRa, please feel free to reach out to our experts here. If you have sales inquiries, please contact us here.

FORUM

LoRa transmission failure

Hello,
I have a problem with the LoRa transmission: I’m using the Heltec LoRa32 V2 module, that includes Semtech SX1276 LoRa module, for a few applications in a farm network. The network is constructed from central monitor that polls few remote units; between transmissions the ESP32 go into deep sleep, while the SX1276 doesn’t.

Based on the deep-sleep, transmit and receive examples from Heltec’s LoRa for ESP32 library I prepared a mid-level library that includes the code from the example after enhancing its robustness. I also created new myBegin, myEndPacket and myWrite methods in Heltec’s LoRa library based on the original methods with modifications in the same sense.

The problem is that the transmission is not completed. I found that the loop in myEndPacket method (based on Heltec’s library’s endPacket), that checks IRQ_TX_DONE_MASK (0x8) bit of REG_IRQ_FLAGS was stuck. I added [email protected] 100 mSec timeout to solve it, so it does not stuck any more but the transmission keeps failing.

By the way - to my opinion the library contains few conflicts to DX1276 datasheet (rev. 7 - May 2020). I looked only for these values – I don’t know if these conflicts are in the library or in the datasheet.

on page 96 of the datasheet address 0x12 is of the RegRxBw, and bit #3 is the LSB of  RxBwMant; while on page 104 it is written that bit #3 of REG_IRQ_FLAGS2 (0x3f) is PacketSent, which seems to be the correct value. I tested both registers with the same result.
The LoRa library uses two RX mode equates - MODE_RX_CONTINUOUS (0x05) and MODE_RX_SINGLE (0x06). However, 0x06 is defined in the datasheet as reserved.

Debugging experiments:

  1.  Return to the deep sleep example structure, where all the code is in the setup method, with the same results.
    
  2.  Replacement of the HW module with another one.
    
  3.  Inserting a Heltec's ESP32 Wireless sticks module.
    
  4.  Inserting a Heltec's ESP32 Wireless sticks module.
    
  5.  Enhancing the loop timeout to a whole second.
    
  6.  Assuming that I may have an error in the modifications, I tried removing the modifications while keeping the framework:
    

a. I checked all the mid-level code, emphasizing the modifications.
b. In the myWrite the modification is only changing input parameter dimensions to String, to adapt it to all other places. No logic implications.
c. In myEndPacket the modifications are: (1) added timeout to the blocking loop; (2) added success/fail feedback
d. In myBegin I added the following lines:
· setPreambleLength(8);
· setCodingRate4(5);
· writeRegister(REG_DIO_MAPPING_1, 0x3f); // Setting SX1276 GPIO1/2/3 to 3state to
// prevent HW collision With ESP32 GPIOs

The printout; the comments indicate the source of the levels that submitted the messages -
LК?⸮⸮V (⸮⸮d78⸮ ⸮ // This unreadable data is assumed to be printed during the Serial.begin
// required by the deep sleep mode. Is there any way to get rid of it?

Data is good // High level - setup
Wakeup caused by timer. // High level - identifying the wake up source
Transmit Monitor Command: 010YL000000 // High level – reported by TransmitMonitorCommand, called by the loop
myWrite OK // mid level - reported by LoRaTx
Delay: 100; irqFlags2(0x3f)= 0 // Low level - reported by myEndPacket
Transmission failed // High level - reported by the loop
Set delay for 5.10 Seconds, and Go to sleep // High level - reported by the loop , before going to deep sleep mode

Well, after all this long story: any idea to solve?

Best regards
OC
.

The code runs on three levels: main loop is the high level, mid level and the original library.

/**************** High level ***************************************/

bool TransmitMonitorCommand()
{
String TxRadioMessage = “01000000000”;
MessageID++;
if(MessageID > 126)
MessageID = 33;
TxRadioMessage[messageId] = MessageID;
TxRadioMessage[messageLength] = TxRadioMessage.length() + 0x41;
Serial.println("Transmit Monitor Command: " + TxRadioMessage);
return LoRaAdd.LoRaTx(TxRadioMessage);
}
/*************** High level *******************************/

void loop()
{
pinMode(RtcIrqGPIO, INPUT);
pinMode(ConsumptionSensor, INPUT);
pinMode(DIO0, INPUT);

//=============== Identify the wakeup reason for ESP32
int wakeup_reason = (int)esp_sleep_get_wakeup_cause();

/*/=============== ESP SLEEP WAKEUP by timer
if(wakeup_reason == ESP_SLEEP_WAKEUP_TIMER)
{
Serial.println(“Wakeup caused by timer.”);
// The timer wake up is in the monitor station; transmit commands to the field units
if(TransmitMonitorCommand())
{
Serial.println(“Transmitted successfully”);
getResponse();
}
else
Serial.println(“Transmission failed”); // The problem is being reported here
}

else Serial.println(“Wrong wake-up reason”);

//=============== Prepare the next deep sleep
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // Time base
Serial.println("Set delay for " + String(TIME_TO_SLEEP) + " Seconds, and Go to sleep ");
Serial.flush();
esp_deep_sleep_start();
}

/***************/

bool TransmitMonitorCommand()
{
String TxRadioMessage = “01000000000”;
MessageID++;
if(MessageID > 126)
MessageID = 33;
TxRadioMessage[messageId] = MessageID;
TxRadioMessage[messageLength] = TxRadioMessage.length() + 0x41; Make the length readable
Serial.println("Transmit Monitor Command: " + TxRadioMessage);
return LoRaAdd.LoRaTx(TxRadioMessage);
}

/**************** Mid level ***************************************/

bool LoRaAddClass::LoRaTx(String TxMessage)
{
if(TxMessage.length() < valueStart)
return false;
LoRa.beginPacket(0); // The parameter is to ensure explicit mode
int transmitted = LoRa.myWrite(TxMessage);
if(transmitted != TxMessage.length())
{
#ifdef LoRaVerbose
Serial.println("myWrite transmitted " + String(transmitted) +
" instead of " + String(TxMessage.length()));
#endif
return 0;
}
#ifdef LoRaVerbose
Serial.println(“myWrite OK”);
#endif
bool txSuccess = LoRa.myEndPacket();
LoRa.receive(1); // go back into receive mode
return txSuccess;
}
/**************** Low level ***************************************/

bool LoRaClass::myEndPacket()
{
// Modifications to the original endPacket method:
// (a) added timeout;
// (b) added transmission success feedback to mid level

// put in TX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);

long timeout = millis();
// wait for TX done with timeout
while (((readRegister(REG_IRQ_FLAGS2) & IRQ_TX_DONE_MASK) == 0) &&
((millis() - timeout) < TxTimeout))
yield();
Serial.println("Delay: " + String(millis() - timeout) + "; irqFlags2(0x3f)= " + String(readRegister(REG_IRQ_FLAGS2)));
bool success = ((millis() - timeout) < TxTimeout); // The problem is being detected here
// clear IRQ’s
writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
return success;
}
/****************/

int8_t LoRaClass::myWrite(String bufferA)
{
// Modification - change input parameter dimensions to String, to adapt it to all other places

size_t size = TxBuffer.length();

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, TxBuffer[i]);
}

// update length
writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
return size;
}