RAK4631 + Pin Interrupt - Some Rx packets are lost

Hello friends,

I have a new question that you can help me.
I have a low power code that has 1 GPIO pin from RAK4631 attached to a Interrupt Pin from RAK1904 acelerometer (LIS3DH from ST). The acelerometer activates INT pin when feels movement in a previously configured time and force and wake up the RAK4631 to send Lora packets.

The problems it’s that if i want to send Rx packet (from Chirpstack to Wisblock sensors box) i lost some packets if the acelerometer detects two consecutive movements.
I tried to detach the pin interrupt inside the ISR and works better to don’t interrupt the loop process while it’s awake. But i still losing some packets when i recieve two consecutive movements because in the end of the loop i need to re-attach the interrupt pin to go to sleep again.

Do you recommend some way to make sure that the all Rx packets (chirpstack to wisblock sensors box) are effectively delivered?
I know that exists the lmh_send_blocking() command but my code it’s not blocking and i don’t know if exits a more effective way to achieve this and if the lmh_send_blocking() will solve my issue.

To add more information, sometimes (when i recieve two or more interrupts consecutives) the code just pass for the first lines of the function lorawan_rx_handler but dont finish all the lines of the code, because i recieve this message in serial port saying some information about the package recieved but not continues processing the Rx package in the way that was configured in lorawan_rx_handler function.

This it’s the only message that i recieve sometimes:
12:52:00.692 → LoRa Packet received on port 8, size:6, rssi:-15, snr:5

But the lorawan_rx_handler includes all this steps:

static void lorawan_rx_handler(lmh_app_data_t *app_data) {

  detachInterrupt(digitalPinToInterrupt(WB_IO6));  //Quitamos la interrupcion por vibración

  #ifndef MAX_SAVE
  Serial.printf("LoRa Packet received on port %d, size:%d, rssi:%d, snr:%d\n",
                app_data->port, app_data->buffsize, app_data->rssi, app_data->snr);
  #endif

  // Copy the data into loop data buffer
	memcpy(rx_lora_data, app_data->buffer, app_data->buffsize);

  eventType = 4;

  xSemaphoreGiveFromISR(taskEvent, pdFALSE);

}

From the code-snippet, I am guessing you build your code using the RAK4631-DeepSleep-LoRaWAN example?

Are you using Class C to receive downlinks from Chirpstack at any time, which is different to Class A which can receive only after it has sent a packet?

How often are you sending downlinks from Chirpstack? It sounds strange that you would loose incoming packets because of multiple interrupts are happening. Unless you trigger an upload immediately on every interrupt, which could lead to some problems (TX/RX cycle still active while you try to send again or RX cycle still active while you try to send again).

One option to handle external interrupts that come too fast to properly handle them would be to queue them up and handle one by one.
I did this in my RAK13011-Alarm-Msg-Queue example.
Not sure if it is easy to implement in your code, as this example is based on my WisBlock-API-V2 and you need to figure out how to do it in the deep sleep example.

Basically the RAK13011-Alarm-Msg-Queue is waiting for interrupts from an external device (RAK13011 instead of RAK1904, but basically the same). When the interrupt arrives, the status is put into a FreeRTOS queue. The loop() (in my example called 'app_event_handler`) is then woke up, checks if a TX is still in process. If not, it sends immediately, if still sending, it retries after a delay.

1-. Yes, i’m building my code using the RAK4631 DeepSleep LoRaWAN code.
2-. I’m using class A devices, so the Rx windows it’s open only in Tx events.
3-. I’m sending LoRaWAN packets in two situations: when a freefall event it’s detected by the accelerometer and when detects motion above the configured threshold. Sometimes, the motion event it’s activated two or more times consecutively, so i send multiple LoRa packets in the same second. This it’s the problem that i have, i need to discard the new motion events to send just one packet when i receive more than one. Do you know the best way to discard consecutive motion events?

4-. I will try to learn the methods of your example, very thanks.

To discard motion interrupts while sending/receiving LoRaWAN packets, you could disable the interrupt when it hits (detachInterrupt() in the interrupt handler function), then wait for the TX finished or RX finished callbacks (not sure if you trigger a downlink on every uplink) and enable the interrupt in that callback.

Or try to queue up the events, like I do the example.

1 Like

Dear Beegee,

I followed your recommendations but the problem it’s still happening. I detach the motion interrupt pin inside the ISR and only re-attach it in the last line in the loop (before go to sleep with “xSemaphoreTake(taskEvent, 10);” )
But the problem still happening, when i make a lot of motion with the Wisblock box, the system looses the Rx packets.

The “Rx handler” function can’t to run all the code inside it’s function so doesn’t process the Rx package.

I tried to watch the behavior using a Power Profiler Kit II and i can see that when i make a lot of motion, the Wisblock try to send 8 packages to the Gateway.

I think that these packages may interrupt the Rx Handler function. ¿May be it’s a problem inside the SX126x-Arduino library?
When i read the serial port, i can to see that the “Rx Handler” function was interrupted by the lmh_send result and after reports the send status, don’t go back to continue processing the Rx packet inside the “Rx handler” function.

I tried with lmh_send_blocking function, too tried with 1000 ticks instead of 10 in the last command of the loop (“xSemaphoreTake(taskEvent, 10);”) with no results. Too i tried to add a delay(10000) before go to sleep in the loop with no results.

Dear Beegee,

I found the cause of my problem: When i deleted the manual transmission retry lines in my code, the function that try to re-send a package that recieved a “lmh busy” error, the problem was solved. I still losing some packets, but about 1 from 10 or 15 situations. Without my fix all the packet was lost.

Here i share all the lines that i commented (deleted):

      case 3:  // motion wake up reason is DIO interrupt
               //Do custom processing before sending Lora

        {


          // batteryPercent = readBatteryLevel();

          // updateGpsPositionRak1910();
          if (sendLoraPackage(loraFlagsPackaged(), readBatteryLevel(), 0, 0))
          // if (sendLoRaFrame())
          {

            #ifndef MAX_SAVE
            Serial.println("Alerta de movimiento");
            Serial.println("LoRaWan package sent successfully (motion wake up) (mandamos paquete)");
            #endif
            clearAcelerometerRegistersWakeUp();
            
          } else {
            #ifndef MAX_SAVE
            Serial.println("LoRaWan package send failed (motion wake up)");
            #endif
            /// \todo maybe you need to retry here?

            // Probamos un delay de 500 y reintentamos
            // delay(1000);
            // if (sendLoraPackage(loraFlagsPackaged(), readBatteryLevel(), 0, 0)) {
            //   #ifndef MAX_SAVE
            //   Serial.println("Alerta de movimiento");
            //   Serial.println("LoRaWan package sent successfully (motion wake up) 2da vez");
            //   #endif
            //   clearAcelerometerRegistersWakeUp();
              
            // } 
            // else {
            //   #ifndef MAX_SAVE
            //   Serial.println("LoRaWan package send failed (motion wake up) 2da vez");
            //   #endif

            //   //Acá reintentamos
            //   // Probamos un delay de 500 y reintentamos
            //   delay(2000);
            //   if (sendLoraPackage(loraFlagsPackaged(), readBatteryLevel(), 0, 0)) {
            //     #ifndef MAX_SAVE
            //     Serial.println("Alerta de movimiento");
            //     Serial.println("LoRaWan package sent successfully (motion wake up) 3ra es la vencida");
            //     #endif
            //     clearAcelerometerRegistersWakeUp();
                
            //   } else {
            //     #ifndef MAX_SAVE
            //     Serial.println("LoRaWan package send failed (motion wake up) 4ta vez");
            //     #endif

            //     delay(3000);
            //     if (sendLoraPackage(loraFlagsPackaged(), readBatteryLevel(), 0, 0)) {
            //       #ifndef MAX_SAVE
            //       Serial.println("Alerta de movimiento");
            //       Serial.println("LoRaWan package sent successfully (motion wake up) 4ta es la vencida");
            //       #endif
            //       clearAcelerometerRegistersWakeUp();
                  
            //     } else {
            //       #ifndef MAX_SAVE
            //       Serial.println("LoRaWan package send failed (motion wake up) 4to intento, borramos registro igual");
            //       #endif
                  
            //       clearAcelerometerRegistersWakeUp();
            //     }
            //   }
            // }

            clearAcelerometerRegistersWakeUp();
          }

        }
        break;

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.