aiuto x comprendere cosa accade...

Quello che vedete a seguire è il codice con cui sto smanettando per rilevare la temperatura in due punti e mostrarla su un display. Funziona bene anche dopo aver sostituito il delay con il millis tuttavia ho notato un effetto che non mi è del tutto chiaro.
Come vedete il codice ora esegue 50 letture ed il valore T rilevato è molto prossimo a quello rilevato con altro termometro.
Inizialmente facevo fare 10 letture e mi veniva fuori un T più alto di due gradi circa.
Vorrei comprendere il motivo...
Altro effetto che non mi spiego è che aumentando le letture a 200...il codice sembra bloccarsi e non visualizza più nulla....
Vorrei anche qui capire il perchè.
Grazie anticipato a chi avrà la pazienza di leggere e rispondere.

const int NRLETTURE = 50;    // numero letture
const int NRLETTURE2 = 50;
const int SensorPin = A0;    //variabile lettura sensore
const int SensorPin2 = A1;   // seconda variabileb sensore due
float valori[NRLETTURE];     //array con i valori
float valori2[NRLETTURE2];
float sommaGradi;            //variabile somma
float mediaGradi;            //variabile media
float sommaGradi2;
float mediaGradi2;
#include <LiquidCrystal.h>             // include la libreria del display lcd
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //pin display LCD

long previousMillis = 0;  // prova millis
long interval = 1000;      // prova millis

void setup() 
{
  lcd.begin(16, 2);        // set up the LCD's number of columns and rows:
  Serial.begin(9600);      //inizializzo la seriale
  lcd.print("Created by: ");
  lcd.setCursor(0,2);
  lcd.print("ppregeo");
}
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    for(int i = 0; i<=NRLETTURE;i++)
    {
      int sensorVal = analogRead(SensorPin);
      //float voltage = (sensorVal /1024.0) * 5.0; // per TMP36
      //float temperature = (voltage - .5) * 100;
      float temperature = (sensorVal * 4.88)/10;    // per LM35
      valori[i] = temperature;
      // delay(T_campionamento);  // delay funzionante
    }
    analogRead(SensorPin);
    sommaGradi = 0;                        // il primo valore deve essere sia zero, altrimenti poi sballa tutto
    for(int i = 0; i<=NRLETTURE; i++)     //ciclo che somma i valori dell'array
    {  
      sommaGradi = sommaGradi + valori[i];   //sommaGradi2 = sommaGradi2 + valori[i]; 
    }
    mediaGradi = sommaGradi / NRLETTURE;   //media valori
    for(int i = 0; i<=NRLETTURE2;i++)
    {
      int sensorVal2 = analogRead(SensorPin2);
      //float voltage2 = (sensorVal2 /1024.0) * 5.0;
      //float temperature2 = (voltage2 - .5) * 100;
      float temperature2 = (sensorVal2 * 4.88)/10;
      valori2[i] = temperature2;
    }
    analogRead(SensorPin2);
    sommaGradi2 = 0;
    for(int i = 0; i<=NRLETTURE2; i++)        //ciclo che somma i valori dell'array
    {  
      sommaGradi2 = sommaGradi2 + valori2[i]; 
    }
    mediaGradi2 = sommaGradi2 / NRLETTURE2; //divido la somma dei valori per il loro numero (media)     
    lcd.clear();                              //pulire lo schermo
    Serial.print ("Temp In:    ");            //scrive sul display la parola "gradi"
    Serial.println (mediaGradi);
    Serial.print ("Temp Out:   ");
    Serial.println (mediaGradi2);
    Serial.print ("diff:       ");
    Serial.println (mediaGradi-mediaGradi2);
    Serial.println ("---------------------------");
    lcd.print("In ");                    
    lcd.print(mediaGradi);               //scrivo la temperatura
    lcd.print(" d ");
    lcd.print(mediaGradi-mediaGradi2);
    lcd.setCursor(0,2);
    lcd.print("Out ");
    lcd.print(mediaGradi2);
  }
}

Ho guardato solo velocemente il codice e vedo alcune cose strane, anche se non sono sicuro che influiscano sul tuo problema:

  • currentMillis la dichiarerei fuori dal loop
  • previusMillis va dichiarata unsigned

Grazie fratt,

prima il codice aveva un delay che non mi piaceva ed ho inserito il millis. Riesco a gestirlo ma purtroppo la "collocazione" nell'ambito del codice non mi è sempre chiara. Ti sarei grato se potessi essere più chiaro esponendo i motivi così capisco.

Grazie

nel programma complichi parecchio alcuni punti in cui potresti renderle molto più semplici, tipo utilizzi due array float da 50 elementi solo per avere la media delle temperature lette, puoi fare la stessa cosa con due usingned int e con molto meno calcoli per giungere allo stesso risultato.

partiamo dal fatto che per ogni lettura hai un valore letto da un pin analogico e quindi un possibile valore tra 0 e 1023, primo punto, è inutile convertire ogni singolo valore e metterlo singolarmente in un array, fai subito la somma di tutte le letture analogiche e quindi nel caso più estremo avresti un numero massimo di 1023 * 50 = 51.150, quindi una unsigned int è più che adeguata visto che puoi memorizzare un numero massimo di 65.535, da qui lo dividi per 50 e hai la media della temperatura rappresentata sempre da un numero da 0 a 1023, lo converti in temperatura con la formula che hai già usato float temperature = (sensorVal2 * 4.88)/10; è il gioco è fatto... sempre sperando che non ho fatto qualche errore in tal caso sono io ad essere fatto e strafatto :grin:

io invece vedo che se dichiari due array di float (4 byte) con 200 lettura hai consumato 2 * 200 * 4 che a casa mia fanno 1600 byte, solo per gli array, mettici qualcosa d'altro e hai riempito facile facile i 2 K di arduino, se usi la UNO, che arduino usi?

edit: anticipato da zef

grazie per gli utili consigli che cercherò di mettere in pratica...devo studiare molto ancora :confused:

ecco il codice senza array...cmq cambia poco anche come dimensuioni o sbaglio?

const int SensorPin = A0;    //variabile lettura sensore
const int SensorPin2 = A1;   // seconda variabileb sensore due
float SommaGradi;            //variabile somma
float SommaGradi2;
#include <LiquidCrystal.h>             // include la libreria del display lcd
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //pin display LCD
long previousMillis = 0;  // prova millis
long interval = 1000;      // prova millis
void setup() 
{
  lcd.begin(16, 2);        // set up the LCD's number of columns and rows:
  Serial.begin(9600);      //inizializzo la seriale
  lcd.print("Created by: ");
  lcd.setCursor(0,2);
  lcd.print("ppregeo");
}
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  float SommaGradi = 0;
  for ( int i=0; i<=150; i++)
  {
    int SensorVal = analogRead(SensorPin);
    float temp = (SensorVal * 4.88)/10;
    SommaGradi =+ temp;
  }
  {
    float SommaGradi2= 0;
    for ( int i=0; i<=150; i++);
    {
      int SensorVal2 = analogRead(SensorPin2);
      float temp2 = (SensorVal2 * 4.88)/10;
      SommaGradi2 =+ temp2;
    }
    lcd.clear();                              //pulire lo schermo
    Serial.print ("Temp In:    ");            //scrive sul display la parola "gradi"
    Serial.println (SommaGradi);
    Serial.print ("Temp Out:   ");
    Serial.println (SommaGradi2);
    Serial.print ("diff:       ");
    Serial.println (SommaGradi-SommaGradi2);
    Serial.println ("----------------------");
    lcd.print("In ");                    
    lcd.print(SommaGradi);
    lcd.print(" d ");
    lcd.print(SommaGradi-SommaGradi2);
    lcd.setCursor(0,2);
    lcd.print("Out ");
    lcd.print(SommaGradi2);
  }
}
}

Questo dovrebbe fare (non l'ho testato) le stesse cose ma con meno dispendio di memoria e calcoli da parte di arduino.

void loop()
{
  if (millis(); - previousMillis > interval)
  {
    previousMillis = millis();
    unsigned int SensorVal = 0;
    for ( int i = 0; i <= 150; i++)
    {
      SensorVal += analogRead(SensorPin);
      delay( ? );                            //un minimo di ritardo tra una lettura e l'altra, anche 2mS
    }
    SensorVal /= 150;                        //divide il totale per il numero di letture in modo da avere la media
    SommaGradi =  (SensorVal * 4.88) / 10;   //converte il valore in temperatura

    SensorVal = 0;
    for ( int i = 0; i <= 150; i++)
    {
      SensorVal += analogRead(SensorPin2);
      delay( ? );                            //un minimo di ritardo tra una lettura e l'altra, anche 2mS
    }
    SensorVal /= 150;                        //divide il totale per il numero di letture in modo da avere la media
    SommaGradi2 =  (SensorVal * 4.88) / 10;  //converte il valore in temperatura


    lcd.clear();                              //pulire lo schermo
etc. etc.

tra una lettura e l'altra ho inserito un ritardo con delay ma senza inserire il valore, eventualmente vedi se lasciarla o toglierla

vince59:
ecco il codice senza array...cmq cambia poco anche come dimensuioni o sbaglio?

Andiamo per gradi.
Intanto già ti hanno detto che il valore di previousMillis deve essere unsigned:

unsigned long previousMillis = 0; // prova millis

Poi questa variabile globale:

float SommaGradi; //variabile somma

viene mascherata da questa che hai messo nel loop():

float SommaGradi = 0;

Delle due lasciane solo una, nel tuo caso quella globale non la usi affatto!

In ogni caso il calcolo della media delle due misurazioni te l'ha ha correttamente detto -zef-: fai prima e con maggiore affidabilità e minore consumo di memoria se lo fai con i soli valori di analogRead() invece di calcolare la temperatura in float.
Per cui lascia la variabile globale SommaGradi ma cambiagli la classe:

unsigned long SommaGradi = 0;

(ti ho messo long per prudenza, dipende da quanti campioni consideri per ogni ciclo, se la somma non supera 65535 puoi usare unisgned int) e togli la sua creazione locale da dentro al loop (lascia solo l'inizializzazione "SommaGradi=0;"), e accumula solo esattamente quello che leggi dalla analogRead().

Comunque non capisco a cosa ti serva fare 150 letture "sparate" nel giro di pochi microsecondi, il ciclo viene eseguito molto rapidamente e credo tu legga valori molto vicini tra loro: per cui o nel for() ci metti almeno un delay minimo (un paio di ms) e riduci il numero di letture, oppure, meglio, fai una serie di letture "asincrone" in un arco di tempo abbastanza ampio, ad es. mentre attendi il timeout di lettura attuale (1 secondo) e quindi calcoli la media dei precedenti e resetti la variabile ad accumulo.

Per finire, per favore indenta bene! Usa almeno la funzione dell'IDE di Arduino (Ctrl-T), e puoi "vedere" meglio la logica del tuo programma soprattutto quando aumentano di complessità, oltre ad accorgerti ad esempio che a riga 29 hai messo una graffa aperta (chiusa poi a riga 52) assolutamente inutile.

docdoc:
... Comunque non capisco a cosa ti serva fare 150 letture "sparate" nel giro di pochi microsecondi, il ciclo viene eseguito molto rapidamente e credo tu legga valori molto vicini tra loro: per cui o nel for() ci metti almeno un delay minimo (un paio di ms) e riduci il numero di letture ....

... infatti. Occorre che va a vedere il datasheet del sensore che sta usando perché, parecchi, richiedono un tempo ben più lungo tra una lettura ed un'altra !

Guglielmo

...sempre grazie dei consigli...rieccomi a voi.
IN effetti stavo testando il funzionamento per meglio comprendere il tutto.
Sono riuscito a far girare sia la lettura con array che con media e devo dire sono soddisfatto del risultato.
Grazie x l'indicazione dell'eccessivo numero di letture in un arco di tempo effettivamente breve e quindi troppo ravvicinate. L'ho ottimizzato.