Salve a tutti,
sto lavorando con un laser ed una fotoresistenza: un pin analogico prende la tensione in uscita da un partitore (5v--->resistenza--->pinAnalogico<---fotoresistenza--->terra) e se il valore scende troppo, esegue una funzione.
Per evitare "disturbi" sul pin analogico ho scritto una funzione che ritorna la media del valore preso dal pin nell'arco di tempo di un secondo.
//"Debounces" analog readings
int average(char analog){
int value1 = analogRead(analog);
delay(250);
int value2 = analogRead(analog);
delay(250);
int value3 = analogRead(analog);
delay(250);
int value4 = analogRead(analog);
delay(250);
int value5 = analogRead(analog);
//return 5/(1/value1 + 1/value2 + 1/value3 + 1/value4 + 1/value5);
return (value1+value2+value3+value4+value5)/5;
}
Il "problema" è che dichiaro cinque (5!) interi e faccio oziare il processore per un secondo: volevo sapere se è possibile renderla più efficiente.
Ovviamente non intendo utilizzare un unsigned char (mi servono i valori da 0 a 1023).
Idee? (:
ratto93:
non puoi mettere tutto il codice?
A me è molto poco chiaro e capire cosa stai chiedenso senza vederlo interamente è difficile
Ratto, quand'è che sei morto o diventato un sorcio ad alta tensione?
Ciò che vuole l'ha scritto chiaramente: per migliorare la precisione di lettura si affida a cinque letture successive nell'arco di un secondo e ne fa la media. Poiché in questo modo impegna troppo e inutilmente la CPU vuole sapere se esiste un modo più snello per fare la stessa cosa, a che ti serve il resto del codice? XD
La domanda e' chiara, e la fregatura risiede nel "secondo" di attesa.
Potresti fare cosi: tramite la funzione millis() valuti il tempo attuale, scrivi un "if" che dice, se dall'ultima lettura sono passati 250ms allora effettua una lettura, e incrementi una variabile in questo modo fino a 5, le varie letture le sommi sulla stessa variabile. Se ad un certo punto questo tuo valore originario di millis() supera il secondo, effettui la divisione per 5 e ottieni il risultato.
Se hai proprio bisogno mi sbatto anche per il codice, ma e' quasi ora di cena
Non son morto e l'HT non la prendo dalla scorsa estate.... non son schiattato ma non voglio riprovare... sentir la 220v che circola libera nel corpo è una sensazione... come dire... ehm... strana 8)
sarà un vizio che mi ha trasmesso il vecchio prof di informatica...... ma voglio sempre vedere tutto integro e non a frammenti... non per farmi gli affari altrui ma per essere sicuro di ciò che dico e per imparare qualcosa di nuovo
sono sempre alla ricerca di qualche strano modo per fa codice più snello e funzionale anche in questo caso
invece di usare i delay può usare millis senza così dover fermare il programma .... no ?
Federico mi hai fregato..... 8)
Federico:
La domanda e' chiara, e la fregatura risiede nel "secondo" di attesa.
Potresti fare cosi: tramite la funzione millis() valuti il tempo attuale, scrivi un "if" che dice, se dall'ultima lettura sono passati 250ms allora effettua una lettura, e incrementi una variabile in questo modo fino a 5, le varie letture le sommi sulla stessa variabile. Se ad un certo punto questo tuo valore originario di millis() supera il secondo, effettui la divisione per 5 e ottieni il risultato.
Se hai proprio bisogno mi sbatto anche per il codice, ma e' quasi ora di cena
unsigned long last;
int a[5];
int indice = 0;
int delay = 250;
int valore;
Grazie a tutti: non mi aspettavo tutte queste risposte (:
Per il codice ho preso quello di superlol, corretto un buggetto (si rifiutava di confrontare l'output di millis con la somma di last e delay), tradotte le variabili, aggiunto un return ed il suo nome al commento della funzione (se desideri che lo rimuova, lo cancello subito).
Grazie ancora
lesto:
ancora meglio, se non ti serve conservare i singoli valori:...
...
accidenti è vero XD pardon
NeXTWay:
...
Per il codice ho preso quello di superlol, corretto un buggetto (si rifiutava di confrontare l'output di millis con la somma di last e delay), tradotte le variabili, aggiunto un return ed il suo nome al commento della funzione (se desideri che lo rimuova, lo cancello subito).
Grazie ancora
ancora meglio sarebbe fare una media dei valori a seguire, intendo fai la media in 250ms, poi arriva il terzo valore e fai la media tra la media dei primi 2 e lo medi col secondo, vai a vanti col terzo ecc.. però è relativo a come deve variare il sensore e che scopo ha.
comunque il mio nome puoi toglierlo perchè è una cavolatina e non voglio prendermi meriti per cose a cui neanche do troppo peso
Questo sistema ha un errore di base. Se per caso una lettura è atipica, ti sballa tutto il codice.
Mettiamo che tu legga:
50
55
800
60
45
La media è 202, assolutamente inesatta.
Potresti fare così: prendi 5 letture, dopodiché le metti in ordine e prendi quella nel mezzo.
int lettoreSensore() {
byte contatore;
int letture[4];
byte i,j;
int temporaneo;
for (i=0; i<5; i++) {
letture[i]=analogRead(sensore);
}
//bubble sort
for (i=0; i<4; i++) {
for (j=i+1; j<5; j++) {
if (letture[i]>letture[j]) {
temporaneo=letture[j];
letture[j]=letture[i];
letture[i]=temporaneo;
}
}
}
return (letture[2]);
}
In questo modo hai una specie di media ma, soprattutto, scarti valori assurdi.
La funzione, nel caso di prima, restituisce infatti 55, che è quasi la media vera di tutti i valori "normali" letti:
45+50+55+60=52,5
rimane da capire che sensore è ed in che campo deve lavorare, se è un sensore di temperatura è un conto, sui giri un'altro e cosa deve fare di conseguenza? secondo me è meglio sapere queste cose
leo72:
Questo sistema ha un errore di base. Se per caso una lettura è atipica, ti sballa tutto il codice.
Mettiamo che tu legga:
[...]
Il principio di funzionamento della media è proprio questo: normalizzare i dati.
Per intenderci, se metti i valori letti in un grafico avrai una specie di grafico molto altalenante (zoomando i particolari).
Più aumenti il numero di dati su cui effettuare la media ARITMETICA (perchè ne esistono altri tipi) più il grafico sarà curvilineo e "stabile" su di un valore.
Poi, oltre ai vari tipi di media, c'è la moda e la mediana (più o meno quello che suggerisci), ma quì ci stiamo buttando nella statistica... un'altra mia grossa lacuna
leo72:
50
55
800
60
45
La media è 202, assolutamente inesatta.
Non funziona così, se uno dei valori letti è molto maggiore, o minore, rispetto agli altri valori hai un problema con la modalità di acquisizione.
Mi spiego meglio se prevedi di fare la media di tot valori per compensare l'onnipresente rumore, che normalmente ha valore medio quasi 0, prendi questi campioni con una velocità pari a n volte (n = numero di campioni) di quella prevista dalla banda del sensore, altrimenti non ha senso farlo, se uno dei valori presi varia moltissimo vuol dire che hai problemi di transienti veloci dovuti a disturbi esterni oppure che stai campionando troppo lento rispetto alla velocità del segnale.
Se il problema è dovuto a sporadici transienti veloci si elimina facilmente verificando che ogni valore letto sia pari al valore medio precedente +/- la variazione massima possibile durante un singolo campionamento, se non è così il campione viene gettato e al suo posto inserito il valore medio precedente.