I'm trying to implement LoRa communications using an SX1276 module (DRF1276G) and an ATmega328P on a custom PCB. I've got it mostly working but I'm having a strange issue with the timeout interrupt. I've set it to use RX-Single mode, with a timeout for the full 1023-symbols, but SOMETIMES it times out before that.

EDIT: Note that for the tests i've shown below, SF=7 and BW=125kHz, so the symbol period is ~1.02ms, so timeout window should be ~1043ms. The reported timeout window in the screenshots in only an approximation, as i'm dividing these values with integers. No floating-points here. But you can assume that if it's something like 643ms or 27ms, it is a shorter amount of time before the timeout flag fired.

See the image below, where 1023 symbols is indicated by it taking "~1026 ms" to time out. Anything much less than that amount of time is a shorter period for the receive-function to return, indicated the RX-timeout flag was fired before the expected 1023sym/"~1026ms" window. [EDIT: Please ignore the "TX..." text, the program doesn't actually transmit anything, i just forgot to change that in my print-out]

enter image description here

My test setup is simply listening for incoming packets. No packets are being transmitted.

ONE TIME ONLY, in the (i'm estimating) 4 hours of total run-time of these boards, this happened...

enter image description here

Here's a summary of my testing:

  • It happens on all my devices, so its not faulty hardware
  • Testing Dragino boards in the same environment, the Draginos work perfectly. Indicates it's not environment noise/transmissions (though the Draginos use RX-continuous mode not RX-single).
  • A program to output RSSI readings shows a constant ~-100dBm output. Doesn't look like it's environment noise.
  • Adding 5-second delays between receive-function calls doesn't help.
  • Changing settings such as data rate, frequency, coding rate, sync word, preamble length etc. don't affect its behaviour.
  • Testing multiple power configurations and CRO testing show's it's not a power issue.
  • Testing showed it's not noise on the SPI bus causing wrong reads of the interrupt flag register.

Googling hasn't yielded any answers, and the only thing in the datasheet I have to go off is the following snippet...

enter image description here

Thing is, I'm not transmitting anything for it to pick up.

Here is the relevant code.

Main loop

// main loop
while(1) {  
    rxPktNo = sx127X_RxPacket((uint8_t *)localDataBuffer);

    USARTSendString("timeout: ~");

    // if data was received, print stuff
    if (rxPktNo) {

Receive Routine

/* ------------------------------------------/
    Set to single receive mode and poll for 
    the reception of a single packet of data.
    Upon reception write data from FIFO 
    buffer to the given array.
uint8_t sx127X_RxPacket(uint8_t* dataPtr) {
    uint8_t var = 0; // dual-purpose variable
    uint8_t returnValue = 0;

    // Enter standby mode

    // Configure for RX if not done already
    if (rxtxConfig != CONFIGGED_FOR_RX) {

    // Poll for RX-ongoing status, wait till stopped
    //while (sx127X_SPIReadReg(LR_RegModemStat) & 0x04);

    // Clear interrupts

    // Set to receive mode

    // Start timer
    TCNT1 = 0;

    // Poll for timeout, sx127x will go to MODE_STDBY upon timeout
    while (!(sx127X_SPIReadReg(LR_RegIrqFlags) & 0x80)) {

        // Poll for the RX-done flag
        if (sx127X_SPIReadReg(LR_RegIrqFlags) & 0x40) {

            // Read starting address of the last received packet...
            var = sx127X_SPIReadReg(LR_RegFifoRxCurrentaddr);
            // ... Write it to the address pointer for the FIFO buffer
            sx127X_SPIWriteReg(LR_RegFifoAddrPtr, var);

            // Retrieve packet size of last received packet
            var = sx127X_SPIReadReg(LR_RegRxNbBytes);

            // Use packet size and FIFO to read RX packet
            sx127X_SPIBurstRead(LR_RegFifo, dataPtr, var);

            // If successfully retrieved a packet, return true with number of bytes
            returnValue = var;
    // give timer value to global variable
    lastTimeoutDuration = TCNT1;

    // If no packet has been retrieved this call return false
    return returnValue;


/* -------------------------------------------------------- /
  Configuration settings common to both the receiver and 
  transmitter modes of operation.
  ------------------------------------------------------- */ 
void sx127X_ConfigCommon(void) {
    /*------------ Hardware Settings ------------*/
    // Set the access-shared-registers mode
    // Set low or high frequency mode
    // Set either PA_RFO (+14dB) or PA_BOOST (+20dB)
    // Set the output power in dBm (PA_BOOST 2 to 17)
    // Set the PA ramp-up time
    // Set overload current protection
    // Set overload current protection limit
    // Set the low noise amp gain
    // set LNA boost for low frequency
    // set LNA boost for high frequency
    // Set LNA gain manual or auto

    /*----------- Communication Settings -----------*/
    // Set base frequency (channel) of the LoRa module
    // Set the data rate (bandwidth and spreading factor) of the LoRa module
    // Set the coding rate of the LoRa module
    // Set the toggle for implicit header
    sx127X_setImplHeaderMode(IHM_OFF); // Explicit
    // Set TX continuous mode on or off(normal/packet mode)
    // Set RX payload CRC mode on or off
    // Set the RX symbol timeout in symbols
    // Set preamble length in symbols
    // Set the payload length in bytes
    sx127X_setPayloadLength(0x01); // default
    // Set payload maximum length in bytes
    // Set the frequency hopping period (0=disable)
    // Set Sync Word
    // Select inversion of I and Q signals

/* -------------------------------------------------------- /
  Configure the sx127x module for receiver operation.
  Use entire FIFO.
  ------------------------------------------------------- */
void sx127X_ConfigRX(void) {
    uint8_t addr;
    // Set DIO0 for the RX done flag
    sx127X_SPIWriteReg(REG_LR_DIOMAPPING1, 0x00);
    // Set interrupt mask for RX timeout and RX done
    sx127X_SPIWriteReg(LR_RegIrqFlagsMask, 0x3F);

    // Set the RX base address to bottom of FIFO
    sx127X_SPIWriteReg(LR_RegFifoRxBaseAddr, 0x00);
    // Set address pointer to bottom of FIFO as well
    sx127X_SPIWriteReg(LR_RegFifoAddrPtr, 0x00);

    // locally store RX mode config flag
    rxtxConfig = CONFIGGED_FOR_RX;

If anyone knows what the issue might be, or can give me more ideas to test, it would be much appreciated.

  • \$\begingroup\$ it is unclear how the first image proves that a timeout occurred before 1023 symbols were received \$\endgroup\$
    – jsotola
    Sep 27, 2018 at 1:37
  • \$\begingroup\$ Thanks for the comment. I'll edit it to make it more clear. Essentially, the timeout window is 1023 symbols, which at the data rate for that time of testing was about ~1100ms (says ~1027 but thats because of my integer divisor in the calculation). Anything less than that time is a shorter window than the full 1023 symbols. \$\endgroup\$
    – Joe
    Sep 27, 2018 at 1:41
  • \$\begingroup\$ it is quite possible that the LoRa module "thinks" that it has received 1023 symbols \$\endgroup\$
    – jsotola
    Sep 27, 2018 at 1:49
  • \$\begingroup\$ It doesn't look for 1023 symbols. The '1023 symbols' is the length of its timeout window for reception of symbols. The symbol rate (and hence 1023 symbols) is dependent on the data rate (spreading factor (SF) and bandwidth (BW)). In the tests I've shown above, SF=7 and BW=125kHz, so the symbol period is ~1.02ms, so timeout window should be ~1043ms. \$\endgroup\$
    – Joe
    Sep 27, 2018 at 1:55
  • \$\begingroup\$ It looks like your code would declare a "timeout" if it actually receives something that looks like a packet, either yours, or someone else's on the shared band, or even by misinterpreting noise. \$\endgroup\$ Sep 27, 2018 at 4:45


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.