leOS, acronimo di little embedded Operating System, è un sistema di gestione dell’esecuzione in background di piccole routine con intervalli di lancio personalizzabili mediante l’uso di uno schedulatore che le avvia in maniera indipendente dal ciclo principale del programma. leOS è scritto per le schede Arduino ed i microcontrollori Atmel. leOS è capace di gestire piccoli compiti (o task), avviandoli, arrestandoli, riprendendoli ed eventualmente eliminandoli. Questi task possono compiere piccoli lavori in background (grazie all’uso di interrupt) sollevando l’utente dal dover continuamente controllare tramite millis() se è giunto il momento di effettuare una certa operazione. In realtà leOS si piazza a metà strada tra un sistema operativo in tempo reale (RTOS) ed uno schedulatore (scheduler in inglese). E’ distante dal primo nel senso che non ha nessun metodo per gestire i task con prelazione (preemptive multitasking), ossia assegnare dei tick di tempo per far girare i task per un determinato periodo di tempo e poi interromperli arbitrariamente per riprenderli in un secondo tempo, ma è anche qualcosa di più di altri schedulatori già visti su Arduino perché lavora usando gli interrupt quindi non è interrotto da eventuali blocchi nel codice principale (esempio l’uso di delay). leOS usa il timer 2 per gestire i task dell’utente e, ovviamente, fa perdere le funzionalità PWM sui pin 3 e 11. leOS può eseguire semplici task che non richiedano gravosi impegni di CPU però può risultare utile in tutti quei casi in cui si deve gestire un compito ripetitivo che si vuole rendere indipendente dal loop principale del programma. Per testare leOS basta scaricare il pacchetto allegato e scompattarlo. Dentro trovate una cartella denominata /leOS che dovete copiare all’interno della cartella /libraries contenuta nella cartella dei vostri sketch. Di solito è /home/utente/sketchbook/libraries per gli utenti Linux e /Documenti/Arduino/libraries per gli utenti Windows. Per usare leOS basta includere la sua libreria e creare una nuova istanza della classe leOS:
#include "leOS.h" leOS myOS;
A questo punto va chiamato nel setup() il metodo begin, che prepara lo schedulatore del leOS, e dopo si possono aggiungere i propri task col metodo .addTask(). Ecco un esempio:
void setup() { myOS.begin(); myOS.addTask(miaFunzione, intervallo[, stato]); .... }
Con miaFunzione indicate la funzione che volete schedulare, con intervallo un numero che indica ogni quanti ms volete far ripetere la vostra funzione (il valore massimo ammesso è 3.600.000 ms, 1 ora, ma è possibile cambiarlo editando il file leOS.cpp).. stato è lo stato del task e può essere: PAUSED, per un task che non deve partire subito dopo essere stato aggiunto; SCHEDULED (opzione predefinita), per un normale task che deve partire subito; ONETIME, per un task che deve essere eseguito solo una volta (leggi più sotto), SCHEDULED_IMMEDIATESTART per un task che deve essere eseguito non appena aggiunto allo scheduler. Per provare leOS ho allegato un piccolo sketch dimostrativo. Per usarlo collegate (con le debite resistenze) 3 led rispettivamente ai pin 7, 8 e 9 e poi caricate lo sketch. Vedrete che ogni led lampeggia con una frequenza differente! Il led collegato al pin 8 è quello gestito dal loop principale, a dimostrazione che ogni task è indipendente dal loop e che nessun task ferma il programma. Ogni 10 secondi il programma arresta un task (un led cessa di lampeggiare) per poi essere ripresto dopo altri 10 secondi. leOS ha altri 3 metodi principal:
myOS.removeTask(nomeFunzione) myOS.pauseTask(nomeFunzione); myOS.restartTask(nomeFunzione);
I metodi hanno nomi autoesplicativi ma riassumo brevemente. removeTask serve a rimuovere permanentemente un task dallo scheduler. pauseTask serve a mettere in pausa un task, mentre restartTask serve a farlo ripartire. Lo sketch allegato fa comunque vedere l’uso di questi ultimi due task. Una caratteristica interessante introdotta a partire dalla versione 0.0.7 sono i task monouso, o one-time task. Un one-time task è un compito che deve essere eseguito solo una volta e poi deve essere rimosso dallo scheduler. Questa caratteristica è utile se si deve programmare un’azione da svogersi nel futuro. Per attivare un task di tipo one-time basta aggiungere la parola chiave ONETIME dopo l’intervallo di esecuzione del task:
myOS.addTask(nomeFunzione, intervallo[, ONETIME]);
A partire dalla versione 1.0.0 è stato introdotto un metodo per verificare lo stato di un task:
myOS.getTaskStatus(nomeFunzione);
Esso restituisce lo stato del task con i valori PAUSED, SCHEDULED o ONETIME. L’utente è tenuto a scrivere il suo codice affinché lo stato del task al momento della messa in pausa, della ripartenza o della sua rimozione sia coerente e/o compatibile con il resto del codice e con il circuito collegato. Mi spiego: se al posto di un led, si pilota ad esempio un transistor che alimenta un altro dispositivo bisogna prevedere il fatto che se il pin resta alto ed il transistor in conduzione, che tale stato sia compatibile con il circuito ed il restante codice. Ma mi sembra logico. Aggiornamenti di versione e maggiori info disponibili nei documenti allegati al package. Buon divertimento con leOS!
leOS2
Leggendo alcuni commenti degli utenti che l’hanno usato, uno dei più ricorrenti problemi era l’utilizzo nell’utilizzo del leOS era l’uso in abbinamento ad altre librerie che usano il timer 2: ciò è impossibile perché un timer può essere impostato per un solo compito. Studiando un po’ l’architettura dei microcontrollori che normalmente uso, ho pensato di utilizzare il WatchDog Timer, WDT. Questo circuito, che contiene un contatore, viene normalmente usato per resettare il microcontrollore se l’utente non provvede a resettarlo prima che sia trascorso il tempo preimpostato. Il WatchDog è utile nel caso di applicazioni critiche in cui lo sketch non deve bloccarsi durante l’esecuzione, sia per errori logici che per loop causati da eventi esterni (ad esempio, dati che dovrebbero arrivare da una connessione ethernet o seriale). Il WatchDog è particolare perché utilizza come sorgente di clock un oscillatore interno a 128 kHz e quindi lavora in modo indipendente dal clock di sistema; inoltre può non solo resettare il microcontrollore ma anche sollevare un interrupt. Sfruttando quest’ultima possibilità, possiamo impostarlo come generatore di interrupt ed inserire nella corrispondente ISR lo schedulatore del leOS: in questo modo lo schedulatore non occuperà nessun timer del microcontrollore. E’ così che è nato leOS2. Per utilizzare leOS2 basta copiarlo nella cartella /libraries, contenuta all’interno della propria cartella degli sketch, e poi aggiungere al proprio sketch l’inclusione della libreria ed una nuova istanza di leOS2:
#include "leOS2.h" leOS2 myOS;
A questo punto si può utilizzare leOS2 come il suo predecessore. Sono cambiati solo un paio di metodi, addTask e modifyTask. Vediamoli in dettaglio. Essendo il leOS2 basato sul WDT, ci sono delle limitazioni sugli intervalli impostabili per l’esecuzione di un task. Siccome il WDT ha un clock fisso e solo alcuni prescaler, il minimo intervallo temporale selezionabile è 16 millisecondi, che rappresentano un “tick”: per questo motivo anche gli intervalli devono essere multipli di questo valore. addTask e modifyTask perciò non accettano più l’intervallo specificato in millisecondi ma in tick, per cui addTask(funzione, 100) non aggiunge un task da eseguire ogni 100 ms ma ogni 100 tick, ossia 1600 ms. Per aiutare nella conversione, se non si vuole eseguire la conversione in anticipo (basta uno spostamento dei bit a destra di 4 posizioni, es.: variabile>>4) si può usare la nuova funzione convertMs() che accetta in ingresso il numero di millisecondi e restituisce il corrispondente numero di tick. Esempi:
myOS.addTask(funzione1, 10); //aggiunge un task da eseguire ogni 160 ms (10*16 ms) myOS.addTask(funzione2, myOS.convertMs(160)); //come sopra, ma la conversione è fatta dal sistema myOS.modifyTask(funzione1, myOS.convertMs(300)); //reimposta funzione1 a 300 ms
Gli altri metodi del leOS sono rimasti uguali. Visto che il leOS2 modifca il WatchDog, non si può usare la corrispondente libreria per gestire il reset del microcontrollore. A tale scopo ho aggiunto il metodo reset() che resetta il microcontrollore immediatamente:
myOS.reset(); //resetta il microcontrollore
leOS2 supporta quasi tutti i microcontrollori utilizzabili con l’IDE di Arduino, sia tramite il core originale sia con core addizionali (esempio: core Tiny per i microcontrollori Attiny). L’unico microcontrollore non compatibile è l’Atmega8/A per via del fatto che Atmel lo ha dotato di un WDT che non può sollavere interrupt. Nel caso in cui si usi questa MCU è necessario quindi utilizzare leOS versione 1.
leOS2 – IMPORTANTE PER GLI UTENTI DELLA ARDUINO MEGA/MEGA2560
Il bootloader originale delle schede Arduino MEGA e MEGA2560 non disattiva il watchdog al riavvio del microcontrollore per cui si incorre in un reset infinito che blocca il chip. Per evitare questo problema, se si vuole usare il leOS2 bisogna sostituire il bootloader con uno aggiornato che è esente da questo problema. Il bootloader è prelevabile da questa pagina.
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?.
Regards
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.
Grazie Leonardo,
It is a shame, but I will try to check it out and if I succeeded, I’ll let you know…
thanks!
Hi Leonardo!
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
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
Thank you for your answer, and for reminding me of the “volatile” keyword 🙂
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.
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,
3dotter
To do that, you need an interpreter language like Bitlash:
http://bitlash.net/
it can executes script programs so you can set your board to load up the sketch/es from an external SD.
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
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?
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
Secondo_task()
{
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
ciao, sto usando arduino mega 2560, come faccio a sostituire il bootloader per poter usare LeOS2?
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
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 🙂
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
Odd, my original message appears to have been mangled (though still retaining the sense). Maybe as a result of a translation process.
Jim
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.
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!
Never used those libs.
PS:
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.
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
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.
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)
Il captcha rompe anche a me ma purtroppo questo livello di “rompitura” è l’unico che riesce a tenere fuori dal sito i bot.
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!
Julen
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?
Thanks!
Damian
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..
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
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.
Alex
leOS 1ver.
void tFlashLed2() {
digitalWrite(LED2, HIGH);
delay(2000);
digitalWrite(LED2, LOW);
delay(200);
}
does not work
Hello. mihail_nik, your code doesn’t work because it’s wrong. You can not use the delay() function inside an interrupt driven function.
leOS (and leOS2) raises an interrupt every a fixed interval, then call an ISR (interrupt service routine) that runs the pending tasks. While the microprocessor is executing an ISR, it disables the global interrupts so that another interrupt can not stop the current ISR. Since the delay() function on Arduino is interrupt-driven, inside an ISR it simply stops counting time. So you created a never ending function.
I suggest you to look at the examples “leOS_BlinkWithoutDelay” and “leOS_ModifyTask” to understand how to blink a led with specific duty cycles without using delay(): you have to create a task and change the interval based on the on/off cycle.
Dear Mr. Milani good morning,
I’m using your ” leOS2″ lib from long time ago and I’m very happy. I want ask you if you planning a new version that can work with “arduino nano every” I hope will be helpful for me and all the community.
Best regards
Igor Giavitto