SoftwareTimer Wisblock

Hi. Need some help to set the timer to > 1hour. It’s a limitation somewhere ?
Our Heavy machinery position don’t need to be checked every ~1h, maybe daily/weekly/… so,
the q. is: How I can increase the periodical running task time ?

I Should to use something else to manage this large data update period ?

Thank for all your suggestions, I’ll need them !

/// I made some tests using the folowing code from this forum:

#include <Arduino.h>
#include <SPI.h>


bool initMsg = true;

/* Time the device is sleeping in milliseconds = 2 minutes * 60 seconds * 1000 milliseconds */
#define SLEEP_TIME 7200000    // 2h

extern SemaphoreHandle_t loraEvent;

// Main loop stuff
void periodicWakeup(TimerHandle_t unused);
extern SemaphoreHandle_t taskEvent;
extern uint8_t rcvdDataLen;
extern uint8_t eventType;

/** Semaphore used by events to wake up loop task */
SemaphoreHandle_t taskEvent = NULL;

/** Timer to wakeup task frequently and send message */
SoftwareTimer taskWakeupTimer;

void periodicWakeup(TimerHandle_t unused)
{
  // Give the semaphore, so the loop task will wake up
  xSemaphoreGiveFromISR(taskEvent, pdFALSE);
}

void setup(void)
{
  time_t serial_timeout = millis();
  Serial.begin(115200);
  while (!Serial)
  {
    if ((millis() - serial_timeout) < 5000)
    {
            delay(100);
        }
        else
        {
            break;
        }
  }
  Serial.println("RAK Init => OK");

  
  // Create the LoRaWan event semaphore
  taskEvent = xSemaphoreCreateBinary();
  // Initialize semaphore
  xSemaphoreGive(taskEvent);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_CONN, OUTPUT);
  digitalWrite(LED_CONN, LOW);
  digitalWrite(LED_BUILTIN, LOW);
  xSemaphoreTake(taskEvent, 10);
  taskWakeupTimer.begin(SLEEP_TIME, periodicWakeup);
  taskWakeupTimer.start();
}
void loop(void)
{
  // Try getting the semaphore, sleep while doing that
  if (xSemaphoreTake(taskEvent, portMAX_DELAY) == pdTRUE || initMsg)
  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    Serial.println("***");
    
    digitalWrite(LED_BUILTIN, LOW);

    initMsg = false;
    // Go back to sleep
    xSemaphoreTake(taskEvent, 10);
  }
}

What i’m doing wrong ?
got always 1h max !

i cant be smart be smart to all tech q.

Hello Zoltan,

There is an overflow in the SoftwareTimer class. I can confirm that the timer is triggered every 50 minutes, even if the value is set to 2 hours.

I avoid using the SoftwareTimer in my own applications and use instead my own timer functions like this:

// Define alternate pdMS_TO_TICKS that casts uint64_t for long intervals due to limitation in nrf52840 BSP
#define mypdMS_TO_TICKS(xTimeInMs) ((TickType_t)(((uint64_t)(xTimeInMs)*configTICK_RATE_HZ) / 1000))

void api_timer_init(void)
{
	g_task_wakeup_timer = xTimerCreate(NULL, mypdMS_TO_TICKS(g_lorawan_settings.send_repeat_time), true, NULL, periodic_wakeup);
}

/**
 * @brief Start the timer for frequent sending
 * 
 */
void api_timer_start(void)
{
	if (isInISR())
	{
		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
		xTimerChangePeriodFromISR(g_task_wakeup_timer, mypdMS_TO_TICKS(g_lorawan_settings.send_repeat_time), &xHigherPriorityTaskWoken);
		xTimerStartFromISR(g_task_wakeup_timer, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	}
	else
	{
		xTimerChangePeriod(g_task_wakeup_timer, mypdMS_TO_TICKS(g_lorawan_settings.send_repeat_time), 0);
		xTimerStart(g_task_wakeup_timer, 0);
	}
}

/**
 * @brief Stop the timer for frequent sending
 * 
 */
void api_timer_stop(void)
{
	// g_task_wakeup_timer.stop();
	if (isInISR())
	{
		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
		xTimerStopFromISR(g_task_wakeup_timer, &xHigherPriorityTaskWoken);
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
	}
	else
	{
		xTimerStop(g_task_wakeup_timer, 0);
	}
}

/**
 * @brief Restart the time with a new time
 * 
 * @param new_time 
 */
void api_timer_restart(uint32_t new_time)
{
	api_timer_stop();
	if ((g_lorawan_settings.send_repeat_time != 0) && (g_lorawan_settings.auto_join))
	{
		// g_task_wakeup_timer.setPeriod(new_time);
		// g_task_wakeup_timer.start();

		if (isInISR())
		{
			BaseType_t xHigherPriorityTaskWoken = pdFALSE;
			xTimerChangePeriodFromISR(g_task_wakeup_timer, mypdMS_TO_TICKS(new_time), &xHigherPriorityTaskWoken);
			portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
		}
		else
		{
			xTimerChangePeriod(g_task_wakeup_timer, mypdMS_TO_TICKS(new_time), 0);
		}
	}
}

Hi Sir !
Thanks. I need some time to check your solution. I’m using 5860 with Mqtt connection what all something else what you’re practicing …

thank you Sir. Illl check tomorrow !