Fare la media di un valore

Ciao a tutti,
Vorrei porvi una domanda:
Come fareste la media di un valore contando che viene letto per ogni ciclo di arduino?
Senza rischiare un overflow delle variabili?
Contanto che arduino può rimanere acceso anche 3 ore continuative... Il valore può andare solo da 0 a 100 e rimane intero... Stavo pensando a
Somma di tutti i valori/ numero di valori
Ma cosi ho paura di andare overflow...
Avete qualche idea su come potrei impostare l algoritmo?

Esistono varie possibilità

Dipende....

Potresti fare la media degli ultimi n valori letti, ti serve un array dove memorizzare i valori a mano a mano che li acquisisci.

Se il valore in ingresso al massimo vale 100, ipotizzando il caso peggiore con tutte le letture pari a 100, usando come accumulatore una variabile a 32 bit, unsigned, al massimo puoi sommare 42,95 milioni di valori.
Dato che in tre ore ci sono 10800 secondi ne consegue che per andare in overflow devi fare più di 3976 letture al secondo, basta che metti una delay di 1ms all'interno della loop per essere sicuro di non superare questo limite, anzi con la delay 1 ms lo porti come minimo a 11 ore di acquisizione prima di andare in overflow, stiamo sempre parlando del caso peggiore con tutti i valori a 100.

Uhm no… Il delay non lo posso mettere perche mi serve che l lcd sia veloce nel rispondere…
Quindi dite che in 3 ore non rischio l overflow?

Ps: mi serve la media di tutti i valori… Quindi non posso accumulare solo gli ultimi valori diciamo…

marcobiondo13:
Quindi dite che in 3 ore non rischio l overflow?

Noi non sappiamo quanti campioni devi leggere... Se, come dice astro, stai entro i 42949672 campioni (con massimo valore 100), allora sicuramente con una variabile uint32_t non hai problemi.

Il delay non lo posso mettere perche mi serve che l lcd sia veloce nel rispondere...

L' LCD è già molto più lento di suo rispetto a quel delay.

L'informazione mancante è la durata base del ciclo di programma...

cosa significa la durate base del ciclo?

Immagino che il programma all'interno della funzione loop eseguirà continuamente una sequenza del tipo:

  • leggi input
  • elabora
  • aggiorna output

marcobiondo13:
Uhm no... Il delay non lo posso mettere perche mi serve che l lcd sia veloce nel rispondere...

Prima di tutto se la scrittura del LCD sta in mezzo al loop, ed eseguita ad ogni ciclo, da sola richiede diversi ms, quindi non ti serve delay.
Seconda cosa, i display lcd sono molto lenti come refresh del display vero e proprio, aggiornare più di 20-30 volte al secondo non solo non serve a nulla, ma rischi di peggiorare la leggibilità del display per gli eccessivi refresh.

nid69ita:
Fa così schifo il float per la non precisione sul numero di cifre che può memorizzare (7 mi pare) ?

Il float richiede molti più cicli macchina, rispetto ad un long, per essere trattato, sopratutto quando fai la divisione, poi introduce di suo un errore di arrotondamento cumulativo visto che non appena superi il valore di qualche milione cominci a perdere cifre significative, ovvero cominci ad ottenere risultati sempre più troncati ad ogni somma con relativo errore incrementale quando fai la divisione, arrivi addirittura al punto che sommare 100 non cambia in nessun modo il risultato perché con solo 6-7 cifre di risoluzione, più l'esponente, i piccoli valori non sono più significativi e non possono essere trattati.
Esempio pratico, se ad un float che contiene 100000000 sommi 100 il risultato è sempre 100000000, o meglio sarà una cosa del tipo 99.9999*10^6

allora l lcd lo aggiorno ad ogni ciclo del loop e non ho sfarfallamenti strani dell lcd contando pero che se posso non sovrascrivo i dati gia esistenti:
del tipo se su 2 riche ho 4 caratteri e quei caratteri non vanno aggiornati rimangono costanti e la riscrittura non avviene...

per la media alla fine sto usando quella che avevo scritto io all inizio e sembra funzionare tutto correttamente senza overflow..

astrobeed:
Prima di tutto se la scrittura del LCD sta in mezzo al loop, ed eseguita ad ogni ciclo, da sola richiede diversi ms, quindi non ti serve delay.
Seconda cosa, i display lcd sono molto lenti come refresh del display vero e proprio, aggiornare più di 20-30 volte al secondo non solo non serve a nulla, ma rischi di peggiorare la leggibilità del display per gli eccessivi refresh.

questa idea mi piace, anche se appesantisce di più il codice rispetto alla mia... nel momento che mi rendero conto di un overflow userò il tuo algoritmo...
grazie a tutti... :slight_smile:

Potresti anche usare millis() in modo da acquisire i dati con un intervallo di campionamento prestabilito.

Così puoi anche resettare le variabili dopo X ore e scongiurare il rischio di overflow.