LMIC, Lowpower Sleep and Interrupts

Hi All,

I am making a sensor for a feral pig trap for a farmer here in Australia.

It is using a Lora32u4ii with LMIC and a weather proof switch to tell me when the gate has been tripped on the trap, My idea is to attach it to Pin 2 and Ground, to send the interrupt LOW.

What I would like to happen is the node to send a heartbeat message once a day containing the voltage of the battery and a “no pig” identifier (0), and then send the voltage and a “pig” identifier (1) immediately the trap is triggered and then every hour after that (instead of the heartbeat 24hr period)

This would be very similar to a door alarm, gate open alarm etc

Can anybody point me to an example of some code that does this sort of thing please

I need some help on where to put the lowpower.powerdown call and the interrupt code.

cheers
Paul

4 Likes

In ABP mode using this worked for me
Not sure about the interrupt code

Hi Paul,

i try exacly the same like you. I want a Door Switch Alarm System via Interrupt.

I added Pin Interrupt and a WatchDog/Heartbeat. But i have still Problems to send a LoraPackage if the Door Switch changed.

(GitHub - CK1-CK/Arduino-Pro-Mini-LoRa-Sensor-Node: Arduino Pro Mini TTN LoRaWAN Node with RFM95 module battery-powered)

Maybe the code helps you to find a solution.

Welcome, please note you’ve replied to a topic that’s between 4.5 and 3.75 years old.

Is this something you need help with?

Is this something you need help with?

Thanks for your offer. I think i have to test the program detailed first .

I have added a DoorSwitch Interrupt Routine to queue a new package. But a have the feeling that the packages aren’t queued right.

void interruptDoorFunction() // Interrupt Function for DoorSwitch
{
  if ((millis() - oldTime) > debounceTime) // Debouncing Switch
  {
    door_state = digitalRead(PIN_DOOR_SWITCH);
    watchdog = 0; // Real Alarm  // Watchdog/Heartbeat, Differentiation between watchdog and real alarm.   1=WatchDogSignal 0=Real DoorAlarm

    disableDeepSleep();

    // Send Lora Package
    LoRaWANDo_send(&sendjob);

    watchdog = 1; // Reset Watchdog

    oldTime = millis(); // letzte Schaltzeit merken
  }
}

[(ttps://github.com/CK1-CK/Arduino-Pro-Mini-LoRa-Sensor-Node/blob/master/src/main.cpp)

In addition, I have the problem that I am far away from a gateway and my signal is very weak.

That’s a HUGE interrupt handler - not sure what happens to the millis interrupt and the whole timing of the LoRaWAN send.

Perhaps best to set a flag and have the main loop kick off a send and when it’s finished, reset the flag.

Sending an uplink from within the ISR is bad practice and is asking for problems.
Like @descartes mentioned, the ISR should actually not do very much more than setting a flag and then let handle the flag elsewhere in the code.

The article is 4 years old and since, important things have changed:

  • We currently use TTS V3 and no longer have TTN V2. TTS V3 requires better LoRaWAN compliance from end devices.
  • The referred ‘Classic LMIC’ library is deprecated and not LoRaWAN compliant. MCCI LMIC should be used instead.
  • It is strongly advised to use OTAA instead of ABP.

Hi thanks for advice,

  • i have shortened the Interrupt Routine and added CheckDoorStateAndSendLoraPackage() function in the loop().
  • i use the MCCI LMIC Lib in my project
  • i use OTAA for activation and key transfer.

Do you know, is there a possibility to list or view all queued packages? In the event of a door alarm, I would like to empty the queue and requeue my new Lora-Package.

void interruptDoorFunction() // Interrupt Function for DoorSwitch
{

  if ((millis() - oldTime) > debounceTime) // Debouncing/Entprellung Switch
  {
    door_state = digitalRead(PIN_DOOR_SWITCH);
    watchdog = 0;       // Real Alarm  // Watchdog/Heartbeat, Differentiation between watchdog and real alarm.   1=WatchDogSignal 0=Real DoorAlarm
    oldTime = millis(); // Remember last run time.
    
    // Debug
    // Serial.print("Interrupt Routine: DoorState: ");
    // Serial.println(door_state, DEC);
  }
}

void CheckDoorStateAndSendLoraPackage()
{
  if (watchdog == 0)
  {
    disableDeepSleep();
    
    // Send Lora Package
    LoRaWANDo_send(&sendjob);
  }
  watchdog = 1; // Reset Watchdog
}

(Arduino-Pro-Mini-LoRa-Sensor-Node/main.cpp at master · CK1-CK/Arduino-Pro-Mini-LoRa-Sensor-Node · GitHub)

I don’t think there’s really a “queue” just the possibility of being busy already handling one.

If you look at the code path through the library that’s involved in sending data, you can see the check it does to see if it’s able to. Do that check yourself before trying to send a message, and for the most part you won’t be leaving things latent.

However, there is still the issue of having network level state that needs to be exchanged first before you can send application messages - particularly if the node is not yet joined, or if there are MAC command responses that need to be sent that would bump a packet over the maximum allowed size for current settings. Generally these issues should be confined to early in the overall operation or after some major change in TTN behavior.

The internal operations of LMiC are a bit complex, and effective re-entrancy loops have historically been a concern, so you want to be sure that you’re not doing anything which could further contribute to creating such a self-blocking and re-nesting-call type of situation.

If you are anticipating multiple triggers from this door that are faster than the legal and FUP restrictions allow you to send, then you need a re-design or a different sort of transmission method.