Go Down

Topic: looper - un semplice schedulatore senza timer/interrupt (Read 25885 times) previous topic - next topic

leo72

@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.  ;)

erpomata

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
}

lestofante

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
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

nid69ita

#63
Apr 04, 2013, 09:05 am Last Edit: Apr 04, 2013, 09:11 am by nid69ita Reason: 1
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.
my name is IGOR, not AIGOR

leo72

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  ;)

nid69ita

#65
Apr 04, 2013, 09:25 am Last Edit: Apr 04, 2013, 09:30 am by nid69ita Reason: 1
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.
my name is IGOR, not AIGOR

leo72

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  ;)

lestofante

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)
}
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

nid69ita

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:
my name is IGOR, not AIGOR

leo72

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.

nid69ita


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:
my name is IGOR, not AIGOR

testato

#71
Apr 04, 2013, 09:26 pm Last Edit: Apr 04, 2013, 09:28 pm by Testato Reason: 1
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:
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

nid69ita

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;}}
my name is IGOR, not AIGOR

leo72

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?

nid69ita

#74
Apr 04, 2013, 10:17 pm Last Edit: Apr 05, 2013, 01:59 pm by nid69ita Reason: 1
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.
my name is IGOR, not AIGOR

Go Up