Pages: [1]   Go Down
Author Topic: È "efficiente" questa funzione?  (Read 1036 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
//"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? (:
Logged

Monselice PD Italy
Offline Offline
Faraday Member
**
Karma: 25
Posts: 5480
фон Крыса
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non puoi mettere tutto il codice?
A me è molto poco chiaro e capire cosa stai chiedenso senza vederlo interamente è difficile smiley
Logged

Se corri veloce come un fulmine, ti schianterai come un tuono.

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 411
Posts: 11986
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

non puoi mettere tutto il codice?
A me è molto poco chiaro e capire cosa stai chiedenso senza vederlo interamente è difficile smiley
Ratto, quand'è che sei morto o diventato un sorcio ad alta tensione?  smiley-mr-green
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?  smiley-lol
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Milano, Italy
Offline Offline
Faraday Member
**
Karma: 10
Posts: 3085
Sideralis Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 :-)
Logged

Federico - Sideralis
Arduino &C: http://www.sideralis.org
Foto: http://blackman.amicofigo.com

Monselice PD Italy
Offline Offline
Faraday Member
**
Karma: 25
Posts: 5480
фон Крыса
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-razz smiley-cool
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 smiley-wink
sono sempre alla ricerca di qualche strano modo per fa codice più snello e funzionale anche in questo caso smiley-razz

invece di usare i delay può usare millis senza così dover fermare il programma .... no ?
Federico mi hai fregato.....  smiley-cool
Logged

Se corri veloce come un fulmine, ti schianterai come un tuono.

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 7
Posts: 2247
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 :-)
Code:
unsigned long last;

int a[5];
int indice = 0;
int delay = 250;

int valore;

nel tuo loop metti:
Code:
if(millis() >= last+delay) {
if(indice == 4) {
valore = (a[0]+a[1]+a[2]+a[3]+a[4])/5;
indice = 0;
}
a[indice] = analogRead(analog);
indice++;
}
dovrebbe andare, ogni secondo ti si aggiorna il valore  smiley-cool
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

Milano, Italy
Offline Offline
Faraday Member
**
Karma: 10
Posts: 3085
Sideralis Arduino!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

meglio di come me l'ero immaginato!
Logged

Federico - Sideralis
Arduino &C: http://www.sideralis.org
Foto: http://blackman.amicofigo.com

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ancora meglio, se non ti serve conservare i singoli valori: (ah manca l'aggiornamento di last nel codice di superlol)

Code:
int somma=0;
int media=0;
int pausa = 250;

void setup(){
    //precalcolo la media
    for (int i=0;i<5;i++){
        somma+= analogRead(analog);
        delay(pausa);
    }
    media=somma/5;
}

void loop(){
   if(millis() >= last+pausa) {
      somma-=media;
      somma+= analogRead(analog);
      media=somma/5;
      last=millis();
   }
}

così hai un valore di media aggiornato ogni 250 ms, pena però 250*5 ms di attesa prima che parta il loop
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Full Member
***
Karma: 0
Posts: 108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-grin
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ricordati di aggiungere  last=millis(); altrimenti dopo la prima lettura, quelle successive avvengono come se non ci fosse delay!
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 7
Posts: 2247
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

ancora meglio, se non ti serve conservare i singoli valori:...
...
accidenti è vero  smiley-lol pardon  smiley-roll-blue

...
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 smiley-grin

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  smiley-razz
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Code:
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
Logged


Riva del Garda, TN / Forlì
Offline Offline
Edison Member
*
Karma: 7
Posts: 2247
Il piu' modesto al mondo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Il nuovo forum italiano sull'elettronica: http://www.electroit.tk/ <--- Nuovamente online!

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-razz
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9185
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Jump to: