Jun 26 2012

leOS, a simple OS for Arduino

Go to leOS2

Today I’ll show you leOS (little embedded Operating System), a system that can manage the background execution of little routines with customizable interval launch times using a scheduler that can start them indipendently by the main loop of the user’s program. 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 trasparent 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 a 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. leOS uses timer 2 to manage the tasks so the user looses the PWM functionalities over pins 3 & 11. leOS can run simple tasks that don’t require excessive CPU time but it can be useful in all of those situations where the user wants to let a task run itself out of the main loop. To test leOS just download the attached package and decompress it. After that move the resulting folde /leOS inside your /libraries’ folder. Usually this folder is in /home/user/sketchbook/libraries on a Linux box and into /Documents/Arduino/libraries on a Windows system. To use leOS just include its library at the beginning of your sketch and then create a new istance of the class:

#include "leOS.h"
leOS myOS;

Now you have to call the begin() method from the setup() routine, to initialize the timer used by leOS. Then you can add your tasks using the method addTask():

void setup() {
  myOS.addTask(myFunction, interval[, status]);

With myFunction you pass the method the function you want to be scheduled, with interval you specify how many milliseconds have to pass between a call and the following (the maximun allowed value is 3,600,000 ms, 1 hr., but you can modify this number by editing the file leOS.cpp). yourFunction must be a routine that is inside your sketch. status is the status of the task and it can be: PAUSED, for a task that doesn’t have to start immediately; SCHEDULED (default option), for a normal task that has to start after its scheduling; ONETIME, for a task that has to run only once (read below).

To test the attached test connect 3 LEDs (with their resistors) to Arduino pins 7, 8, and 9 and then upload the sketch. You will see the 3 LEDs flashing with 3 differents times: the middle LED is driven by the code into the main loop() while the other two are managed by 2 tasks. Every 10 seconds you will see that a LED cease to flash and that after 10 seconds more it will start flashing again, to demonstrate the use of pause and restart methods. These are the other 3 methods leOS has:


It is easy to understand what those methods do, but I’ll give you a little explanation: removeTask can be used to permanently remove a task from the scheduler; pauseTask pauses a task while restartTask resume it. Don’t worry, there’s a sketch in the attached package that shows the use of these methodes.

An interesting feature are the one-time tasks, introduced since version 0.0.7. A one-time task is a task that has to run only once. After its execution, leOS will remove it from the scheduler. To set a task as a one-time task simpy add the keyword ONETIME after the interval in the addTask method:

myOS.addTask(myFunction, interval, ONETIME);

A new method to check the current status of a task has been introduced with version 1.0.0:


It returns the status of the task using the values PAUSED, SCHEDULED, or ONETIME.

In case the user is pausing, resuming or removing a task, he has been asked to check if the status of the circuit or the code managed by the task paused, resumed or removed is coherent and compatible with the new condition: i.e., if a task was driving a transistor that was driving a circuit, the user has to foresee if the last state of the transistor will represent a critical situation for the circuit itself. But this is logic, don’t you?

Version updates & more info in the docs included in the package.

Enjoy with leOS!


One of the most frequent appointment that I’ve found reading the messages of the users that tried leOS is about the incompatibility between the scheduler and other libraries that use timer 2: this is due to the fact that a timer can only be used by one application.

So I’ve read about the architecture of the microcontrollers I usually use and I’ve realized to use the WatchDog Timer, WDT. This circuit is usually used to reset the microcontroller if the user doesn’t reset its counter before this one has expired. This is good in critical applications where the sketch must never freeze, both for logical errors or for infinite loops caused by external factors (i.e. datas that should arrive through an ethernet or serial connection). The WatchDog is particular because it uses the internal 128 kHz oscillator as clock source, so it can operate asynchronously respect to the system clock; additionally, it can not only reset the microcontroller but it can also raise an interrupt. We can use the latter and intercept the corresponding ISR putting in it the leOS’s scheduler: in this manner the scheduler won’t use any timer of the MCU. This is leOS2.

To use leOS2 you just have to copy it into the folder /libraries that is included in your sketchs’ folder, and then add your sketch the inclusion of the library and the creation of a new instance of leOS2:

#include "leOS2.h"
leOS2 myOS;

You are now ready to use leOS2 like its predecessor. Only 2 methods are changed, let’s see them in detail. Due to the fact that leOS2 is based on WDT and that this only has a fixed clock and a few prescalers, there are some limitations on the suitable intervals for a task: the minimum available interval is 16 ms, and the intervals must also be multiplies of this value. So, 16 ms represents a “tick” and the intervals must be passed to addTask() & modifyTask() in ticks and not in milliseconds as in leOS. So, addTask(function, 100) will not add a task scheduled to be run every 100 ms but every 100 ticks, or 1,600 ms. To help converting from milliseconds to ticks (if you don’t want to add a simple bit shift, i.e.: interval>>4) I’vew added a new function called convertMs() that accepts a time in milliseconds and returns the corresponding number of ticks. Here are some examples:

myOS.addTask(function1, 10); //add a task to be run every 160 ms(16 ms*10)
myOS.addTask(function2, myOS.convertMs(160)); //same above, but with the conversion
myOS.modifyTask(function1, myOS.convertMs(300)); //re-set function1 to 300 ms

The other methods are unchanged.

Due to the fact that leOS2 uses the WatchDog, the user can not use the Avr library wdt.h to reset the microcontroller. For this reason I’ve added a new method reset() to reset the MCU immediately:

myOS.reset(); //reset the microcontroller

leOS2 supports almost every microcontroller that is supported by the Arduino IDE, by the original core or by a third party one (i.e. the Tiny core for the Atmel Attiny microcontrollers). The only common chip that is incompatible with leOS2 is the Atmega8/A because Atmel didn’t provide it of a WDT capable to raise interrupts. In this case you have to use the first version of leOS.

the original bootloader flashed into the Arduino MEGA and MEGA2560 boards doesn’t deactivate the watchdog at the microcontroller’s startup so the chip will freeze itself in a neverending loop caused by eternal resets. To solve this problem, users that want to use leOS2 have to change the bootloader with one that it isn’t affected by this issue. The bootloader can be downloaded by this page.

Version: 1.2.1
2.1 MiB
Version: 2.3.1
1.9 MiB


2 pings

Skip to comment form

  1. Hi,

    Yout library is very interesting and simple of use. I have a Teensy 2++ board that is Arduino’s compatible. I have downloaded you library and tried to use it, but there is a compatibility issue that is checked by your code.

    This is a real limitation?.

    The error is:
    En el fichero incluído de leOS_basic_usage.cpp:30:
    /home/ydirgan/SCRIPTS/Arduino/arduino-1.0.1/libraries/leOS/leOS.h:70:2: error: #error Sorry, microcontroller not supported!

    Or can the code be modified to try to compile for teensy microcontrollers?.


  2. The code itself doesn’t support the AT90USB1286 of the Teensy 2++, which is an AT90USB1286, isn’t it?
    The library support a variety of microcontrollers that can be used with Arduino IDE due to the availability of a specific core. I didn’t have any core for AT90USB1286 so I couldn’t try leOS on it.
    You can add that micro just by editing the header file of the lib (leos.h) and adding the check for it and then adding the correct settings for a timer of that micro. You have to have a little programming skill and a good knowledge of the timers/interrupts of AT90USB1286 to do that.

  3. Grazie Leonardo,

    It is a shame, but I will try to check it out and if I succeeded, I’ll let you know…


    • on Monday September 3rd, 2012 at 11:35 AM

    Hi Leonardo!

    So it can’t be used with other libraries witch use interrupts like twi, spi with attach mode, e.t.c ?

    • mromani on Wednesday September 5th, 2012 at 09:32 AM

    Hi Leonardo. Just tried with a NuElectronics lcd+keypad Arduino shield and it worked great.
    I could even have different “tasks” write to different regions of the LCD.
    I have one question: what about inter-task communication ? I looked at the code but didn’t see any specific function for this. Is it enough to use global variables ?

    Thank you

  4. leOS at the moment doesn’t support any kind of data-exchange between tasks.
    You can try with global variables. I suggest you to use the “volatile” keyword so that the compiler won’t optimize their management inside the ISRs

    • mromani on Saturday September 8th, 2012 at 10:04 PM

    Thank you for your answer, and for reminding me of the “volatile” keyword 🙂

    • on Thursday October 4th, 2012 at 04:12 PM

    Great small OS. I’d want to integrate it with the “SWAP” stack made by Daniel Berenguer for its small panstamps wireless sensor nodes (see http://www.panstamp.org/forum/showthread.php?tid=111 ). That’s going to be a really winning combination IMHO. I’ll keep you posted of my progress.

    • on Saturday January 19th, 2013 at 05:33 PM

    Hi Leonardo,

    Great OS! I like the time tasks approach. It would be great if your LeOS could pick up tasks from a (u)SD card. Will such be possible in the future?

    Best wishes,

  5. To do that, you need an interpreter language like Bitlash:
    it can executes script programs so you can set your board to load up the sketch/es from an external SD.

    • mar.conte on Wednesday January 30th, 2013 at 08:23 PM

    Salve volevo sapere con un atmega1284 quanti task si possono i stanziare contemporaneamente? Faccio questa domanda perché ho inserito due addtask e mi si resetta con uno no grazie

  6. La lib è preimpostata per gestire fino a 10 task, anche se il numero è modificabile nel file .cpp.
    Mi suona strano che con 2 task il 1284 si resetti, ho fatto dei test in queste ultime ore con 2 blink proprio su un 1284 (sto provando la programmazione via bootloader con un altro bootloader). Che c’è nel secondo task?

    • mar.conte on Thursday January 31st, 2013 at 10:50 AM

    nel secondo task richiamo una funzione chiamata temp che mi calcola su a0 la temperatura di un sensore temp
    Una volta ottenuta la temperatura nel task inviò sms rs
    Temp();//chiedo alla A0 valore
    InvioSms( temperatura);// inviò valore tramite serial1 ad un modulo sim900
    Non ho il codice sottomano ma in sintesi è quello sopra descritto grazie a presto

    • borgonovo on Thursday October 10th, 2013 at 03:18 PM

    ciao, sto usando arduino mega 2560, come faccio a sostituire il bootloader per poter usare LeOS2?

  7. Ti serve un altro Arduino per programmare la tua scheda, oppure un programmatore tipo l’Avr Dragon o l’USBtinyISP. C’è una guida di un mio amico che spiega poi in dettaglio come fare. La puoi prelevare da http://www.michelemenniti.it

    • mcmajan on Monday October 14th, 2013 at 01:59 AM

    Ciao Leonardo, ho letto questo articolo dopo averne visto il riferimento sulla risposta che mi hai dato sul forum. Mi sembra estremamente interessante e se non mi occuperà troppa flash / ram lo userò sicuramente nel progettino che sto sviluppando. Volevo segnalarti che a metà articolo scrivi ONETINE anzichè ONETIME, e poi sto maledetto Captcha mi ha fatto impazzire per loggarmi e scrivere questo commento 🙂

    • Jim Ford on Friday December 6th, 2013 at 02:04 PM

    Hi Leonardo.

    First let me thank you for your leOS2, which looks like it may suit my needs. It’s particularly valuable that you supply comprehensive documentation and examples, fully describing its use.

    Two questions:

    Does leOS2 completely supersede and replace leOS? I can’t see where leOS would be used in preference to leOS2.

    Where does ‘looper’ fit in with leOS2? As leOS2 doesn’t use the ‘normal’ interrupts, I don’t see a need for looper.


    • Jim Ford on Friday December 6th, 2013 at 02:07 PM

    Odd, my original message appears to have been mangled (though still retaining the sense). Maybe as a result of a translation process.


  8. Hi Jim.
    Answers to your questions:
    1) leOS and leOS2 are similar in what they do but completely different in the way they do it 😉
    let me explain. leOS is based on a timer (timer 2) and thus you cannot use that timer and the related PWM pins in your projects. This is frustating if you use a third party library that uses the timer 2 for its own needs. leOS2 solves this problem using the watchdog timer. Moreover, it can permit the control of a task because if your code goes into a deadlock and freezes the MCU, the leOS2 scheduler will see it and reset the microcontroller. The price to pay is that leOS2 has a minimum resolution of ~16 ms while leOS has a resolution of 1 ms. So, there are PROs and CONs. One should use the scheduler that fits its own need.

    2) looper doesn’t use interrupts so all the jobs are executed outside of an ISR. This could be a need if you intend to put into a job a piece of code that make use of delay/millis because the delay/millis won’t be work inside an ISR (they are based on an interrupt too, so inside an interrupt routine the value of millis won’t be incremented). Or maybe a job that calls another function of the Arduino that uses another ISR. So, you have several instruments that you can mix together to obtain a powerful sketch.

    • Jim Ford on Monday December 9th, 2013 at 08:27 PM

    Thanks for the reply, Leonardo.

    I’m using leOS2 because I suspect that interrupts may be used by the libraries I’m using (but I really ought to look through them to check).

    I’m using Dr Liu’s phi_prompt and phi_interfaces libraries for a menu system on my project and am having ‘lock-ups’. Have you used the ‘phi’ libraries in conjunction with leOS2, or had reports of other users doing so?

    Best wishes, Jim

    P.S. I’m having lots of problems with your site’s ‘Captcha’. I sometimes take more than attempts at it!

  9. Never used those libs.

    sorry for the Captcha, but I had to adopt a very aggressive system to limit the registrations of users to leave out trolls/spammers and to avoid the security problems I had in the past.

    • Imer on Sunday February 16th, 2014 at 02:24 PM

    ciao ,
    ho provato la tua liberia leOS2 con arduino uno e mega e funziona perfettamente , ma quando ho abbianto la tua libreria con una scritta da me che usa i comandi digitalwrite() e digitalread() per gestire una scheda che tramite 3 74HC195 controlla un display lcd 20×2 , 5 led bicolore, 1 led monocolore, la retraoilluminazione e 1 cicalino e fin qui funziona tutto , se gestisco gli 8 pulsanti tramite un 74HC165 la mia scheda va in titlt . ossia quando chiamo lo gli stati del 74HC165 .
    La mia libreria funziona correttamente se non aggiungo la tua , quindi la causa è un conflitto tra le 2 , ma non ne vengo a capo.
    Sia su uno che mega uso i PIN : 7, 6, 5 , 4, 3, 2.
    Ciao Imer

  10. leOS2 usa solo il watchdog, se la libreria che hai scritto non usa anch’essa la periferica in questione, deve funzionare. Diversa cosa è se stai usando un task che fa uso di funzioni che si bloccano se usate all’interno di una ISR (tipo delay) o che rendono il task molto lungo da eseguire.

    • Imer on Thursday February 20th, 2014 at 09:49 AM

    Ciao ,
    grazie per la risposta , questa sera controllo se non ho qualche delay sparso per il software , volevo appunto usare la tua libreria per eliminare i vari delay che ho in giro per gestire i lampeggi che fanno muovere il display e la tastiera a scatti.

    CIao e grazie

    PS un Captcha meno rompib….e no !
    lo devo ripetere 10 volte prima di centrarlo :o)

  11. Il captcha rompe anche a me ma purtroppo questo livello di “rompitura” è l’unico che riesce a tenere fuori dal sito i bot.

    • julen on Monday January 5th, 2015 at 12:37 PM

    Hi Leo,
    I am interested in using your library for a small project. I am quite new to Arduino, and I own a Yún.
    I have a question, what is the maximum time amount that can be scheduled for a task to be done?
    For example, can I program a task to be executed every hour? or it can’t be as long?
    Thanks in advance!


    • DamianUru on Wednesday January 28th, 2015 at 11:15 AM

    Hi Leo! Exellent SO! Im using some Mega board, (with 1280) do you have links for download the bootloader ready to load? With you SO enters in loop reset. I didn’t find the bootloader for download.
    Can i donate for your project?



  12. I don’t have a link. But you can compile it by yourself, just follow che article I cited and do the same changes. It should work..

  13. Ciao complimenti per il sito,
    senti sto utilizzando la libreria leOS2 ma ho un problema, in pratica ho realizzato un programma semplice con due task separati il primo parte appena accendo Arduino e fa partire un orologio per il quale utilizzo un RTC di tipo DS1307, mentre con il secondo task gestisco un timer di tipo software. In pratica questo task inizialmente sta in pausa e parte appena premo un pulsante poi quando ripremo si ferma.
    Il problema è che dopo un po’ che ho fatto partire il secondo task, quindi sto timer software, mi si blocca tutto. Ho provato ad implementarlo sia su Arduino Mega, sia su Arduino Uno. Ma ho esattamente lo stesso problema.

    Avresti qualche suggerimento?

    PS: “leOS” e “leOS2” non è possibile utilizzarle insieme.

    Grazie mille

    • Alex on Friday October 14th, 2016 at 10:35 PM

    Ciao Leo
    I am using your leOS with a Leonardo ATmega32u4 16MHz board and IDE 1.6.12. First I did get Error regarding warning: converting to non-pointer in the H file which was easy fixed by replacing NULL with 0. After that the first addtask did and still does work quit well, but if I add a second one all locks up and it looks like the watchdog gets into a loop mode. So I only can fix this by reset and try to load new clean sketch (hard to do). Do you think it is a bootloader watchdog problem like the MEGA has? Or should I use leOS2.


  1. […] System (leOS) è un progetto di Leonardo Miliani, un programmatore fiorentino, e consiste in una specie di sistema operativo in C per gestire l’esecuzione del codice su Arduino. Lo stesso Miliani premette che la […]

  2. […] the arduino side, using a hardware timer is the best way, see LeOS for a nice scheduler on […]

Leave a Reply