Cuando trabajamos en proyectos con microcontroladores y debemos mostrar información en un LCD, 6 pines dedicados al control de este último pueden ser demasiados. Al comenzar a expandirnos en entradas analógicas o digitales, y a su vez, actuar en el exterior con salidas para relés, indicadores LED y otras aplicaciones, los pines I/O del microcontrolador se agotan rápidamente. Aprende a construir tus propios LCD I2C con sólo dos pines. Cuando encontramos soluciones a nuestros inconvenientes cotidianos sentimos alivio y sensación de bienestar.
A muchos de nosotros, quienes nos dedicamos a “cacharrear” con la electrónica, nos sucede ese fenómeno particular cada vez que descubrimos aplicaciones prácticas y sencillas que nos ayudan a resolver problemas complejos. El bus I2C es una de las herramientas que nos hace más sencillo el trabajo de interconexión entre un microcontrolador y una interfaz. Ya hemos visto muchas aplicaciones útiles que incorporan el bus I2C en forma nativa: termómetros, potenciómetros digitales, preamplificadores de audio, y muchos otras que nos restan ver y analizar. En el caso de los LCD alfanuméricos, que utilizamos habitualmente en nuestros desarrollos con microcontroladores, debemos reservar 6 pines (conexión mínima) para su control: RS, EN, D4, D5, D6 y D7, ya que estos displays convencionales, basados en el controlador HD44780, traen un tipo de conexión que involucra muchos cables. La necesidad de los usuarios ha llevado a muchas empresas fabricantes de estos dispositivos a desarrollar entradas de datos seriales, ya sean por Puerto Serie o por bus I2C.
Lamentablemente, el precio de estos displays suele ser muy alto comparado con el de un LCD de iguales características y conexión paralela. Las diferencias monetarias suelen ser del doble o triple de valor. Por lo tanto, lograr desarrollar un circuito económico que nos permita manejar un display convencional a través del bus I2C, mediante sólo dos pines, puede ser una alternativa muy interesante para ahorrar pines del microcontrolador y, por supuesto, dinero. A esto debes sumarle la posibilidad de manejar muchos displays LCD conectados al mismo bus, donde cada uno tendría una dirección específica e inequívoca. Es decir, si habitualmente los dispositivos poseen una dirección (address) donde los últimos 4 bits definen su “subdirección” dentro del bus, con sólo dos pines podremos manejar hasta 16 LCD conectados a un microcontrolador sencillo de encapsulado pequeño.
Seleccionando el microcontrolador
Podemos convertir un LCD convencional en un dispositivo I2C a través de un expansor de puertos controlable por I2C, como puede ser el PCF8574 (del que nos ocuparemos en otro artículo) o un microcontrolador que posea un módulo SSP (Synchronous Serial Port) integrado en su interior. Un ejemplo de este último tipo de microcontrolador es el 16F819, al que podemos utilizar como unidad I2C esclava (slave) de nuestros proyectos. El costo agregado al LCD será despreciable respecto a una unidad LCD I2C comercial. Podremos así construir una unidad a nuestra medida que satisfaga las necesidades de uso y aprovechar el ahorro de pines en el microcontrolador que oficiará de maestro (master). Sin ir demasiado lejos, y con algo de imaginación, un PIC 12F675 puede:
- Controlar un reloj en tiempo real (RTC), basado en un DS1307.
- Actuar como datalogger, registrando temperaturas tomadas con un STCN75.
- Almacenar valores máximos y mínimos de temperatura y guardar muestras de los datos obtenidos en una memoria EEPROM, tipo 24C256, capaz de retener enormes cantidades de información. Por supuesto, todo este proceso puede ser mostrado en un display LCD de hasta 40 caracteres por 4 renglones.
- Conectar otros dispositivos que creamos oportunos para nuestro diseño o dejar la conexión preparada para eventuales ampliaciones.
Todo esto se realiza gracias a un sencillo microcontrolador de 4 pines por lado y gracias a la tecnología del bus I2C. Lo que te proponemos es sólo un ejemplo, tu imaginación es el límite. Circuito práctico a implementar El circuito es un montaje clásico de conexión, con 4 líneas de datos, un control de contraste mediante P1, un control de tres niveles de iluminación backlight (0, 50 y 100%) para el LCD, controlado por PWM a través de T1 (ampliación a futuro), un conector ICSP para programar el PIC una vez concluido el montaje mecánico de la placa controladora, y algunos capacitores de desacoplo y resistencias de polarización. Como podrás observar, y tal como te habíamos adelantado, el costo adicional al LCD nunca alcanzará el valor comercial de un display LCD – I2C. Podríamos utilizar el clock interno del microcontrolador, pero sería a una frecuencia baja (8 Mhz), tal vez insuficiente para obtener una transferencia de datos a 400 Khz a través del bus. Un cristal de 20 Mhz nos asegura una frecuencia de trabajo ideal para altas velocidades dentro del bus.
El hardware es sencillo y no debería presentar demasiadas complicaciones. Además, con cualquier software sencillo puedes desarrollar y construir el circuito impreso (PCB) correspondiente. Generalmente, los modelos comerciales de display LCD con conexión serie traen una placa montada en forma paralela, con separadores plásticos de donde salen y llegan las conexiones de alimentación, tierra y datos, es decir, 5 Volts, GND, SDA y SCL. El Firmware del PIC Como es habitual en nuestro caso, no vamos a darte los archivos listos para utilizar y “customizar” a tu gusto. Vamos a compartir contigo los conocimientos que hemos empleado nosotros para lograr el objetivo, pero al trabajo deberás realizarlo tú mismo. En primera medida, porque no queremos que mueras en el desconocimiento de cómo llegar a realizar este diseño. Y en segundo término, porque queremos que lo mejores, lo modifiques, lo replantees desde otro punto de vista y puedas llegar a hacerlo a tu medida y gusto.
Luego si lo deseas, puedes compartirlo con nosotros para que mostremos con orgullo tu trabajo de investigación a partir de la ayuda que aquí te brindamos. No importa cuál sea el lenguaje de programación de microcontroladores que utilices habitualmente; puedes armar la estructura del programa partiendo de los conceptos que te explicaremos de la forma más didáctica que nos sea posible. Ten presente que un programa eficiente requiere de un ajuste de tiempos de transmisión y recepción que siempre deberás respetar. Por ejemplo: cuando le enviemos al LCD (ya transformado en I2C) una instrucción definida, como puede ser “Limpiar Pantalla” (CLS o CLEAR), debemos esperar (según nuestro ejemplo) 30 milisegundos hasta enviar la instrucción siguiente, para darle tiempo al LCD a que recepcione la orden y la ejecute.
Debes tener en cuenta, además, que el ejemplo que te proponemos aquí sirve para los LCD que traen el controlador HD44780 o cualquiera display compatible con éste. Lo primero a tener en cuenta es que utilizaremos dos microcontroladores: uno como maestro y otro como esclavo (Master – Slave). El esclavo es el mostrado en el circuito presentado; se trata del 16F819. Al microcontrolador maestro lo seleccionarás tú cada vez que realices alguna aplicación. Sólo deberás ocuparte de acoplarle apropiadamente un dispositivo I2C adicional que será, en realidad, el microcontrolador que utilizaremos: el 16F819.
Armando la estructura del programa
Recomendación inicial: Imprime o ten a mano el datasheet del PIC para poder comprender mejor este texto o para estar más seguro al armar la estructura de tu programa. Luego de definir el dispositivo a utilizar, su frecuencia de clock y la conexión del LCD según el circuito propuesto, debes ordenar y configurar los registros que manejan el módulo SSP (los encontrarás en el datasheet del PIC, en la página 71, capítulo 10.0). El SSPCON es el registro con el que vas a determinar el funcionamiento del PIC en modo I2C – Slave, con un direccionamiento de 7 bits. Dentro de este registro también se programa el modo de evitar colisiones de datos dentro del bus, la habilitación de trabajo del bus (Enable) y otros parámetros importantes.
El byte o palabra final del registro debe quedar (para un funcionamiento correcto) en ‘00110110. En la figura 2-3 del datasheet, que se encuentra en la página 11, podrás encontrar (en el Bank1, dirección 93h) el registro SSPADD. Este registro se utiliza para escribir en él, al momento de inicializar el sistema, la dirección que tendrá nuestro LCD dentro del Bus. En nuestro caso, hemos adoptado la posición 8, es decir ‘00001000, pero tú utiliza la que desees o te convenga, con tal de que vaya desde 0 a 15 (‘00000000 a ‘00001111) para evitar eventuales conflictos con otros dispositivos colgados al bus. Siempre es interesante dotar al sistema de un mensaje de bienvenida al inicializarlo para asegurar su funcionamiento y correcto arranque.
Si lo deseas, puedes agregarle al circuito propuesto un pulsador de RESET ante eventuales arranques fallidos. En el ejemplo que puedes ver en el video, existe un mensaje de bienvenida de 2 segundos que nos sirve de aviso de un arranque seguro y efectivo. También deberás crear una variable BYTE que utilizarás de buffer (donde almacenarás cada palabra de 8 bits que ingrese por el bus) a la que volcarás en el registro SSPBUF (Bank 0, 13h) para su posterior impresión en el LCD. Una vez que todo esto esté listo, ya tienes el sistema en condiciones de comenzar a recibir datos a través del bus. Luego de recibir un dato válido (que corresponda a nuestra dirección), se levantará la bandera de interrupción SSPIF del registro PIR1 (PIR1.3), y el dato se volcará dentro del registro SSPBUF de manera automática.
Luego tú lo transportarás dentro de la variable que hayas creado y lo imprimirás en pantalla. Recuerda que por cada dato recibido y válido debes bajar la bandera SSPIF. Cada byte enviado al LCD (luego de ser cargado en la variable que hace las veces de buffer) será un caracter ASCII, lo que significa que lo que se verá en pantalla es una seguidilla de caracteres apropiadamente enviados. Ten cuidado con esto ya que no todos los displays de las distintas marcas utilizan el mismo mapa de memoria en los símbolos que se encuentran más allá de la dirección 127 del código ASCII. También deberás experimentar con ello al programar el controlador maestro del sistema, leyendo bien la hoja de datos del LCD que uses.
Otra alternativa válida es desarrollar un pequeño soft en el controlador maestro, que te devuelva todos los caracteres que posee tu LCD y que te indique en qué posición se encuentran. (Mira el video de demostración). Encontrarás un ejemplo muy útil de cómo lograr el funcionamiento que te estamos explicando en la siguiente página, con su correspondiente código (BASIC). El código realizado por nosotros difiere bastante del mostrado allí, pero puede serte muy útil para ver todos los registros que intervienen en la habilitación y el uso del módulo SSP. Funciones “extras” Además de la función elemental de poder escribir en la pantalla del LCD los caracteres recibidos, puedes utilizar caracteres “no útiles” dentro de las direcciones del código ASCII. Nosotros hemos utilizados los números del 1 al 7 para desarrollar las acciones que figuran en la imagen y que también se aprecian en el vídeo.
Si el PIC detecta un “1” en la entrada de datos, limpiará la pantalla mediante la impresión de la instrucción CLS. Si recibe un “2”, se ubicará en el primer espacio del primer renglón (o fila). Con un “3” lo hará en el primer espacio del segundo renglón; con un “4”, en el tercer renglón; y con un “5”, en el primer caracter de la cuarta fila. Un byte cargado con el número “6” hará aparecer el cursor de forma intermitente, y un “7” se encargará de borrar el mencionado cursor. ¿Notaste que hablamos de cuatro renglones o filas? Esto significa que el programa que te vamos a dejar para que practiques y para que lo instales en un PIC 16F819 te servirá para construir tu propio LCD / I2C con cualquier tipo de display (compatible con el controlador HD44780). Tendrás la posibilidad de utilizar cualquier display, independientemente de la cantidad de renglones que el mismo posea (1, 2, 3 o 4). PIC Maestro Cuando desarrolles el programa a utilizar en el microcontrolador maestro, ten en cuenta “cómo y cuándo” enviarle los datos a tu nuevo display LCD / I2C. Si utilizas Basic, recuerda que lo hacemos con la siguiente estructura:
- BSTART ‘Abrimos el bus
- BUSOUT Dirección, [Dato] ‘Enviamos la dirección y luego el dato
- BUSTOP ‘Cerramos el bus
Con esta sencilla estructura podremos manejar el LCD. Un ejemplo de uso de la instrucción BUSOUT sería la siguiente:
- BUSOUT %00001000, [“Hola Mundo”]
Podemos ver que es muy sencillo escribir un texto, es decir, un dato o una cadena de datos. Luego, para limpiar la pantalla, enviaremos el siguiente comando:
- BUSOUT %00001000, [1]
El “1” enviado significa que el programa del 16F819 debe limpiar la pantalla del LCD. Observa también la estructura diferente al enviar un dato numérico o un string, el cual debe encerrarse entre comillas. Ten en cuenta que, luego de enviar un dato numérico, tendrás que agregar un retardo de 30 milisegundos hasta enviar la siguiente instrucción, ya que en el programa que te dejamos hemos determinado esa condición. Y el último punto importante a tener en cuenta es que cada vez que escribas un renglón, deberás hacerlo ocupando 40 espacios (a pesar que tu LCD sea de 8, 16 o 20 caracteres). Es decir, si deseas escribir “Hola NeoTeo”, deberás hacerlo de la siguiente forma:
- BUSOUT %00001000, [“ Hola NeoTeo ”]
Debes dejar 40 espacios entre las comillas. ¿Por qué lo hacemos así? Pues muy sencillo. Con el programa que te brindamos, puedes utilizar cualquier tipo de display, hasta incluso los de 4 filas y 40 caracteres. Si hubiésemos limitado las filas a sólo 2, y los caracteres a 16, habría muchos desarrollos en los que no te sería útil el sistema que te brindamos. En cambio, de esta forma, puedes utilizar el LCD que sea, en la aplicación que sea, sin restricciones.Descarga el ejemplo de los videos desde aquí. (Sólo el archivo HEX para el PIC 16F819)
Ensaya, practica, juega, experimenta. Todo es aprendizaje, todo es descubrir, todo es crecer. Recuerda que nadie nace sabiendo y que trabajando entre todos es más fácil.
¡Éxitos en las construcciones!