Hello, I am looking for some ideas on how to design a system that executes several periodic tasks, with specified timings using a Cyclic Executive.
to keep it simple, let's say I have 3 tasks and would like to execute them at the following rates:
thanks for your answer. I simplified my problem to just two tasks:
task 1 - turn on the red LED for 1 second - execute every 4 seconds
task 2 - turn on green LED for 1 second - execute every 10 seconds
and I wrote this code:
/*
task 1 - turn on red LED - execute every 4 seconds
task 2 - turn on green LED - execute every 10 seconds
*/
const long eventTime_Red = 4000; //execute every 10 seconds
const long eventTime_Green = 10000; //execute every 10 seconds
unsigned long previousTime_Red = 0;
unsigned long previousTime_Green = 0;
const byte LED_Red=15; //LED red connected to pin 15
const byte LED_Green=21; //LED green connected to pin 21
void setup() {
Serial.begin(9600);
pinMode(LED_Red, OUTPUT); //configure pin 15 to behave as an output
pinMode(LED_Green, OUTPUT); //configure pin 21 to behave as an output
digitalWrite(LED_Red, LOW); //have the red LED initially off
digitalWrite(LED_Green, LOW); //have the green LED initially off
}
void loop() {
unsigned long presentTime = millis();
//for task 1
if (presentTime-previousTime_Red >= eventTime_Red){
while (presentTime
digitalWrite(LED_Red, HIGH);
delay(1000); //keep Red on for 1 sec
Serial.print(presentTime/1000);
Serial.println("Red ON");
digitalWrite(LED_Red, LOW);
previousTime_Red = presentTime;
}
//for task 2
if (presentTime-previousTime_Green >= eventTime_Green){
digitalWrite(LED_Green, HIGH);
delay(1000); //keep Red on for 1 sec
Serial.print(presentTime/1000);
Serial.println("Green ON");
digitalWrite(LED_Green, LOW);
previousTime_Green = presentTime;
}
}
is this sort of what you meant?..obviously with different numbers.
And it works the way I want but there is just one problem: since I am using delay() to control how long LEDs are on, other instructions are blocked. This is problematic during instances where the red led and the green led must turn on simultaneously. I know I probably have to use millis() to control the delays but I don't know how.
Yes, I am using ESP32, but I was hoping to use Cyclic Executive to bypass the coding of the real-time system. I've never used freeRTOS before, but I think I won't get the chance to exhibit Cyclic Executive coding with it...
Actually, I think I figured it out. So I first defined how long each LED will be on for, e.g. for the red LED:
const long red_period = 1000; //keep red LED on for 1 second
Then I nested an if statement inside the if statement for each task, so for task 1:
//for task 1
if (presentTime - previousTime_Red >= eventTime_Red) {
if (presentTime >= (previousTime_Red + red_period)) {
//keep Red on for 1 sec
digitalWrite(LED_Red, HIGH);
Serial.print(presentTime / 1000);
Serial.println("Red ON");
}
digitalWrite(LED_Red, LOW);
previousTime_Red = presentTime;
}
Now the problem is that the LEDs flash so fast I can't even see them. The timings look accurate though when I analysed them on the serial monitor...so I'm confused .... I'll be back with an update
It is nice, incidentally, to switch the led on only once and off only once per cycle.
Especially so if you write a message to the serial console on each switch because this would otherwise get clogged up with all the messages.
Something like (pseudo code):
if ( <led is off> && <led should be on> ) switch led ON ;
if ( <led is on> && <led should be off> ) switch led OFF ;
Hello cinnamonroll
Take view to the sketch below. The sketch is using the BWOD example of the IDE as mother of all Arduino timers with an added function caller for the timed scheduled functions calls.
/* BLOCK COMMENT
ATTENTION: This Sketch contains elements of C++.
https://www.learncpp.com/cpp-tutorial/
Many thanks to LarryD
https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
https://forum.arduino.cc/t/how-to-do-schedule-tasks-using-cyclic-executive/962598
*/
#define ProjectName "How to do schedule tasks using Cyclic Executive?"
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
constexpr byte LedPins[] {9, 10, 11}; // portPin o-------[LED]-----|220ohm|---GND
// CONSTANT DEFINITION
enum {One, Two, Three};
// VARIABLE DECLARATION AND DEFINITION
unsigned long currentTime;
//_____ information block for task timer
void task1();
void task2();
void task3();
struct TASKTIMER { // has the following members
void (*task)(); // task name
unsigned long duration; // memory for interval time
unsigned long stamp; // memory for actual time
} taskTimers [] {
{task1, 500, 0 }, // task1 @ 2Hz
{task2, 200, 0 }, // task2 @ 5Hz
{task3, 167, 0 }, // task2 @ 6Hz
};
//______________ scheduled task ____________
void task1() {
Serial.println(__func__);
toggleLed(LedPins[One]);
}
void task2() {
Serial.println(__func__);
toggleLed(LedPins[Two]);
}
void task3() {
Serial.println(__func__);
toggleLed(LedPins[Two]);
}
//__________________________________________
void toggleLed(int pin) {
digitalWrite(pin, !digitalRead(pin));
}
// -------------------------------------------------------------------
void setup() {
Serial.begin(9600);
Serial.println(F("."));
Serial.print(F("File : ")), Serial.println(__FILE__);
Serial.print(F("Date : ")), Serial.println(__DATE__);
Serial.print(F("Project: ")), Serial.println(ProjectName);
pinMode (LED_BUILTIN, OUTPUT); // used as heartbeat indicator
// https://www.learncpp.com/cpp-tutorial/for-each-loops/
for (auto Output_ : LedPins) pinMode(Output_, OUTPUT);
}
void loop () {
currentTime = millis();
digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
//__________________ task timer
for (auto &taskTimer : taskTimers) {
//______________ based on BWOD with attached function call
if (currentTime - taskTimer.stamp > taskTimer.duration) {
taskTimer.stamp = currentTime;
taskTimer.task();
}
}
}
Have a nice day and enjoy coding in C++.
Thank you for the code. It's slightly too complex for my level but I sort of see what's going on. I'd appreciate if you (or anyone else) can clarify the purpose of
Just going back here a minute, You not only want to be able to specify the "ON" time for each led. You also want to be able to specify the "OFF" time. Is that correct ?
It is not very clear because originally you appeared to want simply to trigger a task without considering the execution time of the task.
Anyway, if you want to check that its is working correctly, print also to the serial monitor. That will work even if the leds flash too quickly to see.
Incidentally, if this is school homework, no doubt the teacher will be impressed if you are able to manipulate range based for loops as fluently as @paulpaulson
Ok, I want the LEDs to be on for a second, I should've written this:
/*
task 1: turn on red LED for 1 second, execute every 4 seconds
task 2: turn on green LED for 1 second, execute every 10 seconds
*/
I made another post about this with more details because I got somewhere with my solution but now have a new problem, so I didn't want to confuse this thread: How to simultaneously execute two tasks?
This is for an assignment but it's not the assignment question, I am trying to get an idea of how to do Cyclic executive using a very simple example so that I can apply it to a complex problem for my assignment