Los display LCD de caracteres pueden conectarse de forma directa a un microcontrolador, pero esto demanda una gran cantidad de pines. Afortunadamente existen módulos, como los basados en el chip PCF8574 que resuelven este problema al permitir la conexión usando sólo los dos pines del bus I2C. En este artículo veremos como controlar un LCD con uno de estos módulos desde una placa STM32 Blue Pill programada en el Arduino IDE.
Introducción
Los display LCD fueron utilizados durante muchos años como pantallas para una infinidad de proyectos. Desde los mas simples de una o dos líneas de texto hasta los mas grandes, con capacidad de mostrar gráficos o incluir una capa sensible al tacto (touchscreen) en distintas variedades de formatos, marcas y colores. En la actualidad se está popularizando el uso de pantallas OLED, que son capaces de mostrar gráficos de mayor resolución con gran nitidez, y también podemos usar algunos modelos de pantallas de tinta electrónica (e-ink o e-paper), tecnologías que ofrecen algunas ventajas pero también inconvenientes. El tiempo dirá si desplazan totalmente a los LCD o si se convertirán en una opción para algunas aplicaciones. En este artículo nos centraremos en los LCD de texto y veremos como controlarlos con el auxilio de un módulo con conexión I2C basado en el PCF8574.
LCD de texto
Aunque existe una gran variedad de display LCD, muchos de ellos comparten el mismo chip controlador: el HD44780 de Hitachi o una variante mas moderna del mismo. Este chip se hizo tan popular que estableció una especie de estándar de hecho en la interface eléctrica y de programación de los LCD, haciéndolos bastante compatibles, salvo algunas pequeñas diferencias introducidas por algunos fabricantes. Esto permitió el desarrollo de mucho código y librerías que nos facilitan enormemente la utilización de estos displays, así como los módulos I2C que nos permiten controlarlos con sólo un par de pines.
Conexiones
Gracias a la compatibilidad de hecho antes mencionada, los display de texto presentan una interfaz electrica, unos pines de conexión similares entre distintos modelos, que tienen una distribución como la que se aprecia en la siguiente imagen (aunque siempre conviene asegurarse revisando la hoja de datos antes de conectar nuestro LCD):
Es una gran cantidad de señales, entre las que tenemos:
GND y VCC: Alimentación (Masa y 5V)
Vo: Tensión de contraste
RS, RW, EN: Señales de control para acceder, leer y escribir en el LCD
D0 a D7: Señales de datos para enviar comandos y datos al display.
BL+, BL-: Alimentación del backlight (iluminación posterior). En algunos modelos estos pines no tienen conexión y el backlight se alimenta empleando otro conector.
Aunque existe la posibilidad de usar un modo en el que nos comunicamos con el LCD usando sólo 4 bits de datos, en lugar de 8, sigue siendo una gran cantidad de señales.
El módulo I2C
El módulo que utilizaremos viene a resolver el problema de la cantidad de pines del LCD, sobre todo en aquellos micros que tienen pocos pines disponibles, ya que cuenta con un circuito integrado PCF8574 que, como ya vimos antes, nos permite tener 8 pines bidireccionales que podemos controlar con sólo dos señales del bus I2C. Las salidas de este módulo tienen la misma disposición del LCD, por lo que la conexión es directa, pudiendo montarse frente al LCD o directamente sobre los mismos pines del conector. Además de los pines que van al LCD, la placa tiene otro conector de 4 pines por donde debemos alimentarlo (VCC y GND) y enviar los datos de control (SCL y SDA).
También se incluye un preset para controlar el contraste del display y tres jumpers para soldar marcados A0, A1 y A2 que definen la dirección de la placa en el bus I2C según la siguiente tabla:
Conexión con la Blue Pill
La Blue Pill tiene dos interfaces I2C, llamadas I2C1 (PB6 y PB7 como pines principales y PB8, PB9 como pines alternativos) e I2C2 (PB10, PB11). Las librerías que veremos mas adelante y que usamos en el programa utilizan por omisión I2C1 en PB6 y PB7, así que conectaremos allí nuestro módulo (hacia el final veremos como modificarlo si es necesario).
Debemos prestar especial atención a los niveles de alimentación, ya que la Blue Pill funciona con 3.3V y el LCD con 5V (hay algunos que si trabajan con 3.3V pero son mas difíciles de conseguir). Esto significa que debemos alimentar el módulo I2C con 5 Voltios, ya que desde allí se deriva la alimentación del LCD. Mientras hacemos pruebas, podemos sacar esta tensión del ST-Link, pero luego si queremos que el circuito funcione de manera autónoma debemos desconectar el ST-Link y proveer de otra fuente de 5V, por ejemplo desde el puerto USB.
El PCF8574 que está en el módulo I2C admite que las señales SCL y SDA no alcancen los 5V, así que los 3.3V de la Blue Pill serán suficientes. Además, los pines que usaremos (PB6 y PB7) son 5V tolerant, así que si en algún momento funcionan como entradas, no se dañarán con señales de este valor.
El circuito se completa con las resistencias de Pull-up de 4,7K y el jumper de Backlight que debe quedar conectado en el módulo para iluminar el LCD.
Programación
Para el programa necesitaremos de dos librerías: una para controlar la interfaz I2C y la otra para el LCD. Para lo primero podemos emplear la libería Wire, que viene instalada en el IDE. Para el LCD podemos usar varias. En mi caso elegí esta que es una adaptación de la conocida librería LiquidCrystal para funcionar a través de I2C. Para utilizarla primero debemos descargarla del repositorio en formato ZIP y luego agregarla al IDE en Programa – Incluir librería – Añadir biblioteca .ZIP
El siguiente programa nos permite comprobar que todo funcione correctamente:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LCD_ADDRESS 0x27 //Cambiar si es necesario
LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);
void setup() {
lcd.init ();
lcd.setCursor (0,0);
lcd.print ("Hola Mundo!");
}
void loop() {
}
Al compilar el programa seguramente se mostrará un mensaje de alerta (Warning) como el siguiente:
ATENCIÓN: la librería LiquidCrystal_I2C-master pretende ejecutarse sobre arquitectura(s) avr y puede ser incompatible con tu actual tarjeta la cual corre sobre arquitectura(s) stm32.
Que nos alerta de que la librería no es original para STM32, pero podemos ignorarlo ya que no afecta a su funcionamiento.
Funciones de la librería LiquidCrystal_I2C
init () : Inicializa la interfaz I2C y el LCD
clear () : Borra el display, lleva el cursor a 0,0
home () : Lleva el cursor a 0,0
setCursor (uint8_t col, uint8_t fila) : Posiciona el cursor en fila,col. Desde esta posición se mostrarán los elementos que se impriman.
noDisplay () : Apaga el display
display () : Prende el display
noCursor () : Apaga el cursor
cursor () : Prende el cursor
noBlink () : El cursor no parpadea
blink () : El cursor parpadea
print (char c[]) : Imprime un texto
scrollDisplayLeft () : Hace un scroll a la izquierda
scrollDisplayRight () : Hace un scroll a la derecha
leftToRight () : Configura la impresión de de izquierda a derecha
rightToLeft () : Configura la impresión de derecha a izquierda
autoscroll () : Mueve el texto a la izquierda una posición cada vez que se imprime un caracter
noAutoscroll () : Inhabilita el modo anterior.
createChar (uint8t location, uint8t charmap[]) : Escribe la definición de un carácter redefinible en location (0 a 7). charmap contiene la definición del caracter con los 8 patrones de bits. Luego explicaré con mas detalle como usar los caracteres definibles por el usuario (custom chars)
noBacklight () : Apaga el backlight
backlight () : Prende el backlight
write (char) : Imprime el caracter char
Caracteres definibles por el usuario
Los controladores HD44780 y compatibles tienen los patrones de los caracteres a imprimir almacenados en una memoria ROM y por tanto no se pueden modificar. Sin embargo, existe un espacio de memoria denominado CGRAM (Character Generator RAM) donde podemos almacenar los patrones de hasta 8 caracteres definidos según nuestras necesidades.
Cada caracter se define con 8 bytes, de los cuales se emplean sólo los 5 bits mas bajos, puesto que cada uno se representa como una matriz de 5×8 puntos. En cada byte, un valor “1” ilumina un punto y un valor “0”. Lo apaga.
Por ejemplo, estos son los 8 bytes necesarios para definir el patrón de un corazón:
Siempre conviene dejar la última línea en blanco porque es la posición que toma el cursor cuando está visible.
Ejemplo:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LCD_ADDRESS 0x27 //Cambiar si es necesario
LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);
byte corazon [8] = {
B00000,
B00000,
B01010,
B11111,
B11111,
B01110,
B00100,
B00000,
};
void setup() {
lcd.init ();
lcd.clear ();
lcd.createChar (0, corazon); //Define el caracter del usuario 0
lcd.setCursor (0,0);
lcd.print ("Hola");
lcd.write (0); //Imprime el caracter 0
}
void loop() {
// put your main code here, to run repeatedly:
}
Remapeo de pines I2C
Si por alguna razón necesitamos conectar el LCD en otros pines que no sean PB6 y PB7, tenemos la posibilidad de remapear los pines I2C, como se puede ver en el siguiente ejemplo:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LCD_ADDRESS 0x27 //Cambiar si es necesario
LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);
void setup() {
//Remapear a PB8, PB9
//Wire.setSDA(PB9);
//Wire.setSCL(PB8);
//Wire.begin();
//Remapear a PB10, PB11
Wire.setSDA(PB11);
Wire.setSCL(PB10);
Wire.begin();
lcd.init ();
lcd.setCursor (0,0);
lcd.print ("Hello Mundo!");
}
void loop() {
// put your main code here, to run repeatedly:
}
Esta página les puede ser de gran ayuda para definir sus propios caracteres.
Conclusión
En este artículo vimos como conectar un LCD de texto a una placa Blue Pill usando el puerto I2C. También vimos como emplear la librería LiquidCrystal_I2C para controlar el display, sus distintas funciones y el procedimiento para definir caracteres especiales y mostrarlos en pantalla.
Espero que la información les sea de utilidad para sus proyectos! Cualquier duda o sugerencia pueden dejarla mas abajo en la sección de comentarios.