Sensor de temperatura Lm35DT

Con el codigo que pongo seguidamente hago 100 lecturas de un sensor LM35DT y las guardo en un array para hacer una media.

Mi problema es que si muestro las mediciones por Serial.print todas ellas varian.
Las mediciones se hacen seguidas, una tras otra, y hay variaciones desde decimas de grado hasta 2 grados de diferencia. Como puede ser?

GRACIAS.

#define VALOR 100

#include "Wire.h"
#include "BlinkM_funcs.h"
#define blinkm_addr 0

int lm35 = 0; 
int pinLED = 13;
int sensorPin = 0;
float valor_temp = 0;


float calcular_temperatura()
{
  float temp=0;
  float array_temp[VALOR];
  float temp_total = 0;

  for(int n=0;n<VALOR;n++)
  {
    temp = ((5 * analogRead(lm35)*100.0)/1023.0);
    delay(10);
    array_temp[n] = temp;
  }
  for(int n=0;n<VALOR;n++)
    {
     temp_total = temp_total + array_temp[n];
    }
  temp = temp_total / VALOR;
  return(temp);
}

void setup()
{
  Serial.begin(9600);
  pinMode(pinLED, OUTPUT);
  BlinkM_beginWithPower();  
  BlinkM_stopScript( blinkm_addr );  // turn off startup script
} 

void temperatura(int pausa)
{
  valor_temp = calcular_temperatura();
  Serial.print("Valor: ");
  Serial.println(valor_temp);

  if (valor_temp >= 30){VERMELL(pausa);}
  else if (valor_temp >= 28 && valor_temp < 30){LILA(pausa);}
  else if (valor_temp >= 24 && valor_temp < 28){TARONJA(pausa);}
  else if (valor_temp >= 22 && valor_temp < 24){GROC(pausa);}
  else if (valor_temp >= 21 && valor_temp < 22){PISTATXO(pausa);}
  else if (valor_temp >= 20 && valor_temp < 21){VERD(pausa);}
  else if (valor_temp >= 19 && valor_temp < 20){CYAN(pausa);}
  else if (valor_temp >= 18 && valor_temp < 19){BLAVOS(pausa);}
  else if (valor_temp < 18){BLAU(pausa);}  
  else{BLANC(500);NEGRE(500);BLANC(500);NEGRE(500);BLANC(500);NEGRE(500);}
  digitalWrite(pinLED, HIGH);
  delay(pausa);
  digitalWrite(pinLED, LOW);
}

void loop()
{
  temperatura(1);
}

void VERMELL(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 0, 0 );  delay(pausa);}

void VERD(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 0, 255, 0 );  delay(pausa);}

void BLAU(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 0, 0, 255 );  delay(pausa);}
  
void BLANC(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 255, 255 );  delay(pausa);}

void NEGRE(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 0, 0, 0 );  delay(pausa);}

void GROC(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 255, 0 );  delay(pausa);}

void LILA(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 0, 255 );  delay(pausa);}

void TARONJA(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 128, 0 );  delay(pausa);}

void MORAT(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 255, 0, 128 );  delay(pausa);}

void CYAN(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 0, 255, 255 );  delay(pausa);}

void BLAVOS(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 0, 128, 255 );  delay(pausa);}

void PISTATXO(int pausa){
  BlinkM_fadeToRGB( blinkm_addr, 128, 255, 0 );  delay(pausa);}

El LM35 proporciona 10mV por cada grado centígrado y una resolución de 0,5 grados. Tener un error de 2 grados significa tener un error de 20mV en la medida.

Por otra parte el convertidor analógico digital de la placa Arduino es de 10bits y su resolución es de 5V/1024, esto es, algo menos de 5mv. Si el error típico de medida es de +/- una cuenta, tenemos un error en la medida de unos 10 mV.

Además de eso la longitud de los cables, el echo de que el convertidor esté dentro del propio convertidor, el ruido eléctrico... son factores que afectan (negativamente) a la medida.

Soluciónes:

1 - Hacer promedios es una buena forma de diminuir el ruido (aleatorio) y hacer que la medida sea más estable. No hace falta que metas en un array todas las medidas, las puedes acumular (sumar) en una variabla (previamente inicializada a cero) y el promedio lo conviertes a grados. Lo mejor es hacer promedios potencia de 2, para así poder hacer la división con desplazamientos (>>)

2 - Poner un amplificador entre el sensor y la entrada analógica

3 - Cambiar la referencia del convertidor

Por cierto, ya que hablamos del LM35 me gustaría comentar el siguiente circuito que podemos encontrar con bastante facilidad en la red, es como si unos se lo copiaran de otros:

La resistencia de 100K no pinta nada de esa manera, yo creo que alguien vió esto en la hoja de caracerísticas del LM35:

Y pensó: "como no tengo tensión negativa, conecto la resistencia a masa"

Pero en realidad esa resistencia tiene que estar conectada a -V para que el LM35 nos pueda dar medidas de tensión negativas, en concreto el valor de dicha resistencia se calcula de la siguiente forma: R1 = -Vs/50uA

Si no tenemos tensión negativa el LM35 solo nos puede dar valores positivos de temperatura (2 grados como mínimo) y su conexión es muy sencilla: quitamos la resistencia de 100K del primer circuito.

Es cierto que hay algunas maneras más o menos sofisticadas para conseguir medidas de temperatura negativa con el LM35. Las más sencillas como desplazar el potencial de la pata GND del LM35 con un dido tienen el inconveniente de que son sensibles a la variación de la temperatura.

En resumen, que si quiero medir temperaturas positivas con el LM35, no necesito resistencia alguna, y si queremos medir temperaturas negativas igual sería mejor que me bsucase otro sensor :slight_smile:

Según tengo entendido, el sensor te dará una corriente máxima de 1,5 V para una temperatura de 150ºC. Como lo más normal es moverte en un rango más pequeño (eso me lo supongo yo y puedo estar equivocado), puedes disminuir el error introduciendo la tensión correspondiente a la temperatura máxima en la entrada de referencia analógica de Arduino. Así, si lo más caliente que esperas medir son 80 grados, si poner 0.8V en la entrada AREF, la resolución será 0.8/1024, con lo que los 5 mV que calculaba Complubot pasan a ser 0.78 mV... es decir, pasas de medio grado a menos de una décima.
El problema de conseguir 0.8 voltios puedes resolverlo con un par de resistencias puestas en divisor de tensión. Supongo que sabrás hacerlo, pero si no es así, no dudes en preguntar.

Que sensor recomendariais para tomar lecturas de (-20º a +55º). y que no presente muchos problemas de ruido.

Iria instalado dentro de una unidad exterior de Aire Acondicionado, la verdad es que he probado con varios y en cuanto se pone en marcha, un desastre, el ruido electrico tiene que ser impresionante (variaciones de +-10º)

Gracias Pofenas por la información, pero no se como hacerlo, mi problema es la electronica. No la domino mucho.

Que sensor recomendariais para tomar lecturas de (-20º a +55º). y que no presente muchos problemas de ruido.

Iria instalado dentro de una unidad exterior de Aire Acondicionado, la verdad es que he probado con varios y en cuanto se pone en marcha, un desastre, el ruido electrico tiene que ser impresionante (variaciones de +-10º)

Puedes usar el DS18B20 http://pdfserv.maxim-ic.com/en/ds/DS18B20.pdf, tiene una precisión de 0,5ºC de -10 a +85ºC, la mínima (teórica) son -55ºC, aunque la precisión baja un poco (como es lógico) según baja la temperatura. El DS18B20 tiene la ventaja de incorporar el convertidor A/D en el propio sensor y por lo tanto tendremos una mejor relación señal/ruido.

La comunicación con la placa Arduino es digital, mediante un conexión serie de 1 Bit. Aquí tienes más información al respecto http://www.arduino.cc/playground/Learning/OneWire

Gracias Pofenas por la información, pero no se como hacerlo, mi problema es la electronica. No la domino mucho.

Aquí tienes la información de como usar la "tensión de referencia analógica" analogReference() - Arduino Reference

La Referencia Analógica fija el máximo valor de tensión que podemos medir en una entrada analógica de nuestra placa. Por defecto la referencia es de 5V, así que la resolución de nuestra medida es 5/1024 (no 5/1023, como ponen algunos, página 254 del manual del Atmega168). Cuando leemos una entrada analógica conseguimos una lectura de "cuentas del convertidor" que varía entre 0 y 1023. Si queremos pasar esta medida a voltios solo tenemos que multiplicarla por 5/1024. Efectivamente, nunca conseguimos 5V, como mucho 1023*5/1024.

Ahora bien, si conectamos una tensión externa a la entrada "AREF" de nuestra placa, podemos modificar el valor máximo de nuestra medida (fondo de escala).

Hay una manera de poner una Referencia Analógica distinta sin conectar nada (por sotware), llamando a la función analogReference(INTERNAL); en el setup, por ejemplo.

De esta forma nuestra referencia pasa a ser 1,1V (110ºC en el caso del LM35), la resolución 1,1/1024 y para convertir a voltios lo que conecte a una entrada analógica: lectura * 1,1/1024. De esta forma tu resolución aumenta, aunque seguiras necesitando hacer promedios para disminuir el ruido.

Una cosa importante. Si cambiamos la referencia analógica con analogReference(), esto afecta a todas las entradas analógicas de la placa. Si quiero combinar medidas con la referencia de 1,1 y 5V en el mismo programa, tendré que llamar a la función analogReference() antes de cambiar el tipo de medida en el programa.

Justamente estoy trabajando en un control de temp con LM35 para macerar el mosto de la cerveza. Controla una resistencia de 1KW a traves de un triac y realmente a pasar de conmutarse en su paso por 0 genera mucho ruido que "lee" el LM35. Hay que cuidar el detalle del desacople y la regulacion de la fuente de alimentacion, desvincular la tension de referencia con un reguladorcito solo para ella y en lo posible si usas un display (yo lo hice con el SAA1064) tambien regular la tension aparte. Hay que apantallar el cable del sensor (Cable blindado estereo de buena calidad) y desacoplar lo mas cerca posible del LM35 con un par de capacitores y si tiene ficha de conexion, que sea buena, asi como la puesta a masa del chasis. Cuanto mas cuidado mejor!!. Sino pasate al sensor digital. Saludos

Complubot,

Muchas gracias por tu información (como siempre...)

Un Saludo,

Gracias a todos, voy a realizar pruebas a ver que tal.

GRACIAS.