Go Down

Topic: Errore differenza Millis()(RISOLTO) (Read 935 times) previous topic - next topic

ibbba

Oct 20, 2013, 05:53 pm Last Edit: Oct 21, 2013, 05:27 pm by ibbba Reason: 1
Salve a tutti,espongo un problema che sto riscontrando a cui non riesco a venire a capo,sicuramente banale,ma non ne esco:
allora spiego il codice:
durante il ciclo salvo un preciso istante in una variabile unsigned long che chiamo salvamillis.
Più avanti nel codice eseguo una semplice differenza per controllare se un determinato intervallo è trascorso:
Code: [Select]

if (millis() - salvamillis < secondiRitardoMillis)bitSet(qualcosa);
     else bitClear(qualcosa);

specifico che secondiRitardoMillis è di tipo unsigned long e ,per salvare il settaggio in eeprom,la ricavo nel setup con una moltiplicazione del byte salvato in eeprom moltiplicato mille:
secondiRitardoMillis = secondiRitardo * 1000;

Allora fino a che secondiRitardo vale 32 tutto fila liscio,mentre se aumento il valore oltre l'if mi restituisce sempre una condizione vera.
Immagino che sia un solo problema di overflow,però avendo utilizzato il giusto tipo di variabili tra le operazioni di confronto non riesco a capire come correggere il ciclo!!....mi date qualche dritta??...grazie

PaoloP

Di solito si mette > nell'IF non minore.
In quel modo controlli se sei ancora nell'intervallo e non se lo hai superato.
Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

ibbba

provato anche con >,non cambia,viene sempre verificata come vera la scelta che secondo la mia logica è sbagliata....

leo72

La logica, come ti ha detto Paolo, è sbagliata perché se devi misurare il tempo trascorso a PARTIRE da un certo momento, si usa fare la differenza fra l'istante corrente e l'istante passato.

Ma, a parte questo, quanto vale secondiRitardoMillis? Non è che c'è qualche altro errore nel tuo codice? Potresti postarlo per vedere?

ibbba

Ciao Leo,purtroppo non posso postare tutto il codice,è lunghissimo e chunque si annoierebbe a morte a leggerlo tutto!!...a parte questo,la logica con cui funziona quell'if risponde in maniera errata sia che usi < sia che usi >,ovvero ottengo sempre che l'if mi resituisce l'ooposto di ciò che mi aspetto.


secondiRitardoMillis vale secondiRitardo (che è un byte salvato in eeprom ) * 1000 ,ovvero è il valore di secondiRitardo trasformato in millisecondi.Questo mi serve per salvare solo un byte in eeprom come impostazione.

La cosa strana è che fino a che secondiRitardo vale 32 o numeri minori tutto fila liscio,se vale 33 (e quindi secondiRitardoMillis vale 33000)la risposta dell'if si inverte .
Quel 32000 mi fa pensare a qualcosa che ha a che fare con un overflow,ma non riesco a trovare una soluzione logica.....

gingardu


provato anche con >,non cambia,viene sempre verificata come vera la scelta che secondo la mia logica è sbagliata....


mah quasi sicuramente hai dichiarato in modo errato una variabile
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

leo72


La cosa strana è che fino a che secondiRitardo vale 32 o numeri minori tutto fila liscio,se vale 33 (e quindi secondiRitardoMillis vale 33000)la risposta dell'if si inverte .
Quel 32000 mi fa pensare a qualcosa che ha a che fare con un overflow,ma non riesco a trovare una soluzione logica.....

Vedi perché ti chiedevo il codice?
Perché questo mi fa pensare solo una cosa: hai dichiarato la variabile di tipo int, quindi dopo 32767 valori, invece di passare a 32768 va a -32768 perché è di tipo signed. Inoltre per confrontarla con millis non solo deve essere di tipo unsigned ma anche di tipo long proprio come millis.

nid69ita

Ma poi per fare un pò di debug da te, non puoi stampare sul serial monitor i 2 valori salvamillis e secondiRitardoMillis prima di quell'if ?
my name is IGOR, not AIGOR

ibbba

Rispondo a tutti: le varibili sono dichiarate come UNSIGNED LONG (millis restituisce un unsigned long ,quindi dovrebbe essere un confronto tra due variabili uguali)quelle relative al ciclo IF,mentre quella salvata in eeprom,che poi viene moltiplicata per mille per trasformarla da secondi a milliswecondi e poter eseguire il controllo è BYTE.
Anche a me quel 32 fa presumere un overflow ,ma il punto è che le variabili sono dichiarate CORRETTAMENTE secondo logica e secondo la documentazione uffiaciale....per questo non mi spiego il perchè del baco.
@Nid69...se sei di Ivrea io sono di Rivarolo...a momenti fai prima a vedere a casa mia...!!!...hi hi hi

ibbba

riporto a livello pseudo code il funzionamento di quell'id.
Nel setuo carico da eeprom il valore letto da una locazione in secondiRitardo (byte),immaginiamo 30
poi moltiplico secondiRitardo per mille e lo carico in secondiRitardoMillis (unsigned long),quindi 30000
nel loop principale ad un certo punto salvo valore di millis in salvamillis (unsigned long)
il ciclo IF controlla quando la differenza tra millid() attuale e salvamillis diventa maggiore o minore di secondiRitardoMillis.
Come logica mi pare ci siamo....funziona bene fino a che secondiRitardo vale 32,dopodiche sballa il ragionamento.
Le variabili sono tutte dichiarate giuste,la logica mi pare sia corretta.....mi chiedo perché

astrobeed


Nel setuo carico da eeprom il valore letto da una locazione in secondiRitardo (byte),immaginiamo 30
poi moltiplico secondiRitardo per mille e lo carico in secondiRitardoMillis (unsigned long),quindi 30000


Hai un problema di casting, aggiungi  "(unsigned long)" nella moltiplicazione per 1000, se non fai in questo modo il compilatore promuove in automatico il valore calcolato come int perché 1000 rientra in questa tipologia di dato.

Code: [Select]

secondiRitardoMillis = (unsigned long) secondiRitardo * 1000;

ibbba



Nel setuo carico da eeprom il valore letto da una locazione in secondiRitardo (byte),immaginiamo 30
poi moltiplico secondiRitardo per mille e lo carico in secondiRitardoMillis (unsigned long),quindi 30000


Hai un problema di casting, aggiungi  "(unsigned long)" nella moltiplicazione per 1000, se non fai in questo modo il compilatore promuove in automatico il valore calcolato come int perché 1000 rientra in questa tipologia di dato.

Code: [Select]

secondiRitardoMillis = (unsigned long) secondiRitardo * 1000;



Ecco il perché... Ed ecco un'altra cosa che non sapevo!!grazie per il chiarimento,ho imparato qualcosa in più !!... Grazie anche a tutti gli altri che hanno partecipato al topic!!

ibbba

Confermo che con l'indicazioni di Astro funziona senza problemi...ne ho imparata una nuova!!!!

nid69ita


@Nid69...se sei di Ivrea io sono di Rivarolo...a momenti fai prima a vedere a casa mia...!!!...hi hi hi


Azz... siamo a un tiro di sputo  :smiley-mr-green:

Una info in più, anche cosi funziona, specificando per la costante 1000 al fondo che è unsigned long
Code: [Select]
secondiRitardoMillis =  secondiRitardo * 1000UL;

my name is IGOR, not AIGOR

ibbba



@Nid69...se sei di Ivrea io sono di Rivarolo...a momenti fai prima a vedere a casa mia...!!!...hi hi hi


Azz... siamo a un tiro di sputo  :smiley-mr-green:

Una info in più, anche cosi funziona, specificando per la costante 1000 al fondo che è unsigned long
Code: [Select]
secondiRitardoMillis =  secondiRitardo * 1000UL;




Grassie!

Go Up