più analogRead valori sballati

Salve

E' da qualche ora che non riesco a risolvere questo piccolo bug.

Ho un sensore di temperatura lm35 e luigino328 (arduino duemilanove).

Ho fatto i collegamenti a dovere:
pin sx 5v
pin centrale analog in 0
pin dx gnd

Nel codice:
appena accosto due analogRead inizio ad avere valori sballati.... vi posto il codice se no non ci capiamo:

void setup(){
  Serial.begin(9600);

}

void loop() {
  
  Serial.println ("+-------------------------------------+");
  
  int sensorCelsius = analogRead(0);   
  sensorCelsius = (5.0 * sensorCelsius * 100.0)/1024.0;
  Serial.print("Temperatura C : ");
  Serial.println(sensorCelsius); 
  
 
  int sensorKelvin = analogRead(1);    //    Se commento questa riga sensorCelsius è affidabile altrimenti sensorCelsius varia di 3/4 gradi alla volta


//lm335 NON collegato

 /* sensorKelvin = ((5.0 * sensorKelvin* 100.0 ) / 1024)- 273.15 ;  
  Serial.print("Temperatura K : ");
  Serial.println(sensorKelvin); */

 delay (1000);
}

In cosa sbaglio?

Seriale con seconda read NON commentata:

+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 17
+-------------------------------------+
Temperatura C : 19
+-------------------------------------+
Temperatura C : 17
+-------------------------------------+
Temperatura C : 19
+-------------------------------------+
Temperatura C : 18
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 17
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 16
+-------------------------------------+
Temperatura C : 18
+-------------------------------------+
Temperatura C : 18
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 16
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 17
+-------------------------------------+
Temperatura C : 21
+-------------------------------------+
Temperatura C : 16
+-------------------------------------+
Temperatura C : 18
+-------------------------------------+

Serial con seconda read COMMENTATA:

+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 19
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20
+-------------------------------------+
Temperatura C : 20

prova a fare un campionamento di 50 valori

ad esempio qui lo fa di 8

ciao

pablos71:
prova a fare un campionamento di 50 valori

ad esempio qui lo fa di 8
Temperature Sensor + Arduino - Daniel Andrade
ciao

l'ho fatto.... se guardi i due campionamenti che ho postato fa SEMPRE così....

no io indendevo nello sketch

for(i = 0;i< =7;i++){ // gets 8 samples of temperature

samples = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;
_ tempc = tempc + samples*;_
_
delay(1000);_
_
}*_
tempc = tempc/8.0; // better precision
questo prende 8 valori li somma e al termine fa la media dividendo per 8

Provo a dire la mia, no uccidetemi se sbaglio :slight_smile:
Prova a usare millis anzichè il delay, magari è proprio il delay che bloccando il processore falsa le letture
Ciao

pablos71:
no io indendevo nello sketch

for(i = 0;i< =7;i++){ // gets 8 samples of temperature

samples = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;
_ tempc = tempc + samples*;_
_
delay(1000);_
_
}_
tempc = tempc/8.0; // better precision
questo prende 8 valori li somma e al termine fa la media dividendo per 8
_
[/quote]*_
ok. ho capito quello che dici ma.... non credo che il problema sia di tipo matematico.
è l'arduino che legge e mi da sulla seriale valori sballati... ora provo con millis

Ho messo il tester sul pin centrale e mi da una tensione costante (sarebbe la temperatura)...

Stessa storia con millis, appena uso il secondo analogread mi sballa il primo:

long previousMillis = 0;


void setup(){
  Serial.begin(9600);

}

void loop() {

  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > 1000) {

    previousMillis = currentMillis;  

    Serial.println ("+-------------------------------------+");

    int sensorCelsius = analogRead(0);   
    sensorCelsius = (5.0 * sensorCelsius * 100.0)/1024.0;
    Serial.print("Temperatura C : ");
    Serial.println(sensorCelsius); 

    int sensorKelvin = analogRead(1);

  }
}

io attualmente ho 2 35dz accostati e non ho problemi le temp sono uguali e stabili

int campion=30;
float tempc1=0; // temperature variables
float tempc2=0; // temperature variables
float samples1[campion]; // variables to make a better precision
float samples2[campion]; // variables to make a better precision

for(ii = 0; ii <= campion-1 ; ii++)
{
samples1[ii] = (( 5.0 * analogRead(PinA1) * 100.0) / 1024.0);
tempc1 = tempc1 + samples1[ii];

samples2[ii] = (( 5.0 * analogRead(PinA2) * 100.0) / 1024.0);
tempc2 = tempc2 + samples2[ii];
}

tempc1 = tempc1/campion; // better precision
tempc2 = tempc2/campion; // better precision

non uso il serial print, ma li mando al server, cmq non credo cambi molto, sul server li leggo bene e stabili

Allora provo a fare la media....

Giusto per incasinarmi ulteriormente, i pin analog in, fino a che tensione leggono?

Vorrei provare a mettere la 5v nel pin analog in e vedere che succede :slight_smile:

skaxxo:
Stessa storia con millis, appena uso il secondo analogread mi sballa il primo:

Questa è una cosa di cui abbiamo discusso molte volte, l'ADC vuole in ingresso una impedenza massima di 10k, ora non solo l'LM35Z ha un valore molto maggiore in uscita, se non mi ricordo male siamo a circa 100k, ma per giunta vai a leggere un secondo ingresso lasciato flottante, il risultato è che falsi le misure dell'ADC di molti count.
Per risolvere devi fare almeno 10 letture consecutive su ogni ingresso ADC e collegare a GND tutti quelli che stai utilizzando, ADC1 nel tuo caso, ma ancora non vi hai collegato il relativo utilizzatore.

astrobeed:
Questa è una cosa di cui abbiamo discusso molte volte, l'ADC vuole in ingresso una impedenza massima di 10k, ora non solo l'LM35Z ha un valore molto maggiore in uscita, se non mi ricordo male siamo a circa 100k, ma per giunta vai a leggere un secondo ingresso lasciato flottante, il risultato è che falsi le misure dell'ADC di molti count.
Per risolvere devi fare almeno 10 letture consecutive su ogni ingresso ADC e collegare a GND tutti quelli che stai utilizzando, ADC1 nel tuo caso, ma ancora non vi hai collegato il relativo utilizzatore.

Attenzione, si è vero, nello sketch precedente ho tolto il secondo sensore in quanto ho notato che quando ENTRAMBI i sensori erano collegati (quindi due analogread in cascata) il primo mi dava valori sballati e il secondo mi dava valori corretti.
Così ho fatto un debug software e hardware per capire dov'era il problema e ho notato che c'era qualcosa che non andava con nelle analogread.

Circa quello che hai scritto tu, perchè con un sola analogRead (commentando la seconda) i valori non sono sballati?

skaxxo:
Circa quello che hai scritto tu, perchè con un sola analogRead (commentando la seconda) i valori non sono sballati?

I valori sono sballati perché l'impedenza d'uscita dei LM35 è molto maggiore di 10k, quando cambi l'ingresso ADC il sample & hold non fa in tempo ad adattarsi al nuovo valore, ecco perché devi fare più letture consecutive sulla stessa linea se vuoi ottenere misure corrette.

astrobeed:

skaxxo:
Circa quello che hai scritto tu, perchè con un sola analogRead (commentando la seconda) i valori non sono sballati?

I valori sono sballati perché l'impedenza d'uscita dei LM35 è molto maggiore di 10k, quando cambi l'ingresso ADC il sample & hold non fa in tempo ad adattarsi al nuovo valore, ecco perché devi fare più letture consecutive sulla stessa linea se vuoi ottenere misure corrette.

Ok, credo di aver capito...

Domanda da ignorante: a parte il sampling software a livello hardware non posso fare nulla per abbassare l'impedenza?

Per avere buone letture analogiche le regole sono semplici:

  1. ridurre al minimo le piste o i fili tra i pin del micro ed i sensori
  2. mettere un paio di condensatori di decoupling da 0.1uF tra Vcc/GND dei pin 7/8 e tra AVcc/GND dei pin 20/22
  3. fare più letture del pin una dietro l'altra per far caricare il Sample&Hold
  4. usare l'analogReference interno a 1V1 in modo da aumentare la precisione della conversione

Relativamente al punto 3, tu dici di aver fatto più campionamenti dello stesso pin ma a me pare proprio di no. Per lo meno non col codice che hai postato, dove c'è uin delay(1000) fra una lettura e l'altra.

Io uso questa funzione per leggere un pin analogico:

//lettura pin analogico
int letturaPin(byte pin) {
    int tempLett=0;
    for (byte i=0; i<20; i++) {
        tempLett=analogRead(pin);
    }
    return tempLett;
}

Come vedi, leggo 20 volte lo stesso pin in successione e poi restituisco l'ultima lettura, dando così modo al S&H di caricarsi per bene.

Grazie a tutti per le risposte, ora ho corretto il codice e funziona bene...

Ora sto cercando di aumentare la precisione con i consigli che mi ha dato leo72.

Circa il punto 2, questa miglioria mi raffina di parecchio la precisione?
Circa il punto 3, quanti sampling consiglieresti? Io sto testando per multipli di 10 ma a volte ho scostamenti anche di un paio di gradi fissi e altre volte no.

Circa il punto 4, questa probabilmente potrebbe aiutarmi di più... devo documentarmi.

I C di decoupling dovrebbero essere usati su tutti i micro. Io così faccio, seguendo un vecchio consiglio che lessi tempo fa sul forum internazionale. Stabilizzano il funzionamento dell'intero micro evitando sbalzi anche minimi di tensione, per cui un circuito delicato quale l'ADC, che trasforma un segnale in ingresso in un valore, risente più di altri di eventuali variazioni di tensione. A tal proposito è bene sempre usare un'alimentazione stabilizzata perfettamente, che sia sempre il più vicino possibile ai 5V, proprio perché il riferimento di default per le conversioni è proprio con questa tensione e se tu hai nel tuo circuito un valore di 4V6, ad esempio, già hai in ingresso valori non corretti.

Sui punti 3 e 4, ti consiglio vivamente di adottare il reference interno a 1V1 e di trasformare tramite un partitore di tensione tutti i valori in ingresso in segnali a 1V1. In questo modo le letture saranno ancor meno soggette agli sbalzi dell'alimentazione esterna perché il riferimento è proprio interno al micro.

Il reference è stato trattato negli ultimi giorni diverse volte, cerca sul forum per tutte le spiegazioni del caso, oltre a leggere il Reference del sito che contiene una scheda ben scritta.

EDIT:
io campiono 20 volte quando l'impedenza esterna è molto alta. Ma se stai sui 10K, penso che 10 campionamenti siano sufficienti.
Poi puoi fare o la media oppure prendere l'ultimo valore, dipende dalla precisione. Io prendo l'ultimo.

skaxxo:
Domanda da ignorante: a parte il sampling software a livello hardware non posso fare nulla per abbassare l'impedenza?

potesti usare un operationale tipo mezzo LM358 come:

Ciao Uwe

Scusate la mia domanda da livello 0, ma ho un lm35Dz, collego il primo piedino (come indicato nel datasheet ) a massa l'altro ai 5v di arduino e l'altro sull'ingresso analogico A0 ma dopo pochissimi secondi inizia a bollire, devo fare anche qualcos'altro?
grazie 1000

Dovresti essere più preciso. Qual è per te il 1° piedino? Qual è l'"altro"? E l'"altro" ancora?

Hai ragione leo scusa la domanda fatta, male adesso ho ricollegato tutto e sulla seriale mi stampa 42... che sono troppi gradi, dovrei fare qualche calcolo per normalizzarla? poi adesso mi leggo qui sopra con calma per bene come avete fatto per stampare una media più precisa dei valori letti