problema leyendo temperaturas en arduino-ethernet

Hola recientemente he adquirido un arduino ethernet con un módulo poe para poder fabricarme un controlador de temperatura que me avise cuando suba por encima de una determinada temperatura... hasta aquí todo bien.... He utilizado un TMP36 y he conseguido que por un lado me lea la temperatura y me la muestre sin problemas por el puerto serie, y por otro he conseguido enviar emails a través de gmail usando el arduino...

Cuando leo la temperatura con el cable de red desconectado funciona sin problemas mostrando algo así:

30,86.30,86.30,86.30,86.30,86.30,86.30,86.30,86

El primer valor es temp en grados y el segundo en ºF...

El problema viene cuando leo la temperatura con el cable de red conectado en cuyo caso las lecturas son tal que así:

1,33.-5,23.-25,-13.-27,-16.-8,17.-40,-40.-40,-40.-15,5.-31,-23.-34,-29.-33,-27.

Entiendo que debe haber una solución sencilla colocando una resistencia en algún sitio o algo parecido, pero soy un negado en electrónica y la solución se me escapa...

Bueno muchas gracias por vuestra ayuda :slight_smile:

vaya, parece que el pin analógico 0 se usa para algo cuando conectas el cable de red ya que ha sido cambiarlo al pin analógico A1 y coge los valores perfectamente....

Edito, retiro lo dicho... cuando lleva un rato funcionando mete valores irreales:

29,84.29,84.29,84.29,84.29,84.29,84.-17,1.-7,19.-34,-29.29,84.29,84.29,84.-22,-7.-7,19.-31,-23.-32,-25.-15,5.-35,-31.-45,-49.

Por cierto el trozo de código que lee la temperatura es el siguiente:

void loop(){
val = getVoltage(analogPin);
val = (val - .5)100;
gcent=val;
gfar=gcent
1.8+32;
delay(2000);
Serial.println(String(gcent)+","+String(gfar)+".");
delay(50);
}
float getVoltage(int anapin){
return (analogRead(anapin) * .004882814);
}

Alguna idea?

Gracias.

¿Has comprobado si te saca también valores irreales sin estar conectado el cable de red llevando un tiempo en marcha?

Efectivamente cuando lleva un rato funcionando incluso con el cable de red desconectado empieza a írsele la pinza...

Mira que os empeñais en usar sensores analogicos...

Yo compre al principio el LM35, tarde menos de dos microsegundos en mandarlo a freir esparragos, donde este un sistema digital...

A partir de ahi emplee el DS18B20 un sensor que no depende de valores de precision en la tension ni depende de la resistencia añadida del cable ni gaitas por el estilo...

Digital, comunicacion digital.

Hay mil ejemplos de uso en la red.

¿Puedes poner todo el código para comprobar que el fallo no está por otro sitio? ¿Y el esquema del montaje?

ayer mismo encargué un 18b20s, sin embargo, no entiendo porque fallan cosas qie deben funcionar,...

por cierto en el esquema que adjuntas veo que se montan 3 sensores, esto se hace para aumentar la precisión? o hay alguna razón más que se me escape...

jorgepl:
¿Puedes poner todo el código para comprobar que el fallo no está por otro sitio? ¿Y el esquema del montaje?

Aquí llevas todo el mogollón :slight_smile:

//Como siempre empezamos llamando 
//las librerias necesarias
#include <SPI.h>
#include <Ethernet.h>
//Definimos las variables globales
//Variable de control para no enviar muchos emails seguidos
boolean correo=false;
//Pin donde conectaremos el sensor de temperatura
int anapin = 3;
//Mac address del arduinoethernet viene
//impreso por debajo de la placa, consta de 6 bytes en Hex
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xF2, 0xA6 };
//Servidor de email o en nuestro caso
//servidor donde hemos instalado el stunnel
byte server[] = { 10, 0, 0, 5 }; 
//Variable que guardara los valores leidos 
//en el sensor de temperatura
float val=0;
//Creamos una objeto de clase EthernetClient
EthernetClient client;

//iniciamos el setup
void setup()
{
  //Se inicia el puerto serie
  Serial.begin(9600);
  //Mostramos por pantalla un mensaje
  Serial.println("Conectando el arduino ethernet a la red...");
  //conectamos el ethernet a la red, solo le pasamos la mac
  //ya que tenemos un servidor de dhcp en nuestra red
  //si queremos especificar la ip tendriamos que hacerlo aqui
  if (Ethernet.begin(mac)==0) Serial.println("Fall´ la conexi´n ethernet");
  //Dejamos un pequeño retardo para que se asigne la ip y demas
  delay(5000);
}

//Iniciamos el loop
void loop(){
  //leemeos la temperatura del sensor llamando a la función getVoltage
  //y le aplicamos la formula para que aparezca en grados centígrados
  //en este sketch obviamos la conversión en grados F ya que no la vamos
  //a necesitar
  val = (getVoltage(anapin) - .5)*100;
  //Como método de control imprimimos al puerto serie el 
  //el valor del sensor
  Serial.println(val);
  //Dejamos una pausa para que las 
  //muestras se tomen cada 5 segundos
  delay(5000);
  //Comprobamos si el valor de la temperatura esta 
  //por debajo de 31ºC en cuyo caso no mandamos email
  if (val<31){
    Serial.println("NO SE MANDA EMAIL");
    if(correo) correo=false;
    //si la temp es superior mandamos el email
    //y cambiamos el valor de correo para que no vuelva a enviarse
  }else{
    //Comprobaos el valor de la variable correo
    //Si el valor de correo es falso mandamos el correo 
    //y ponemos el valor de correo a true
    if(!correo){
      //LLamamos a la función que enviara el correo
      sendEmail();
      correo=true;
      //Dejamos un retardo de 1' para que en el caso
      //de que la temperatura se esté moviendo 
      //entre 30 y 32º no envíe montones de correos
      delay(60000);
    }
  }
}

//Función que lee el voltaje del pin 3 de
//entradas analogicas
float getVoltage(int anapin){
  return (analogRead(anapin) * .004882814);
}

//Función que envia el email
byte sendEmail()
{
    //Conectamos el cliente al puerto 25
    //de nuestro servidor en caso de resultar
    //fallida la conexion nos devolverá un error
    //por pantalla
    if (client.connect(server,25)) {
      Serial.println("connected");
    } else {
      Serial.println("connection failed");
      return 0;
    }
    //Para cada comando llamamos la función
    //eRcv a fin de comprobar la respuesta del
    //servidor y de ir limpiando el buffer de recepción
    if(!eRcv()) return 0;
    //estos comandos son los que usariamos
    //en una conexion telnet, empezamos saludando
    //al servidor
    client.println("HELO google");
    if(!eRcv()) return 0;
    //Le decimos que queremos autenticarnos
    client.println("AUTH LOGIN");
    if(!eRcv()) return 0;
    //Enviamos el usuario en base64
    client.println("fjgkriemrerkEE54F=");
    if(!eRcv()) return 0;
    //Enviamos el password en base64    
    client.println("aGTvaiefSA==");
    if(!eRcv()) return 0;
    //especificamos el sender
    client.println("MAIL From:<mi@gmail.com>"); 
    if(!eRcv()) return 0;
    //especificamos el que recepciona el email
    client.println("RCPT To:<otro@gmail.com>");    
    if(!eRcv()) return 0;
    //indicamos que vamos a empezar a escribir el correo
    client.println("DATA");
    if(!eRcv()) return 0; 
    //Aquí ponemos todo el cuerpo del mensaje incluyendo
    //el from el to y el subject
    client.println("From: mi@gmail.com");                
    client.println("To: otro@gmail.com");                         
    client.println("Subject: Alerta de temperatura en el cuarto de servidores!!!!" + String(int(val)) + "ºC");
    client.println("");                              
    client.println("Se ha detectado una temperatura anormalmente alta en el cuarto de servidores, concretamente de " + String(int(val)) + "ºC");
    client.println(""); 
    //Cuando enviamos un punto indica el fin del mensaje
    client.println(".");
    if(!eRcv()) return 0;
    client.println("QUIT");
    //Cerramos la conexion telnet
    if(!eRcv()) return 0;
    //Paramos el cliente
    client.stop();
    return 1; 
}


//Esta función nos permite ir mostrando
//las respuestas del servidor para cada
//comando que enviamos, asi mismo va limpiando
//el buffer RX, hay servidores de correo que funcionan
//sin esta función pero con google es necesario.
byte eRcv()
{
  byte respCode;
  byte thisByte;
  while(!client.available()) delay(2000);
  respCode = client.peek();
  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }
  if(respCode >= '4')
  {
    efail();
    return 0;  
  }  
  return 1;
}

//Esta función nos dara un error en caso
//de que la respuesta del servidor sea un fallo
//y desconectara la sesion
void efail()
{
  byte thisByte = 0;
  client.write("QUIT\r\n");
  while(!client.available()) delay(1);
  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }
  client.stop();
  Serial.println("disconnected");
}

¿Has probado un código sin toda la parafernalia del módulo ethernet? Sin inicializarlo, sin mandar correo,...vamos sin utilizar ethernet, solo medir temperatura. ¿Cuál es el resultado de esta prueba?

En cuanto a la medida de la temperatura, ¿por qué utilizas/creas una función getVoltage() si no devuelve el voltaje? ¿Si utilizas/creas una función por qué no haces todos los cálculos dentro de esa función y devuelves ya la temperatura en ºC? ¿Por qué no simplificas los cálculos [(x*0.004882814-0.5)100 = x0.4882814 - 50]?

Otra opción que valoraría sería eliminar los delay() porque no sé como le pueden afectar a la comunicación por ethernet, utiliza el método del ejemplo del IDE sin delays:

inicio = millis();
...
if(millis()-inicio >= 5000) // Han pasado 5 segundos
{
  ...
}

Y por último, viendo que es un sensor analógico y que se puede meter ruido por cualquier cosa, yo calcularía una media de las medidas (además solo utilizas el valor cada 5 segundos, tienes mucho tiempo para hacerlo).

Por cierto, ¿de dónde has sacado el valor del 0.004882814? ¿Por qué no lo has aproximado por 0.5?

Si no requieres de máxima precisión en las medidas de temperatura tienes una aproximación con error menor de 0.25ºC a la temperatura real en el rango de 25ºC a 46ºC (y menor de 0.1ºC entre 29ºC y 37ºC como es el caso de tu aplicación) con la siguiente formula (más sencilla de implementar, y por consiguiente, con menor probabilidad de fallo):

Temperatura = (x*0.5)-52
o lo que es lo mismo: Temperatura = (x/2)-52

Como no envias la temperatura con decimales en el correo, puedes utilizar el tipo unsigned int en lugar de float para los calculos.

    unsigned int Medida, Temperatura;
    Medida = analogRead(anapin);
    Temperatura = (Medida>>1)-52;

Más sencillo, ¿verdad? :wink:

Mira

si no me he equivocado al copiarlo, este es el codigo que yo empleaba para leer la temperatura en analogico y convertirla a celsius

Aver si te vale

/*  conversion matematica de la temperatura
// double Thermister(int RawADC) {
 double Temp;
 Temp = log(((10240000/RawADC) - 10000));
 Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
 Temp = Temp - 273.15;        // Convierte Kelvin to Celcius
 return Temp;
}*/

Un saludo.

Heke:

/*  conversion matematica de la temperatura

// double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15;        // Convierte Kelvin to Celcius
return Temp;
}*/

:~ :~ :~ :fearful: :fearful: :fearful:

¿De dónde has sacado esa formula? Metiendo logaritmos, multiplicaciones, divisiones, números en rangos que van de los millones a la diez millonésima en una misma formula calculada por un micro de 8 bits dudo mucho que el resultado final se pudiese acercar a la realidad.

Heke:
Mira que os empeñais en usar sensores analogicos...

Yo compre al principio el LM35, tarde menos de dos microsegundos en mandarlo a freir esparragos

Con ese tipo de cálculos no me extraña

En serio, ¿cómo llegaste a esa formula para calcular la temperatura y para qué la utilizabas? El resultado va desde 89ºC a 461ºC con valores del ADC de 1 a 1024

Ufff ni me acuerdo bien pero juraria que era de la pagina oficial de arduino.

Es de cuando empezaba con arduino y estuvimos haciendo pruebas con medidores de temperatura varios buscando a ver cual nos convencia mas, empleamos de todo, desde un diodo como union PN, ntc, ptc, lm35, y al final DS18b20 ah creo que probamos tambien otro distinto pero no recuerdo la marca, de todas formas, el que mejor iba era el 18b20.

He recuperado codigo viejo pero no me preguntes de donde sale, no lo hize yo, solamente lo emplee.

Un saludo.

Jorge vaya repaso me has dado :wink: muchas gracias tio, revisaré todo lo que me dices

Saludos

Edito:

El código de la temperatura lo saqué del libro de sparkfun (Sparkfun inventor's guide).

Aparentemente la función getvoltage Convierte el rango de 0-1024 de la entrada en un rango de 0 a 5...

Lo he probado quitando todo lo referente a ethernet y sigue dando el mismo problema...

No sé, igual el problema es que el sensor está tocado....

Gracias de nuevo a todos.

Vale, ya encontre donde estaba el codigo este.

Esta en el Playground:
http://arduino.cc/playground/ComponentLib/Thermistor2

Lo unico que te he pasado el de la NTC, no era el del lm35, sorry :blush:.

Este es el codigo del LM35 que tenia en casa:

//Variables
float tempC;
int tempPin = 0;

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

void loop()
{
tempC = analogRead(tempPin);           
tempC = (5.0 * tempC * 100.0)/1024.0;  
Serial.print((byte)tempC);             
delay(1000);
}