looper - un semplice schedulatore senza timer/interrupt

Seguendo la scia di leOS, e su richiesta di m_ri ( :stuck_out_tongue: ) ecco looper.
Looper è un semplicissimo lanciatore di routine che NON usa timer/interrupt del microcontrollore. Esegue piccoli task ad intervalli prefissati, calcolati ricorrendo ad uno schedulatore che si appoggia a millis. E' indipendente dall'hardware (quindi gira su ogni micro) proprio perché non usa niente che non sia contenuto nel core di Arduino.

Chi ha usato il leOS si troverà a casa con looper, dato che eredita alcuni metodi da leOS nonché la loro sintassi.
Per usare il looper bisogna caricare la sua libreria ed istanziarne una copia:

#include "looper.h"
looper myScheduler;

Fatto questo, i metodi a disposizione sono 4:

myScheduler.addTask(funzione, intervallo_in_ms[, ONETIME]);
myScheduler.removeTask(funzione);
myScheduler.pauseTask(funzione);
myScheduler.restartTask(funzione);

Per far lavorare looper basta aggiungere questa chiamata in qualunque parte del vostro loop principale:

void loop() {
  ...
  myScheduler.scheduler();
}

La sintassi è identica a quella dei corrispondenti metodi del leOS ed è descritta nel README allegato.
4 esempi corredano la libreria, per mostrare come usare usare looper.

NOTA:
visto che looper non si basa sugli interrupt, la sua precisione dipende totalmente dalla durata del loop principale. looper funziona bene se il loop principale ha una durata inferiore a quella del task con il tempo di intervallo più breve perché altrimenti il task verrà eseguito non alla scadenza prefissata ma dopo il loop principale.
Ad esempio, se impostate un task che fa lampeggiare un led ogni 500 ms e nel loop mettete un delay(1000), il led lampeggerà ogni secondo! Questo è ovvio, dato che a differenza di leOS, looper non viene invocato automaticamente ma solo manualmente. E' in pratica una routine come tutte le altre che richiama altre routine.

Spero di aver fatto cosa gradita, come al solito :sweat_smile:

looper-0.1.zip (20.4 KB)

mmmm.

se ho capito questo e' qualle che io intendevo per delay2.0()
il leOS anche c'era vicino, ma forse era troppo,.

e' vero che il delay1.0 blocca looper, ma, sempre se ho capito, io posso usare looper al posto di ogni delay che ho in uno sketch, eliminando di fatto i delay bloccanti, e tenendo in gioco solo looper.

se imposto looper per accendere un led ogni 500ms, e poi uso vari delay per un totale di 499ms, looper non sara' intaccato? il mio led lampeggera' ogni 500ms ?

Testato:
mmmm.

se ho capito questo e' qualle che io intendevo per delay2.0()
il leOS anche c'era vicino, ma forse era troppo,.

il leOS è tutt'altra cosa, molto più raffinata. E' immune dai vari problemi dei delay.
looper è molto più semplice. E' giusto una routine programmata per richiamare altre routine.

e' vero che il delay1.0 blocca looper, ma, sempre se ho capito, io posso usare looper al posto di ogni delay che ho in uno sketch, eliminando di fatto i delay bloccanti, e tenendo in gioco solo looper.

Se i delay li metti solo per eseguire a determinati intervalli altri compiti, sì: puoi usare looper in quel modo. Lo sketch di esempio "looper_2_task" fa infatti lampeggiare 2 led usando solo looper.

se imposto looper per accendere un led ogni 500ms, e poi uso vari delay per un totale di 499ms, looper non sara' intaccato? il mio led lampeggera' ogni 500ms ?

L'importante è che il loop principale duri sempre meno del task con il più piccolo intervallo, altrimenti quest'ultimo si allinea alla durata del loop principale.
Ad esempio, se metti un task a 500 ms per un flash di un led e poi metti un delay(1000) nel loop, vedrai che il led lampeggia ogni secondo, non ogni mezzo secondo.

yep, ottimo, come al solito

quindi looper puo' sostituire ad esempio il Blink without delay, che e' il classico esempio di millis

Sì. Non so se hai visto gli esempi allegati ma c'è proprio un blinkWithoutMillis (come c'era nel leOS).

Il classico BlinkWithoutDelay compila in 1028 byte, BlinkWithoutMillis in 1558 byte, quindi neanche un grosso carico di risorse in più per avere in cambio molta libertà in più.

leo72:
Seguendo la scia di leOS, e su richiesta di m_ri ( :stuck_out_tongue: ) ecco looper.

very perfect :slight_smile:
mi sa che prima o poi dovrò offrirti una birra x tutte le volte che ti rompo le scatole..

gli ho dato un'occhiata veloce,ma mi sembra tutto ok..
unico suggerimento:penso proprio che puoi evitare di usare "volatile",e così consenti ottimizzazioni al compilatore..
(e io stass non ho fatto niente in quanto ha smesso di piovere,e son uscito..)

m_ri:
unico suggerimento:penso proprio che puoi evitare di usare "volatile",e così consenti ottimizzazioni al compilatore..

Azz... vero :stuck_out_tongue_closed_eyes:
Come detto, looper l'ho sviluppato partendo proprio dal leOS per cui ho preso il suo codice ed ho tolto la roba inutile. Mi pareva di aver fatto pulizia profonda ma invece qualcosa l'ho lasciata. Ottimo appunto :wink:

Ecco, ho modificato lo zip allegato al 1° post. Si guadagnano una trentina di byte sulla compilazione di looper_BlinkWithoutMillis.

leo72:
Ecco, ho modificato lo zip allegato al 1° post. Si guadagnano una trentina di byte sulla compilazione di looper_BlinkWithoutMillis.

ora lo provo un èò complimenti :smiley: come mai non lo hai chiamato LEOoper invece di looper ]:smiley:

benissimo..
altra cosa,ma probab te ne sei già acorto: dopo 49 giorni inizia a eseguire il task a ogni ciclo del loop per un po' di tempo(in quanto plannedTask riperte da 0,e millis è moolto maggiore)

Madwriter:

leo72:
Ecco, ho modificato lo zip allegato al 1° post. Si guadagnano una trentina di byte sulla compilazione di looper_BlinkWithoutMillis.

ora lo provo un èò complimenti :smiley: come mai non lo hai chiamato LEOoper invece di looper ]:smiley:

ssshhh,che non ci aveva neanke pensato a sto nome.... XD

Madwriter:

leo72:
Ecco, ho modificato lo zip allegato al 1° post. Si guadagnano una trentina di byte sulla compilazione di looper_BlinkWithoutMillis.

ora lo provo un èò complimenti :smiley: come mai non lo hai chiamato LEOoper invece di looper ]:smiley:

ROTFL XD

m_ri:
benissimo..
altra cosa,ma probab te ne sei già acorto: dopo 49 giorni inizia a eseguire il task a ogni ciclo del loop per un po' di tempo(in quanto plannedTask riperte da 0,e millis è moolto maggiore)

Sì, lo so. L'alternativa più semplice è usare un contatore a 64 bit come ho fatto con leOS ma in questo caso si appesantisce moltissimo il codice finale (sono diverse centinaia di byte in più di Flash occupata). Oppure rivedere la logica dello scheduler per aggirare l'overflow.

In allegato trovate looper2, è una versione modificata di looper che dovrebbe sistemare il bug dell'overflow di milis mediante l'uso di un contatore di overflow a 8 bit, creando in pratica una variabile a 40 bit, che dovrebbe quindi soffrire del problema dell'overflow dopo 34 anni. Ho modificato anche lo scheduler affinché usi questa nuova gestione a 40 bit.

Siccome non ho potuto provare per 49,7 giorni BlinkWithoutMillis, rilascio il codice così com'è :sweat_smile: :sweat_smile:

looper2.zip (3.1 KB)

ahhaha grande leo, sempre sulla cresta dell'onda (lo so, ultimamente son lento ma troppo lavoro e niente ferie rendono lesto pazzo)

lesto:
ahhaha grande leo, sempre sulla cresta dell'onda (lo so, ultimamente son lento ma troppo lavoro e niente ferie rendono lesto pazzo)

Bisogna sempre inventare qualcosa di utile :wink:

x iscrizione

io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?

m_ri:

io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?

cosi se sei nella stessa provincia eviti di buttarti a mare? ]:smiley:

Madwriter:

m_ri:

io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?

cosi se sei nella stessa provincia eviti di buttarti a mare? ]:smiley:

perspicace il ragazzo!! :stuck_out_tongue:
oltre a quello, anke x sapere dove si può trovare un bagnino a cui fregare alcol e raspberry..