Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« on: June 11, 2012, 12:07:31 pm » |
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 
|
|
|
|
|
Logged
|
|
|
|
|
Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« Reply #1 on: June 11, 2012, 12:12:17 pm » |
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.
|
|
|
|
« Last Edit: June 12, 2012, 04:30:40 am by piratadelestrecho »
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 2
Posts: 504
|
 |
« Reply #2 on: June 13, 2012, 11:17:09 am » |
¿Has comprobado si te saca también valores irreales sin estar conectado el cable de red llevando un tiempo en marcha?
|
|
|
|
|
Logged
|
|
|
|
|
Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« Reply #3 on: June 13, 2012, 11:24:47 am » |
Efectivamente cuando lleva un rato funcionando incluso con el cable de red desconectado empieza a írsele la pinza...
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
God Member
Karma: 16
Posts: 810
Arduino rocks
|
 |
« Reply #4 on: June 13, 2012, 11:30:31 am » |
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... http://tallerarduino.wordpress.com/2012/05/04/arduino-y-sensores-de-temperatura-ds18b20/ Digital, comunicacion digital. Hay mil ejemplos de uso en la red.
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
Full Member
Karma: 0
Posts: 191
|
 |
« Reply #5 on: June 13, 2012, 11:34:39 am » |
¿Puedes poner todo el código para comprobar que el fallo no está por otro sitio? ¿Y el esquema del montaje?
|
|
|
|
|
Logged
|
|
|
|
|
Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« Reply #6 on: June 13, 2012, 11:37:30 am » |
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...
|
|
|
|
« Last Edit: June 13, 2012, 11:41:02 am by piratadelestrecho »
|
Logged
|
|
|
|
|
Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« Reply #7 on: June 13, 2012, 12:05:41 pm » |
¿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  //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"); }
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
Full Member
Karma: 0
Posts: 191
|
 |
« Reply #8 on: June 14, 2012, 02:45:42 am » |
¿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 = x*0.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).
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
Full Member
Karma: 0
Posts: 191
|
 |
« Reply #9 on: June 14, 2012, 03:33:34 am » |
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? 
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
God Member
Karma: 16
Posts: 810
Arduino rocks
|
 |
« Reply #10 on: June 14, 2012, 03:59:40 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
Full Member
Karma: 0
Posts: 191
|
 |
« Reply #11 on: June 14, 2012, 05:14:45 am » |
/* 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; }*/  ¿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. 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
|
|
|
|
|
Logged
|
|
|
|
|
Spain
Offline
God Member
Karma: 16
Posts: 810
Arduino rocks
|
 |
« Reply #12 on: June 14, 2012, 05:30:42 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Algeciras
Offline
Newbie
Karma: 0
Posts: 31
|
 |
« Reply #13 on: June 14, 2012, 08:03:38 am » |
Jorge vaya repaso me has dado  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.
|
|
|
|
« Last Edit: June 14, 2012, 08:12:53 am by piratadelestrecho »
|
Logged
|
|
|
|
|
Spain
Offline
God Member
Karma: 16
Posts: 810
Arduino rocks
|
 |
« Reply #14 on: June 14, 2012, 09:21:08 am » |
Vale, ya encontre donde estaba el codigo este. Esta en el Playground: http://arduino.cc/playground/ComponentLib/Thermistor2Lo unico que te he pasado el de la NTC, no era el del lm35, sorry  . 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); }
|
|
|
|
|
Logged
|
|
|
|
|
|