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:

Code: Untitled.c Select all

#include <Arduino.h>
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.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 progState = 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");
progState = 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");
progState = 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 (progState == 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)
{
progState = 1;
Serial.println("Prog 1 Timer has been scheduled !");
}
}
if (progState != 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 (progState == 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)
{
progState = 1;
Serial.println("Prog 2 Timer has been scheduled !");
}
}
if (progState != 0)
{
remainingTime2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
if (remTimeDisplay2 != remainingTime2)
{
remTimeDisplay2 = remainingTime2;
Serial.print("Time Remaining: ");
Serial.println((int)remainingTime2 + 1);
}
}
}
if (state == 0) {progState = 0;}
if (state != 1 && progTimer1Started == pdPASS)
{ xTimerStop(progTimer1, 100); progState = 0;}
if (state != 2 && progTimer2Started == pdPASS)
{ xTimerStop(progTimer2, 100); progState = 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");
}[/code]
and the main file is as follows:
[Codebox=cpp file=Untitled.cpp] #include <Arduino.h>
#include "DMD_initializer.h"
#include "programTimers.h"

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 (progState);
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);

}
Below is the Serial message print outs:
Image
Attachments
SerialOutput.PNG
SerialOutput.PNG (37.04 KiB) Viewed 3673 times
main.cpp
(1.15 KiB) Downloaded 351 times
programTimers.c.h
(5.45 KiB) Downloaded 372 times

username
Posts: 593
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

Code: Untitled.c Select all

void progTimerEventHandler(uint8_t state)
{
// State == 1 conditions
if (state == 1)
{
if (progState == 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)
{
progState = 1;
Serial.println("Prog 1 Timer has been scheduled !");
}
}
if (progState != 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 (progState1 == 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)
{
progState1 = 1;
Serial.println("Prog 2 Timer has been scheduled !");
}
}
if (progState1 != 0)
{
remainingTime2 = ((xTimerGetExpiryTime(progTimer2) - xTaskGetTickCount())/pdSECOND);
if (remTimeDisplay2 != remainingTime2)
{
remTimeDisplay2 = remainingTime2;
Serial.print("Time Remaining: ");
Serial.println((int)remainingTime2 + 1);
}
}
}
if (state == 0) {progState = 0; progState1 = 0;}
if (state != 1 && progTimer1Started == pdPASS)
{ xTimerStop(progTimer1, 100); progState = 0;}
if (state != 2 && progTimer2Started == pdPASS)
{ xTimerStop(progTimer2, 100); progState1 = 0;}
}
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: Baidu [Spider] and 1 guest