Arduino Forum

International => Italiano => Megatopic => Topic started by: leo72 on Aug 01, 2012, 11:28 pm

Title: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 01, 2012, 11:28 pm
Seguendo la scia di leOS, e su richiesta di m_ri ( :P ) 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:

Code: [Select]
#include "looper.h"
looper myScheduler;

Fatto questo, i metodi a disposizione sono 4:
Code: [Select]
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:
Code: [Select]
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  :smiley-sweat:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Aug 01, 2012, 11:37 pm
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 ?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 01, 2012, 11:50 pm

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.

Quote

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.

Quote

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.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Aug 02, 2012, 12:00 am
yep, ottimo, come al solito

quindi looper puo' sostituire ad esempio il Blink without delay, che e' il classico esempio di millis
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 12:05 am
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ù.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: m_ri on Aug 02, 2012, 12:19 am

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

very perfect :)
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..)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 12:30 am

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

Azz... vero  :smiley-yell:
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  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 12:33 am
Ecco, ho modificato lo zip allegato al 1° post. Si guadagnano una trentina di byte sulla compilazione di looper_BlinkWithoutMillis.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: Madwriter on Aug 02, 2012, 10:04 am

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 :D come mai non lo hai chiamato LEOoper invece di looper  ]:D
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: m_ri on Aug 02, 2012, 10:06 am
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)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: m_ri on Aug 02, 2012, 10:07 am


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 :D come mai non lo hai chiamato LEOoper invece di looper  ]:D

ssshhh,che non ci aveva neanke pensato a sto nome.... XD
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 11:34 am


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 :D come mai non lo hai chiamato LEOoper invece di looper  ]:D

ROTFL  XD
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 11:45 am

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.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 05:00 pm
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'è  :smiley-sweat: :smiley-sweat:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Aug 02, 2012, 08:37 pm
ahhaha grande leo, sempre sulla cresta dell'onda (lo so, ultimamente son lento ma troppo lavoro e niente ferie rendono lesto pazzo)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Aug 02, 2012, 08:40 pm

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  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: PaoloP on Aug 03, 2012, 09:53 am
x iscrizione
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: m_ri on Aug 03, 2012, 01:24 pm
Quote
io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: Madwriter on Aug 03, 2012, 01:26 pm

Quote
io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?

cosi se sei nella stessa provincia eviti di buttarti a mare? ]:D
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: m_ri on Aug 03, 2012, 08:10 pm


Quote
io mi sono inventato un lavoro come bagnino

In che provincia stai lavorando?

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

perspicace il ragazzo!! :P
oltre a quello, anke x sapere dove si può trovare un bagnino a cui fregare alcol e raspberry..
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Aug 04, 2012, 12:20 pm
legacy, ti comunico che sei rientrato nella mia lista dei cattivi  :smiley-yell:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: PaoloP on Mar 15, 2013, 03:49 pm
Ciao Leo,
tramite looper è possibile lanciare una istanza OneTime per effettuare l'accensione e lo spegnimento di un pin con un intervallo settabile?

Mi spiego:
avviene un evento
metto il pin HIGH
passa un tot di tempo
metto il pin LOW

questo solo una volta e per ogni evento.
Lo so che posso usare la millis con variabili di supporto, ma mi si incasina lo sketch.
oppure è meglio la Leos?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Mar 15, 2013, 04:15 pm
Un task di tipo onetime viene eliminato dallo scheduler una volta eseguito.
Quindi pare fatto apposta per il tuo caso.

Se la tempistica non è critica, puoi usare anche il looper invece che il leOS.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: PaoloP on Mar 15, 2013, 04:53 pm
Ok. Provo.  :smiley-roll:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 01, 2013, 11:44 am

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'è  :smiley-sweat: :smiley-sweat:

Leo rileggendo questo punto mi chiedevo: ma la situazione overflow millis e' stata risolta da te/lesto con il discorso dell'articolo del tuo blog ?
A questo punto non puoi usare quel metodo ed eliminare questa variabile da 40bit ?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 01, 2013, 11:50 am
Sì, vero. Ma quel post era di agosto, sai quant'acqua è passata sotto ai ponti... mica me lo ricordavo neanche  :smiley-yell:
Oggi provvedo a sistemare anche il looper. Grazie della segnalazione  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 01, 2013, 12:29 pm
sara' a tutti gli effetti il Delay2.0
spero il team si accorga della grande necessita' di una funzione di ritardo non bloccante integrata nel core
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 01, 2013, 06:44 pm
Nuovo looper 1.0 (http://www.leonardomiliani.com/2012/looper-uno-schedulatore-software-per-arduino/)!

Fantastico, che devo dire di più?  :smiley-yell:
Ecco un piccolo riassunto delle novità:
1) ridotto il codice compilato rispetto al vecchio looper2 (usando struct e ripulendo il codice)
2) mantenuta la sintassi dei metodi del looper2 (quindi addJob, removeJob ecc...) per poter usare il looper abbinato al leOS
3) nuovo metodo myDelay! Adesso è possibile introdurre nel codice principale un'attesa mentre lo scheduler continua a lanciare i job in sospeso!! Allegato alla libreria c'è un esempio che mostra proprio questa possibilità: un job fa lampeggiare un led ogni 100 ms mentre nel loop principale un altro led viene fatto lampeggiare con un intervallo di 1000 ms gestito proprio con myDelay. Come si può vedere, il led che lampeggia con il minor tempo di intervallo non risente del delay di 1000 ms, mentre i precedenti looper e looper2 soffrivano di questo problema.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: pighixxx on Apr 01, 2013, 08:19 pm
@leo72
+1

e complimenti!
Pighixxx
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 01, 2013, 11:43 pm
Grazie pighi.
Tornando ai punti, il 3 è quello più interessante.
L'esempio che ho inserito exnovo è questo:

Code: [Select]

//include the scheduler
#include "looper.h"

looper myScheduler; //create a new istance of the class looper

//variabiles to control the LEDs
byte led1Status = 0;
byte led2Status = 0;
const byte LED1 = 7;
const byte LED2 = 8;

//program setup
void setup() {
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
   
    //add the tasks at the scheduler
    myScheduler.addJob(flashLed1, 100);
}


//main loop
void loop() {
    digitalWrite(LED2, led2Status);
    led2Status ^= 1;   
    myScheduler.myDelay(1000);
    myScheduler.scheduler();
}


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


Ciò che mi preme evidenziare è :
Code: [Select]
myScheduler.myDelay(1000);
Questa istruzione mette il looper in un ciclo in cui per 1000 milisecondi altro non fa che controllare lo scheduler per lanciare i job eventualmente da eseguire. Il job flashLed1 deve essere eseguito ogni 100 ms, e così viene fatto, nonostante il loop si fermi per 1000 ms. Ciò si evidenzia dal fatto che il secondo led lampeggia proprio con la frequenza di 1 secondo.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 02, 2013, 01:13 pm
instancabile leo! posso chiederti come funziona il myDelay? in realtà è una sotto-dalay di 1ms che poi cha il ckeck, oppure fai un delay+delayMisslis fino al primo job schedulato, esegui, e così via fino a fine delay?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 02, 2013, 01:20 pm

instancabile leo! posso chiederti come funziona il myDelay? in realtà è una sotto-dalay di 1ms che poi cha il ckeck, oppure fai un delay+delayMisslis fino al primo job schedulato, esegui, e così via fino a fine delay?

E' una scemenza immane  :smiley-sweat:

Code: [Select]
void looper::myDelay(unsigned long myPause) {
unsigned long _tMillis = millis();
  while (millis() - _tMillis < myPause) {
    scheduler();
  }
}

In pratica è un while basato su millis() che dura per il tempo passato come argomento e dentro a cui chiamo ripetutamente lo scheduler  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 02, 2013, 01:47 pm
ahahaha, ah ragione astro, sono proprio un UCAS  :smiley-mr-green:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 02, 2013, 04:29 pm
Tengo a precisare che la scemenza immane non era quello che avevi detto tu ma la soluzione che avevo adottato io  ;) ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 02, 2013, 04:32 pm
bhe alla luce dei fatti la mia è una scemenza.. è valida per ambienti multithread, dove sprecare CPU vuol dire rubare risorse ad altri processi/thread, ma sull'arduino la tua soluzione è più che ottima  :smiley-mr-green:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 02, 2013, 07:39 pm
leo ma a questo punto possiamo dire di avere inventato il "mio" Delay2.0 ?

cioe' posso usare in autonomia myDelay, sostituendolo ai delay normali di arduino, senza creare nessun AddJob ?

cioe' questo funziona e non e' bloccante ?

Code: [Select]

BLINK 2.0
(idea Testato - creazione Leo :-) )

void loop() {
 digitalWrite(13, HIGH);  
 myScheduler.myDelay(1000);
 myScheduler.scheduler();
 digitalWrite(13, LOW);    
 myScheduler.myDelay(1000);
 myScheduler.scheduler();
}
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 02, 2013, 10:38 pm
funziona e puoi eliminare le due righe myScheduler.scheduler();
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 02, 2013, 10:42 pm

leo ma a questo punto possiamo dire di avere inventato il "mio" Delay2.0 ?

Guarda che l'ho chiamato myDelay, e non testatoDelay  :P

Quote


cioe' posso usare in autonomia myDelay, sostituendolo ai delay normali di arduino, senza creare nessun AddJob ?

Lo puoi fare ma a questo punto è inutile la lib.

Quote

cioe' questo funziona e non e' bloccante ?

Code: [Select]

BLINK 2.0
(idea Testato - creazione Leo :-) )

void loop() {
 digitalWrite(13, HIGH);  
 myScheduler.myDelay(1000);
 myScheduler.scheduler();
 digitalWrite(13, LOW);    
 myScheduler.myDelay(1000);
 myScheduler.scheduler();
}


Funziona ma non va bene ed il myDelay è bloccante per il codice così come il delay. Non è bloccante per i job inseriti nello scheduler. Ma se non usi nessun job nello scheduler, a che ti serve myDelay?

Ti spiego perché il tuo codice non va bene. Questo andrebbe bene:
Code: [Select]

BLINK 2.0
(idea Testato - creazione Leo :-) )

void loop() {
 digitalWrite(13, HIGH);  
 myScheduler.myDelay(1000);
 digitalWrite(13, LOW);    
 myScheduler.myDelay(1000);
}

Non so se hai visto il codice di myDelay che ho postato un paio di messaggi sopra per capire come funziona ma in pratica si tratta di un ciclo while che chiama costantemente lo scheduler finché non sono trascorsi i ms passati come parametro. Se il myDelay è l'ultima istruzione del loop, puoi evitare di chiamare lo scheduler perché l'ultima cosa fatta da myDelay è appunto l'invocazione di esso.

Ma a questo punto il codice qui sopra non va bene lo stesso perché nello scheduler non c'è nulla. Che lo fai a fare uno sketch del genere?  :P
Il codice giusto per avere un Blink non bloccante è invertire le cose e mettere il codice del lampeggio in un job e lasciare tutto il resto nel loop. Ad esempio, questo fa il blink mentre ad intervalli di 1 secondo stampa un valore sulla seriale:

Code: [Select]

#include "looper.h"
looper myScheduler;

byte led1Status = 0;
const byte LED1 = 13;
int counter = 0;

void setup() {
   pinMode(LED1, OUTPUT);
   Serial.begin(19200);
   myScheduler.addJob(flashLed1, 100);
}

void loop() {
   Serial.println(++counter);
   myScheduler.myDelay(1000);
}

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

Questo è un esempio concreto del delay 2.0, che non ferma l'esecuzione dei job in background ma funziona invece come delay classico per il codice principale.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 02, 2013, 11:30 pm
Se nemmeno lesto ha capito che mydelay è bloccante figurati se lo capivo io.

Ma quindi il delay2.0, mio e basta come diritti di autore, intedo come semplive comando da mettere nel loop, non si può tecnicamente fare ? O è difficile farlo ?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 02, 2013, 11:48 pm
Il myDelay ha un senso se ragioni in termini di RTOS o pseudotali.
Gli RTOS sono basati su un multitasking di tipo senza prelazione o cooperativo (cooperativo) o con prelazione (preemptive).
Questi ultimi sono quelli che dopo un certo periodo di tempo congelano lo stato di un task indipendentemente dalla volontà di quest'ultimo di essere bloccato. Quelli di tipo cooperativo passano il controllo al SO in modo volontario. In questo modo lo scheduler può passare il controllo della CPU ad un altro task.
Sull'Arduino DUE è stato implementato una specie di RTOS cooperativo in cui il codice della delay è stato rivisto ed ora fa un po' ciò che fa myDelay. Durante l'esecuzione del delay la CPU non è bloccata in un ciclo inutile ma salta da un task all'altro.

myDelay cerca di fare il verso a questo comportamento, con tutti i limiti di uno scheduler non gestito da interrupt né capace di salvare lo stato della CPU e dei suoi registri per congelare un task. Semplicemente fintanto che bisogna stare fermi ad aspettare viene comunque eseguito lo scheduler.

Rammentiamoci che delay è un'istruzione valida ed utile in alcuni casi. Se metto un delay significa che voglio bloccare il codice per un certo lasso di tempo. Magari, però, potrei voler bloccare solo una determinata parte di codice. I job, appunto, potrei volerli continuare ad eseguire. Quindi myDelay fa proprio questo: ferma il codice nel punto in cui è stata messa ma permette di continuare a fare altro.

Può risultare utile. Pensa ad esempio all'attesa dell'inizializzazione di qualcosa. Pensa ad esempio, per riallacciarsi al problema della Ethernet shield, al delay(300) che c'è in Ethernet.begin. Se ci metto myDelay(300) la libreria Etherner attende che il W5100 abbia fatto la sua inizializzazione ma nel contempo posso continuare ad eseguire altri compiti.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 02, 2013, 11:58 pm

Se nemmeno lesto ha capito che mydelay è bloccante figurati se lo capivo io.


:~ ho datol'impressione di non averlo capito?

la myDelay è a tutti gli effetti una delay() che però al contrario della vera delay permette a looper di funzionare. detta terra terra  :D
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 03, 2013, 12:13 am
Nota mi è più chiaro, grazie,
Vediamo se ho capito tentando di trovare l anello che manca. Io un idea c'è l ho, e magari davvero chiudiamo la questione.

- il delay ufficiale blocca tutto e va bene cosi
- il myDelay ( a questo punto tuo) è una via di mezzo, utile anch'esso
- il testatoDelay deve semplicemente nascondere ciò che facciamo con millis dietro ad una funzione, quindi il classico calcolo di millis a cui passiamo il valore che vogliamo


testatoDelay(1000);
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 03, 2013, 06:51 am

- il testatoDelay deve semplicemente nascondere ciò che facciamo con millis dietro ad una funzione, quindi il classico calcolo di millis a cui passiamo il valore che vogliamo

E' ciò che fa myDelay.
Sembra che sia tutto bloccato ma in realtà mentre è "ferma" può eseguire altre cose.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 03, 2013, 11:14 am
io voglio anche ammettere che non mi spieghi bene, ma voi ci mettete di vostro  :P

volete sapere meglio di un principiante di cosa ha bisogno un principiante ? non e' il vostro campo, fatevi da parte  :)

allora a noi esseri infimi che non capiamo nulla, ne'  abbiamo voglia di capire nulla, serve questo

Code: [Select]
BLINK 2.0
(idea Testato - creazione (se ha voglia e mi riesco a spiegare) Leo :-) )

void loop()
{
 digitalWrite(13, HIGH);  
 testatoDelay(1000);
 digitalWrite(13, LOW);    
 testatoDelay(1000);
 nel_frattempo_che_lampeggi_fai_infinite_cose();
}



in questo momento:
- se usi delay standard essendo bloccante blocchi le infinite cose per 2 secondi
- se crei un job dove mettere le infinite cose il gioco funge, ma come vedi tu stesso il programma diventa piu' grande e ostico.
- se invece vieni incontro al popolo che aspetta e pende dalle tue dita, creando il testatoDelay, avrai fatto la cosa piu' importante ed utile per la community, superiore alla stessa swRTC che ormai il mondo intero ci invidia  :)

Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 03, 2013, 11:37 am

Code: [Select]
BLINK 2.0
(idea Testato - creazione (se ha voglia e mi riesco a spiegare) Leo :-) )

void loop()
{
 digitalWrite(13, HIGH);  
 testatoDelay(1000);
 digitalWrite(13, LOW);    
 testatoDelay(1000);
 nel_frattempo_che_lampeggi_fai_infinite_cose();
}


Questo codice non va bene  :P
Ti dimentichi che la CPU del microcontrollore esegue il codice in maniera sequenziale, ossia una istruzione dietro l'altra.
Tu stai cercando un delay che non sia bloccante ma in realtà vuoi un delay che dica al compilatore: ecco, hai trovato la newDelay? Bene, ignorala e passa oltre.

Ora però ti spiego cosa succede col tuo codice:
1) loop
2) metti su HIGH il led 13
3) testatoDelay? allora salta avanti
4) metti su LOW il led 13
5) altra testatoDelay? salta avanti
6) ho del codice da eseguire, bene lo eseguo
7) torno a 1)

Ecco cosa farebbe testatoDelay  ;)
In realtà tu vorresti qualcosa tipo un blocco di codice da mettere nella tua testatoDelay da eseguirlo solo dopo l'intervallo desiderato. Come lo vuoi te non si può fare, va fatto in un'altra maniera, ad esempio così:
Code: [Select]

testatoDelay(1000, digitalWrite(13, HIGH)); 
testatoDelay(1000, digitalWrite(13, LOW));   
codice_da_eseguire

Ma così dovrei prendere il puntatore alla funzione e passarlo poi ad uno scheduler che lo infilerebbe nell'elenco dei lavori da eseguire, poi ogni volta dovrei passarglielo come parametro e tutte le volte dovrebbe controllare che funzione è, se è da eseguire o se è da saltare.
Ma allora non è meglio la myDelay attuale?
E poi statureresti la delay intesa come funzione che ferma il codice. Può esserci un'occasione in cui la delay serve, con la tua delay la si salta a piè pari.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 03, 2013, 12:51 pm
Ma il delay standard perche dovrebbe essere toccato ? Quello resta, e se mi serve lo uso.
Cosa facciamo ora con millis ? If questo - quello = x allora fai questaltro Else vai avanti.
Se più avanti mi serve delay standard lo uso.
Non vedere la mia idea come sostituto del delay, ma come nuovo tipo di delay.
Io dico solo di nascondere sotto una nuova funzione di looper questo delay nuovo fatto con if e millis
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 03, 2013, 01:16 pm
Mi spiace, io non riesco a capire questo tuo delay. Non riesco a capire proprio cos'è che vuoi fare.
Io ho inteso che quel che vuoi fare tu è ciò che ti ho spiegato nel precedente post. Tu però mi dici che ti serve un delay diverso. E che non riesco a focalizzare.  :~
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 03, 2013, 04:20 pm
purtroppo io meglio di cosi' non posso spiegarmi, perche' non ne ho le capacita'.

tento di resettare almeno per portare a conclusione il discorso con un si o con un no:

l'attuale semplicissima funzione, integrata nel core di arduino, delay(1000) e' bloccante, ed e' giusto cosi', nessuno vuole eliminarla.
ora la domanda semplice:
potra' tecnicamente un domani esistere, creata dal team arduinico stesso ed integrato nel core, una newdelay(1000); che non sia bloccante ?
ripeto cosi' come l'ho scritta, cioe' senza dover includere librerie, senza dover richiamare schedulator, senza dover creare job o altre funzioni, intendo semplicemente mettere newdelay(1000); in un qualsiasi punto dello sketch ?

Se mi dici No, non e' tecnicamente possibile riuscire a gestire un delay non bloccante con questi pochi parametri a disposizione, cioe' il nome newdelay ed il parametro 1000, io mi metto l'anima in pace, e l'essere umano dovra' usare looper o la tecnica millis fino alla fine dei tempi.  :)

Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: erpomata on Apr 03, 2013, 04:22 pm
Scusa ma non capisco neanche io.
Che dovrebbe ritardare(delay) questa nuova funzione?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 03, 2013, 04:36 pm
Credo intenda che la nuova "newdelay" dovrebbe attendere come l'attuale delay ma senza bloccare gli interrupt.

Ho visto nel core.cpp che la delay si basa sulla micros() che internamente chiama cli(); quella cli()  ferma gli interrupt?

La delayMicroseconds invece è fatta in maniera molto diversa. Alla fine poi c'e' un pezzo in asm. Quella è bloccante rispetto agli interrupt?


La millis() anche lei momentaneamente blocca gli interrupt:
Code: [Select]

unsigned long millis()
{ unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 03, 2013, 07:07 pm
Quote
ma senza bloccare ad esempio gli interrupt

non tirare inmezzo gli interrupt, questa librerira NON li usa. ed è per questo che ha creato la cosa leo.

Quote
m = timer0_millis;

questa è l'unica iustruzione per cui gli interrupt sono bloccati, poi li riattiva con
Quote
SREG = oldSREG;

quindi parliamo di una decina di clock, 20 a star larghi direi, andando a naso.

Quote
La delayMicroseconds invece è fatta in maniera molto diversa

non hai timer così precisi, quindi si basa sul fatto che sa che ad una certa frequenza di clock certe istruzioni impiegano tot clock, e quindi tot clock * frequenza = tempo.... e tanta imprecisione :)

Quote
potra' tecnicamente un domani esistere, creata dal team arduinico stesso ed integrato nel core, una newdelay(1000); che non sia bloccante ?

ni.
nel senso: la delay non bloccante come fa a sapere che codice deve eseguire al termine del 1000?
risposta: gli passi come parametro una funzione, che conterrà il codice da eseguire ogni tot.
e già esiste: looper(non usa interrupt quindi ogni tatnto devi chiamare scheduler(), meno preciso, ma permette funzioni lunghe) e leOS(interrupt, basta settare il dalay e la funzione ed eventualmente il tempo di ripetizione, ma essendo la funzione eseguita in interrupt ha i classici svantaggi)

Ora, tu dici creata dal team. io ti dico: perché la SoftSerial attuale è esterna, e poi integrata nel core perchè considerata "degno sostituto". Lo stesso POTREBBE avvenire con il leOS o lo sheduler.

Quote
senza dover includere librerie

Anche la delay che usi è una libreria.. solo che la include in automatico arduino IDE. Quindi si può fare, ma ci vuole una ottima ragione.

Quindi risposta generale:
NO: se non chiami sheduler (come leOS), allora sei bloccato dalle limitazioni interrupt. Se usi looper() e metti sheduler() nel main(nascosto) dell'arduino a fine di ogni loop ( come per SerialEvent() )se il tuo loop() è pieno di delay non avrai mai i task eseguiti con la giusta tempistica.
Quindi non esiste un testatoDelay() come lo intendi.. niente "silver bullet".
A meno che non si riesca a creare un VERO scheduler con due thread: uno per la loop e uno, con priorità superiore, per task schedulati, cche magari lancia ogni sotto-task in un thread a parte. Però a questo punto... che thread a precedenza sugli altri?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 03, 2013, 07:46 pm

Quote
ma senza bloccare ad esempio gli interrupt

non tirare inmezzo gli interrupt, questa librerira NON li usa. ed è per questo che ha creato la cosa leo.


A quale libreria ti riferisci, non capisco!? La delay del core o quella di @leo ?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 03, 2013, 08:22 pm
quella di leo
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 03, 2013, 08:30 pm
Ho scritto:
>>Credo intenda che la nuova "newdelay" dovrebbe attendere come l'attuale delay ma senza bloccare gli interrupt.
Ovvero rispondevo per @Testa, vorrebbe una newdelay non bloccante rispetto agli interrupt cosa che invece fa la delay attuale.
Lo sò anche io che la libreria di @Leo NON è bloccante neppure per gli interrupt.

@Testa, veramente non ha senso quello che chiedi. Solo un discorso di non bloccare gli interrupt può avere senso.
Una newdelay(1000) o è bloccante, oppure che senso ha?
Con la millis() tu, ripeto tu, scrivi del codice che viene eseguito nel mentre conti i millis, per fare la stessa cosa dovresti avere una newdelay che come dice @Leo dovrebbe richiamare una funzione da eseguire mentre la newdelay conta.
E' come se tu chiedessi di poter fare "qualcosa" (istruzioni decise da te) mentre che sò, chiami la digitalWrite() (anche lei è una funzione che ha una serie di istruzioni)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 03, 2013, 08:34 pm
bhe ma da quel punto di vista anche quella di leo usa la millis() quindi è bloccante.. ma è davvero definibile bloccante qualcosa che blocca gli interrupt per 10 clock? io per bloccante per interrupt intendo qualcosa che blocca li interrupt per TUTTA la sua esecuzione.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 03, 2013, 08:42 pm
Scusa, ma che c'entra una o più mills chiamate in una serie di istruzioni rispetto a una delay() che blocca gli interrupt per tutto il tempo t che hai passato come parametro?

Domanda mia però. Ma veramente la delay è così bloccante per gli interrupt?
Code: [Select]

void delay(unsigned long ms)
{ uint16_t start = (uint16_t)micros();
 while (ms > 0) {
if (((uint16_t)micros() - start) >= 1000) {
ms--;
start += 1000;
}
 }
}


La delay richiama più volte la micros() che internamente chiama cli() ma poi all'uscita rimette a posto SREG.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 03, 2013, 10:10 pm
Quote
Domanda mia però. Ma veramente la delay è così bloccante per gli interrupt?

NO! La delay non è bloccante per gli interrupt, da dove salta fuori?

forse c'è stata fonfusione su questa affermazione:


Credo intenda che la nuova "newdelay" dovrebbe attendere come l'attuale delay ma senza bloccare gli interrupt.

Ho visto nel core.cpp che la delay si basa sulla micros() che internamente chiama cli(); quella cli()  ferma gli interrupt?


che come spiegato poi blocca sì gli interrupt, ma solo per una decina di clock.

Quote
Una newdelay(1000) o è bloccante, oppure che senso ha?

quando testato parla di bloccante non intende per i delay, intende una cosa tipo
Code: [Select]
testatoDelay(millisecondiDqaAttenderePrimaDiEseguire, funzioneDaEseguire);
che però come già detto è quello che fa già il looper e il leOS, che però hanno le loro limitazioni a cui non si può scappare, credo(come detto prima dipende dall'architettura del micro, che credo non lo conseta prorpio)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 03, 2013, 11:30 pm
Finalmente ho capito, grazie a tutti  :) (karma per tutti)

x nid69ita: per bloccante non intendo rispetto agli interrupt, ma vista la mia strana richiesta tu giustamente hai pensato a quelli.

credo che la risposta definitiva e che mi ha fatto capire e' quella di Leo
Quote
la delay non bloccante come fa a sapere che codice deve eseguire al termine del 1000?


giustamente con il delay ufficiale e' facile, blocchi tutto il micro e via, alla fine del tempo prefissato riparti con l'istruzione successiva, mentre con una ipotetica newDelay non bloccante, senza passare per looper o altro, come fa il micro a sapere cosa deve gestire ?

grazie per avermi aperto la mente  :)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 03, 2013, 11:43 pm
Potrebbe piacerti questa schifezzuola di codice, molto poco ortodosso, nascondo tutta la millis con delle define (IDE Arduino compila ma non ho provato):
Code: [Select]

#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define BEGINDELAY(t,v) unsigned long MACRO_CONCAT(prev,v)=0; unsigned long MACRO_CONCAT(curr,v)=millis(); if(MACRO_CONCAT(curr,v)-MACRO_CONCAT(prev,v)<(t)) {
#define ENDDELAY(v) MACRO_CONCAT(prev,v)=MACRO_CONCAT(curr,v);}

void setup()
{ }

void loop()
{ BEGINDELAY(500,1)
   // qui metti codice per eseguire mentre conta il primo delay
 ENDDELAY(1)
 BEGINDELAY(600,2)
   // qui metti codice per eseguire mentre conta il secondo delay
 ENDDELAY(2)
}


oppure
Code: [Select]

#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define BEGINDELAY(t,v) unsigned long MACRO_CONCAT(prev,v)=0; unsigned long MACRO_CONCAT(curr,v)=millis(); if(MACRO_CONCAT(curr,v)-MACRO_CONCAT(prev,v)<(t)) { MACRO_CONCAT(prev,v)=MACRO_CONCAT(curr,v);
#define ENDDELAY }

void setup()
{ }

void loop()
{ BEGINDELAY(500,1)
   // qui metti codice per eseguire mentre conta il primo delay
 ENDDELAY
 BEGINDELAY(600,2)
   // qui metti codice per eseguire mentre conta il secondo delay
 ENDDELAY
}


P.S. vietato tirarmi sassi o qualsiasi materiale contundente, valgono solo gli insulti
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 03, 2013, 11:49 pm
nel secondo credo che

Code: [Select]
#define ENDDELAY(v) }

debba essere

Code: [Select]
#define ENDDELAY }

:smiley-mr-green:

edit: buon debug!
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 04, 2013, 06:34 am
@nid69:
siccome io spiego sempre per bene tutto il codice, ora tu ti prendi caffè e brioscia, poi con calma ti metti lì e spieghi ad un programmatore NON professionista, cioè io.., cos'è che fa il tuo codice.  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: erpomata on Apr 04, 2013, 07:03 am
Effettivamente non è chiaro neanche a me.
Non è la stessa cosa di:

Code: [Select]
while(currentMillis - previousMillis1 > interval1){
   // qui metti codice per eseguire mentre conta il primo delay
}
while(currentMillis - previousMillis2 > interval2){
   // qui metti codice per eseguire mentre conta il secondo delay
}
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 04, 2013, 08:28 am
Esatto però le chiama curr# e prev# dove # è il secondo numero dato alla macro.
Però non funsiona perché prev# viene distrutta a fine loop e riceeata ogni loop. Forse rendendola statica o global, non ricordo come ma mi pare sia possibile.

Quindi una macro che crea variabili globali di nascosto...

Come dicevo prima buon debug

Ps ma il secondo definea chè serve?! Credo si possa togliere
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 09:05 am
Il precompilatore sostituisce brutalmente quello che si definisce con la #define. E' possibile però passare anche dei "parametri"
Molte librerie nascondo alcune implementazioni con le define.
Se vai a vedere dentro la Arduino.h scoprirai ad esempio che esiste la #define noInterrupts() cli(), ovvero quando scrivi nello sketch noInterrupts() questa viene sostituita dalla funzione cli().
In teoria le 2 macro che ho scritto volevano fare una cosa molto brutta, l'ho detto. Nascondere questo pezzo di codice in due macro parametriche:
Code: [Select]
unsigned long prev1=0;
unsigned long curr1=millis();
if(curr1-prev1<t)
{                                              // BEGINDELAY(t,v)

 prev1=curr1;                                // ENDDELAY(v)
}


E' una if e non una while, le variabili sono esterne al blocco, perciò sono locali. Effettivamente NON funziona perchè prev non mantiene il valore. ooops!!!
Il parametro t sarebbe il tempo della delay, v un numero per creare variabili con nomi sempre diverse. Volevo usare __COUNTER__ del prepocessore di gcc ma  essendo righe diverse non son riuscito a farmi dare dal preprocessore variabili con nomi sempre diversi.
Ripeto, è una cavolata, io non lo adotterei mai, tanto vale usare il codice completo scritto sopra. Però la potenza della #define, veramente mitica.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 04, 2013, 09:16 am
Non mi riferivo alla #define, so a che serve  ;).
Intendevo come il tuo codice risolveva (se lo faceva) il problema di testato, ossia di istruire il compilatore ad eseguire esclusioni intelligenti e temporizzate del codice  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 09:25 am
Cosi dovrebbe funzionare, mi sembra giusto cercare di dare una versione funzionante. Ma NON la usate, è una cavolata.
Code: [Select]

#define MACRO_CONCAT( x, y ) x##y
#define INITDELAY(v) unsigned long MACRO_CONCAT(g_prev,v)=0; unsigned long MACRO_CONCAT(g_curr,v);
#define BEGINDELAY(t,v) MACRO_CONCAT(g_curr,v)=millis(); if(MACRO_CONCAT(g_curr,v)-MACRO_CONCAT(g_prev,v)<(t)) {
#define ENDDELAY(v) MACRO_CONCAT(g_prev,v)=MACRO_CONCAT(g_curr,v); }

// sketch
INITDELAY(1)
INITDELAY(2)

void setup()
{ }
void loop()
{ BEGINDELAY(500,1)
   // qui metti codice per eseguire mentre conta il primo delay
 ENDDELAY(1)
 BEGINDELAY(600,2)
   // qui metti codice per eseguire mentre conta il secondo delay
 ENDDELAY(2)
}


@Leo mi hai detto di spiegare (giustamente) per chi non conosce il precompilatore. Si, cercavo di "risolvere" il problema di @Testa. Mi chiedevo ieri sera se era possibile nascondere quel che si fa con la millis() (come detto anche da lui stess) e ci ho provato.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 04, 2013, 10:16 am
No, non fraintendermi  :smiley-sweat:
Credevo che avessi trovato davvero una soluzione funzionante e siccome io non sono un programmatore professionista immaginavo che avessi sfruttato qualche procedura o tecnica particolare delle #define  ;)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 04, 2013, 10:22 am
ancora meglio:

usando static si può creare una variabile globale dall'interno di un blocco. In oltre l'inizializzazione fatta nella riga di inizializzazionbe vien fatta una sola volta; quidi se nel primo esempio rendi prev static risolvi il problema.

La tua ultima versione è ok, però se metti un { a inizio BEGINDELAY e un } alla ENDDELAY, gcurr diventa una variabile dichiarata all'interno del blocco e quindi non è più soggetta a problemi di visibilità in tutto il loop. quindi puoi dargli un nome fisso.

io farei così (proprio a volersi fare male), usando il blocco doppio, che rende il codice un pelo più leggibile, e la static, evitando così la #define INITDELAY:

Code: [Select]

#define MACRO_CONCAT( x, y ) x##y
#define BEGINDELAY(t,v) { static unsigned long MACRO_CONCAT(prev,v)=0; unsigned long timeHidden123=millis(); if(timeHidden123-MACRO_CONCAT(prev,v)<(t)) {
#define ENDDELAY(v) MACRO_CONCAT(prev,v)=timeHidden123;}}

void setup()
{ }

void loop()
{ BEGINDELAY(500,1)
   // qui metti codice per eseguire mentre conta il primo delay
 ENDDELAY(1)
 BEGINDELAY(600,2)
   // qui metti codice per eseguire mentre conta il secondo delay
 ENDDELAY(2)
}
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 10:25 am
Bene @Lesto, ora c'e' una versione funzionante. @Leo ora abbiamo risposto a @Testa. Si può fare, anche se poco elegante e secondo me poco utile.
:smiley-mr-green:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 04, 2013, 10:46 am
secondo il mio punto di vista è uno spreco di risorse ed un complicarsi la vita per niente,   ;) dato che tutto ritorna ad essere un semplice if..then.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 11:10 am

secondo il mio punto di vista è uno spreco di risorse ed un complicarsi la vita per niente,   ;) dato che tutto ritorna ad essere un semplice if..then.


:smiley-mr-green:  :smiley-mr-green: :smiley-mr-green:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: testato on Apr 04, 2013, 09:26 pm
io invece credo che il principiante lo preferisca, tanto di cosa significano le define nemmeno gli frega nulla, ed il gestire con un begindelay/endelay un delay non bloccante sia molto intuitivo, non e' l'utopistico testatoDelay() ma e' sempre meglio del gestire il millis.

ma il tutto puo' ulteriormente essere nascosto in una libreria ? in modo che invece di avere le define si dice: we bello usa la libreria newdelay

a questo punto questa libreria, che diventerebbe importantissima a livello planetario porterebbe il mio nome in quanto ideatore, quello di nid69ita in qualita' di operaio, e quello di lesto in qualita' di consulente. Leo invece nulla in quanto ostacolatore del progetto  :smiley-yell:
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 09:46 pm
Basta che metti le #define in un file .h
Che sò, si potrebbe chiamare   testonidlesto.h  :smiley-mr-green:
Code: [Select]

#define MACRO_CONCAT( x, y ) x##y
#define BEGINDELAY(t,v) { static unsigned long MACRO_CONCAT(prev,v)=0; unsigned long timeHidden123=millis(); if(timeHidden123-MACRO_CONCAT(prev,v)<(t)) {
#define ENDDELAY(v) MACRO_CONCAT(prev,v)=timeHidden123;}}
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 04, 2013, 10:12 pm
Testato, io sarò anche assonnato, ora, ma non vedo differenza fra questa newDelay ed il looper in sé, perché in pratica tu vuoi uno scheduler software.
Io ho scritto una delay intelligente, che permette di eseguire altri compiti mentre sta facendo ciò che il suo nome dice, ossia fermare il codice.
Tu stai portando avanti l'idea di uno scheduler, perché questo è il tuo newdelay. Tu vuoi un qualcosa che passi da un punto del programma, faccia un if per verificare che non sia giunto il tempo di eseguire un certo compito, e poi scorra avanti. Mi spieghi però come si deve comportare la tua newdelay nel caso ci sia qualcos'altro subito dopo?
Esempio:

Code: [Select]
void loop() {
  BEGINDELAY(500,1)
    // qui metti codice per eseguire mentre conta il primo delay
  ENDDELAY(1)
  BEGINDELAY(600,2)
    // qui metti codice per eseguire mentre conta il secondo delay
  ENDDELAY(2)
  ....altro codice....
}


Quel "qualcosa" verrà eseguito sempre perché la tua newdelay non è una delay. Come sono confuso io, lo sarà anche l'utente che la userà pensando ad un qualcosa che ferma il codice mentre invece non lo fa.
La tua idea di newdelay è in realtà ciò che è uno scheduler, eseguire cioè dei compiti ad intervalli prefissati. O mi sbaglio?
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: nid69ita on Apr 04, 2013, 10:17 pm
Non ti sbagli per nulla. Effettivamente il nome è ambiguo.
Se al posto del if, mettiamo while, forse la risolviamo, ma mica c'era intenzione di fare una libreria  :smiley-mr-green:
Per me è stata solo una pensata fatta più per gioco/sfida. Se poi @Testa la vuol usare... però bisogna adeguarla.
Code: [Select]

#define MACRO_CONCAT( x, y ) x##y
#define IFDELAY(t,v) { static unsigned long MACRO_CONCAT(prev,v)=0; unsigned long timeHidden123=millis(); if(timeHidden123-MACRO_CONCAT(prev,v)>(t)) { MACRO_CONCAT(prev,v)=timeHidden123;
#define WHILEDELAY(t,v) { unsigned long MACRO_CONCAT(prev,v)=millis(); while(millis()-MACRO_CONCAT(prev,v)<(t)) {
#define ENDDELAY }}

void setup()
{ delay(2000);
 Serial.begin(9600);
}

void loop()
{ Serial.println("prima di if");
 IFDELAY(1000,1)
    Serial.println("--------- dentro la if");
 ENDDELAY
 Serial.println("dopo la if");

/*  commentato per provare il pezzo sopra senza questo sotto
 Serial.println("inizio while");
 WHILEDELAY(500,2)
    Serial.println("==== dentro la while");
 ENDDELAY
 Serial.println("fine while");
*/
}


*** Edit: ho aggiustato il codice e provato con Arduino. Ora mi sembra okay, anche se è solo una cosa accademica, non pretende di essere una libreria o chissà che.
Ci sono 2 tipi di delay, anche se NON è corretto chiamarli delay. E' stato solo un modo per cercare di nascondere l'uso della millis() che non per tutti è semplice da capire.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: lestofante on Apr 05, 2013, 12:01 am
con la while così hai creato un loop infinito, e anche se la correggi hai un sistema per esegiore la stessa cosa per un tot di tempo e poi eseguire altro..

che è un'altra cosa ancora.

Secondo me è più intuitiva la storia dei Task, se visto come un calendario; all'inizio fissi degli appuntamenti, che possono essere eseguiti con un certo ritardo e poi eventualmente ripetuti con un altro ritardo.

La libreria di leo è il calendario, le funzioni cosa fare all'appuntamento, e schedule() il modo per dire all'arduino di controllare se c'è qualche appuntamento in questo momento (o qualche appuntamento scaduto, che arduino porterà comunque a termine.. non è che se oggi non porti fuori la spazzatura non lo farai mai più, quando te ne ricordi provvedi il prima possibile)
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: erpomata on Apr 05, 2013, 05:40 am
Io direi di ripulire il topic e separare le discussioni.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: leo72 on Apr 05, 2013, 06:45 am
Se Testato vuol portare avanti la questione della newDelay come la intende lui lo faccio senza problemi.
Per me può altrimenti restare tutto qui, si tratta sempre di una discussione inerente il modo di eseguire determinati compiti con uno scadenzario.
Title: Re: looper - un semplice schedulatore senza timer/interrupt
Post by: erpomata on Apr 05, 2013, 06:46 am
Bè però non centra nulla col titolo della discussione.
Ma visto che l'hai aperto tu decidi tu.  :D