Go Down

Topic: Lettura Temperatura con Sensore TM36  (Read 926 times) previous topic - next topic

LOLLO65

salve A tutti, gli Arduiniani
dopo qualche mese mi sono cimentato in nuovo proggettino per leggere la temperatuta del motore della  moto e indicarla con due led 7seg per ragioni di spazio sul cruscotto.
Girando sul web ho trovato un schema semplice che fa al caso mio ed ancke lo sketch.
Originariamente lo sketch aveva qualche errore che ho eliminato.
Ora lo sketch funziona correttamente con imprecisione di +- 1 ° almeno sul simulatore proteus8.1
 
Quando misura temperature (es 15° e 16°) li indica come 19 e 18, mentre il 17 torna ad indicarlo corretamente, se imposto una temperatura a 18° rimane ad indicare 17°,
Che una erronea conversione AD di un grado mi sta anche bene ma non che mi indichi un numero sballato. Questa erronea indicazione si ripete per ogni decade dei numeri rappresentati allego qualche foto dove si vede la temp a 44° 45, 46, 47.

ho provaro anche  aseguire un suggerimento di usare il Aref per aumentare un po di èpiù la precisione di lettura ma nulla cambia rimene sempre quella indicazione anomala.

 
Qui di seguito trovate anche lo sketch.
ci sto sbattendo da 1 gg ma non riesco a caprire dove sia l'errrore di conversione o di rappresentazione.
Ho visto anche che ci sono circuiti che utilizzano dei 74hc595 per pilotare i led 7seg in multiplex che andrò sicuramente ad usare ma prima voglio capire, se mi aiutate vi rinhrazio, dov'è l'errore   


Un sentito grazie a tutti coloro che mi diano suggerimenti.

Code: [Select]

int analogPin = A0;     // sensore TM36 applicato al analog pin A0
float temp =0;         
int val = 0;           // variabile di lettura temp

byte seven_seg_digits[10][7] =                                                           
  { //seg. a,b,c,d,e,f,g          nr
         { 1,1,1,1,1,1,0 },  // = 0 
         { 0,1,1,0,0,0,0 },  // = 1
         { 1,1,0,1,1,0,1 },  // = 2
         { 1,1,1,1,0,0,1 },  // = 3
         { 0,1,1,0,0,1,1 },  // = 4
         { 1,0,1,1,0,1,1 },  // = 5
         { 1,0,1,1,1,1,1 },  // = 6
         { 1,1,1,0,0,0,0 },  // = 7
         { 1,1,1,1,1,1,1 },  // = 8
         { 1,1,1,1,0,1,1 },  // = 9
   };
 
    void setup()
{
  Serial.begin(9600);          //  setup serial
  /*pinMode(0, OUTPUT);  //unita a primo led
  pinMode(1, OUTPUT);  //unita b
  pinMode(2, OUTPUT);  //unita c
  pinMode(3, OUTPUT);  //unita d
  pinMode(4, OUTPUT);  //unita e
  pinMode(5, OUTPUT);  //unita f
  pinMode(6, OUTPUT);  //unita g
  pinMode(7, OUTPUT);  //decine A 2ndo led
  pinMode(8, OUTPUT);  //decine B
  pinMode(9, OUTPUT);  //decine C
  pinMode(10, OUTPUT); //decine D
  pinMode(11, OUTPUT); //decine E
  pinMode(12, OUTPUT); //decine F
  pinMode(13, OUTPUT); //decine G
  */
  DDRD=0b11111111;
  DDRB=0b00111111;
//utilizzando l'istruzione analogReference
 //indico al convertitore AD che deve impiegare
 //la tensione presente sul pin AREF come
 //valore di riferimento per la conversione
 analogReference(EXTERNAL);  // 3.3V

}

void loop()
{
 
 //init variabile
 val = 0;
 //eseguo un ciclo
 for(byte Ciclo = 0; Ciclo<100; Ciclo++)
 {
  //acquisisco il valore e lo sommo alla
  //variabile
  val += analogRead(0);
  float temp= val;
  //questo ritardo serve per dare il tempo
  //all' ADC di eseguire correttamente
  //la prossima acquisizione
  delay(10);
 }

 //eseguo la media dei 100 valori letti
 val /= 100;
 //calcolo la temperatura in °C
 temp = ((val * 0.003222) - 0.5) / 0.01;  // 0.003222 valore di precisione di conversione AD

  int pin=0 ; // per i primo 7-seg pins 0,1,2,3,4,5,6 collegati ai pin led posiz. a,b,c,d,e,f,g
  int pin1=7; // per 2ndo 7-seg pins 7,8,9,10,11,12,13 collegati ai pin led A,B,C,D,E,F,G
// Serial.println("temperature in C =");
 //Serial.println(temp); // debug value

  int tempH;//high number
  tempH=int(temp/10);
 
  int tempL; //low number
  tempL=int(temp-tempH*10);

  for(int j=0;j<7;j++)
  {
    digitalWrite(pin,seven_seg_digits[tempL][j]);
  pin++;}
  for(int i=0;i<7;i++)
  {
   digitalWrite(pin1,seven_seg_digits[tempH][i]);
 pin1++;}
  delay(1000);
 
}


Standardoil

A parte il programma un po'  contorto
A parte almeno una variabile inutile

Secondo me quella formula è sbagliata

E non solo la formula, anche la acquisizione ha qualcosa che non va
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

gpb01

#2
Sep 09, 2020, 10:13 am Last Edit: Sep 09, 2020, 10:15 am by gpb01
>LOLLO65: scusa, per chiarire, ma tu stai usando il TMP36?  ... perché TM36 non mi dice nulla ... ::)

SE e solo SE, stai usando il TMP36, ricorda che il suo range va da -40 a +150 e che quindi, dal valore di temperatura calcolato occorre sempre sottrarre 50.

Questo il codice che io uso su ESP8266 collegando direttamente il sensore al pin analogico del ESP:

Code: [Select]
void getTemperature() {
   int   rawvoltage = analogRead(LM35_PIN);
   float celsius    = ( (float) rawvoltage * 0.3125 );
#ifdef USE_TMP36
   celsius -= 50.0;
#endif
}

... funziona sia con TMP35 (che non va sotto zero) che con TMP36 (che va sotto zero). Il pin analogico è definito come LM35_PIN indipendentemente dal tipo di sensore ed una #define (USE_TMP36) mi dice se sto usando o meno il TMP36.

Guglielmo
Search is Your friend ... or I am Your enemy !

LOLLO65

Ciao ragazzi,
cerco di procedere con domando che mi avete posto, la seriale la usata usate solo per vedere a quali valori covertiti corrispondeva la tesione fornita dal TMP36 e poi se i valori di temp sul serial monitor erano esatti ed ottenevo una corretta corrispondenza con la temp impostata sul sensore, che si Guglielmo hai ragione è il TMP36, con uno scarto di +- 0.2°.

Che il programma sia contorto lo capisco, date le mia scarse conoscenze di programmazione.
Ho ovviamente copiato ed incollato diversi programmi da differenti sketch e cercato di metterli insieme da questo deriva il caos del programma.
Igor a quale variabile in piu ti riferisci?
Per la formula è indicata su un link che da info su come usare il TMP36, cmq prima ho verificato e scritto il valore covertito in digitale da Arduino uno r3 dei valori di tensione fornita dal TMP36, es a 10° il TMP36 fornisce il valore di 0.6 volt che convertiti Arduino indica in 123, 20 ° =143, 30°=164 e cosi via 100°=307.
in definitiva ogni 10° ho uno step AD di 20 usando la tensione di alimentazione a 5V.
Applicati i valori digitali alla formule, usando il ext ref. ((123*0.03222) -0.5 )/0.01; dove 0.5 sono il voltaggio fornito dal TMP36 a 0°C e 0.01 sono i 10mV x ogni grado centigrado, mi restituisce.......
Ho capito dove è l'errore nella formula.
Devo verificare i valori AD convertiti con il Aref a 3.3v. Probabile anche nello schema elettrico abbia commesso l'errore di alimentare il sensore con 5 V anziche con 3.3V; mentre se applico il val di precisione ottenuto da 5/1024 la formula mi restituisce esattamnete 10.05° ed alimentando il sensore a 5V.
Ho apportato modifiche alla formula ora lo sketch funziona bene con una indecizione di -1° (accettabile), es a 70° impostati sul TMP36 di ad un valore di 69°
Con un piccolo aggiustamento al 0.01 messo a 0.00985 Arduino mi indica un val di 71 anziche 70, 

In Ogni Caso è grazie ai vostri suggerimenti, che mi danno la possibilità di riflettere sugli errori, che si sistema tutto.
Guglielmo mi cimenterò ad utilizzare la tua soluzzione.

Grazie ancora.

Standardoil

#4
Sep 10, 2020, 07:28 am Last Edit: Sep 10, 2020, 07:30 am by Standardoil
Allora vediamo un po'

Ipotizziamo 60 gradi, per semplicità
Fa 1.1 volt di uscita del sensore

Diviso 3,3 del riferimento e moltiplicato 1023 di fondo scala del convertitore fa 341 di uscita dallo adc

Tu fai cento letture e le sommi tutte
Questo da una somma di (circa, i valori sono solo stimati) di 34100

Non noti nulla?

Inoltre durante la somma, nel ciclo for, scrivi
Code: [Select]

float temp=val;

Variabile locale che muore alla fine del for

Inoltre ti consiglio di ripensare anche a 'come' fai i calcoli, non solo a che calcoli fai
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

Standardoil

Questo il codice che io uso su ESP8266 collegando direttamente il sensore al pin analogico del ESP:

Guglielmo
Pausa pranzo grande noia

Riprendo il filo della discussione e noto una cosa

Ma ti funziona il codice che hai postato?

Perché è una funzione void, infatti manca il return, ma usa solo variabili locali...

Mi rimane dubbio
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

maubarzi

#6
Sep 10, 2020, 01:00 pm Last Edit: Sep 10, 2020, 01:13 pm by maubarzi
...
Ma ti funziona il codice che hai postato?
...
Credo abbia messo una funzione con gli elementi minimi indispensabili a capire il concetto più che una funzione veramente funzionante.

...
SE e solo SE, stai usando il TMP36, ricorda che il suo range va da -40 a +150 e che quindi, dal valore di temperatura calcolato occorre sempre sottrarre 50.
...
So che Guglielmo con 2000 datasheet in testa è sicuramente andato a memoria, ma:
dal datasheet linkato, leggo " The TMP36 is specified from −40°C to +125°C, provides a 750 mV output at 25°C"
Quindi occhio che il range è da -40 a +125, quindi va sottratto 40 e non 50.

Aspe', fermi tutti, anche tu avevi indicato il -40 come min, quindi perchè sottraevi 50? Il max è ininfluente al fine della discussione, quindi chissene...
L'uscita non parte da zero in corrispondenza del -40?
Ora rileggo bene il datasheet per scoprire l'arcano.

EDIT: eliminato tutto perchè ho sbagliato io a leggere il datasheet. Guglielmo è stato redento perchè l'errore sul max è un peccato veniale  ;D

Maurizio
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

Standardoil

#7
Sep 10, 2020, 01:07 pm Last Edit: Sep 10, 2020, 01:08 pm by Standardoil
Credo anch'io

Pero siccome sembrava una citazione...

C'è gente che copia e poi è capace di risponderti:
"tu hai torto e io ho ragione, perché io ho copiato da uno più bravo di te"

E non sto scherzando, mi è successo sul serio...

Quindi non vorrei un giorno sentirmi dire che io sbaglio a usare il return perché Gugliemo non lo fa....

Per la seconda parte: temo che si debba proprio togliere 50

Perche non sono gradi, ma corrispondono allo 'zoccolo' do 500 mV
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

maubarzi

#8
Sep 10, 2020, 01:09 pm Last Edit: Sep 10, 2020, 01:10 pm by maubarzi
Si, ho visto, si capisce bene da questa immagine del datasheet.



La curva B parte da 0 a -50 e sale in modo lineare, quindi è giusto sottrarre 50.
Che poi il cip a -50 non funzioni più correttamente perchè fuori range è un'altro problema.

Maurizio
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

gpb01

#9
Sep 10, 2020, 01:21 pm Last Edit: Sep 10, 2020, 01:23 pm by gpb01
Ma ti funziona il codice che hai postato?
... :D ... in realtà la funzone continua con altre cose che, per semplifcare e mostrare SOLO la parte calcoli ho eliminato.

In pratica, alla fine, converte in una string (globale) il valore letto, string che poi viene usata nella trasmissione HTTP :D

Guglielmo
Search is Your friend ... or I am Your enemy !

LOLLO65

Salve Ragazi, non pensavo di scatenare tanti commenti cmq benvengano.
Io lo ho detto che sono alle prime armi con la programmazione e il mio applicarmi a cio è saltuario e ho anche detto di aver copiato ed incollato vari pezzi di sketch.
Mi scuso se ho dato l'impressione di esprimere concetti e di saperne molto di più di voi, non è mia intenzione,  se  ero così esperto non chiedevo il vostro aiuto; che è sempre gradito.
E' gradito il vostro aiuto al fine di mettere un po di ordine allo sketch.

Mi scuso con Standaroil se non ho seguito il suo primo commento. per la formula funziona bene se anziche inserire il 0.003222 utilizzando il external ref,  vi inserisco il 0.0048828 del gardo di percisione.,
lo ho scritto che avevo capito dove era l'errore commesso nell'utilizzare la formula di coversione.

Per rispondere a IGOR, per i serial begin e println li ho disattivati al momento di utilizzare i 7seg, mi servivano nella prima fase per vedere il val ADC e il valore di temp fornito dal simulatote.

Poi che il misurare temperatura con arduino è più che ampiamente argomentato e con vari metodi.

Se mi aiutate a mettere ordine allo sketch vi clicco 1000 Karma :)  :)  :)  :)
Vi posto l'ultimo sketch con il quale ottengo, a mio parere e per ora solo sul simulatore, buoni risultati con indicazione di +-0.5 gradi.

Code: [Select]

int val_Adc = A0;     // sensore TMp36 applicato al analog pin A0
float temp =0;         


byte seven_seg_digits[10][7] =                                                           
  { //seg. a,b,c,d,e,f,g          nr
         { 1,1,1,1,1,1,0 },  // = 0 
         { 0,1,1,0,0,0,0 },  // = 1
         { 1,1,0,1,1,0,1 },  // = 2
         { 1,1,1,1,0,0,1 },  // = 3
         { 0,1,1,0,0,1,1 },  // = 4
         { 1,0,1,1,0,1,1 },  // = 5
         { 1,0,1,1,1,1,1 },  // = 6
         { 1,1,1,0,0,0,0 },  // = 7
         { 1,1,1,1,1,1,1 },  // = 8
         { 1,1,1,1,0,1,1 },  // = 9
   };
 
    void setup()
{
 /* Serial.begin(9600);          //  setup serial
  pinMode(0, OUTPUT);  //unita a primo led
  pinMode(1, OUTPUT);  //unita b
  pinMode(2, OUTPUT);  //unita c
  pinMode(3, OUTPUT);  //unita d
  pinMode(4, OUTPUT);  //unita e
  pinMode(5, OUTPUT);  //unita f
  pinMode(6, OUTPUT);  //unita g
  pinMode(7, OUTPUT);  //decine A 2ndo led
  pinMode(8, OUTPUT);  //decine B
  pinMode(9, OUTPUT);  //decine C
  pinMode(10, OUTPUT); //decine D
  pinMode(11, OUTPUT); //decine E
  pinMode(12, OUTPUT); //decine F
  pinMode(13, OUTPUT); //decine G
 */ 
  DDRD=0b11111111;
  DDRB=0b00111111;

}

void loop()
{
 delay(300);
 //init variabile
 val_Adc = analogRead(A0);
 //eseguo un ciclo
 for(byte Ciclo = 0; Ciclo<100; Ciclo++)
 {
  //acquisisco il valore e lo sommo alla variabile val_Adc
  val_Adc += analogRead(A0);
  float temp = val_Adc;
  //questo ritardo serve per dare il tempo
  //all' ADC di eseguire correttamente
  //la prossima acquisizione
  delay(10);
 
 }

 //eseguo la media dei 100 valori letti
 val_Adc /= 100;
// calcolo la temperatura in °C
 temp = ((val_Adc * 0.0048828125) - 0.5) / 0.00998;

// Serial.println("temperature in C =");
 //Serial.println(temp); // debug value

  int pin=0 ; // per il primo 7-seg pins 0,1,2,3,4,5,6 collegati ai pin led posiz. a,b,c,d,e,f,g
  int pin1=7; // per 2ndo 7-seg pins 7,8,9,10,11,12,13 collegati ai pin led A,B,C,D,E,F,G

  int tempH;//high number
  tempH=int(temp/10);
 
  int tempL; //low number
  tempL=int(temp-tempH*10);

  for(int j=0;j<7;j++)
  {
    digitalWrite(pin,seven_seg_digits[tempL][j]);
  pin++;}
  for(int i=0;i<7;i++)
  {
   digitalWrite(pin1,seven_seg_digits[tempH][i]);
 pin1++;}
  delay(500);
 
}


Grazie in ogni caso a tutti.

Standardoil

ma con che temperature hai provato?
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

Standardoil

Se mi aiutate a mettere ordine allo sketch vi clicco 1000 Karma :)  :)  :)  :)
Ci conto, comincia ad aggiungere Karma........

Code: [Select]

int val_Adc = A0;     // sensore TMP36 applicato al analog pin A0
float temp =0;         


byte seven_seg_digits[10][7] =                                                           
  { //seg. a,b,c,d,e,f,g          nr
         { 1,1,1,1,1,1,0 },  // = 0 
         { 0,1,1,0,0,0,0 },  // = 1
         { 1,1,0,1,1,0,1 },  // = 2
         { 1,1,1,1,0,0,1 },  // = 3
         { 0,1,1,0,0,1,1 },  // = 4
         { 1,0,1,1,0,1,1 },  // = 5
         { 1,0,1,1,1,1,1 },  // = 6
         { 1,1,1,0,0,0,0 },  // = 7
         { 1,1,1,1,1,1,1 },  // = 8
         { 1,1,1,1,0,1,1 },  // = 9
   };
 
    void setup()
{
 // Serial.begin(9600);          //  setup serial
 // mai tenere codice inutile commentato
  DDRD=0b11111111;
  DDRB=0b00111111;

}
 
void loop()
{
 delay(300);
 //init variabile
 val_Adc = analogRead(A0); // e questa è una lettura
 //eseguo un ciclo
 for(byte Ciclo = 0; Ciclo<100; Ciclo++)
 {
  //acquisisco il valore e lo sommo alla variabile val_Adc
  val_Adc += analogRead(A0);
  float temp = val_Adc;
// questa variabile non la usi mai ( e te lo avevo già detto)

  //questo ritardo serve per dare il tempo
  //all' ADC di eseguire correttamente
  //la prossima acquisizione
// sicuro che serva? magari rileggere il reference ti chiarisce le idee....
  delay(10);
 
 }
// e adesso alla fine del ciclo ne hai fatte altre cento, di letture


 //eseguo la media dei 100 valori letti

// 100? sicuro?
// quante letture hai fatto?
 val_Adc /= 100;

// calcolo la temperatura in °C
 temp = ((val_Adc * 0.0048828125) - 0.5) / 0.00998;
// ecco forse perchè devi dividere per un nnumero così strano

/*
e poi scusa: moltiplicho per 0.004882815, sicuro che ci siano così tante cifre significative?
che poi dividi per 0.00998

forse scrivere 0.48828125 e 0.998 dà lo stesso risultato con meno casini di calcolo
moltiplicare e dividere per uno stesso numero non cambia il risultato, aritmetica da 4 elementare
te lo avevo detto di guardare "come" fai i calcoli, non solo "che" calcoli fai
*/

  int pin=0 ; // per il primo 7-seg pins 0,1,2,3,4,5,6 collegati ai pin led posiz. a,b,c,d,e,f,g
  int pin1=7; // per 2ndo 7-seg pins 7,8,9,10,11,12,13 collegati ai pin led A,B,C,D,E,F,G

  int tempH;//high number
  tempH=int(temp/10);
 
  int tempL; //low number
  tempL=int(temp-tempH*10);

  for(int j=0;j<7;j++)
  {
    digitalWrite(pin,seven_seg_digits[tempL][j]);
  pin++;}
  for(int i=0;i<7;i++)
  {
   digitalWrite(pin1,seven_seg_digits[tempH][i]);
 pin1++;}
  delay(500);
 
}


Leggi i commenti che ti ho scritto nel programma

che mi sono meritato una buona fetta dei 1000 karma promessi

quando vedrò moneta ti mostrerò il resto del cammello
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

LOLLO65

Con il simulatore (proteus8.1) le letture da 0° a 98° con indicazione di quest ultima a 99°.
Il mio campo di misura arriva fino 90°.
Poi ho dato una pulita allo sketch eliminando il cilo for e media, funziona lo stesso.
il valore 0.048828125 è cio che risulta dal calcolo 5/1024. So di per certo che non è necessario mettere un valore così lungo ed era solo una mia curiosita.
Mettere 0.00998 mi è servito solo per far leggermente sovrastimare la temperatura che con 0.01 invece me la sottostimava di 1° (es a 98 ° serduino indicava 97°), sicuramente dovuto ad approssimazioni della conversione.

PS  spero che il cammello non si chiami Serafino.  :D.

Standardoil, posso chiederti l'origina del tuo nick name?

Standardoil

Tu facevi 101 letture e dividevi per 100, ecco l'origine delle varie imprecisioni

cambia simulatore, quello che usi è fallato

sommare 100 (e una) letture su una variabile int ti fa superare 32mila e fischia per temperature oltre i 60 gradi

questo è il significato del mio post di stamattina

se il tuo simulatore non va in overflow cambialo, non è adatto a fare prove che abbiano un minimo di affidabilità

per il resto domani, adesso è tarduccio
Prima legge di Nelson (che sono io): A parità di risultato maggiore il pensiero minore il sudore
Io penso, ma tu vuoi proprio asciugarti la fronte?

Non bado a studenti, che copino altrove
Hai problema-Ti domando-Non rispondi: Non ti serve più

Go Up