Siccome in questi giorni ho lavorato facendo il turno di notte, le sere erano lunghe, quindi per ammazzare il tempo ho scritto il leOS.
Il leOS, da little embedded Operating System, è un semplice sistema operativo in tempo reale (RTOS). Usa il timer 2 per gestire i task dell'utente e, ovviamente, fa perdere le funzionalità PWM sui pin 3 e 11. Il leOS può eseguire semplice task che non richiedano gravosi impegni di CPU però può risultare carino in tutti quei casi in cui si deve gestire un compito ripetitivo che si vuole rendere indipendente dal loop principale del programma.
Per testare il 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 il leOS basta includere la 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 indicata la funzione che volete schedulare, con intervallo un numero non più grande di 1000 (potete modificare questo valore nel file leOS.cpp) che indica ogni quanti ms volete far ripetere la vostra funzione. stato indica invece allo scheduler lo stato del task. Può essere: PAUSED, ed il task viene aggiunto ma in modalità "pausa", ossia non parte finché non viene avviato esplicitamente dall'utente con restartTask(); SCHEDULED (opzione predefinita), che indica lo stato normale di un task, che viene eseguito non appena aggiuntO; ONETIME, che viene eseguito solo una volta.
Per provare il leOS ho allegato diversi sketch dimostrativi.
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.
Al momento il leOS può solo aggiungere task, metterò a breve i metodi per cancellare i task schedulati.
Buon divertimento e fatemi sapere che ne pensate XD XD
DOWNLOAD:
l'ultima versione aggiornata delle libreria è disponibile sulla pagina del leOS sul mio sito personale
STORICO:
v. 0.0.3:
questa versione introduce la gestione dei task aggiunti allo scheduler. Nello specifico ho introdotto 3 nuovi metodi:
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.
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.
v. 0.0.4:
introdotto l'uso di un contatore interno a 64 bit per cui lo schedulatore andrà in overflow dopo 584.942.417 anni!
v. 0.0.5:
corretti alcuni bug, ottimizzato il codice e ridotto l'uso della memoria del programma compilato.
v. 0.0.7:
implementata la gestione dei task one-time, ossia un tak che deve essere eseguito solo 1 volta. Comodo per impsotare lavori da eseguire dopo un certo periodo di tempo dall'avvio dell'Arduino.
v. 0.1.1:
aggiunta la possibilità di scegliere fra la matematica a 32 e 64 bit. La differenza in termini di consumo di risorse è notevole dato che per gestire i numeri a 64 bit il compilatore introduce diverse centinaia di byte in più nel firmware finale. Ad esempio, lo sketch "leOS_2_tasks" compilato con matematica a 64 bit occupa su un Amtega328 3544 byte mentre compilato con la matematica a 32 bit ne occupa solo 2392. Bisogna solo tener presente che con contatori a 32 bit si verifica un overflow dopo 49.7 giorni mentre cn quello a 64 bit dopo 584K anni. Ciò non è un grosso problema se gli intervalli sono limitati a pochi minuti o secondi, dato che situazioni atipiche si possono verificare solo nel caso in cui si modifichi il codice in modo da poter inserire intervalli così grandi che, sommati con il valore attuale del contatore dei millisecondi portino all'overflow con la conseguenza di avere un valore finale inferiore a quello rappresentato dal contatore, con l'ovvio salto dell'esecuzione di quel task.
v. 0.1.2:
sistemato un bug nella gestione dei task one-time
v. 0.1.3:
adesso è possibile aggiungere un task impostandolo come "PAUSED" in modo che sia inserito nello scheduler ma che non venga eseguito immediatamente. Per far partire il task basta usare il metodo restartTask(). Aggiunti anche due nuovi sketch di esempio.
v. 0.1.4:
ho riscritto il core usando le Struct per tenere più ordinata la gestione dei parametri dei task
v. 0.1.5:
introdotto il supporto all'Atmega344
v. 1.0.0:
prima versione stabile. Introdotto anche un nuovo metodo per verificare lo stato di un task:
myOS.taskIsRunning(nomeFunzione)
Viene restituito PAUSED, SCHEDULED o ONETIME
v. 1.0.1:
introdotto un fix per eliminare il problema dell'overflow del contatore interno quando si usa la matematica a 32 bit permettendo, rispetto all'uso dei registri a 64 bit, una maggior compattezza del codice generato (diverse centinaia di byte in meno) senza il rischio di incorrere in comportamenti strani dopo 49,7 giorni.
v. 1.0.1a:
il metodo taskIsRunning è stato rinominato in getTaskStatus.