ESP32 Arduino FreeRTOS Software Timer

Hailwiz9
Posts: 4
Joined: Fri Mar 18, 2022 9:20 pm

ESP32 Arduino FreeRTOS Software Timer

Postby Hailwiz9 » Sun Apr 10, 2022 1:24 pm

Hello,

I was trying to learn about freeRtos but I've encountered a problem so I've decided to put up a program.

I am using platform IO
What I intend to do is this:
- We have 2 one-shot timers (I actually wanted to use more but tried with 2 after trying with 1)
- I wanted to define them as static.
- We have an eventhandler to specify when they should work (state = 1 for timer 1, state = 2 for timer 2)
- I want these timers to be stoppable at anytime (even if it doesn't reach the callback function) from another program

If I don't include the 2nd timer, the code works fine but when I include it some sort of problem occur

And also I haven't been able to use TaskScheduler the program always crashes.

Would be grateful if anybody guided me though this, thanks in advance.

What I've done so far is like below:
  1. #include <Arduino.h>
  2. #include "freertos/queue.h"
  3. #include "freertos/task.h"
  4. #include "freertos/timers.h"
  5.  
  6. // The buffer used to hold the software timer's data structure.
  7.  
  8. // Defining one second in ticks of time
  9.  
  10. #define pdSECOND pdMS_TO_TICKS(1000)
  11. #define staticDONT_BLOCK    ( ( TickType_t ) 0 )
  12.  
  13. bool progState = 0;
  14. bool relay1Control = 0;
  15. uint8_t state = 0;
  16. int j = 0;
  17. int k = 0;
  18.  
  19. static StaticTimer_t xTimerBuffer1;
  20. static StaticTimer_t xTimerBuffer2;
  21.  
  22. // Define a timer handle
  23. TimerHandle_t progTimer1;
  24. TimerHandle_t progTimer2;
  25.  
  26. StackType_t progTimer1Started;
  27. StackType_t progTimer2Started;
  28.  
  29. TickType_t remainingTime1;
  30. TickType_t remainingTime2;
  31.  
  32. TickType_t remTimeDisplay1;
  33. TickType_t remTimeDisplay2;
  34.  
  35. // The callback function upon timer exit
  36. void progTimerCallBack1( TimerHandle_t progTimer1)
  37. {
  38.     xTimerStop(progTimer1, 0);
  39.     Serial.println("Timer 1 has Ended");
  40.     progState = 0;
  41.     relay1Control = 0;
  42.     state = 0;      // If the callback function is called, the timer has ended, state should return to neutral
  43.     j = 0;
  44. }
  45.  
  46. // The callback function upon timer exit
  47. void progTimerCallBack2( TimerHandle_t progTimer2)
  48. {
  49.     xTimerStop(progTimer2, 0);
  50.     Serial.println("Timer 2 has Ended");
  51.     progState = 0;
  52.     relay1Control = 0;
  53.     state = 0;      // If the callback function is called, the timer has ended, state should return to neutral
  54.     j = 0;
  55. }
  56.  
  57. // The event handler for timer start
  58. void progTimerEventHandler(uint8_t state)
  59. {
  60.     // State == 1 conditions
  61.     if (state == 1)
  62.     {
  63.         if (progState == 0)
  64.         {    
  65.             if( progTimer1 != NULL ) // If the timer has been created
  66.             {
  67.                 progTimer1Started = xTimerStart(progTimer1, 10); // Starts the timer
  68.                 Serial.println("The Timer 1 has been issued");
  69.                 remTimeDisplay1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
  70.             }
  71.            
  72.             if (progTimer1Started == pdPASS)
  73.             {
  74.                 progState = 1;
  75.                 Serial.println("Prog 1 Timer has been scheduled !");
  76.             }  
  77.         }
  78.         if (progState != 0)
  79.         {
  80.             remainingTime1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
  81.             if (remTimeDisplay1 != remainingTime1)
  82.             {
  83.                 remTimeDisplay1 = remainingTime1;
  84.                 Serial.print("Time Remaining: ");
  85.                 Serial.println((int)remainingTime1 + 1);
  86.             }
  87.  
  88.         }
  89.          
  90.     }
  91.  
  92.     // State == 2 conditions
  93.     if (state == 2)
  94.     {
  95.         if (progState == 0)
  96.         {        
  97.             if( progTimer2 != NULL ) // If the timer has been created
  98.             {
  99.                 progTimer2Started = xTimerStart(progTimer2, 10); // Starts the timer
  100.                 Serial.println("The Timer has been issued");
  101.                 remTimeDisplay2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
  102.             }    
  103.             if (progTimer2Started == pdPASS)
  104.             {
  105.                 progState = 1;
  106.                 Serial.println("Prog 2 Timer has been scheduled !");
  107.             }        
  108.         }
  109.         if (progState != 0)
  110.         {
  111.             remainingTime2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
  112.             if (remTimeDisplay2 != remainingTime2)
  113.             {
  114.                 remTimeDisplay2 = remainingTime2;
  115.                 Serial.print("Time Remaining: ");
  116.                 Serial.println((int)remainingTime2 + 1);
  117.             }
  118.         }  
  119.     }
  120.     if (state == 0) {progState = 0;}
  121.     if (state != 1 && progTimer1Started == pdPASS)
  122.     {  xTimerStop(progTimer1, 100); progState = 0;}
  123.     if (state != 2 && progTimer2Started == pdPASS)
  124.     {  xTimerStop(progTimer2, 100); progState = 0;}
  125.    
  126.  
  127. }
  128.  
  129. // Timer with the the time info given by seconds
  130. void progTimerSet(uint16_t time1, uint16_t time2)
  131. {
  132.     progTimer1 = xTimerCreateStatic("progTimer1",             // Text name
  133.                                     (pdSECOND * (time1)),     // Timer period converted from ticks to seconds
  134.                                     pdFALSE,                  // State that the timer is one-shot
  135.                                     (void*) 1,                // ID of the timer
  136.                                     progTimerCallBack1,       // The callback func upon exit
  137.                                     &xTimerBuffer1            // The buffer that will hold software timer
  138.                                    );
  139.  
  140.     Serial.println("The initialiser of the software timer 1");
  141.  
  142.     progTimer2 = xTimerCreateStatic("progTimer2",             // Text name
  143.                                     (pdSECOND * (time2)),     // Timer period converted from ticks to seconds
  144.                                     pdFALSE,                  // State that the timer is one-shot
  145.                                     (void*) 2,                // ID of the timer
  146.                                     progTimerCallBack2,       // The callback func upon exit
  147.                                     &xTimerBuffer2            // The buffer that will hold software timer
  148.                                   );
  149.  
  150.     Serial.println("The initialiser of the software timer 2");
  151. }[/code]
  152. and the main file is as follows:
  153. [Codebox=cpp file=Untitled.cpp] #include <Arduino.h>
  154. #include "DMD_initializer.h"
  155. #include "programTimers.h"
  156.  
  157. uint16_t timeVacuum = 14;
  158. uint16_t timeAir = 10;
  159. uint8_t relay1Pin = 2;
  160.  
  161.  
  162. void setup() {  
  163.   while (!Serial){}
  164.   Serial.begin(115200);
  165.  
  166.   pinMode(relay1Pin, OUTPUT);
  167. //  DmdTimeStart();
  168.   progTimerSet(timeVacuum, timeAir); // Setting up the FreeRtos Software Timers
  169. }
  170.  
  171. void loop() {
  172.  
  173.   if (state == 1 || state == 2) {relay1Control = 1; digitalWrite(relay1Pin, HIGH);}
  174.   else if (state == 0) {relay1Control = 0; digitalWrite(relay1Pin, LOW);}
  175.  
  176.   if (state == 0)
  177.   {
  178.     vTaskDelay(pdSECOND);
  179.     Serial.print ("j: ");
  180.     Serial.print (j);
  181.     Serial.print (" ,progstate: ");
  182.     Serial.print (progState);
  183.     Serial.print (" ,state: ");
  184.     Serial.println (state);
  185.     j++;
  186.     k++;
  187.   }
  188.  
  189.   if (j == 5)
  190.   {
  191.     j++;
  192.     Serial.print ("j: ");
  193.     Serial.print (j);
  194.     Serial.print ("k: ");
  195.     Serial.print (k);
  196.     state = 2;
  197.   }
  198.  
  199.   if (k == 7)
  200.   {
  201.     j++;
  202.     Serial.print ("j: ");
  203.     Serial.print (j);
  204.     k++;
  205.     Serial.print ("k: ");
  206.     Serial.print (k);
  207.     state = 1;
  208.   }
  209.  
  210.   progTimerEventHandler(state);
  211.  
  212. }
Below is the Serial message print outs:
Image
Attachments
SerialOutput.PNG
SerialOutput.PNG (37.04 KiB) Viewed 3025 times
main.cpp
(1.15 KiB) Downloaded 311 times
programTimers.c.h
(5.45 KiB) Downloaded 331 times

username
Posts: 532
Joined: Thu May 03, 2018 1:18 pm

Re: ESP32 Arduino FreeRTOS Software Timer

Postby username » Sun Apr 10, 2022 10:13 pm

I didn't examine it to closely for other issues, but your problem is that your using the variable progState for both timers which is what is causing the problem.
You also need to add a delay in loop() or your going to cause the watch dog timer to panic.

Code: Select all

#include <Arduino.h>
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
//#include "DMD_initializer.h"
//#include "programTimers.h"

// The buffer used to hold the software timer's data structure.
 
// Defining one second in ticks of time
 
#define pdSECOND pdMS_TO_TICKS(1000)
#define staticDONT_BLOCK    ( ( TickType_t ) 0 )
 
bool progState1 = 0;
bool progState2 = 0;
bool relay1Control = 0;
uint8_t state = 0;
int j = 0;
int k = 0;
 
static StaticTimer_t xTimerBuffer1;
static StaticTimer_t xTimerBuffer2;
 
// Define a timer handle
TimerHandle_t progTimer1;
TimerHandle_t progTimer2;
 
StackType_t progTimer1Started;
StackType_t progTimer2Started;
 
TickType_t remainingTime1;
TickType_t remainingTime2;
 
TickType_t remTimeDisplay1;
TickType_t remTimeDisplay2;
 
// The callback function upon timer exit
void progTimerCallBack1( TimerHandle_t progTimer1)
{
    xTimerStop(progTimer1, 0);
    Serial.println("Timer 1 has Ended");
    progState1 = 0;
    relay1Control = 0;
    state = 0;      // If the callback function is called, the timer has ended, state should return to neutral
    j = 0;
}
 
// The callback function upon timer exit
void progTimerCallBack2( TimerHandle_t progTimer2)
{
    xTimerStop(progTimer2, 0);
    Serial.println("Timer 2 has Ended");
    progState1 = 0;
    relay1Control = 0;
    state = 0;      // If the callback function is called, the timer has ended, state should return to neutral
    j = 0;
}
 
// The event handler for timer start
void progTimerEventHandler(uint8_t state)
{
    // State == 1 conditions
    if (state == 1)
    {
        if (progState1 == 0)
        {    
            if( progTimer1 != NULL ) // If the timer has been created
            {
                progTimer1Started = xTimerStart(progTimer1, 10); // Starts the timer
                Serial.println("The Timer 1 has been issued");
                remTimeDisplay1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
            }
           
            if (progTimer1Started == pdPASS)
            {
                progState1 = 1;
                Serial.println("Prog 1 Timer has been scheduled !");
            }  
        }
        if (progState1 != 0)
        {
            remainingTime1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
            if (remTimeDisplay1 != remainingTime1)
            {
                remTimeDisplay1 = remainingTime1;
                Serial.print("Time Remaining: ");
                Serial.println((int)remainingTime1 + 1);
            }
 
        }
         
    }
 
    // State == 2 conditions
    if (state == 2)
    {
        if (progState2 == 0)
        {        
            if( progTimer2 != NULL ) // If the timer has been created
            {
                progTimer2Started = xTimerStart(progTimer2, 10); // Starts the timer
                Serial.println("The Timer has been issued");
                remTimeDisplay2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
            }    
            if (progTimer2Started == pdPASS)
            {
                progState2 = 1;
                Serial.println("Prog 2 Timer has been scheduled !");
            }        
        }
        if (progState2 != 0)
        {
            remainingTime2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
            if (remTimeDisplay2 != remainingTime2)
            {
                remTimeDisplay2 = remainingTime2;
                Serial.print("Time Remaining: ");
                Serial.println((int)remainingTime2 + 1);
            }
        }  
    }
    if (state == 0) {progState1 = 0;progState2 = 0;}
    if (state != 1 && progTimer1Started == pdPASS)
    {  xTimerStop(progTimer1, 100); progState1 = 0;}
    if (state != 2 && progTimer2Started == pdPASS)
    {  xTimerStop(progTimer2, 100); progState2 = 0;}
   
 
}
 
// Timer with the the time info given by seconds
void progTimerSet(uint16_t time1, uint16_t time2)
{
    progTimer1 = xTimerCreateStatic("progTimer1",             // Text name
                                    (pdSECOND * (time1)),     // Timer period converted from ticks to seconds
                                    pdFALSE,                  // State that the timer is one-shot
                                    (void*) 1,                // ID of the timer
                                    progTimerCallBack1,       // The callback func upon exit
                                    &xTimerBuffer1            // The buffer that will hold software timer
                                   );
 
    Serial.println("The initialiser of the software timer 1");
 
    progTimer2 = xTimerCreateStatic("progTimer2",             // Text name
                                    (pdSECOND * (time2)),     // Timer period converted from ticks to seconds
                                    pdFALSE,                  // State that the timer is one-shot
                                    (void*) 2,                // ID of the timer
                                    progTimerCallBack2,       // The callback func upon exit
                                    &xTimerBuffer2            // The buffer that will hold software timer
                                  );
 
    Serial.println("The initialiser of the software timer 2");
}
 
uint16_t timeVacuum = 14;
uint16_t timeAir = 10;
uint8_t relay1Pin = 2;
 
 
void setup() {  
  while (!Serial){}
  Serial.begin(115200);
 
  pinMode(relay1Pin, OUTPUT);
//  DmdTimeStart();
  progTimerSet(timeVacuum, timeAir); // Setting up the FreeRtos Software Timers
}
 
void loop() {
 
  if (state == 1 || state == 2) {relay1Control = 1; digitalWrite(relay1Pin, HIGH);}
  else if (state == 0) {relay1Control = 0; digitalWrite(relay1Pin, LOW);}
 
  if (state == 0)
  {
    vTaskDelay(pdSECOND);
    Serial.print ("j: ");
    Serial.print (j);
    Serial.print (" ,progstate: ");
    Serial.print (progState1);
    Serial.print (" ,state: ");
    Serial.println (state);
    j++;
    k++;
  }
 
  if (j == 5)
  {
    j++;
    Serial.print ("j: ");
    Serial.print (j);
    Serial.print ("k: ");
    Serial.print (k);
    state = 2;
  }
 
  if (k == 7)
  {
    j++;
    Serial.print ("j: ");
    Serial.print (j);
    k++;
    Serial.print ("k: ");
    Serial.print (k);
    state = 1;
  }
 
  progTimerEventHandler(state);

  delay(1);
 
}

Hailwiz9
Posts: 4
Joined: Fri Mar 18, 2022 9:20 pm

Re: ESP32 Arduino FreeRTOS Software Timer

Postby Hailwiz9 » Mon Apr 11, 2022 7:20 pm

  1. void progTimerEventHandler(uint8_t state)
  2. {
  3.     // State == 1 conditions
  4.     if (state == 1)
  5.     {
  6.         if (progState == 0)
  7.         {    
  8.             if( progTimer1 != NULL ) // If the timer has been created
  9.             {
  10.                 progTimer1Started = xTimerStart(progTimer1, 10); // Starts the timer
  11.                 Serial.println("The Timer 1 has been issued");
  12.                 remTimeDisplay1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
  13.             }
  14.            
  15.             if (progTimer1Started == pdPASS)
  16.             {
  17.                 progState = 1;
  18.                 Serial.println("Prog 1 Timer has been scheduled !");
  19.             }  
  20.         }
  21.         if (progState != 0)
  22.         {
  23.             remainingTime1 = ((xTimerGetExpiryTime(progTimer1) - xTaskGetTickCount())/pdSECOND);
  24.             if (remTimeDisplay1 != remainingTime1)
  25.             {
  26.                 remTimeDisplay1 = remainingTime1;
  27.                 Serial.print("Time Remaining: ");
  28.                 Serial.println((int)remainingTime1 + 1);
  29.             }
  30.  
  31.         }
  32.          
  33.     }
  34.  
  35.     // State == 2 conditions
  36.     if (state == 2)
  37.     {
  38.         if (progState1 == 0)
  39.         {        
  40.             if( progTimer2 != NULL ) // If the timer has been created
  41.             {
  42.                 progTimer2Started = xTimerStart(progTimer2, 10); // Starts the timer
  43.                 Serial.println("The Timer has been issued");
  44.                 remTimeDisplay2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
  45.             }    
  46.             if (progTimer2Started == pdPASS)
  47.             {
  48.                 progState1 = 1;
  49.                 Serial.println("Prog 2 Timer has been scheduled !");
  50.             }        
  51.         }
  52.         if (progState1 != 0)
  53.         {
  54.             remainingTime2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
  55.             if (remTimeDisplay2 != remainingTime2)
  56.             {
  57.                 remTimeDisplay2 = remainingTime2;
  58.                 Serial.print("Time Remaining: ");
  59.                 Serial.println((int)remainingTime2 + 1);
  60.             }
  61.         }  
  62.     }
  63.     if (state == 0) {progState = 0; progState1 = 0;}
  64.     if (state != 1 && progTimer1Started == pdPASS)
  65.     {  xTimerStop(progTimer1, 100); progState = 0;}
  66.     if (state != 2 && progTimer2Started == pdPASS)
  67.     {  xTimerStop(progTimer2, 100); progState1 = 0;}
  68. }
When I changed to code as shown above it started to work, thanks for your guidance.
I added a normal arduino delay in loop; delay(10);
But it works without the delay as well.

Although I've seen this, I still can not get my head around about the "progState" variable, I figured I can use a single variable to note any of the timers starting condition since I'm also using the "state" variable to act as the differentiating variable (state = 1 for timer 1, state = 2 for timer 2). Does it have something to do with the timing scheme.

Who is online

Users browsing this forum: No registered users and 96 guests