Skip to Content

Cómo controlar un LCD de caracteres I2C con Arduino

Cómo controlar un LCD de caracteres I2C con Arduino

Este artículo incluye todo lo que necesitas saber sobre cómo usar un Character I2C LCD con Arduino. He incluido un diagrama de conexiones y muchos ejemplos de código para ayudarte a empezar.

La primera parte de este artículo cubre los conceptos básicos para mostrar texto y números. En la segunda parte, profundizaré en cómo mostrar caracteres personalizados y cómo puedes usar otras funciones de la biblioteca LiquidCrystal_I2C.

Una vez que sepas cómo mostrar texto y números en la LCD, te sugiero que eches un vistazo a los artículos que aparecen a continuación. En esos tutoriales aprenderás a medir y mostrar datos de sensores en la LCD.

Materiales

Componentes de hardware

lcd16×2 character I2C LCD× 1Amazon
lcd20×4 character I2C LCD (alternativa)× 1Amazon
Arduino Uno Rev 3Arduino Uno Rev3× 1Amazon
Jumper wires (macho a hembra)× 4Amazon
USB cable type A/B× 1Amazon

Herramientas

Small screwdriverAmazon

Software

Arduino IDEArduino IDE

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Conceptos básicos del LCD I2C

Esta guía forma parte de nuestro conjunto de artículos sobre Displays. Este tipo de LCD es ideal para mostrar texto y números, de ahí su nombre ‘character LCD’.

El LCD I2C que usamos en este tutorial incluye un pequeño circuito adicional montado en la parte trasera del módulo. Este módulo cuenta con un chip PCF8574 (para comunicación I2C) y un potenciómetro para ajustar la retroiluminación LED.

La ventaja de un LCD I2C es que el cableado es muy sencillo. Solo necesitas dos pines de datos para controlar el LCD. Los LCD estándar suelen requerir alrededor de 12 conexiones, lo que puede ser un problema si no tienes muchos pines GPIO disponibles.

Por suerte, también puedes comprar el circuito adicional I2C por separado en Amazon, así puedes actualizar fácilmente un LCD estándar.

Para un tutorial y diagrama de conexiones de LCDs de caracteres estándar, consulta el siguiente artículo:

Si miras de cerca el LCD, verás pequeños rectángulos que forman los caracteres individuales. Cada rectángulo está compuesto por una cuadrícula de 5×8 píxeles. Más adelante en este tutorial te mostraré cómo controlar los píxeles individuales para mostrar caracteres personalizados en el LCD.

LCD Pixels
Píxeles del LCD

Especificaciones

Las especificaciones de los LCDs 16×2, 20×4 y otros tamaños son en su mayoría iguales. Todos usan el mismo HD44780 Hitachi LCD controller, por lo que puedes intercambiarlos fácilmente. Solo tendrás que cambiar las especificaciones de tamaño en tu código Arduino.

Las especificaciones de un display I2C típico 16×2 se encuentran en la tabla a continuación.

Especificaciones del LCD I2C 16×2

Voltaje de operación5 V
ControladorControlador LCD Hitachi HD44780
Dirección por defecto0x27
Resolución de pantalla2 líneas × 16 caracteres
Resolución de caracteres5 × 8 píxeles
Dimensiones del módulo80 × 36 × 12 mm
Dimensiones del área visible64.5 × 16.4 mm
PrecioCheck price

Para más información, puedes consultar las hojas de datos a continuación.

Las hojas de datos de los modelos 16×2 y 20×4 incluyen las dimensiones del LCD y puedes encontrar más información sobre el controlador Hitachi en la hoja de datos del HD44780.

El chip PCF8574 se usa en el módulo I2C en la parte trasera del LCD.

Cómo conectar el LCD I2C al Arduino UNO

El diagrama de conexiones a continuación muestra cómo conectar el LCD I2C al Arduino. Conectar un LCD I2C es mucho más fácil que un LCD estándar. Solo necesitas conectar 4 pines en lugar de 12.

I2C-LCD-with-Arduino-Wiring-Diagram-Schematic-Pinout
Diagrama de conexiones del LCD I2C con Arduino

Las conexiones también se detallan en la tabla a continuación.

Conexiones del LCD I2C

LCD de caracteres I2CArduino
GNDGND
VCC5 V
SDAA4
SCLA5

Si no usas un Arduino Uno, los pines SDA y SCL pueden estar en una ubicación diferente.

Ten en cuenta que un Arduino Uno con el diseño R3 (pinout 1.0) también tiene los pines SDA (línea de datos) y SCL (línea de reloj) cerca del pin AREF. Consulta la tabla a continuación para más detalles.

PlacaSDASCL
Arduino UnoA4A5
Arduino NanoA4A5
Arduino Micro23
Arduino Mega 25602021
Arduino Leonardo23
Arduino Due2021
Ubicación de los pines SDA y SCL en diferentes placas Arduino.

Ajustar el contraste del LCD

Después de conectar el LCD, necesitarás ajustar el contraste de la pantalla. En el módulo I2C encontrarás un potenciómetro que puedes girar con un pequeño destornillador.

Conecta el Arduino por USB para alimentar el LCD. Deberías ver que se enciende la retroiluminación. Ahora gira el potenciómetro hasta que aparezca una fila (en un LCD 16×2) o dos filas (en un LCD 20×4) de rectángulos. Puedes ajustar el contraste más adelante si es necesario.

Una vez hecho esto, podemos empezar a programar el LCD.

Instalación de la biblioteca LiquidCrystal_I2C para Arduino

En este tutorial usaré la LiquidCrystal_I2C biblioteca. Esta biblioteca tiene muchas funciones integradas que facilitan la programación del LCD.

La última versión de esta biblioteca se puede encontrar aquí:

Asegúrate de tener instalada esta biblioteca exacta y elimina cualquier otra con el mismo nombre (LiquidCrystal_I2C). Otras bibliotecas probablemente funcionen, pero pueden usar nombres ligeramente diferentes para las funciones.

La biblioteca LiquidCrystal_I2C funciona en combinación con la Wire.h biblioteca que permite comunicarte con dispositivos I2C. Esta biblioteca viene preinstalada con el IDE de Arduino.

Para instalar esta biblioteca, ve a Tools > Manage Libraries (Ctrl + Shift + I en Windows) en el Arduino IDE. Se abrirá el Library Manager y actualizará la lista de bibliotecas instaladas.

Installing an Arduino library step 1 open Library Manager
Manage Libraries

Ahora busca ‘liquidcrystal_i2c’ y busca la biblioteca de Frank de Brabander. Selecciona la última versión y haz clic en Install.

Instalación de la biblioteca LiquidCrystal_I2C para Arduino

La biblioteca incluye algunos ejemplos que puedes usar, pero tendrás que modificarlos para que coincidan con tu configuración de hardware. He incluido muchos ejemplos de código más abajo que puedes usar con el cableado que mostré antes.

Primero te mostraré un código básico de ejemplo y luego explicaré las funciones con más detalle.

¿Cómo encontrar la dirección I2C de mi LCD?

La mayoría de los LCD I2C vienen con la dirección por defecto ‘0x27’, pero puede variar según el lote o fabricante. Si es así, necesitarás encontrar la dirección real del LCD antes de usarlo. En la web de Arduino puedes encontrar un sketch de ejemplo que escanea el bus I2C en busca de dispositivos. Si encuentra uno, mostrará la dirección en el monitor serial.

/*I2C_scanner
  This sketch tests standard 7-bit addresses.
  Devices with higher bit address might not be seen properly.
*/
  
#include "Wire.h"

void setup() {
  Wire.begin();

  Serial.begin(9600);
  while (!Serial);
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for (address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);
}

Si subes este sketch al Arduino y lo ejecutas, deberías ver la siguiente salida en el Monitor Serial (Ctrl + Shift + M).

I2C Address finder serial monitor output
Salida del escáner de direcciones I2C en el Monitor Serial

Anota la dirección que encuentres, la necesitarás más adelante para programar el LCD.

Código básico de ejemplo para LCD I2C con Arduino

Este sketch de ejemplo mostrará el clásico ‘Hello World!’ en la primera línea del LCD y ‘LCD tutorial’ en la segunda línea.

/* I2C LCD with Arduino example code. More info: https://www.makerguides.com */

#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD

// Wiring: SDA pin is connected to A4 and SCL pin to A5.
// Connect to LCD via I2C, default address 0x27 (A0-A2 not jumpered)
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // Change to (0x27,20,4) for 20x4 LCD.

void setup() {
  // Initiate the LCD:
  lcd.init();
  lcd.backlight();
}

void loop() {
  // Print 'Hello World!' on the first line of the LCD:
  lcd.setCursor(2, 0); // Set the cursor on the third column and first row.
  lcd.print("Hello World!"); // Print the string "Hello World!"
  lcd.setCursor(2, 1); //Set the cursor on the third column and the second row (counting starts at 0!).
  lcd.print("LCD tutorial");
}

Deberías ver la siguiente salida en el LCD:

i2c lcd with arduino hello world
Salida en la pantalla LCD

A continuación, explicaré cómo funciona el código.

Cómo funciona el código

Primero se incluyen las bibliotecas necesarias. Como mencioné antes, necesitamos tanto Wire.h como LiquidCrystal_I2C. En el resto de este tutorial cubriré más funciones integradas de esta biblioteca.

#include "Wire.h" // Library for I2C communication
#include "LiquidCrystal_I2C.h" // Library for LCD

El siguiente paso es crear un objeto LCD con la clase LiquidCrystal_I2C y especificar la dirección y dimensiones. Para esto usamos la función LiquidCrystal_I2C(address, columns, rows).

Aquí es donde tendrás que cambiar la dirección por defecto por la que encontraste antes si es diferente. Si usas un LCD 20×4, cambia esta línea a LiquidCrystal_I2C(0x27,20,4);

Ten en cuenta que hemos llamado al display ‘lcd’. Puedes darle otro nombre si quieres, como ‘menu_display’. Tendrás que cambiar ‘lcd’ por el nuevo nombre en el resto del sketch.

// Connect to LCD via I2C, default address 0x27 (A0-A2 not jumpered)
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // Change to (0x27,20,4) for 20x4 LCD.

Setup

En el setup, se inicia el LCD con lcd.init() y se enciende la retroiluminación con lcd.backlight().

void setup() {
  // Initiate the LCD:
  lcd.init();
  lcd.backlight();
}

Loop

En la sección loop del código, el cursor se posiciona en la tercera columna y primera fila del LCD con lcd.setCursor(2,0).

Ten en cuenta que la cuenta empieza en 0 y el primer argumento especifica la columna. Así que lcd.setCursor(2,1) posiciona el cursor en la tercera columna y segunda fila.

Luego se imprime la cadena ‘Hello World!’ con lcd.print("Hello World!"). Ten en cuenta que debes poner comillas (” “) alrededor del texto ya que estamos imprimiendo un text string.

Cuando quieres imprimir números, no necesitas comillas. Por ejemplo lcd.print(12345).

void loop() {
  lcd.setCursor(2, 0); // Set the cursor on the third column and first row.
  lcd.print("Hello World!"); // Print the string "Hello World!".
  lcd.setCursor(2, 1); //Set the cursor on the third column and the second row.
  lcd.print("LCD tutorial"); // Print the string "LCD tutorial".
}

Si quieres ver un ejemplo para mostrar (cambiar) variables en el LCD, consulta mi tutorial del sensor ultrasónico HC-SR04:

Otras funciones útiles de la biblioteca LiquidCrystal_I2C

El sketch de ejemplo anterior te muestra lo básico para mostrar texto en el LCD. Ahora veremos otras funciones de la biblioteca LiquidCrystal_I2C.

clear()

Limpia la pantalla LCD y posiciona el cursor en la esquina superior izquierda (primera fila y primera columna). Puedes usar esta función para mostrar diferentes palabras en un bucle.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
}

void loop() {
  lcd.clear();
  lcd.print("Monday");
  delay(2000);
  lcd.clear();
  lcd.print("13:45");
  delay(2000);
}

home()

Posiciona el cursor en la esquina superior izquierda del LCD. Usa clear() si también quieres limpiar la pantalla.

cursor()

Muestra el cursor LCD: un guion bajo (línea) en la posición del siguiente carácter a imprimir.

noCursor()

Oculta el cursor LCD. El siguiente ejemplo crea un cursor parpadeante al final de “Hello World!”.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("Hello World!");
}

void loop() {
  lcd.cursor();
  delay(500);
  lcd.noCursor();
  delay(500);
}

blink()

Crea un cursor LCD en forma de bloque parpadeante: un rectángulo que parpadea en la posición del siguiente carácter a imprimir.

noBlink()

Desactiva el cursor en forma de bloque. El siguiente ejemplo muestra el cursor parpadeante durante 5 segundos y luego lo desactiva por 2 segundos.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("blink() example");
}

void loop() {
  lcd.blink();
  delay(5000);
  lcd.noBlink();
  delay(2000);
}

display()

Esta función enciende la pantalla LCD y muestra cualquier texto o cursor que se haya impreso.

noDisplay()

Esta función apaga cualquier texto o cursor impreso en el LCD. El texto/datos no se borran de la memoria del LCD.

Esto significa que se volverán a mostrar cuando se llame a la función display() .

El siguiente ejemplo crea un efecto de texto parpadeante.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("Blinking text");
}

void loop() {
  lcd.display();
  delay(2000);
  lcd.noDisplay();
  delay(2000);
}

write()

Esta función se usa para escribir un carácter en el LCD. Consulta la sección sobre cómo crear y mostrar caracteres personalizados para más información.

scrollDisplayLeft()

Desplaza el contenido de la pantalla (texto y cursor) un espacio a la izquierda.

Puedes usar esta función en la sección loop del código junto con delay(500), para crear una animación de texto desplazándose.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("Hello World!");
}

void loop() {
  lcd.scrollDisplayLeft();
  delay(500);
}

scrollDisplayRight()

Desplaza el contenido de la pantalla (texto y cursor) un espacio a la derecha.

autoscroll()

Esta función activa el desplazamiento automático del LCD. Esto hace que cada carácter que se imprime empuje los caracteres anteriores un espacio.

Si la dirección actual del texto es de izquierda a derecha (por defecto), la pantalla se desplaza hacia la izquierda; si es de derecha a izquierda, la pantalla se desplaza hacia la derecha.

Esto tiene el efecto de imprimir cada nuevo carácter en la misma posición del LCD.

El siguiente sketch de ejemplo activa el desplazamiento automático e imprime los caracteres del 0 al 9 en la posición (16,0) del LCD. Cambia esto a (20,0) para un LCD 20×4.

#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

void setup() {
  lcd.init();
  lcd.backlight();
}

void loop() {
  lcd.autoscroll();
  lcd.setCursor(16, 0);
  for (int x = 0; x < 10; x++) {
    lcd.print(x);
    delay(500);
  }
  lcd.clear();
}

noAutoscroll()

Desactiva el desplazamiento automático del LCD.

leftToRight()

Esta función hace que el texto fluya hacia la derecha desde el cursor, como si la pantalla estuviera alineada a la izquierda (por defecto).

rightToLeft()

Esta función hace que el texto fluya hacia la izquierda desde el cursor, como si la pantalla estuviera alineada a la derecha.

¿Cómo crear y mostrar caracteres personalizados?

Con la función createChar() es posible crear y mostrar caracteres personalizados en el LCD. Esto es especialmente útil si quieres mostrar un carácter que no forma parte del ASCII character set.

CGROM y CGRAM

Los LCD basados en el controlador Hitachi HD44780 tienen dos tipos de memoria: CGROM y CGRAM (Character Generator ROM y RAM).

CGROM genera todos los patrones de caracteres de 5 x 8 puntos a partir de los códigos estándar de 8 bits. CGRAM puede generar patrones de caracteres definidos por el usuario.

Para pantallas de 5 x 8 puntos, CGRAM puede almacenar hasta 8 caracteres personalizados y para pantallas de 5 x 10 puntos, 4. Para más información consulta la hoja de datos.

Ejemplo de código para caracteres personalizados

El siguiente sketch crea y muestra ocho caracteres personalizados (numerados del 0 al 7). Puedes copiar el código haciendo clic en el botón en la esquina superior derecha del campo de código.

/* Arduino example code to display custom characters on I2C character LCD. More info: www.www.makerguides.com */

// Include the library:
#include "LiquidCrystal_I2C.h"

// Create lcd object of class LiquidCrystal_I2C:
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // Change to (0x27,20,4) for 20x4 LCD.

// Make custom characters:
byte Heart[] = {
  B00000,
  B01010,
  B11111,
  B11111,
  B01110,
  B00100,
  B00000,
  B00000
};

byte Bell[] = {
  B00100,
  B01110,
  B01110,
  B01110,
  B11111,
  B00000,
  B00100,
  B00000
};

byte Alien[] = {
  B11111,
  B10101,
  B11111,
  B11111,
  B01110,
  B01010,
  B11011,
  B00000
};

byte Check[] = {
  B00000,
  B00001,
  B00011,
  B10110,
  B11100,
  B01000,
  B00000,
  B00000
};

byte Speaker[] = {
  B00001,
  B00011,
  B01111,
  B01111,
  B01111,
  B00011,
  B00001,
  B00000
};

byte Sound[] = {
  B00001,
  B00011,
  B00101,
  B01001,
  B01001,
  B01011,
  B11011,
  B11000
};

byte Skull[] = {
  B00000,
  B01110,
  B10101,
  B11011,
  B01110,
  B01110,
  B00000,
  B00000
};

byte Lock[] = {
  B01110,
  B10001,
  B10001,
  B11111,
  B11011,
  B11011,
  B11111,
  B00000
};

void setup() {
  // Initialize LCD and turn on the backlight:
  lcd.init();
  lcd.backlight();

  // Create new characters:
  lcd.createChar(0, Heart);
  lcd.createChar(1, Bell);
  lcd.createChar(2, Alien);
  lcd.createChar(3, Check);
  lcd.createChar(4, Speaker);
  lcd.createChar(5, Sound);
  lcd.createChar(6, Skull);
  lcd.createChar(7, Lock);

  // Clear the LCD screen:
  lcd.clear();

  // Print a message to the lcd:
  lcd.print("Custom Character");
}

// Print all the custom characters:
void loop() {
  lcd.setCursor(0, 1);
  lcd.write(0);

  lcd.setCursor(2, 1);
  lcd.write(1);

  lcd.setCursor(4, 1);
  lcd.write(2);

  lcd.setCursor(6, 1);
  lcd.write(3);

  lcd.setCursor(8, 1);
  lcd.write(4);

  lcd.setCursor(10, 1);
  lcd.write(5);

  lcd.setCursor(12, 1);
  lcd.write(6);

  lcd.setCursor(14, 1);
  lcd.write(7);
}

Deberías ver la siguiente salida en el LCD:

i2c lcd with arduino custom characters
Mostrar caracteres personalizados

Cómo funciona el código

Después de incluir la biblioteca y crear el objeto LCD, se definen los arrays de caracteres personalizados. Cada array consta de 8 bytes (solo se consideran 5 bits). Hay 1 byte para cada fila de la matriz LED 5 x 8. En este ejemplo se crean 8 caracteres personalizados.

// Make custom characters:
byte Heart[] = {
  B00000,
  B01010,
  B11111,
  B11111,
  B01110,
  B00100,
  B00000,
  B00000
};

Al observar el array, verás lo siguiente. Cada fila consta de 5 números que corresponden a los 5 píxeles en un carácter de 5 x 8 puntos. Un 0 significa píxel apagado y un 1 significa píxel encendido. El prefijo ‘B’ es el formato binario específico de Arduino.

Es posible editar cada fila a mano, pero recomiendo usar esta aplicación online LCD Custom Character Generator. Esta aplicación crea automáticamente el array de caracteres y puedes hacer clic en los píxeles para encenderlos o apagarlos.

En el setup, los caracteres personalizados se crean con lcd.createChar(num, data). El primer argumento de esta función es el número del carácter personalizado (0-7) y el segundo es el array de caracteres que creamos.

  // Create new characters:
  lcd.createChar(0, Heart);
  lcd.createChar(1, Bell);
  lcd.createChar(2, Alien);
  lcd.createChar(3, Check);
  lcd.createChar(4, Speaker);
  lcd.createChar(5, Sound);
  lcd.createChar(6, Skull);
  lcd.createChar(7, Lock);

En el loop, todos los caracteres se muestran con lcd.write(). Como argumento usamos el número del carácter personalizado que queremos mostrar.

  lcd.setCursor(0, 1);
  lcd.write(0);

Conclusión

En este artículo te he mostrado cómo usar un LCD I2C de caracteres con Arduino. También tenemos un artículo sobre How To Control A Character I2C LCD with ESP32, si quieres trabajar con un microcontrolador ESP32 en su lugar.

Si tienes alguna pregunta, sugerencia o crees que falta algo en este tutorial, por favor deja un comentario abajo.