Using this method: [Code Share] Simple lightweight cooperative multi-tasking code - Libraries - Arduino Forum
I have written a central/static Delay class a Task can use to 'schedule' a delay wait. It's not really scheduling but it does do the timekeeping for the tasks. Each iteration of the main loop, the time is updated and waiting tasks that have their delay elapsed, are run.
I have spend a couple of hours trying to get a scheduler, but I was not pleased with the amount of overhead versus the gain it provided to the developer. I went back to letting the developer write the 'scheduler' in the main loop and determine the flow of Tasks.
Here is a Task class for blinking a LED. Refer to the link for the Task_Begin, Task_Yield and Task_End macros.
template<const int rate, const byte pin>
class BlinkLedTask
{
public:
BlinkLedTask()
{
pinMode(pin, OUTPUT);
digitalWrite(pin, false);
_state = false;
}
Task_Begin(Execute)
{
while(true)
{
Task_YieldUntil(Delay::Wait((int)this, rate));
// toggle led
_state = !_state;
digitalWrite(pin, _state);
}
}
Task_End
private:
bool _state;
int _task;
};
The Delay class is used to do the timekeeping on Task waiting times.
#define MAXTASKS 4
class Delay
{
public:
static void Init(Time* time)
{
_time = time;
for(int i = 0; i < MAXTASKS; i++)
{
_ids[i] = 0;
_delays[i] = 0;
}
}
static unsigned long Update()
{
_delta = _time->Update();
return _delta;
}
static bool Wait(int id, int milliseconds)
{
for(int i = 0; i < MAXTASKS; i++)
{
if (_ids[i] == id)
{
if (_delta >= _delays[i])
{
_ids[i] = 0;
return true;
}
_delays[i] -= _delta;
return false;
}
}
for(int i = 0; i < MAXTASKS; i++)
{
if (_ids[i] == 0)
{
_ids[i] = id;
_delays[i] = milliseconds;
break;
}
}
return false;
}
private:
static unsigned long _delta;
static Time* _time;
static int _ids[MAXTASKS];
static int _delays[MAXTASKS];
Delay(){}
};
I use the Arduino to test this and have 3 leds blinking away at me.
Time time;
BlinkLedTask<1000, 13> ledTask1;
BlinkLedTask<2000, 12> ledTask2;
BlinkLedTask<500, 11> ledTask3;
void setup()
{
Delay::Init(&time);
}
void loop()
{
Delay::Update();
ledTask1.Execute();
ledTask2.Execute();
ledTask3.Execute();
}
I'm pretty happy with the result.
Thanx for all the feedback.