LMiC's TX_COMPLETE event takes 20-30 seconds to fire

What I meant was that, if you tell LMIC to transmit a packet shortly after a previous packet (e.g. when the duty cycle limitation from that previous packet is still preventing TX), then that duty cycle limitation will indeed delay TX_COMPLETE (but not from the duty cycle delay after the next packet, but before the next packet). This is not something that I think should change.

What you’d want to do in this case is sleep until the TX time has approached. LMIC does not currently offer a solid API to get at this info. Until this is changed, you could:

  • Detect that TX is delayed by checking LMIC.opmode for the OP_TXRXPEND (or something similar, didn’t check just now) bit. If it is set, TX is happening, if it is unset (after queueing a packet), LMIC is waiting for airtime to become available. In the latter case, you could cancel your packet, sleep for some time and try again, until you eventually see the TXRXPEND bit set. I’m using this approach in a sketch I’m using.
  • In addition to the above, you could pry in LMIC’s list of “osjobs” to see when the next job is pending, and sleep that long. In either case, you’ll have to make sure that the micros() counter is updated through sleep, which does not normally happen on AVR.

Thinking of the latter, the fact that micros() does not update might even be the cause of your problem in the first place: you queue a new packet after the duty cycle delay is over, but because you’ve been sleeping, LMIC doesn’t know that time has passed. Ideally, the micros() counter would be adapted to compensate for the sleep time which requires some changing some global variable internal to the Arduino code, but that might not be so portable. I wonder if Arduino should get a API to do this instead…

I’m planning to change this in the LMIC library, see this comment about what I’m planning to change if you want to do this now (to save these 3 seconds of “safety zone”).