2024-10-12
LCD BigFonts
Muchas veces queremos mostrar números grandes en un display LCD que tiene limitaciones en tamaño, por lo que hemos de recurrir a alguna técnica que nos permita mostrar dichos números en gran tamaño.
Para ello podemos usar la memoria CG-RAM del display, en la cual podemos crear hasta ocho caracteres propios. Dichos caracteres los podremos usar para formar nuestros digitos.
Usando la CG-RAM con Arduino.
Los usuarios disponemos de un total de 8 carácteres que podemos personalizar y cada carácter se dibuja como una matriz de puntos de 5x8 bits. Así que basta con definir cada uno de los puntos de la matriz y crearlos en memoria usando un array:
El array de la imagen tiene el valor:
byte charX[8]={ B01110, B10001, B10011, B10101, B11001, B10001, B01110, B00000 };
Dentro de la carpeta cores de arduino encontraremos un fichero llamado binary.h donde se define todas las macros que crean los números en binario desde el 0 al 255 usando desde 1 digito hasta 8 digitos.B11111111 -> 0xFF -> 255
Ahora tan solo hemos de usar la funcion createChar para hacer que el Arduino grabe en la memoria del display el carácter.
lcd.createChar(0, charX);
Esta función acepta dos parámetros: el carácter que queremos personalizar y el búfer al array. Como hemos dicho, sólo disponemos de 8 carácteres que van enumerados desde 0 al 7.
Si queremos usar un carácter personalizado debemos tener en cuenta que la función print de la librería LiquidCrystal solo acepta los carácteres ASCII imprimibles y estos caracteres están fuera de dichos valores. Por lo tanto hemos de recurrir a la write para ello. Ejemplo
lcd.setCursor(0,0); lcd.write(byte(0));
NOTA: Es necesario hacer el casting byte() para que funcione, si no dará resultados impredecibles.
Creando una fuente.
Ahora que ya sabemos podemos crear nuestro propio carácter en grande. Básicamente lo que tenemos que hacer es crear una serie de "segmentos" de cifra, cada uno de los cuales será un carácter de la cifra.
Tan solo tenemos 8 carácteres para editar y esto nos limita mucho. También tenemos a nuestra disposicion los caracteres 32 (espacio) y 255 (todos los pixeles encendidos) que nos ayudarán a mejorar el resultado.
Una vez hemos creado el "despiece" tan solo hace falta crearlos colocando cada segmento en la posición adecuada. En la imagen anterior se puede ver un ejemplo de como se puede hacer.
Podemos crear imagenes de 2x2, 3x3 o incluso si usamos un lcd de 20x4 de otros tamaños, el límite son los 8 carácteres que se pueden usar y la imaginación de cada uno.
Ejemplo de uso
En el siguiente código se ha creado una fuente 2x2 para utilizar en un reloj, además se ha optado por tener en memoria flash los arrays de cada uno de los carácteres para optimizar el espacio de memoria.
#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Este bufer no servirá de intermediario entre la memoria flash y el LCD. byte bufer[8]; // Cada uno de los carácteres personales. const byte char0[8] PROGMEM = { 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00 }; const byte char1[8] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F }; const byte char2[8] PROGMEM = { 0x1E, 0x1D, 0x1B, 0x17, 0x0F, 0x1F, 0x1F, 0x1F }; const byte char3[8] PROGMEM = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1D, 0x1F, 0x1F }; const byte char4[8] PROGMEM = { 0x1F, 0x1F, 0x17, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F }; const byte char5[8] PROGMEM = { 0x1F, 0x1F, 0x1F, 0x1E, 0x1D, 0x1B, 0x17, 0x0F }; const byte char6[8] PROGMEM = { 0x1E, 0x1D, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; const byte char7[8] PROGMEM = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x17, 0x0F }; // Función que inicializa los carácteres. Copia el contenido de la flash en // el bufer y este se copia a la LCD. void initChars() { memcpy_P(bufer, char0, 8); lcd.createChar(0, bufer); memcpy_P(bufer, char1, 8); lcd.createChar(1, bufer); memcpy_P(bufer, char2, 8); lcd.createChar(2, bufer); memcpy_P(bufer, char3, 8); lcd.createChar(3, bufer); memcpy_P(bufer, char4, 8); lcd.createChar(4, bufer); memcpy_P(bufer, char5, 8); lcd.createChar(5, bufer); memcpy_P(bufer, char6, 8); lcd.createChar(6, bufer); memcpy_P(bufer, char7, 8); lcd.createChar(7, bufer); } // Muestra un digito x a partir de la columna f. void printDigit(int x, int f) { if ( f>14) return; switch (x) { case 0: lcd.setCursor(f,0); lcd.write(byte(255)); lcd.write(byte(7)); lcd.setCursor(f,1); lcd.write(byte(6)); lcd.write(byte(255)); break; case 1: lcd.setCursor(f,0); lcd.write(byte(32)); lcd.write(byte(2)); lcd.setCursor(f,1); lcd.write(byte(32)); lcd.write(byte(255)); break; case 2: lcd.setCursor(f,0); lcd.write(byte(0)); lcd.write(byte(5)); lcd.setCursor(f,1); lcd.write(byte(255)); lcd.write(byte(1)); break; case 3: lcd.setCursor(f,0); lcd.write(byte(0)); lcd.write(byte(5)); lcd.setCursor(f,1); lcd.write(byte(1)); lcd.write(byte(255)); break; case 4: lcd.setCursor(f,0); lcd.write(byte(2)); lcd.write(byte(1)); lcd.setCursor(f,1); lcd.write(byte(0)); lcd.write(byte(255)); break; case 5: lcd.setCursor(f,0); lcd.write(byte(255)); lcd.write(byte(0)); lcd.setCursor(f,1); lcd.write(byte(1)); lcd.write(byte(2)); break; case 6: lcd.setCursor(f,0); lcd.write(byte(255)); lcd.write(byte(0)); lcd.setCursor(f,1); lcd.write(byte(3)); lcd.write(byte(4)); break; case 7: lcd.setCursor(f,0); lcd.write(byte(0)); lcd.write(byte(255)); lcd.setCursor(f,1); lcd.write(byte(32)); lcd.write(byte(5)); break; case 8: lcd.setCursor(f,0); lcd.write(byte(3)); lcd.write(byte(4)); lcd.setCursor(f,1); lcd.write(byte(3)); lcd.write(byte(4)); break; case 9: lcd.setCursor(f,0); lcd.write(byte(3)); lcd.write(byte(4)); lcd.setCursor(f,1); lcd.write(byte(1)); lcd.write(byte(255)); break; default: break; } } // Muestra la hora en la forma HH:MM. Se le pasa la hora (h) y el // minuto (m). dot se usa para dibujar los ':' o no. void printTime(int h, int m, bool dot) { printDigit(h/10, 7); printDigit(h%10, 9); if ( dot ) { lcd.setCursor(11, 0); lcd.write(165); lcd.setCursor(11, 1); lcd.write(165); } else { lcd.setCursor(11, 0); lcd.write(32); lcd.setCursor(11, 1); lcd.write(32); } printDigit(m/10, 12); printDigit(m%10, 14); } void setup() { initChars(); lcd.begin(16, 2); printTime(17,55,true); } int digit; void loop() {}
Editor de caracteres.
He creado una pequeño programa en Javascript para crear caracteres propios y que facilita el trabajo.
Referencias
small display BIG DIGITS project.
BigNums2x2 Library for Arduino.
projedefteri - about the 16x2 lcd screen big guide.
lastminuteengineers - arduino 1602 character lcd tutorial.
Conjunto de caracteres predifinidos en la ROM del LCD.