Go Down

Topic: Azzerare la funzione millis() (Read 12415 times) previous topic - next topic

marcello.romani

Intendiamoci: se riesci a far funzionare ciò che hai già, tutti contenti. Non era mia intenzione dare giudizi :D

Dico solo che per mia esperienza il pilotaggio dei PP, anche se semplice in linea di principio, nella pratica è talmente pieno di criticità e trabocchetti da giustificare ampiamente (a meno che non sia lo scopo principale del progetto, ovvio) l'acquisto di una soluzione "chiavi in mano". Quanto "chiavi in mano" dipende da caso a caso e dalle preferenze / capacità del singolo.

"internals" sta per "gli oscuri meccanismi interni"... :D

qsecofr

#16
Dec 04, 2012, 01:12 pm Last Edit: Dec 04, 2012, 01:16 pm by qsecofr Reason: 1


Volevo chiedervi secondo voi all'interno del seguente ciclo While, il valore della variabile upDelayTime, viene incrementato solo all'inizio di ogni nuovo blocco delle 4 istruzioni che contiene o  viene incrementata blocco dopo blocco?? In altre parole, viene incrementata solo ogni 4 passi o dopo ogni passo del motorino?? E di quanto? quello che credo io è che venga incrementata di un valore pari a decelfactor, è corretto secondo voi??



updelaytime viene calcolato solo ad ogni inizio di ciclo while quindi hai 4 delay tutti uguali ogni ciclo.
Non so se il mio intervento può essere utile ma devi prestare un attimo attenzione alla "granularità" del millis e alla moltiplicazione con il tuo decelFactor... l'arrotondamento degli interi... presta attenzione...
dopo un'altra annotazione: se per esempio decel factor = 1 questo implica che tra millis =1 e millis = 2 hai un dimezzamento netto della velocità....mentre tra millis = 9 e millis = 10 avresti un calo del 10% della velocità... non so se è quello che vuoi...

un'altra cosa: ti hanno già parlato della lentezza del writedigital... io ti parlo della "asincronia" dei quattro movimenti che fai sugli avvolgimenti... a piccole velocità probabilmente non te ne renderai conto ma sarebbe bene che i 4 valori di uscita fossero settati contemporaneamente perchè se no rischi di dare corrente seppur per qualche microsecondo all'avvolgimento sbagliato... dovresti vedere l'uso delle porte.

leandro78

#17
Dec 04, 2012, 01:26 pm Last Edit: Dec 04, 2012, 01:39 pm by leandro78 Reason: 1

Ciao qsecofr, grazie mille per la risposta, era proprio come pensavo io...

Quanto al problema relativo al dimezzamento della velocità, questo in realtà non si pone, perchè il nuovo valore viene sommato al precedente, cioè il motorino non è fermo iniziamlemte ma parte già con una certa velocità che viene progressivamente ridotta.

Scusate questa istruzione dovrebbe incrementare il valore della variabile upDelayTime di un valore pari a decelFactor ogni 100 millisecondi, è corretto?

Quote

   upDelayTime += decelFactor*(millis()/100);



Grazie ancora infinitamente a tutti gli intervenuti....

marcello.romani

Se ricordo bene il mio codice era più o meno così:

const N = 4
byte portValue[N] = { ... }

loop():
   PORTB = portValue[passo]
   delay(d)
   passo++
   if passo >= N
       passo = 0
   endif

PORTB va ovviamente sostituita in base agli specifici collegamenti.
I valori da assegnare a portValue vanno calcolati in base alle configurazioni degli avvolgimenti.
Inoltre se PORTB è usata anche per altri scopi le cose si complicano.

lestofante

internals non vuol dire niente, è inteso per indicare questi comportamenti a basso livello.

Arduino a causa delle risorse limitate ha molti "accrocchi" per far funzionare le cose (vedi micros() spiegata da leo poco sopra), quindi se cambi qualcosa di basso livello normalmente "rompi" alcune funzioni di arduino o delle sue librerie, quindi se non sai cosa stai toccando è molto probabile che gli effetti collaterali di una modifica a basso livello vadano a rompere un'altra parte del tuo codice.
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

leandro78

Scusami lesto ma quali sarebbero queste modifiche a basso livello che avrei apportato? non ho capito bene a cosa vi riferite....

qsecofr




Scusate questa istruzione dovrebbe incrementare il valore della variabile upDelayTime di un valore pari a decelFactor ogni 100 millisecondi, è corretto?

Quote

   upDelayTime += decelFactor*(millis()/100);



Grazie ancora infinitamente a tutti gli intervenuti....


...mi pare di no... ogni volta che la chiami lei incrementa... che siano trascorsi i 100 millis o meno...
supponiamo per semplicità decelFactor = 1 e che la funzione venga chiamata ogni 10 millisecondi per i primi 100 millis
non cambia perchè hai updelayTime = updelaytime + 1* ( (<100)/100) quindi sommi sempre 0... poi quando arrivi allo scatto dei 100 millisecondi il risultato della divisione >100/100 ti torna 1 e da allora ogni volta che chiami questa funzione lui ti somma 1 fino ai 200 millisecondi dove ti sommerà 2 ma praticamente tra i 100 ed i 200 millisecondi ipotizzando appunto di chiamarla ogni 10 millisecondi lui ti ha già fatto diventare updelaytime = 10.
Stai attento quindi all'assegnazione += ... è una assegnazione amata dai programmatori C/C++ ma porta spesso a questi errori dovuti a minore leggibilità del codice... un "ingeniere del software" amerebbe maggiormente scrivere A = A+x;




leandro78

#22
Dec 04, 2012, 02:37 pm Last Edit: Dec 04, 2012, 02:40 pm by leandro78 Reason: 1
E' vero, non me n'ero reso conto!!!  :(

Ma se scrivessi

millis()/100.

continuerebbe a restituirmi un intero? Come potrei fare ad ottenere un valore reale e non intero da quella divisione??

lestofante


Molti suggeriscono di fare un semplice timer0_millis=0 ma quando si ha a che fare con variabili manipolate all'intero di interrupt è bene sempre prima fermare gli interrupt stessi e riattivarli dopo che si è fatto ciò che si doveva fare.


uhmm da quel che so gli interrupt non si possono sovcrepporre, in pratica clie e sei sono chiamati in automatico

Quote
Come potrei fare ad ottenere un valore reale e non intero da quella divisione??


100.0, con quel .0 il numero diventa float (ovvero a virgola mobile) e quindi tutta la divisione viene eseguita con i float. Però anche la variabile risulatto deve essere float, altrimenti il risultato viene tagliata la parte dopo la virgola (tieni solo la parte INTera)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

leo72



Molti suggeriscono di fare un semplice timer0_millis=0 ma quando si ha a che fare con variabili manipolate all'intero di interrupt è bene sempre prima fermare gli interrupt stessi e riattivarli dopo che si è fatto ciò che si doveva fare.


uhmm da quel che so gli interrupt non si possono sovcrepporre, in pratica clie e sei sono chiamati in automatico

Sì, gli interrupt non si possono sovrapporre ma tu non stai invocando un interrupt ma stai manipolando una variabile aggiornata da un interrupt. E di interrupt ce ne sono molti in un microcontrollore, non solo quello legato al timer 0.
Io consiglio di disattivarli a livello globale (cli), è una singola istruzione assembly, perdi 1 solo ciclo di clock.

qsecofr

...prova a vedere se su questo codice********RIGOROSAMENTE NON TESTATO****** trovi qualcosa che può illuminarti.
...questo incrementa ogni 100 millisecondi... però ricorda che quando scorporerai dal ciclo loop la funzione dovrai ricordarti di chiamarla almeno ogni 100 millisecondi altrimenti ti scappa un aggiornamento... quindi ipotizzando di cacciarla in qualche parte del tuo codice devi stare attento che il upDelayTime non superi i 25millisecondi  (...per 4 = 100...)

Per l'esperienza che ho avuto con i motori passo passo, e premetto che avevo pure un controllore che si arrangiava con i 4 avvolgimenti voglio chiederti che velocità di rotazione ti aspetti... perchè ho avuto i miei c@zzi a non mandare in blocco i miei... 400 impulsi giro, fino a 1000 giri di velocità, accellera e decellera in max 2 secondi.

Code: [Select]

int upDelayTime =0;
long start = 0;
int decelFactor=1;


void setup() {
 start = millis();
}

void loop() {

 if ((millis()- start ) > 100) {
   upDelayTime = upDelayTime + decelFactor ;
   start = millis();
   };

}



Pelletta

Scusate la domanda, quando possibile non conviene resettare sempre mllis?
Al posto di

Code: [Select]
if(millis() - millisPrecedente > intervallo)
{
   millisPrecedente = millis();
   ....
}


basterebbe fare se non ho capito male

Code: [Select]
if(millis() > intervallo)
{
  resetMillis();
  ...
}


In questo modo si risparmierebbe l'uso di una variabile (millisPrecedente) e un'operazione

leo72

In teoria non serve resettare millis(), se si usa millis() correttamente:
http://www.leonardomiliani.com/?p=576

lestofante


tai manipolando una variabile aggiornata da un interrupt


woops, confusione mia

Quote
In questo modo si risparmierebbe l'uso di una variabile (millisPrecedente) e un'operazione


sì, in cambio però probabilmente rompi il PWM e qualsiasi libreria che usi la millis() in modo "correrto".

Ogni programma deve essere pià indispensabile possibile, se no te lo immagini se ogli libreria arduino facesse quello che vuole con timer etc? già succedono casini cercando di usare il minimo indispensabile.

e poi iuscire a tracciare un bug del genere diventa pressochè impossibile. Definitiva: 4byte in più valgono ben millemila ore di debug in meno, specialmente se sei "carne fresca"  ]:)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

Pelletta

Hai ragione Lesto, proprio per questi motivi infatti avevo scritto "quando possibile"

Go Up