Termómetro con LCD 3310.
Serie LCD gráficas GLCD.
INTRODUCCIÓN.
Este es el cuarto artículo de la serie que, trata las pantallas LCD 3310, que también sirve para el LCD 5110 ya que, normalmente vienen equipados con el mismo controlador PCD8544 de Philips. Hemos visto ejemplos que nos han permitido poner en servicio una pantalla de un viejo móvil tipo Nokia 3310, hemos visto que con una librería que funciona bien, se desaprovechan algunos bits que en ocasiones nos permiten mostrar una mayor información en la misma pantalla y es aquí, en el uso de las librerías donde se debe tener en cuenta, cual es la que más nos interesa utilizar.
Sin embargo, a estas alturas, después de haber seguido los anteriores tres títulos, LCD gráficos, Pantallas LCD y Termómetro con LM35. Considero un buen momento para abordar una aplicación más concreta. Por otra parte, ya se han descrito las características del controlador que suelen acompañar estas pantallas, el mencionado PCD8544, por lo que no voy a incidir más en ello. Si necesita usted dicha información, debería leer los artículos mencionados, entre otros.
En los mencionados artículos, se ha estudiado como manejar una pantalla LCD, de un viejo Nokia3310 o Nokia5110, hemos desarrollado ejercicios en los que hemos aplicado esta sencilla pantalla. Ahora, vamos a utilizar otro sensor más sofisticado que el usado anteriormente (LM35), me estoy refiriendo al DS18B20 de Dallas.
La imagen que sigue, pertenece a una pantalla recuperada de un viejo móvil, como ya he descrito en anteriores ocasiones, es algo complicado realizar las soldaduras de los hilos a los terminales de la pantalla, esto es lo más engorroso y difícil, pero se hace una sola vez por pantalla. De todas formas sugiero que se intente, estas pantallas están testeadas a fondo. No quiero decir que, las que adquirimos no lo estén, sin embargo, alguna diferencia técnica, si la hay.
SERIES DS18S20/DS18B20.
Los DS18S20 y DS18B20 son dos sensores de temperatura de Dallas. Funcionan en un bus de un alambre, lo que significa que, la comunicación con el microcontrolador o PC, necesita un solo cable. Esto nos recuerda al bus I2C, claro, hay una diferencia el I2C utiliza un bus de dos hilos y el OneWire, como su nombre indica sólo uno.
Veremos alguna coincidencia más. Recordemos que cada ‘chip’ del I2C, tiene una dirección única de localización en el bus, mediante esa dirección, entre otras cosas, se pueden enviar ordenes y datos y recibir datos del dispositivo interrogado. En el actual caso, cada dispositivo DS18B20, tiene un número o código único, mediante el cual podemos comunicarnos con él.
Dicho código único, viene grabado internamente y sin el cual se hace imposible la comunicación. Téngase en cuenta que, pueden haber más de cuatro dispositivos en el bus y en cada momento tenemos que enviar/recibir información de cada uno, sin dicho código, se haría imposible saber quien responde nuestras llamadas.
CONOCIENDO EL DS18B20.
Veremos como proyectar un termómetro, en el que utilizaremos el sensor de Dallas DS18B20. Antes, conoceremos este sensor, se trata de un dispositivo complejo, de hecho, Dallas no lo llama sensor, lo llama, termómetro digital que, proporciona lecturas de temperatura en centígrados y precisión de 9 a 12 bits, con una función no volátil de alarma programable por el usuario, con puntos de activación superior e inferior.
El DS18B20 utiliza un exclusivo protocolo de bus 1-Wire de Maxim que implementa la comunicación del bus mediante una señal de control. La línea de control requiere una resistencia pull-up débil ya que todos los dispositivos están vinculados al bus a través de un puerto 3-estado o drenaje abierto (el pin de DQ en el caso de la DS18B20).
En este sistema de bus, el microprocesador (el dispositivo maestro) identifica y aborda los dispositivos en el bus con el código único de 64 bits de cada dispositivo. Debido a que cada dispositivo tiene un código único, el número de dispositivos que se pueden abordar en un bus es prácticamente ilimitada. El protocolo de bus 1-Wire, con explicaciones detalladas de los comandos y los «intervalos de tiempo», se trata en la sección System Bus 1-Wire, de las hojas de datos del fabricante.
Otra característica de la DS18B20 es la capacidad de funcionar sin una fuente de alimentación externa. La alimentación se suministra por la resistencia pullup 1-Wire a través del pin DQ cuando el bus está a nivel alto. La señal de bus a nivel alto, también carga un condensador interno (CPP), que a su vez alimenta el dispositivo cuando el bus está a nivel bajo. Este método de obtención de energía del bus 1-Wire se conoce como alimentación «parásito.» Como alternativa, el DS18B20 también puede ser alimentado por una fuente externa de VDD.
El DS18B20, tiene un rango de temperaturas de funcionamiento de -55 °C a 125 °C. La resolución del sensor de temperatura es configurable por el usuario a 9, 10, 11, o 12 bits, correspondiente a incrementos de 0,5 ° C, 0,25 ° C, 0.125 ° C y 0,0625 ° C, respectivamente. La resolución por defecto en el encendido es de 12 bits. Los DS18B20 encienden en un estado de reposo de bajo consumo. Para configurar estas, existe un registro dentro de la memoria (Scratchpad) bolc de notas, llamado «registro de configuración». Dentro de éste, existen dos bits, los cuales, colocando diferentes combinaciones de 0 y 1, podemos modificar la resolución.
Resumiendo.
La memoria de bloc de notas contiene el registro de temperatura de 2 bytes que almacena la salida digital del sensor de temperatura. Además, la memoria de trabajo proporciona acceso a los registros de activación de alarma de 1 byte superior e inferior (TH y TL) y el registro de configuración de 1 byte. El registro de configuración permite al usuario ajustar la resolución de la conversión de la temperatura-a-digital para 9, 10, 11, o 12 bits. El TH, TL, y registros de configuración son no volátil (EEPROM), por lo que conservará los datos cuando el dispositivo está apagado.
ALARMAS: TH y TL Formato Registro.
1 2 |
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 S 2^6 2^5 2^4 2^3 2^2 2^1 2^0 |
Sólo 11 bits a través de 4 registros de temperatura son usados en la comparación TH y TL desde el TH y TL son registros 8 bits. Si la temperatura medida es <= TL (menor que o igual a TL) o >= TH (mayor que o igual que TH), existe una condición de alarma y un indicador de alarma se establece dentro del DS18B20. Esta bandera se actualiza después de cada medición de temperatura, por lo tanto, si la condición de alarma desaparece, la bandera se desactivará después de la siguiente conversión de la temperatura.
Esta información se ha de tener presente y muy en cuenta. En una primera lectura, a parte de que tiene un bus de 1 cable, nos dice que tiene una función no volátil, programable por el usuario, con dos puntos de activación inferior y superior, esto, nos permite configurar una alarma con una ventana de temperaturas entre dichos márgenes, no está nada mal, vamos, que es muy interesante.
Si revisamos las librerías que entrega DallasTemperature para sus termómetros, podremos comprender que hacen y aprender a utilizarlas de un modo más apropiado. Si no dispone de estas librerías, descárguelas de aquí. También, debe disponer de las librerías OneWire, en las que se apoyan las de DallasTemperature.
La librería OneWire, nos permite comunicarnos con dispositivos 1-wire, hechas por Maxim/Dallas, tales como sensores de temperatura y de memorias Secure ibutton. La librería DallasTemperature, se puede usar en conjunción con la librería OneWire. Para conectar un dispositivo 1-Wire, se necesita una resistencia de 4k7 de RPA, conectada entre el pin de datos y 5V. Entonces sólo tiene que conectar, todos los dispositivos 1-wire, al pin 2 y el pin1 a masa. Algunos dispositivos 1-Wire, también pueden conectarse con el pin 3 al positivo u obtener su energía de la señal de cable.
En la imagen anterior, puede ver el dispositivo, conectado alimentado como ‘parásito’ y debajo alimentado normal. Es de agradecer, el hecho de tener un número ‘secreto’, nos abre un abanico de posibilidades añadido. Ya lo iremos viendo, con el tiempo, alguna idea se nos ocurrirá.
Como ya se ha mencionado, cada dispositivo DS18B20, tiene su código de serie único. Esto es debido a la comunicación OneWire, cuya librería v2008, puede descargar de aquí. A lo que íbamos, si usted no conoce ese código, no es posible (al menos en teoría) poner en servicio el dispositivo, en otras palabras, no podrá leer los datos de las lecturas que realiza su DS12B20.
Habitualmente, en el código a utilizar, se incluye la función encargada de identificar dicho número, esto lo leerá del propio dispositivo, al extraer los valores de los 4 bytes localizados en los bits 9, 10, 11 y 12. Puede encontrar más información por ejemplo, en la librería ‘DallasTemperature.cpp’.
Crear un objeto 1-Wire.
Vamos a crear el objeto OneWire myWire(pin), usando un pin específico. Usted, puede conectar muchos dispositivos de 1-Wire al mismo pin, si tuviera un gran número de sensores, haga grupos más pequeños, cada uno en su propio pin, puede ayudar a aislar los problemas de cableado. Puede crear varios objetos OneWire, uno por cada pin.
Para utilizar un dispositivo OneWire (DS12B20), usted, necesita una resistencia de 4k7Ω conectada entre +5VCC y el pin elegido del micro. Sólo tiene que conectar todos los dispositivos 1-wire a ese pin y las patillas 1 y 3 del DS12B20 a masa o tierra. Quizás una imagen aclare mejor lo descrito.
Con la rutina, myWire.search(addrArray), el addrArray es una matriz de 8 bytes, de modo que, si se encuentra un dispositivo, addrArray estará lleno, devolverá la dirección del dispositivo y verdadero. Si no se encuentran más dispositivos, se devuelve ‘false’.
Con myWire.reset_search(), comenzará una nueva búsqueda. El siguiente uso de la búsqueda, comenzará con el primer dispositivo.
Con myWire.reset(), se restablecerá el bus 1-wire. Por lo general, esto es necesario antes de comunicarse con cualquier dispositivo.
Con myWire.select(addrArray), se selecciona un dispositivo en función de su dirección. Después de un reset, esto es necesario para elegir el dispositivo que va a utilizar, y luego, toda la comunicación será con ese dispositivo, hasta que realice otro reset.
Con myWire.write(num);, escribe un byte. Y, myWire.read(), lee un byte. Estas rutinas nos serán de utilidad. Para mayor detalle en las H. de D. del DS18B20.
PRIMER ASALTO.
Bien, consideremos que ya hemos dado un buen repaso a la teoría y los datos del fabricante, entre otros. Es hora de empezar con las esperadas practicas. Donde se demuestran los conocimientos adquiridos. Así que, vamos a poner en practica nuestro proyecto de medición de temperaturas mediante el DS18B20.
Veamos, este es un primer sondeo de alcance, según experimentemos, seguiremos avanzando. Utilizaremos un código que encontramos en la red y que será suficiente para esta prueba.
Termómetro digital con DS18B20.
Este es un ejemplo de termómetro con el DS18B20.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// // acuariotempds18b20.pde // basado en: // http://www.malaleche.cl/ // controlar-temperatura-del-agua-con-arduino // #include "DallasTemperature.h" #include "OneWire.h" #define PIN_TEMPERATURA 10 // pin asignado al sensor. // Ventana de temperaturas de la alarma. #define TEMP_MINIMA 25.50 // margen mínimo de temp. #define TEMP_MAXIMA 26.00 // margen máximo de temp. DeviceAddress TemperaturaAgua; OneWire oneWire(PIN_TEMPERATURA); DallasTemperature termometro(&oneWire); void setup(){ Serial.begin(9600); termometro.begin(); pinMode(PIN_TEMPERATURA, INPUT); if(!termometro.getAddress(TemperaturaAgua, 0)){ Serial.println("Sensor de Temperatura Desconectado"); } termometro.setHighAlarmTemp(TemperaturaAgua, TEMP_MAXIMA); termometro.setLowAlarmTemp(TemperaturaAgua, TEMP_MINIMA); } void loop(){ leerTemperatura(); } void leerTemperatura(){ float TemperaturaDelAgua; termometro.requestTemperatures(); TemperaturaDelAgua = termometro.getTempC(TemperaturaAgua); Serial.print (TemperaturaDelAgua); //#para ver la temperatura que lee Serial.print (" "); if(termometro.hasAlarm(TemperaturaAgua)){ if(termometro.getTempC(TemperaturaAgua) < termometro.getLowAlarmTemp(TemperaturaAgua)){ Serial.println("La temperatura del agua esta bajo el minimo"); } if(termometro.getTempC(TemperaturaAgua) > termometro.getHighAlarmTemp(TemperaturaAgua)){ Serial.println("La temperatura del agua esta sobre el maximo"); } } } /* EOF - acuariotempds18b20.pde */ |
Seleccione, copie y pegue el código, pruebe este código y experimente sus propios resultados. La prueba, es bastante explicita, para demostrar las peculiaridades del sensor DS18B20. Observamos que, utiliza las dos librerías que hemos comentado. He cambiado el pin original de entrada del sensor, el pin 10, es seleccionado por mi y los márgenes de las temperaturas alta y baja, de la alarma, no se modificaron. Estos son los cambios relevantes.
Ahora, procedamos del mismo modo con este segundo código y comparemos las diferencias entre ambos. En principio, pretendemos mostrar la lectura de la temperatura en dos escalas diferentes, en Europa, se utiliza los grados Centígrados y en los países Americanos se suele utilizar los grados Fahrenheit, aquí puede ver un gráfico aclaratorio. Por cierto, para convertir los ºC a ºF, se utiliza la fórmula:
C=(F−32)*5/9 o la más simplificada: C=(F-32)/1.8.
Termómetro digital con DS18B20.
Ejemplo de un termómetro con el DS18B20 en grados Centígrados y Fahrenheit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
// // leecelsiusfahrenheit.pde // temperatura en grados Celsius y Fahrenheit // #include "OneWire.h" //init the one wire interface on pin 10 OneWire ow(10); //Escriba aquí la dirección que usted recibe del otro programa byte sensor[8] = {0x10, 0x1D, 0x30, 0xF9, 0x01, 0x08, 0x00, 0x51}; void setup(void) { Serial.begin(9600); } void writeTimeToScratchpad(byte* address){ //reset the bus ow.reset(); //select our sensor ow.select(address); //CONVERT T function call (44h) which puts the temperature into the scratchpad ow.write(0x44,1); //sleep a second for the write to take place delay(1000); } void readTimeFromScratchpad(byte* address, byte* data){ //reset the bus ow.reset(); //select our sensor ow.select(address); //read the scratchpad (BEh) ow.write(0xBE); for (byte i=0;i<9;i++){ data[i] = ow.read(); } } float getTemperature(byte* address){ int tr; byte data[12]; writeTimeToScratchpad(address); readTimeFromScratchpad(address,data); //put in temp all the 8 bits of LSB (least significant byte) tr = data[0]; //check for negative temperature if (data[1] > 0x80){ tr = !tr + 1; //two's complement adjustment tr = tr * -1; //flip value negative. } //COUNT PER Celsius degree (10h) int cpc = data[7]; //COUNT REMAIN (0Ch) int cr = data[6]; //drop bit 0 tr = tr >> 1; //calculate the temperature based on this formula : //temperature=temp_read-0.25+(count per celsius degree - // - count remain)/(count per celsius degree) return tr - (float)0.25 + (cpc - cr)/(float)cpc; } //fahrenheit to celsius conversion float f2c(float val){ float aux = val - 32; return (aux * 5 / 9); } //celsius to fahrenheit conversion float c2f(float val){ float aux = (val * 9 / 5); return (aux + 32); } void loop(void) { float temp; float tmp2; tmp2 = getTemperature(sensor); temp = c2f(tmp2); Serial.print(tmp2); Serial.println(" C or "); Serial.print("Temp = "); Serial.print(temp); Serial.print(" F"); // espera 30 segundos y repite proceso. delay(30000); } |
Claro que, tenemos que visualizar los resultados en la propia Consola de Arduino. Viendo que el código funciona, hacer unas pocas modificaciones y lograr que nos muestre los valores de la temperatura en una pantalla LCD, no debe ser demasiado complicado.
Hagamos los cambios necesarios para lograr lo descrito en el párrafo anterior. En primer lugar, he añadido las librerías: «NokiaLCD.h» y «PCD8544.h», para localizar un punto determinado de la pantalla, de esta forma nos resultará más cómodo y sencillo posicionar un píxel, gráfico o texto, en el punto que deseamos.
Termómetro digital con DS18B20 y LCD3310.
Ejemplo de termómetro con el DS18B20 y LCD3310.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
// // tmpds18b20.pde // // basado en: http://www.malaleche.cl // Modificado y adaptado by V. García // from hispavila.com #include "DallasTemperature.h" #include "OneWire.h" #include "NokiaLCD.h" // añadida #include "PCD8544.h" // añadida #define PIN_TEMPERATURA 10 // #define TEMP_MINIMA 25.50 #define TEMP_MAXIMA 26.00 // NokiaLCD NokiaLCD(3,4,5,6,7); // (SCK, MOSI, DC, RST, CS) DeviceAddress TemperaturaAgua; int grados, decimas, gradR, deciR; float TemperaturaDelAgua; float temperature = 0.0; int val,cnt; int tempread, tmedia; // lm35read, tmedia; OneWire oneWire(PIN_TEMPERATURA); DallasTemperature termometro(&oneWire); // A custom "degrees" symbol... static const byte DEGREES_CHAR = 1; static const byte degrees_glyph[] = { 0x00, 0x07, 0x05, 0x07, 0x00 }; // A bitmap graphic (10x2) of a thermometer... static const byte THERMO_WIDTH = 10; static const byte THERMO_HEIGHT = 2; static const byte thermometer[] = { 0x00, 0x00, 0x48, 0xfe, 0x01, 0xfe, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x62, 0xff, 0xfe, 0xff, 0x60, 0x00, 0x00, 0x00}; static PCD8544 lcd; void setup() { Serial.begin(9600); NokiaLCD.init(); // Init screen. NokiaLCD.clear(); // Clear screen. // Register the custom symbol... lcd.createChar(DEGREES_CHAR, degrees_glyph); termometro.begin(); pinMode(PIN_TEMPERATURA, INPUT); if(!termometro.getAddress(TemperaturaAgua, 0)){ Serial.println("Sensor de Temperatura Desconectado"); NokiaLCD.setCursor(1,2); NokiaLCD.print("Sensor "); NokiaLCD.setCursor(1,3); NokiaLCD.print(" Desconectado"); } termometro.setHighAlarmTemp(TemperaturaAgua, TEMP_MAXIMA); termometro.setLowAlarmTemp(TemperaturaAgua, TEMP_MINIMA); } void loop(){ if(!termometro.getAddress(TemperaturaAgua, 0)){ NokiaLCD.setCursor(1,5); NokiaLCD.print("Falta Sensor"); } else { tmedia=0; leerTemperatura(); float temp = TemperaturaDelAgua; termometro.setHighAlarmTemp(TemperaturaAgua, TEMP_MAXIMA); termometro.setLowAlarmTemp(TemperaturaAgua, TEMP_MINIMA); NokiaLCD.setCursor(1,0); NokiaLCD.print("Temperatura: "); NokiaLCD.setCursor(20,2); // NokiaLCD.print(termometro); // no se permite conversión leerTemperatura(); lcd.print(DEGREES_CHAR); lcd.print("C"); NokiaLCD.setCursor(0,5); NokiaLCD.print(" con Arduino "); NokiaLCD.setCursor(0,7); NokiaLCD.print("tmpds18b20.pde"); } } void leerTemperatura(){ float TemperaturaDelAgua; termometro.requestTemperatures(); TemperaturaDelAgua = termometro.getTempC(TemperaturaAgua); Serial.print(TemperaturaDelAgua); //#para ver la temperatura que esta marcando lcd.print(TemperaturaDelAgua); // temp. en ºC Serial.print (" "); if(termometro.hasAlarm(TemperaturaAgua)){ if(termometro.getTempC(TemperaturaAgua) < termometro.getLowAlarmTemp(TemperaturaAgua)){ Serial.println("La temperatura del agua esta bajo el minimo"); } if(termometro.getTempC(TemperaturaAgua) > termometro.getHighAlarmTemp(TemperaturaAgua)){ Serial.println("La temperatura del agua esta sobre el maximo"); } } } |
Como siempre, seleccione el código, cópielo y después de compilarlo, compruebe que en cierto modo se ha logrado razonablemente, realizar lo que había propuesto. Los componentes necesarios son muy pocos.
Fig. 7
Notas.
1. Si tiene la necesidad de utilizar un gran número de dispositivos en red 1-Wire, es importante el diseño de dicha red, de lo contrario tendrá problemas, perdidas de datos, lentitud, rebotes, etc. Es recomendable, hacer redes pequeñas; cada sensor se conecta a través de su propio cable de 50mm máximo, a un punto central y luego se conecta 1 cable, al adaptador Serial. Vigile que, se conecte cada sensor a un cable único que, recorre de un sensor a otro (en cadena), reduciendo el potencial de errores de lecturas debido a las reflexiones en el cable. No se recomienda la conexión de más de 10 sensores, para evitar problemas debido a la carga del bus de datos.
2. He utilizado el IDE de Arduino v0023. Sólo, he insertado unas librerías y unos comandos que, después de unas intentonas, me han dado el resultado esperado. Sin duda que usted, puede tener una idea mejor, para hacer esto mismo. No dude en indicármelo y así podremos mejorar el código.
Exención de responsabilidad:
Este es un software y hardware experimental. Úselo bajo su propio riesgo. El software y hardware presentado en estas páginas aunque ha sido probado por el mantenedor/desarrollador de estas paginas, no se hace responsable bajo ninguna circunstancia por los daños de hardware o software, pérdida de datos o cualquier otro daño directo o indirecto, como resultado del uso de este software o hardware. Ni del mal uso que usted haga con él.
Si usted no está de acuerdo con estas condiciones, no podrá utilizar o distribuir más este software o utilizar cualquier plantilla de piezas, para la construcción que aquí se presenta.