Limitations on RUI3 Timers

I am using a RAK4631 with RUI 4.1.0 on a RAK19001 board for my application. I was able to do most of the work, then I tried to reduce the power usage and started to sleep the processor when not in use. I have utilized timers for everything to make the application event driven. There is basically no code in the loop, just the api.system.sleep.all();.

I have noticed I can use LoRaWAN or a 50ms timer without much issue, when I use both and try to sleep, there isn’t much reduction in power usage. After looking around a bit, I noted the processor is waking up what seems to be about every 3ms and every so often, a timer event is delayed long enough to consider it a “missed” event.

When I change the timer to 1000ms, the processor does not wake up nearly as often, but I still notice it wakes again about 3ms after the 1000ms has completed.

The LoRaWAN checkin is triggered from the 50ms timer once every 60 minutes. Not sure what timers it is using internally.

Are there limitations on the timers I should be aware? I am assuming this is not an RUI limitation but rather an issue with the nRF52840 CPU.

Hi @ksadowski ,

Thanks for providing the details. I haven’t checked the details of the timer. @beegee has more experience on it and created event driven libraries for RUI3.

However, if you can share me the code you use to measure current consumption and timing measurement, I can try to replicate it in my own setup and report it to the team if it there is timing related issue. Btw, how do you measure 3ms discrepancy? Did you use oscilloscope/logic analyzer via IO pin? Print it out via serial? If you need 3ms precision timing, I am not sure if using RUI3 is a good idea. Unless of you are only that without any LoRa/LoRaWAN/BLE stack running.

The setup is fairly simple. Starting with a basic LoRaWAN configuration, I added the timer in setup() and I toggle a GPIO pin in both the timer handler and the loop.

In setup()

  // Initialize module
  Wire.begin();
	
  // setup the lora hardware
  loraSetup();
	
  // add the custom at commands
  initCustomAT();

  // create a test timer
  api.system.timer.create(RAK_TIMER_3, tHandler, RAK_TIMER_PERIODIC);
  api.system.timer.start(RAK_TIMER_3, 50, NULL);
  
  // Enable low power mode
  api.system.lpm.set(1);

Timer handler:

uint32_t tCount;
void tHandler(void *) {
  digitalWrite(LED_BLUE, HIGH);
  // take some time so we can see the pin toggle
  for(int x=0; x < 1000; x++) tCount++;
  digitalWrite(LED_BLUE, LOW);
}

And in the loop:

void loop()
{
  digitalWrite(LED_GREEN, LOW);
	api.system.sleep.all();
	// api.system.scheduler.task.destroy();
  digitalWrite(LED_GREEN, HIGH);
}

I then look at the pins on a scope. Top trace is the loop, bottom trace is the timer handler. This first capture shows when the device transitions to successfully joining the network. Note how both pins are toggles every ~50ms. Then once joined, the loop is waking up more often than what I would expect. This does not appear to settle down after waiting 5+minutes. Note this pattern appears to repeat in the top trace.

This next image is zoomed in to show the ~3ms wake up I am seeing on the loop. It is the same capture, just zoomed in.

For this application I am looking to use the 50ms timer. I have no idea where the 3ms wakeup is coming from. At this point of the application, the only thing that should be running is the 50ms timer. I am not using BLE and the LoRa module should be sleeping as all traffic on the LoRa stack is completed (Class A).

No explanation, just a limitation (for now)

Running some tests with a timer and api.system.scheduler.task.destroy(); in the loop() to kill the loop() forever.

Down to a 110ms timer interval, the system behaves as expected.

Starting with ~100ms (and below) timer interval the system seems to call the timer callback multiple times.

Between end of timer callback and start to deep sleep is a 6ms delay with a single current peak in the middle. This could be the “delay” caused by RUI3 to prepare the system to go into deep sleep (need clarification)

1 Like

That is what I am seeing here. Thank you for your help on this.

Based on how the timers work, it looks like I can’t utilize timers below 110ms. That is good to know. I will design around it.

Thanks again for your help.