Pages: [1] 2   Go Down
Author Topic: leOS - a simple taskmanager/scheduler  (Read 9328 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

leOS, standing for little embedded Operating System, is a scheduler/taskmanager (a prototype of an OS) for Arduino boards and Atmel microcontrollers that can manage background tasks. leOS can start new tasks, pause and resume them and delete them too. All is done using a scheduler that can start tasks without the partecipation of the user so that the tasks will appear trasparents at the main loop. To be honest, it should more correct to say that leOS is actually something that is halfway a simple prototype of an real-time operating system (RTOS) and a scheduler. In fact it doesnt have the methods to give a task a tick of time to run itself and a preemptive sistem to stop them, freeze their state and resume them in a later moment; but it’s something that is more complex and efficient of several other schedulers  that just use millis() to schedule when launch a task because i.e. leOS isn’t affected by the use of delay() in the main loop.

It uses an interrupt driven scheduler (based on an 8-bit timer of the micro, usually Timer 2) that checks is time has come to start an active task. The user can choose the interval time from 1 to 3600000 ms (1 hour at the moment, the max value can be changed). The library offers 4 methods to manage tasks:
addTask(function, interval)
pauseTask(function)
restartTask(function)
removeTask(function)

addTasK add the "function" in the scheduler with interval "interval". pauseTask and restartTask halts and resume the execution of a task, removeTask removes a task from the scheduler.

The library should run on several micros albeit it has been tested only on Arduino/Atmega328 at the moment.

More info and the code are available here:
http://www.leonardomiliani.com/?p=516&lang=en

leOS is at a very early stage, comments, suggestions and critics are welcome  smiley-sweat

EDIT:
a stable version is attached at this post

EDIT2:
if someone has found this lib usefull,I publish for him the new version 0.1.1, that let the user chooses between 32-bit & 64-bit counters (the first ones consume much less Flash memory), it's compatible with Atmega32U4 (Arduino Leonardo), can manage one-time tasks, can modify a running task.

EDIT3:
leOS is now updated to version 0.1.3.
I've introduced the ability to add a paused task at the scheduler, so that it won't start running immediately after adding. This is useful i.e. if your task drives something like a LED or a transistor and you want to choose the right moment to start the action. So the new sintax of the method addTask is now as follow:
Code:
addTask(function, interval[, status]);
with status that can be:
PAUSED: to add a task in paused mode, so that it won't start until the user won't use the restartTask() method;
SCHEDULED (default option): a task that start running immediately
ONETIME: a task that will have to be run only once

Thank you for your feedback.

N.B.:
starting from v. 0.1.3 the library will be available only from my web site, due to the fact that in this manner I can keep track of the whole number of downloads
« Last Edit: September 16, 2012, 04:44:19 am by leo72 » Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27434
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So one would do things like read buttons, watch the state of data,  etc. and then call one of the functions to make some recurring task (or one-time tasks too I suppose) occur/stop occurring, etc?
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, I've designed it to be indipendent so it can run tasks in the background without interfering with the main loop.
If you want to see more clearly what leOS can do, try the sketch with 3 LEDs.
You'll see that a LED is driven by the main loop, the other 2 are flashed by 2 indipendent tasks. In the main loop there's also a piece of code that every 10 seconds pauses a task and then resumes it again.
Code:
//include the OS
#include "leOS.h"

leOS myOS; //create a new istance of the class leOS

//variabiles to control the LEDs
byte led1Status = 0;
byte led2Status = 0;
byte led3Status = 0;
const byte LED1 = 7;
const byte LED2 = 8;
const byte LED3 = 9;
byte counter = 10;
char direction = -1;


//program setup
void setup() {
    myOS.begin(); //initialize the scheduler
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT);
   
    //add the tasks at the scheduler
    myOS.addTask(flashLed1, 600);
    myOS.addTask(flashLed2, 350);
}


//main loop
void loop() {
    digitalWrite(LED2, led2Status);
    led2Status ^= 1;   
    delay(1000);
   
    //every 10 secs pause/restart the second task
    counter += direction;
    if (counter == 0) {
        myOS.pauseTask(flashLed1); //pause the task
        direction = 1;
    }
    if (counter == 10) {
        myOS.restartTask(flashLed1); //restart the task
        direction = -1;
    }
}


//first task
void flashLed1() {
    led1Status^=1;
    digitalWrite(LED1, led1Status);
}


//second task
void flashLed2() {
    led3Status^=1;
    digitalWrite(LED3, led3Status);
}



Let me show you another example.
This is the sketch BlinkWithoutMillis (funny name, isn't it  smiley-wink):
Code:
//include the OS
#include "leOS.h"

leOS myOS; //create a new istance of the class leOS

//variabiles to control the LEDs
byte led1Status = 0;
const byte LED1 = 13;

//program setup
void setup() {
    myOS.begin(); //initialize the scheduler
    pinMode(LED1, OUTPUT);
   
    //add the tasks at the scheduler
    myOS.addTask(flashLed1, 1000);
}


//main loop
void loop() {
    //empty
}


//flashing task
void flashLed1() {
    led1Status^=1;
    digitalWrite(LED1, led1Status);
}

You can see that the main loop doesn't contain ANY code, by the way the led on the thirtheen pin will flash every 1 second.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Really looks useful to me. It might be better to rename it to a taskmanager? Or can we expect more functionality soon? smiley

edit: What I'm trying to say is, an abstract layer like this for timer interrupts can be quite useful for the beginners. Will definetly check it out myself as well.
« Last Edit: July 03, 2012, 11:14:08 am by Riemer » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, Riemer, for your appreciation   smiley-sweat

It isn't a real OS, I know... But more sophisticated than other schedulers or taskmanagers that use millis(). And it's simpler than an [RT]OS that store and restore the task's status into the stack. I chose leOS because it's a pun with my nick, leo  smiley-wink
And maybe there could be some improvements, who knows about that?

BTW, here is version 0.1.0. It's fully compatible with Arduino Leonardo and its Atmega32U4. Moreover, leOS 0.1.0 supports one-time tasks (a task that should be executed only 1 time and then removed from the scheduler) and the ability to modify the interval and the type of the task. Info on the README file, and more examples in the package.


* leOS-0.1.0.zip (24.21 KB - downloaded 20 times.)
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

this project may be interesting as an easy demonstration of "IO Callback function (1) scheduling" performed into FIFO way, extremely easy to understand and extremely short in his implementation: it sounds good for arduino =P
Thank you for your appreciation
Logged


Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, nice effort! I've seen the code - and let me kindly ask you following:

1. why we need to deal with float in:
    //set the initial value of the counter depending on the prescaler
    _starter = 256 - (int)((float)F_CPU * 0.001 / prescaler);
would not be better to do it as
#define _starter   256-F_CPU/1000/prescaler
or something like that?
2. the clock limitation (1,4,8,16MHz) - that is related to point 1. only, so when I'll find a good _starter (in order to get 1ms timer interrupt) I can use ie 22.11MHz as well, I guess
3. would it be possible to use it outside the arduino environment as well?
P.
« Last Edit: July 12, 2012, 04:41:17 pm by pito » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, nice effort! I've seen the code - and let me kindly ask you following:

1. why we need to deal with float in:
    //set the initial value of the counter depending on the prescaler
    _starter = 256 - (int)((float)F_CPU * 0.001 / prescaler);
would not be better to do it as
#define _starter   256-F_CPU/1000/prescaler
or something like that?
The basic core of leOS (the management of Timer 2) derives from another project of mine, swRTC, a library to implement a software RTC in an Atmel MCU using only a timer. That code was inspired by MsTimer library, from which I initially studied and replicated the formulas to computer the timer prescaler and other things. Your notice is interesting, no need to use floats there  smiley-wink

Quote
2. the clock limitation (1,4,8,16MHz) - that is related to point 1. only, so when I'll find a good _starter (in order to get 1ms timer interrupt) I can use ie 22.11MHz as well, I guess
Yeah. I just put several checks to get an initial value for the timer that could give 1 overflow per millisecond. But, due to the fact that usually internal oscillators or external resonators are not as precise as their nominal clock, I should find a formula that could try to reach the nearest value to obtain 1 overflow/ms.

Quote
3. would it be possible to use it outside the arduino environment as well?
P.
If you want to know if the library can be compiled inside other IDEs the answer is: I don't know.
At the moment I only use the Arduino IDE, so the library has been written using parts from the Arduino core. But I think that you could convert it to be Arduino IDE indipendent: the timer's setting is made using directly the MCU's registers, I think there a just few things to check that could not work
Logged


Buena Vista, CO
Offline Offline
Full Member
***
Karma: 0
Posts: 192
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is really helpful! however the ONETIME keyword does not work. I'm starting task1 to happen every two seconds. Task2 is onetime and I restart is each time task1 happens. However, task2 happens continually.

Jim
Logged

8000ft above the average

Offline Offline
Newbie
*
Karma: 7
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks cool.
I was looking at your source and wondering:
  • Why don't you make a 'task' struct. That would be a more intuitive approach in your library because you would only need one array instead of four or five distinct arrays for each task.
  • Why don't you allocate the array(s) to dynamic memory so that you can resize it in addTask() (and possibly removeTask()) as necessary. Is there a good reason to be limited to 9 tasks?
  • In your source there are two places where you slide all of the array elements over to fill in a gap (in removeTask() and ISR() interrupt handler when cleaning out one time functions). I recommend you either break the common code out into a common function or just call removeTask() from ISR(). It will make your code easier to read and it will do magical things to your code size.
  • I see that you declare
Code:
const uint8_t ONETIME=2;
const uint8_t SCHEDULED=1;
    inside your header, but you never actually bother to use them anywhere in the code. Better than arbitrary constant ints would be to use an enum, that way using the name in place of the raw integer is enforced by the compiler.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is really helpful! however the ONETIME keyword does not work. I'm starting task1 to happen every two seconds. Task2 is onetime and I restart is each time task1 happens. However, task2 happens continually.

Jim
I apologize if I answer your question only today but I forgot to follow this thread  smiley-sweat
Can you provide the sketch you're using? Which platoform are you using? Which version of the Arduino IDE?
Thank you for you feedback.

EDIT:
I found a little bug in the management of onetime pads... can you try the new version 0.1.2?
http://www.leonardomiliani.com/?p=516&lang=en
« Last Edit: August 30, 2012, 09:57:48 am by leo72 » Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@runnerup:
I appreciate your comments.
This is a kind of pre-stable release. leOS works and is sufficiently stable and usable for using it in everyday's sketches, but it can be improved in a lot of thing. My wills are to review the leOS source to improve it, as soon as possibile.
Logged


Offline Offline
Full Member
***
Karma: 1
Posts: 196
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I haven´t still had time to look at the code, but i still have two questions.

  • Is LeOS able to keep up with realtime, does it have any kind of RTC feature?
  • Does LeOS have limitations in terms of number of tasks it can manage?

Regards
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 23152
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Is LeOS able to keep up with realtime, does it have any kind of RTC feature?[/li][/list]
At the momento, it doesn't. To make a very good real-time software we have to use the built-in RTC (Real-TimeCounter) module with an external crystal, so that we can set the timer 2 to work in asynchronous mode.
(i.e. in my "Micrologio" project, that is available on my website)

Quote
Does LeOS have limitations in terms of number of tasks it can manage?[/li][/list]
The limitations are set by SRAM memory. By default leOS can manage up to 10 tasks: you can change this value in the source of the library.
Logged


Offline Offline
Full Member
***
Karma: 1
Posts: 196
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

How much memory does a task take?

The LeOS in oriented to all the range of MCUs or only for 328?
Logged

Pages: [1] 2   Go Up
Jump to: