Media su 5 letture sensore

Salve a tutti,non riesco a fare una cosa semplicissima che sicuramente voi saprete fare.Vorrei fare in modo che arduino aspetti che un sensore dia un valore(analogico) maggiore di una certa soglia,quando il valore del sensore è maggiore della soglia(stabilita da me) allora l'arduino prende in considerazione quel valore e lo conserva. Questo procedimento dovrebbe avvenire per 5 volte e alla fine dovrebbe fare una media dei 5 valori del sensore. Io ci ho provato ma non riesco a "far aspettare" ad arduino che il valore superi la soglia senza quindi fargli prendere in considerazioni valori che non voglio.Perfavore datemi un aiuto.Grazie

Devi far leggere il valore del sensore all'interno di un ciclo di WHILE da cui si esce solo se il valore letto supera il valore soglia. Il tutto all'interno di un ciclo FOR da 0 a 4 che memorizza in un array i 5 valori letti sopra la soglia. All'uscita del ciclo fai la media dei valori memorizzati nell'array.

Ciao, P.

Ciao ,grazie per la risposta,ho provato in questo modo ma dopo che il sensore supera la soglia la prima volta,salta tutte le altre misurazioni,come posso fare?

for(int i=0;i<=5;i++){
  while(pollicepin<pollicebase){  //pollicebase è la soglia pollicepin è il sensore
    pollicepin=analogRead(A0);
  }
  valore=pollicepin+valore;

}

int media=valore/5;
Serial.println(valore);

ciao...secondo me è anche più semplice (pseudo codice):

leggo sensore // ad ogni ciclo loop? oppure con intervallo di tempo? se supero soglia registro valore nell'array posizione x aumento x di uno

se x > di lunghezza array faccio media dei valori dell'array stampo media azzero X

Avevo pensato a una cosa così:

int valori[5];
int media;

for(int i=0; i<5; i++){
  while(pollicepin <= pollicebase){  //pollicebase è la soglia pollicepin è il sensore
    pollicepin=analogRead(A0);
  }
  valori[i]=pollicepin;
}
media = (valori[0]+valori[1]+valori[2]+valori[3]+valori[4])/5;
Serial.println(media);

Ciao,
P.

Ho provato il tuo sketch,purtroppo da lo stesso problema:arduino aspetta solo la prima lettura del sensore,poi salta tutte le altre.Infatti ho provato a fargli scrivere in seriale il valore del sensore ad ogni lettura,e dopo aver letto il primo dato del sensore vedo sulla seriale 5 valori uguali.Come posso risolvere?Grazie ancora per le risposte.

Quello che leggo nella seriale:

Inizio calibrazione 
467
467
467
467
467

Se con ho capito male quello che desideri ottenere ,secondo me devi ribaltare la logica ovvero nel loop verifichi il valore del sensore di continuo, se il valore è copra la tua soglia lo conservi nell'array ed incrementi una variabile che di dice a che numero di valori memorizzato sei arrivato, quando questa variabile supera il numero di letture da effettuare allora fai la media, una cosa del tipo:

byte numLett = 0;
void loop()
{
  sensore=analogRead(PIN);
   if(sensore>soglia)
  {
    array[numLett] = sensore;
    numLett++;
    if(numLett>5) 
    {
       //calcolo della media ecc.
       numLett = 0;
    }
  }
}

@fabpolli:…anche per me è così…vedi mio post precedente…così non sei vincolato con il while() ed il loop() può fare “anche altro” nel frattempo.

Purtroppo da lo stesso errore,salta le altre misure,nel senso che appena faccio arrivare il sensore oltre il valore soglia,è come se arduino ripete cosi velocemente quel loop che per lui ho già fatto le altre misurazioni.Non so più cosa provare

Mi mostri il codice?

ciao…prova a fare così:

byte numLetto = 0;
unsigned long myMillis = millis();

void loop() {
  int letturaSens = analogRead(PIN);

  if (millis() - myMillis > 500) {
    int average = 0;
    if (letturaSens > Xvalue) {
      myArray[numLetto] = letturaSens;
      numLetto++;
    }
    if (numLetto == sizeof(myArray) / sizeof(int)) {
      for (byte i = 0; i < sizeof(myArray) / sizeof(int); i++) {
        average += myArray[i];
      }
      average = average / (sizeof(myArray) / sizeof(int));
      Serial.println(average);
      numLetto = 0;
    }
    myMillis = millis();
  }
}

Orso2001 ho provato il tuo codice,adesso sulla seriale compare un valore ogni volta che porto il sensore sopra la soglia,ma quel valore è già la media dei 5 valori?

ciao...nel mio codice ho presupposto che la tua array sia di int...diversamente va modificato. il mio codice deve stampare a seriale dopo almeno 2 secondi che il tuo valore è stato raggiunto...il primo if(), quello che contiene tutto, se lo hai implementato giusto viene verificato ogni 500 millisecondi.

quello che stampo è la media di 5 registrazioni della lettura sopra il valore che imposti...poi ricomincia.

posta il tuo codice che si fa prima

Grazie per l’aiuto :slight_smile: ,ecco il codice:

byte numLetto = 0;
unsigned long myMillis = millis();
int myArray[5];
int soglia;

void setup(){

  soglia=analogRead(A0);
  Serial.begin(9600);
  
}

void loop() {
  int letturaSens = analogRead(A0);

  if (millis() - myMillis > 500) {
    int average = 0;
    if (letturaSens > soglia) {
      myArray[numLetto] = letturaSens;
      numLetto++;
    }
    if (numLetto == sizeof(myArray) / sizeof(int)) {
      for (byte i = 0; i < sizeof(myArray) / sizeof(int); i++) {
        average += myArray[i];
      }
      average = average / (sizeof(myArray) / sizeof(int));
      Serial.println(average);
      numLetto = 0;
    }
    myMillis = millis();
  }
}

poche cose mi balzano all’occhio:
non serve impazzire a calcolare la dimensione dello array con due sizeof, dato che gli array sono statici la dimensione la sai a compile time, e comunque non serve prorpio lo array, basta contare i campioni validi
per come hai scritto non serve nemmeno la loop, fatte 5 letture valide stampa la media, è quello che ti serve e la cosa finisce li’, no altro lavoro no loop
vedi se ti sconfinfera:

byte numLetto = 0;
unsigned long myMillis = millis();
#define CAMPIONI 5 // il numero di campioni da considerare
#define INTERVALLO 500 // il tempo tra una lettura e la successiva
int soglia;
int average;

void setup()
{
    soglia = analogRead(A0); // why this? la soglia non ti conviene imporla invece che sperare che la prima lettura sia OK?
    Serial.begin(9600);

    if (millis() - myMillis > INTERVALLO)
    {
        int lettura = analogRead(A0);
        myMillis = millis();
        // esegui la lettura solo ogni intervallo

        if (lettura > soglia)
        {
            average = average + lettura / CAMPIONI;
            numLetto++;
        }

        if (numLetto == CAMPIONI)
        {
            Serial.print("Media di ");
            Serial.print(CAMPIONI);
            Serial.print(" Letture: ");
            Serial.println(average);

            // fine, non serve la loop(), la media è stata calcolata e stampata, no altre letture
        }
    }
}

void loop()
{
}

Ciao...ok...ti suggerisco di spostare l'assegnazione di myMillis=millis() nel setup() ultima riga...giusto per essere sicuri che prenda il valore prima di entrare nel loop(). dopodichè ti confermo che stampi la media di 5 letture...come ti confermo che se fai un campionamento del valore di A0 e lo usi come riferimento...supponiamo 500...per tutta una serie di cose le altre letture possono ritornarti 501 e quindi dopo 2 secondi stamparti una media di 501....basterebbe che aggiungessi un:

Serial.print(soglia);
Serial.print(" ");

prima della stampa di average fai il confronto dei due valori

Grazie Standardoil e Orso2001 per le risposte,provo i vostri consigli e vi faccio sapere il risultato.Grazie ancora. :)