Go Down

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

maubarzi

Io per aumentare la precisione delle letture uso dei voltage reference, ad es. il LM336 a 2,5V fisso oppure uno variabile, es. il TL431 che in base ai valori delle resistenze del circuito tipico ti permette di "scegliere" la tensione di riferimento desiderata.
Uso due pin analogici (che spreco  ;D ) con uno leggo il voltage reference conoscendo la tensione esatta e con l'altro la tensione di interesse.
Con il primo ho una taratura esatta, da cui si riesce anche a calcolare la tensione di alimentazione.
Basta fare le dovute proporzioni avendo come prima equazione, un'equazione con tutte le variabili conosciute.
Mi ci trovo bene perchè così sono sicuro della bontà delle letture, ovviamente fatte più ravvicinate possibile o anche con la media di N letture consecutive, giusto per non beccare dei picchi strani.

Per la temperatura, in genere anche io uso sensori digitali, ma in altri casi, dove l'uscita è analogica, adotto la tecnica dei voltage reference.
Cippettini che trovo super economici e molto interessanti per i miei scopi.
Ne ho presi a decine per poco più di 1 euro, spedizione inclusa, su AliExpress tempo fa e ora sono a posto per un bel po'.  8)

Maurizio
Nessuna buona azione resterà impunita!

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

LOLLO65

Ciao Maurizio,
Grazie ancora dei tuoi suggerimenti, teorici e pratici.
infatti quello che non mi spiegavo era perche ottene vo dei valori di temperatura leggermente sottostimati.
Poi mi sono riletto il tuo post del 15 sept. ed ho apportato la correzione alla formula adesso il tutto mi funziona bene, infatti adesso alla temp di 99° corrisponde l'indicazione di 99 sul display,
Ogni valore letto sul display corrispoinde a quello impostato sul sensore.
Per me l'indicazione +- 1° è piu che soddisfacente.
Quello che mi lascia più sconcertato è che su alcune esempi nel web riportano la formula x il calcolo temperatuta con il dividendo 1024 anziche 1023.
Colpa mia di non conoscere bene tutte le caratteristiche della scheda Arduino.

Ho provato anche ad usare la funzione map() leggendo alcuni post in merito e prendendo spunto da uno sketch per un anemometro, ed ho scritto questo:

Code: [Select]

int misure[20];
int somma;
int sensore;
float media;
float TEMP=0;
float inMin=102;
float inMax=305;
float tensMin=0.5;
float tensMax=1.5;

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() {
 DDRD=0b11111111;
 DDRB=0b00111111;
// Serial.begin(9600);
}

float fmap (float TEMP, float inMin, float inMax, float tensMin, float tensMax)
 {
   return (TEMP- inMin) * (tensMax - tensMin) / (inMax - inMin) + tensMin;
 }

void loop(){
 // sensore=analogRead(A0);
 
 Serial.println(sensore);
 int i;
   for (i=0;i<20;i++){
    misure[i]=analogRead(A0);
  Serial.println(misure[i]);
 }
  somma=0;
  for (int i=0;i<20;i++) {
  somma=somma+misure[i];
 Serial.print("la somma e' ");
  Serial.println(somma);
 
  }

  media=somma/20;
Serial.print("la media e' ");
Serial.println(media);
 float voltage = (media * 500);
 voltage /= 1023.0;
float temperatureC = (voltage - 50);
TEMP = fmap(TEMP,inMin,inMax,tensMin,tensMax);
 Serial.print(" TEMP ");
 Serial.println(temperatureC);
 
 // usara il calcolo seguente per convertire in Fahrenheit
// float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
// Serial.print(temperatureF); Serial.println(" degrees F");
 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(temperatureC/10);
 
  int tempL; //low number
  tempL=int(temperatureC-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);
}




Sicuramente non la ho impostata nel modo giusto.  Non ho trovato grandi benefici e ho deciso di eliminarla dallo sketch che adesso è questo:
Code: [Select]

int misure[20];
int somma;
int sensore;
float media;
float TEMP=0;
float inMin=102;
float inMax=305;
float tensMin=0.5;
float tensMax=1.5;

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() {
 DDRD=0b11111111;
 DDRB=0b00111111;
// Serial.begin(9600);
}


void loop(){
 // sensore=analogRead(A0);
 
 Serial.println(sensore);
 int i;
   for (i=0;i<20;i++){
    misure[i]=analogRead(A0);
  Serial.println(misure[i]);
 }
  somma=0;
  for (int i=0;i<20;i++) {
  somma=somma+misure[i];
 Serial.print("la somma e' ");
  Serial.println(somma);
 
  }

  media=somma/20;
Serial.print("la media e' ");
Serial.println(media);
 float voltage = (media * 500);
 voltage /= 1023.0;
float temperatureC = (voltage - 50);

 Serial.print(" TEMP ");
 Serial.println(temperatureC);
 
 // usara il calcolo seguente per convertire in Fahrenheit
// float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
// Serial.print(temperatureF); Serial.println(" degrees F");

 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(temperatureC/10);
 
  int tempL; //low number
  tempL=int(temperatureC-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);
}

 
Sono più che contento, provero a far lampeggiare i display raggiunta una certa temperatura es 95°

Ciao Grazie ancora

maubarzi

Ottimo, son contento che sei contento  ;D

Per il 1024, è una brutta bestia, perchè l'umano tende sempre a ragionare uno based, cioè iniziando a contare i valori da 1, invece in informatica è molto più comune iniziare da zero. Ci si incasinano in molti.

Per map(), no problem, tanto fa solo la proporzione che avevi fatto anche tu. semplicemente poteva rendere più compatto e leggibile il codice, ma se uno non ci è abituato, o non ci si trova, fa l'effetto contrario di peggiorare la leggibilità, quindi hai fatto bene a tralasciarla.

Ciao e buon proseguimento.
Maurizio
Nessuna buona azione resterà impunita!

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

gpb01

#33
Sep 17, 2020, 09:25 am Last Edit: Sep 17, 2020, 09:38 am by gpb01
Quello che mi lascia più sconcertato è che su alcune esempi nel web riportano la formula x il calcolo temperatuta con il dividendo 1024 anziche 1023.
Ed infatti è sbagliato dividere per 1023, bisogna dividere per 1024  dato che gli step sono proprio 1024  :smiley-evil:  ...
... se ne è discusso molto tempo fa (... ed è sufficiente leggere con attenzione il datasheet per capire come funziona), comunque trovi tutto QUI :)

Guglielmo

P.S.: Per uleriori spiegazioni .. ci si ritrova nel tardo pomeriggio :D
Search is Your friend ... or I am Your enemy !

LOLLO65

Ciao ragazzi,
oggi sono contentissimo xkè ho implementato lo sketch con la brutta bestia del millis, come dice Maurizio.
Mi ero già inbattuto nel millis combattendoci per svariati giorni con un altro mio proggettino (indicatore di livello carburante), postato un po di tempo, da cui ho preso spunto.

Questa volta ci ho impiegato solo 1gg e quel che è bello, con mia somma sorpresa, è che i display lampeggiano alla temperatura impostata 95°, e continuano a lampeggiare anche quando la temp supera il limite impostato a 95 indicando 96,97,98,99. :D   
Per rispondere a Guglielmo, il 1024 credo sia solo una questione di conteggio matematico umano,
infatti come tu affermi e anche come afferma Maurizio nella discussione linkata rispondendo a Paolo; i numeri sono 1024 ed il 1024mo corrisponde al 1023 dell' ADC di Ardu.
Usando il 1023 mi ritornano le diciamo giuste conversioni.   

Ce un a cosa che non riesco a capire nel parte del calcolo della media come si vede dall'allegato
la lettura inizia con il 205 ( temp impostata 50°) ma la media restituita da un valore negativo perché la prima lettura, così come le successive, viengono subito divise x 20 (valore dell'array);
 poi proseguendo con le letture e la loro somma e media si stabilizzano; quando l'array vien riempito dalle 20 letture il ritorno della media è 205 e la temp indicata è 50°.

Domanda, la media non dovrebbe essere calcolata solo dopo che l'array è stato riempito con le 20 letture?


 Qui di seguito lo sketch che sottopongo al vostro parere.
Code: [Select]



int sensore = A0;

float TEMP=0;
int const fsize = [20]; 
int fil[fsize]; 
int i=0;
int j=0;
float avg=0;
const int ledPin0 = 0;
const int ledPin1 = 1; 
const int ledPin2 = 2;
const int ledPin3 = 3;
const int ledPin4 = 4;
const int ledPin5 = 5;
const int ledPin6 = 6;
const int ledPin7 = 7;
const int ledPin8 = 8;
const int ledPin9 = 9;
const int ledPin10 = 10;
const int ledPin11 = 11;
const int ledPin12 = 12;
const int ledPin13 = 13;
int ledState = LOW;


unsigned long previousMillis = 0;       
const long interval = 500;     

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() {
 DDRD=0b11111111;
 DDRB=0b00111111;

}

void loop(){
  sensore=analogRead(A0);
 
  fil[i]= sensore;
   if (i < (fsize-1)) i++;
  else i = 0;
  avg=0;
  for (int j=0; j< fsize; j++) {
    avg +=(float)fil[j];
  }
  avg = avg / (float)(fsize);   // questa la linea incriminata
 

 float voltage = (avg * 500);
 voltage /= 1023.0;
float temperatureC = (voltage - 50);


int DSP1=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 DSP2=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(temperatureC/10);
 
  int tempL; //low number
  tempL=int(temperatureC-tempH*10);

  for(int j=0;j<7;j++)
  {
   digitalWrite(DSP1,seven_seg_digits[tempL][j]);
  DSP1++;}
  for(int i=0;i<7;i++)
  {
   digitalWrite(DSP2,seven_seg_digits[tempH][i]);
 DSP2++;}

 
 unsigned long currentMillis = millis();
  if ( temperatureC >= 95 ){
 if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  if (ledState == LOW) {
      ledState  == HIGH;
 } else {
     ledState  = LOW;
     
    }
    digitalWrite(ledPin0, ledState);
    digitalWrite(ledPin1, ledState);
    digitalWrite(ledPin2, ledState);
    digitalWrite(ledPin3, ledState);
    digitalWrite(ledPin4, ledState);
    digitalWrite(ledPin5, ledState);
    digitalWrite(ledPin6, ledState);
    digitalWrite(ledPin7, ledState);
    digitalWrite(ledPin8, ledState);
    digitalWrite(ledPin9, ledState);
    digitalWrite(ledPin10, ledState);
    digitalWrite(ledPin11, ledState);
    digitalWrite(ledPin12, ledState);
    digitalWrite(ledPin13, ledState);
   
  }
  }
  delay(300);
}

 


Grazie per i vostri suggerimenti.

   


LOLLO65

correggo non è lan mesia in negativo ma la temperatura.

 

Standardoil

#36
Today at 07:20 am Last Edit: Today at 09:31 am by Standardoil
Programma complicato, semplificati

Inoltre non vedo le stampe che dici di fare, in effetti anche se ci fossero non farebbero il problema che dici tu


E comunque devi dividere per 1024, questo è certo

Se hai misure errate usando 10234 stai sbagliando da qualche parte

Metti sempre il programma che fa le stampe che mostri, altrimenti fai come si dice : una scarpa e una ciabatta
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

#37
Today at 08:51 am Last Edit: Today at 10:35 am by gpb01
... Per rispondere a Guglielmo, il 1024 credo sia solo una questione di conteggio matematico umano,
infatti come tu affermi e anche come afferma Maurizio nella discussione linkata rispondendo a Paolo; i numeri sono 1024 ed il 1024mo corrisponde al 1023 dell' ADC di Ardu.
Usando il 1023 mi ritornano le diciamo giuste conversioni ...
Perdona la brutalità, ma ... stai scrivendo delle "sciocchezze" ... si DEVE dividere per 1024 e lo dice il "datasheet", non "una questione di conteggio umano" ... evidentemente, NON hai letto neanche con attenzione il thread che ti ho linkato, altrimenti avresti capito "quanto valgono" i vari "step" del ADC e per "quale motivo" ... ::)

Detto questo ... per me fai come ti pare ... t'è stato detto che è sbagliato, se a te va bene così ... nessun problema!  :smiley-mr-green:

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

maubarzi

#38
Today at 11:51 am Last Edit: Today at 11:51 am by maubarzi
Per il 1024, è una brutta bestia .... Ci si incasinano in molti.
A volte pure io  ;D

Quello che dicono il Sommo (Guglielmo) e il socio (Standardoil) è corretto.
E come hai visto ci casco pure io a volte.
Ora mi manca il tempo per capire esattamente dov'è l'inghippo e per fornire una spiegazione dettagliata della questione.
Però è molto probabile che ci sia un secondo errore che fa produrre il risultato attuale andando contro quanto scritto sul datasheet.
Magari è proprio il simulatore, che facendo lo stesso errore sul 1023/1024, produce questi risultati.

Maurizio
Nessuna buona azione resterà impunita!

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

Go Up