Campionamenti valori analogici su array

Buongiorno.
Ho cercato varie discussioni sul funzionamento degli array , ma nonostante questo non sono riuscito a trovare la soluzione al mio problema.
In sostanza voglio fare dei campionamenti (uno al secondo per 10 secondi) di un segnale analogico fornito dalla mia sonda anemometrica artigianale (ventolina di pc).
Partendo dall'inizio visualizzo al monitor seriale i valori della sonda con questo sketch

int anemometro;
int tempo=1000;
void setup () {
Serial.begin (9600);
}
void loop () {
anemometro= analogRead (A0);
Serial.println (anemometro);
delay (tempo);

E tutto funziona.
Come detto vorrei creare un array di valori dei valori misurati dall'anemometro.
Nel reference di array mi è sembrato di aver capito che posso dichiarare un array senza sapere cosa ci sarà dentro, semplicemente definendolo così :
int valori[9];
In questo modo dichiaro l'array prima del setup e so che è composto da 10 valori, è corretto?
Successivamente per assegnargli i valori che ci andranno al suo interno si fa con un ciclo for come questo?

int i;
for (i=0;i <10;i++) {
Serial.println (valori [i]);
delay (tempo);

washe850:
Nel reference di array mi è sembrato di aver capito che posso dichiarare un array senza sapere cosa ci sarà dentro, semplicemente definendolo così :
int valori[9];
In questo modo dichiaro l'array prima del setup e so che è composto da 10 valori, è corretto?

fin qui è corretto

washe850:

int i;

for (i=0;i <10;i++) {
Serial.println (valori [i]);
delay (tempo);

con questo ciclo scorri l'array, ma non assegni nessun valore, ti limiti a stamparli sulla seriale.
per assegnarli dovresti fare qualcosa del tipo

valori[i] = analogRead (A0);

Si, ecco, adesso mi stampa i 10 valori in sequenza. Grazie.
Questo era uno step intermedio.
Vorrei adesso fare in modo che i valori all'interno dell'array slittino la loro posizione di uno, in modo che il primo valore che è stato letto venga dimenticato, il secondo prenda il posto dell'ultimo ecc, in modo che ogni nuova lettura sia implementata nell'array. Perché questo?
Perché siccome è una sonda anemometrica che dovrà comandare un motore passo passo che azionera un freno di una pala eolica, dovrà appunto azionare il motore quando la media dei valori dell'array sarà superiore di una certa soglia, e aprire il freno quando questo valore scenda al di sotto di quella stessa soglia.
Ma comunque è possibile shiftare la posizione dei valori?

Lo puoi fare anche senza vettore.
Acquisisci il nuovo valore e calcola la media fra la vecchia media ed il nuovo valore assegnandogli un peso di 1/10. Otterrai lo stesso risultato senza la necessità di memorizzare i 9 valori precedenti che sono inutili visto che li usi soltanto per calcolare la media.

Ti spiego meglio cosa intendo.
Immagina di avere una media di 10 ottenuta dai valori
10 9 10 11 12 8 10 10 9 11
acquisisci il nuovo valore, per ipotesi 12
avresti
12 9 10 11 12 8 10 10 9 11
con media 10.2
ottieni la stessa media 10.2 senza disporre di tutti i singoli valori

vecchia media = 10
nuovo dato = 12
la vecchia media sarebbe stata =10 anche se avessi avuto
10 10 10 10 10 10 10 10 10 10
invece di
10 9 10 11 12 8 10 10 9 11
quindi ti basta fare la media fra
10 10 10 10 10 10 10 10 10 12
ed ottieni sempre 10.2

per cui in generale se
MP = media precedente
NV = nuovo valore
ottieni la nuova media considerando la media fra
MP MP MP MP MP MP MP MP MP NV
9 volte la media precedente ed 1 volta il nuovo valore

Il codice per fare tutto questo è abbastanza semplice e lascio a te il piacere di scriverlo
poi se hai difficoltà ti diamo una mano

Docsavage però così non vale!! Mi hai scritto il codice e ti sei pure corretto

Figurati

ecco questo è quello che ho fatto, visto quello che già avevo, anche se mi voglio studiare anche il metodo proposto da paulus1969.

innanzitutto ho buttato giù questo che mi pareva essenzialmente corretto:

int anemometro;
int misure[5];
int tempo=1000;
int tempo2=2000;
int somma;
void setup() {
  Serial.begin(9600);
}

void loop() {
  analogRead(A0);
  int i;
  for (i=0;i<6;i++){
    misure[i]=analogRead(A0);
    Serial.println(misure[i]);
    delay(tempo);
  }
  media=somma/6;
  Serial.print("la media è: ");
  Serial.println(media);
  delay(tempo2);
  Serial.println("nuova sequenza");
  }
}

e devo dire che a parte il calcolo della media si comportava bene, ossia mi dava i valori dell'array ogni secondo, e mi scriveva correttamente il testo, tipo così.

50
55
47
66
49
44
la media è: 0
(aspetta 2 secondi)
nuova sequenza
ecc ecc

successivamente ho cercato come si calcola la media di un array, visto che 0 non può essere ci doveva essere un qualche errore importante, e ho trovato questo:

  somma=0;
  for (int i=0;i<6;i++) {
  somma=somma+misure[i];
  media=somma/6;

e l'ho integrato nel codice ottenendo questo.

int anemometro;
int misure[5];
int tempo=1000;
int tempo2=2000;
int somma;
float media;
void setup() {
  Serial.begin(9600);
}

void loop() {
  analogRead(A0);
  int i;
  for (i=0;i<6;i++){
    misure[i]=analogRead(A0);
    Serial.println(misure[i]);
    delay(tempo);
  }
  somma=0;
  for (int i=0;i<6;i++) {
  somma=somma+misure[i];
  media=somma/6;
  Serial.print("la media è: ");
  Serial.println(media);
  delay(tempo2);
  Serial.println("nuova sequenza");
  }
}

ma adesso l'unica cosa che fa è mandarmi in stampa in modo ciclico e continuo i valori di array, uno al secondo, senza scrivere nient'altro.
è sbagliato questo modo di calcolare la media? praticamente non esegue la seconda parte di codice..

perchè il sistema che mi è stato detto prima che prevede la dicitura

int i;
for (i=0;i<10;i++){
  media=media+(valori[i]=valori[i+1]);
  media=media+(valori[9]=analogRead(A0));
  media=media/10;

non mi è di immediata comprensione e lo vedo macchinoso..

in realtà con questo codice vorrei creare degli array senza shiftare più nulla, farli, come avrete visto, ogni 6 secondi, e i risultati poi saranno i valori di un secondo array che calcola la media di 3 medie, quindi una media totale ogni 30 secondi circa

Innanzitutto

int valori[9];

è un array di 9 elementi, non di 10.

Si, in realtà nel mio sketch principale l'array è costituito da 6 misure, quello a cui fai riferimento tu, succopera, è un pezzo di un altro codice, ma in sostanza non cambia il funzionamento

c'è almeno un errore di graffe... la parte media=somma/6; va fuori dal for

Beh, spero allora che avrai dichiarato un array di 6 elementi, e non di 5 ;).

Buongiorno fratt .. io l'errore di graffe non riesco proprio a trovarlo .. l'avrebbe dovuto trovare anche il compilatore invece lo carica. In che senso poi la parte
media=somma/6;
va fuori dal for?
C'è qualche altro errore di sintassi? O è posizionato male?
Poi per l'osservazione di suoi opera, si, certamente ho dichiarato l'array come
valori [5];
che dovrebbe essere un array di 6 valori o sbaglio?

Ecco, appunto... Così è di 5 elementi...

secondo me stiamo mettendo troppa carne al fuoco e si rischia di fare confusione a washe850.
concentrati su una sola delle versioni di codice. cerca di capire cosa fa e perché lo fa. se cambi qualcosa, cerca di farlo dopo aver capito il perché, altrimenti ogni cambiamento rischia di portare più difetti che pregi.

sul for, come dice docsavage, la parte di calcolo della media devi portarla fuori dalla graffa (lascia dentro le graffe solo la somma).

docsavage:
Invece per Paulus

ho fatto una prova, il metodo da te consigliato per calcolare la media mobile non è esatto

è vero che tende al valore corretto, ma appunto ci tende, non lo raggiunge

ho provato il caso di una sollecitazione a gradino

una caterva di misure basse e poi un solo picco altissimo
col tuo metodo il valore comincia a scendere fin da subito, e già questo non è media mobile
e poi, ci mette molto più di 10 letture a ritornare al valore di equilibrio

se vuoi posto il file xls della simulazione

Lascia perdere il file xls, mi interessa di più vedere il codice che hai implementato

Certo, è una tecnica che uso spesso.

Ovviamente a seconda del contesto può essere preferibile o meno, dipende.

In certi casi invece adopero la tecnica "opposta", conservo almeno 20 dati ma oltre alla media calcolo anche la deviazione standard che uso anche per determinare se scartare o meno i nuovi dati in arrivo. Dipende da quanto la grandezza che stai misurando sia variabile e quanto ti interessano - o meno - eventuali variazioni repentine.

Salve signori!
allora vediamo un attimo.. ripartendo dalla risp di Docsavage..
Sicuramente, il codice proposto è validissimo, magari non fa la media delle ultime misurazioni assolute perchè è influenzata dalle medie precedenti, però è sicuramente molto interessante, potrei adottare la tua soluzione.
detto questo, provo a rispondere alle tue domande, così vediamo se ho capito
quando mi dici

"for i=0;i<9;i++;
perchè minore di 9 e non 10?"

sicuramente dovevo scrivere 10 perchè l'arrary, essendo valori[9] è costituito da 10 elementi, anche se in realtà il mio array è valori[5], quindi di 6 elementi.

quando mi dici

media=media+(valori*=valori[i+1]);*
-da una parte si usa "i" perchè si riferisce ai valori dentro l'array
-dall'altra si usa "i+1" perchè indica l'incremento del numero di campionamenti, che saranno 6, cioè 5(che è il nome dell'array ma che siccome esiste anche l'indice 0 bisogna aggiungere 1 per ottenere 6 valori), ( vuol dire quello?)
se leggo da sx a dx leggo così:
la media è data dal valore precedente della media (ad esempio dichiaro che all'inizio è=0), poi viene sommata a tutti i valori memorizzati nell'array, cioè i 6 valori (5+1);
se leggo da dx a sx leggo così:
l'array di nome valori che è formato da valori[i+1], quindi 6 campionamenti, si somma alla media precedente per ottenere la media attuale. sarà così? questo mi sembra di aver capito...
per la dicitura:
media=media+(valori[9]=analogRead(A0));
a partire da destra leggo:
la lettura analogica del pin A0, che mi costruisce l'array di 10 elementi chiamato valori[9], lo sommo alla media precedente per ottenere la media attuale.
ABBIATE PIETA' DI ME :slight_smile: sto cercando di ragionare...
Sukkopera, quando mi dici
Ecco, appunto, così è di 5 elementi...
ma se io scrivo valori[5], non ha 6 elementi, cioè index0, index1, index2, index3, index4, index5?
Docsavage
quando mi dici
Ostia... ecc ecc
quello che è scritto nel for viene ripetuto tante volte quante volte sono indicate nel confronto, questo credo di averlo capito bene, quindi viene letto un analogRead ad esempio 6 volte nel caso
for (i=0;i<5;i++); ma non capisco a cosa ti riferisci esattamente...
"che ti interessa ripetere una divisione per calcolare una media, se NON hai ancora finito di fare la somma?"
in effetti, la divisione devo scriverla fuori dalla graffa di chiusura del ciclo precedente, tipo:
```
*somma=0;
for (int i=0;i<6;i++) {
  somma= somma+misure[i];
  }
media=somma/6;

[code]

così prima calcola la somma e poi, una volta uscito dal for, calcola la media,giusto?
_
```*_

Chiedo scusa Docsavate.. mi sono reso conto che la parte

"

quando mi dici

media=media+(valori=valori[i+1]);

-da una parte si usa "i" perchè si riferisce ai valori dentro l'array
-dall'altra si usa "i+1" perchè indica l'incremento del numero di campionamenti, che saranno 6, cioè 5(che è il nome dell'array ma che siccome esiste anche l'indice 0 bisogna aggiungere 1 per ottenere 6 valori), ( vuol dire quello?)

se leggo da sx a dx leggo così:
la media è data dal valore precedente della media (ad esempio dichiaro che all'inizio è=0), poi viene sommata a tutti i valori memorizzati nell'array, cioè i 6 valori (5+1);
se leggo da dx a sx leggo così:
l'array di nome valori che è formato da valori[i+1], quindi 6 campionamenti, si somma alla media precedente per ottenere la media attuale. sarà così? questo mi sembra di aver capito...
"
non c'entra nulla ma è riferito allo sketch proposto da te, dove si dichiara un array da 10elementi, ma nel ciclo for se ne immagazzinano 9, si fa la media partendo dai 9 e di volta in volta con l'ultimo acquisito. Corretto?
Avevi ragione quando dicevi che mi sarei confuso .. Ora ci sono.
Il tuo sketch l'ho provato e funziona .. quello che non riesco a far funzionare è il mio ...

Si, mi sembra di ricordare questo tipo di assegnazioni in c, le abbiamo fatte a scuola ma io ero un asino :slight_smile:

E il K&R cos'è?

Per il momento sto provando il tuo codice, con 5 letture e mi faccio stampare l'ultima lettura (quella istantanea) e la media dell'array, che mi sembra per i miei utilizzi sia più pratico e verosimile.