Saltar al contenido

LCD I2C Raspberry Pi Pico

En esta guía completa, te enseñaremos a programar un LCD 16×2 I2C con la Raspberry Pi Pico utilizando MicroPython. Además, exploraremos cómo el mismo código y librería pueden ser aplicados en otras plataformas como NodeMCU ESP8266 o ESP32. Si estás trabajando con módulos I2C para pantallas LCD, este tutorial te proporcionará todas las herramientas y conocimientos necesarios para simplificar tus proyectos de electrónica.

Si estás familiarizado con otros microcontroladores como PIC o Arduino, y has trabajado con el protocolo I2C, este tutorial te resultará bastante sencillo. Si aún no has explorado el uso del I2C con PIC, te invitamos a revisar nuestra guía detallada sobre I2C con PIC, donde cubrimos la implementación de este protocolo en microcontroladores PIC como el PIC16F877A. También, si estás usando Arduino, no te pierdas nuestro tutorial sobre I2C con Arduino, donde exploramos cómo conectar y programar periféricos I2C como pantallas LCD en placas Arduino.

Antes de comenzar te invito a que visites nuestro CURSO GRATUITO DE MICROPYTHON en Raspberry Pi Pico o ESP.

Y que te suscríbas al canal, si te interesa los temas de programación en microcontroladores y principalmente la teoría de la ingeniería de control:

Entendiendo el Protocolo I2C: Comunicación Simple y Eficiente

El protocolo I2C (Inter-Integrated Circuit) es una tecnología de comunicación serie ampliamente utilizada en proyectos electrónicos, desde sistemas embebidos hasta microcontroladores como el Raspberry Pi Pico. Su principal ventaja es que permite conectar múltiples dispositivos a un mismo bus utilizando solo dos cables: SDA (Serial Data Line) para la transmisión de datos y SCL (Serial Clock Line) para la sincronización de estos datos.

i2c conexión
18. Comunicación I2C

¿Cómo Funciona I2C?

A diferencia de otros protocolos como SPI, que requiere múltiples cables para cada dispositivo, I2C simplifica la comunicación permitiendo que todos los dispositivos compartan el mismo bus de datos. Esto es posible porque cada dispositivo conectado al bus tiene una dirección única, que se utiliza para identificarlo durante la comunicación.

Cuando un dispositivo maestro, como la Raspberry Pi Pico, desea comunicarse con un dispositivo esclavo, como un LCD 16×2 o un sensor de temperatura, primero envía un pulso de reloj a través de la línea SCL para sincronizar todos los dispositivos en el bus. Luego, el maestro envía la dirección del esclavo con el que quiere comunicarse a través de la línea SDA, seguida por los datos que quiere transferir. El dispositivo esclavo que tiene la dirección correspondiente responde y recibe o envía los datos según sea necesario.

Configuración de Dispositivos en I2C

Para usar el I2C en tus proyectos con Raspberry Pi Pico o cualquier otro microcontrolador, lo primero que debes hacer es configurar los pines SDA y SCL en tu código. Estos pines deben estar conectados correctamente a los dispositivos esclavos, como el LCD I2C, que estamos utilizando en este tutorial. Por ejemplo, en la Raspberry Pi Pico, los pines comunes para I2C son el Pin 0 para SDA y el Pin 1 para SCL.

Es importante mencionar que el protocolo I2C también requiere la adición de resistencias pull-up en las líneas SDA y SCL para garantizar que las líneas se mantengan en un estado alto cuando no se está transmitiendo datos. Esto es esencial para evitar errores de comunicación en el bus I2C.

Aplicaciones del Protocolo I2C

El protocolo I2C es increíblemente versátil y se utiliza en una variedad de aplicaciones más allá de la conexión de pantallas LCD. Por ejemplo, puedes conectar varios sensores (como acelerómetros, giroscopios, o sensores de temperatura), módulos de memoria EEPROM, relojes en tiempo real (RTC), y más. La capacidad de conectar múltiples dispositivos a través de un solo bus hace que I2C sea la opción preferida en muchos proyectos de sistemas embebidos y electrónica.

En este tutorial, hemos enfocado nuestro uso de I2C en la Raspberry Pi Pico, pero si estás trabajando con otros microcontroladores como el ESP8266, ESP32, o incluso PIC y Arduino, el proceso es muy similar. La clave está en configurar correctamente los pines y entender cómo identificar la dirección I2C de cada dispositivo para asegurar una comunicación eficiente.

I2C con MicroPython en Raspberry Pi Pico / ESP8266/32

Una de las maneras más efectivas de conectar un LCD 16×2 o LCD 20×4 a una Raspberry Pi Pico o a un ESP8266/ESP32 es mediante un módulo I2C. Este protocolo simplifica considerablemente la conexión al usar solo dos pines: SDA y SCL. Si quieres aprender más sobre cómo configurar I2C en PIC o I2C en Arduino, no dudes en visitar nuestras guías especializadas.

Módulo LCD I2C

Inicialmente, debemos conocer las funciones de i2c con micropython para poder determinar la dirección i2c del componente y posteriormente conectar la Raspberry Pi Pico lcd 16×2 i2c o el esp8266 micropython lcd i2c. A partir de la documentación oficial de MicroPython podemos determinar:

i2c = machine.I2Cid = -1 , * , scl , sda , frecuencia = 400000 )

Se construye el objeto I2C usando los siguientes parámetros:

  • id identifica un periférico I2C en particular. El valor predeterminado de -1 selecciona una implementación de software de I2C que puede funcionar (en la mayoría de los casos) con pines arbitrarios para SCL y SDA. Si id es -1, entonces se deben especificar los pines scl y sda . Otros valores permitidos para id dependen del puerto / placa en particular, dado que hay placas que poseen varios puertos I2C y la especificación de scl y sda puede o no ser requerida o permitida en este caso.
  • scl debe ser un objeto pin que especifique el pin que se utilizará para SCL.
  • sda debe ser un objeto pin que especifique el pin que se utilizará para SDA.
  • freq debe ser un número entero que establezca la frecuencia máxima para SCL.

Dirección Modulo LCD I2C

Cuando trabajas con un LCD 16×2 I2C en una Raspberry Pi Pico o un ESP8266 programado en MicroPython, es crucial identificar la dirección I2C del módulo para una correcta configuración. Este paso es similar al proceso que seguimos en otros microcontroladores, como los PIC o Arduino, donde también se requiere conocer la dirección I2C para establecer la comunicación adecuada. Puedes encontrar más información sobre cómo hacerlo en nuestros tutoriales dedicados a I2C en PIC y I2C en Arduino.

Podemos usar el siguiente código estandar con MicroPython para ver cual es la dirección del Módulo I2C.

import machine
import utime


i2c = machine.I2C(0, scl=machine.Pin(9), sda=machine.Pin(8), freq=200000)

direccion = hex(i2c.scan()[0])

print('La dirección I2C es ', direccion)

LCD I2C con MicroPython

En este tutorial de la Raspberry Pi Pico con Display LCD via I2c donde empleamos también el nodemcu esp8266 donde conectamos un lcd de los que venden en el mercado veremos como programarlo paso a paso en MicroPython.

Inicialmente, deberemos descargar alguna librería que sea capaz de controlar el LCD via I2C directamente con MicroPytho, esto la podremos encontrar directamente en el IDE de Thonny, pero para este caso usaremos la librería RPI-PICO-I2C-LCD (click para descargar)

Instalación de la Librería

Una vez descargada y descomprimida la librería, verás tres archivos con extensión .py. Para que la librería funcione correctamente en tu Raspberry Pi Pico, asegúrate de transferir los archivos lcd_api.py y pico_i2c_lcd.py a la memoria de la placa utilizando el IDE de Thonny. Si estás familiarizado con la configuración de I2C en otros microcontroladores, como los PIC o Arduino, este proceso te resultará sencillo y rápido.

Se abrirá la ventana de archivos, donde en la parte superior te muestra los archivos que tiene tu computador y en la parte inferior los archivos de tu raspberry pi pico, debes dar click derecho sobre los archivos que deseas pasar a la memoria de la pico y dar click donde dice Upload to/

Finalmente verifica que los archivos se encuentren dentro de la Flash de la PICO

librería lcd i2c raspberry pi pico

Funciones de la librería

  • lcd.putstr («¡El texto va aquí!») – Envía una cadena de caracteres a la pantalla. IMPORTANTE: para imprimir una variable puedes usar la siguiente instrucción: lcd.putstr (str (Variable)) [Convierte la variable en una cadena]
  • lcd.show_cursor() / lcd.hide_cursor() – Mostrar / Ocultar el cursor de la pantalla lcd (barra blanca)
  • lcd.blink_cursor_on() / lcd.blink_cursor_off() – Enciende / apaga el cursor parpadeante al imprimir
  • lcd.backlight_on() / lcd.backlight_off() – Enciende / apaga la luz de fondo de la pantalla LCD (controlada por un pequeño transistor en la biblioteca)
  • lcd.display_on() / lcd.display_off() – Enciende / apaga la pantalla (no la retroiluminación sino todo el chip)
  • lcd.clear(): borra todos los caracteres o cualquier cosa escrita en la pantalla
  • lcd.move_to(Col, Row) – Mover a la posición según los valores de fila y col (Y, X)
  • lcd.custom_char(Num, bytearray ([caracteres HEX]))) – Num puede ser cualquier número entero 0 – 8 (escribiendo en ubicaciones CGRAM) simplemente utilizado para numerar. Los caracteres HEX se crean simplemente usando este enlace: https://maxpromer.github.io/LCD-Character-Creator/ . Proporcionará una cadena de caracteres hexadecimales que pueden reemplazar los «caracteres HEX» en el comando de ejemplo

Raspberry Pi Pico LCD I2C

El circuito empleado en micropython con la Raspberry Pi Pico usando el módulo I2C y un LCD16x2 será el siguiente, donde alimentaremos el display con el pin VBUS de la placa (Pin 40)

Raspberry Pi Pico LCD I2C

ESP8266 LCD display

El circuito con el esp8266 empleando un lcd 16×2 será el siguiente:

ESP8266 LCD display
Sensor de Nivel con PIC

Sensor de Presión MPX con PIC

Código en MicroPython Display LCD – I2C

El siguiente código puede ser usado tanto con la Raspberry Pi Pico como en un ESP, a modo de ejemplo el NodeMCU ESP8266, basta solo configurar los pines empleados para la comunicación i2c.

import utime
from machine import I2C,Pin
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd

#Dirección del I2C y tamaño del LCD
I2C_ADDR  =  0x27
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16

# Raspberry Pi Pico
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)

#Esp8266
#i2c = I2C(sda=Pin(4), scl=Pin(5), freq=100000)

#Configuración LCD
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)

battery_0 = [0x0E,
  0x1B,
  0x11,
  0x11,
  0x11,
  0x11,
  0x11,
  0x1F]
battery_15 = [0x0E,
  0x1B,
  0x11,
  0x11,
  0x11,
  0x11,
  0x1F,
  0x1F]
battery_30 = [  0x0E,
  0x1B,
  0x11,
  0x11,
  0x11,
  0x1F,
  0x1F,
  0x1F]
battery_45 = [0x0E,
  0x1B,
  0x11,
  0x11,
  0x1F,
  0x1F,
  0x1F,
  0x1F]
battery_60 = [0x0E,
  0x1B,
  0x11,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F]
battery_75 = [0x0E,
  0x1B,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F]
battery_100 = [0x0E,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F]


def lcd_str(message, col, row):
    lcd.move_to(col, row)
    lcd.putstr(message)


def main():
    lcd.custom_char(0, bytearray(battery_0))
    lcd.custom_char(1, bytearray(battery_15))
    lcd.custom_char(2, bytearray(battery_30))
    lcd.custom_char(3, bytearray(battery_45))
    lcd.custom_char(4, bytearray(battery_60))
    lcd.custom_char(5, bytearray(battery_75))
    lcd.custom_char(6, bytearray(battery_100))
    
    
    while True:
        lcd.clear()
        lcd_str("Battery:", 0, 0)
        lcd.move_to(0,1)
        for i in range(0,7):
            lcd.putchar(chr(i))
        utime.sleep(3)
        
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Suscribete a    ")
        utime.sleep(1)
        lcd.move_to(0,1)
        lcd.putstr("Control       ")
        utime.sleep(1)
        lcd_str("Automatico    ", 0, 0)
        utime.sleep(1)
        lcd_str("Educacion    ", 0, 1)
        utime.sleep(1)
        
        lcd.clear()
        lcd_str("Numeros en", 3,0)
        lcd_str("Esquinas", 4,1)
        utime.sleep(1)
        
        lcd_str("1", 0,0)
        utime.sleep(1)
        lcd_str("2", 15,0)
        utime.sleep(1)
        lcd_str("3", 0,1)
        utime.sleep(1)
        lcd_str("4", 15,1)
        utime.sleep(1)
        
        lcd.clear()
        lcd_str("Suscribete", 0, 0)
        lcd_str("Activa: CAMPANA", 0, 1)
        lcd.blink_cursor_on()
        utime.sleep(2)
        
        #Backspace
        for j in range(1, -1, -1):
            for i in range(15, -1, -1):
                lcd.move_to(i, j)
                lcd.putstr(' ')
                utime.sleep_ms(100)
        utime.sleep(1)
        lcd.hide_cursor()
        
        #BackLight
        lcd.clear()
        lcd.backlight_off()
        lcd_str("BackLight OFF", 0, 0)
        utime.sleep(3)
        
        lcd.clear()
        lcd.backlight_on()
        lcd_str("BackLight ON", 0, 0)
        utime.sleep(3)


if __name__ == '__main__':
    main()

Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:

👉 Invitar a Sergio a un Café ☕️

Que esten muy bien, nos vemos en la siguiente entrada.

Entradas relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Comentarios (22)

Sergio:
Ya he dado con el problema, debo tener mal I2C0, he cambiado a I2C1 y todo funciona muy bien. Disculpa y muchas gracias.

Responder

perfecto Luis, que bueno que diste con la solución. Éxitos.

Responder

Buenos días Sergio:
Un curso estupendo!!
Al correr el programa me da el siguiente error:

MPY: soft reboot
Traceback (most recent call last):
File «», line 18, in
File «pico_i2c_lcd.py», line 22, in __init__
OSError: [Errno 5] EIO

La línea 18 es: lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
¿Podrías ayudarme a resolverlo?

Responder

Hola he estado trabajando con una LCD 20X4, Raspberry Pi Pico y un sensor MPU6050, he logrado mostrar los datos del sensor en la pantalla pero ahora quiero que estos mismos datos se guarden en un documento ya sea .txt o .csv como podría realizarlo?

Responder

Hola Sergio
Estoy siguiendo tus videos
te consulto existe alguna librería para rasberry pi pico para el manejo de pantallas LCD graficas de 128×64 con controlador ST7920?

Responder

Busca en google por Micropython ST7920, te deben aparecer algunas librerías relacionadas.

Responder

Hola buenos días
Me aparece este error tanto el la ESP8266 como en la Pico no tengo idea que sea. por favor me podrías ayudar.

%Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File «», line 23, in
File «», line 11, in main
NameError: name ‘pin’ isn’t defined

import utime
from machine import I2C,Pin
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd

I2C_ADDR = 0x27
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16

def main():
i2c = I2C(0,sda=pin(0), scl=pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)

while True:
lcd.clear()
lcd.move_yo(0,0)
lcd.putstr(«hola «)
lcd.move_to(0,1)
lcd.putstr(«control «)
utime.sleep(1)

if __name__ == ‘__main__’:
main()

Responder

Hola Antonio, estas copiando «pin» en lugar de «Pin», debe ser con la ‘P’ en mayúscula, cuando creas el objeto i2c.

Mas abajo tienes también el lcd.move_yo, y en realidad es lcd.move_to

Responder

Muchas gracias.

Me podrías mencionar en donde puedo encontrar la lista completa de las funciones para controlar la lcd con i2c, quiero usar una función similar a esta lcd.autoscroll();.

Responder

despues de probar varias veces y revisar el codigo no me funciona, siguen arrojando error:

Traceback (most recent call last):
File «», line 72
SyntaxError: invalid syntax

lo que hay en la linea 72 es lcd.move_to(col, row)

Responder

Hola Jorge, has grabado inicialmente los archivos lcd_api.py y pico_i2c_lcd.py en la memoria de la Raspberry Pi Pico? Como se muestra en el video. He actualizado la entrada colocando el paso a paso de como instalar la librería para que la Raspberry Pi Pico reconozca la librería.
Recuerda que el código del post puede ser copiado en su totalidad dando click en la parte superior derecha del cuadro del código en un botón que dice «copy to clipboard»

Responder

gracias por responder, si sr, he grabado el lcd_api.py y el pico_i2c_lcd.py en la pico, he utilizado el scan y mi lcd es 0x27 de 2×16, toda esta bien conectado pero tu codigo arroja error, lo he copiado con copy to clipboard, podrias pasarme tu archivo .py para probar por favor?

Responder

Hola Jorge estuve revisando y por ejemplo si conecto al revés los pines SCL y SDA el código da un error, hay que realizar bien la conexión una vez se modifica la conexión es necesario darle al boton STOP varias veces. Verifica que el PIN SCL del modulo LCD este conectado al PIN2 de la PICO y el SDA del modulo LCD en el PIN1 de la PICO.
Mi código .py lo puedes bajar de mi github: https://github.com/sergioacg/MicroPython/tree/main/LCD_I2C

Responder

el pin SDA de la lcd esta en GP0 (pin 1 pico) y el pin SCL de la lcd esta en GP1 (pin 2 pico)……..si estuviera mal conectados creo que el i2c scan no lo hubiera alcanzado…….es decir, no lo hubiera leido y lo leyo, dice que mi lcd es 0x27 (ambos jumpers abiertos).

el codigo que publicas en github ambos arrojan error, aun intercambiando los pines sda y scl, los he mirado y estan para una lcd 4×20 de todas formas los he modificado y aun asi arrojan los mismos errores………… desde mi infinta ignorancia creo que es el codigo o son las librerias.

Hola Jorge, que estraño, realmente no se que pueda estar sucediendo, lo volvi a verificar aquí, y me funciona instantaneamente sin problemas. Incluso, verifiqué y grabe el programa principal en la placa con el nombre main.py y cada que desenergizo y energizo muestra los mensajes sin inconvenientes. Me prodrias indicar que error te esta saliendo? te sale el mismo SintaxError que me colocaste anteriormente en la linea 72?
Por ejemplo en mi caso cuando lo conectaba mal, me salia un error en la linea 20 de la librería, pero no me ha salido ese error de la linea 72. Intenta grabarlo con main.py en la placa solo para descartar esa parte.
Otra cosa, prueba actualizar el firmware de la placa, por ejemplo hay un nuevo firmware lanzada justo esta semana.

lo siento sr sergio, despues de probrar otros sketchs, no tuve solucion con el tuyo, se atasca en lcd.move_to(col, row) :

Traceback (most recent call last):
File “”, line 72
SyntaxError: invalid syntax

El interprete de micropython dice que hay un error de sintaxis.

Realmente es extraño Jorge, talvez podrías compiarme todo tu código aqui en los comentarios para ver si consigo ver alguna cosa del porque se está generando el error. Saludos.

# Hola don sergio este sencillo codigo si me corre ok !
# Se utiliza I2C 0 y SDA GP8 (pin 11) y SCL GP9 (pin 12)
# Muestra el mensaje inicial PROTOCOLO I2C LCD 2×16
# por 3 segundos y despues queda titilando con el mensaje
# subscribete indefinidamente

from utime import sleep_ms
from machine import I2C, Pin
from pico_i2c_lcd import I2cLcd

DEFAULT_I2C_ADDR = 0x27

def test_main():

i2c = I2C(0,scl=Pin(9), sda=Pin(8), freq=400000)
lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16)
lcd.putstr(«PROTOCOLO I2C\nLCD 2×16″)
sleep_ms(3000)
lcd.clear()
count = 0

while True:

lcd.move_to(0, 0)
lcd.putstr(» SUBSCRIBETE! «)
sleep_ms(1000)
lcd.clear()
sleep_ms(1000)

test_main()

mmm que extraño, será que te estará dando error con la inclusión de caracteres especiales? ya que aquí no tienes caracteres especiales y te funcionó. Intenta colocar uno en este código para ir descartando, en tu otro código realmente no consigo ver que pueda estar dando error. Saludos Jorge.

hola ing. sergio

Con mas calma me he sentado a revisar el codigo y ver tu video y he encontrado la falla.

Aunque el codigo es correcto el problema estaba en la identacion, viendo el video ajuste el codigo y funciono correctamente. Al final el interprete de python tenia razon, habia un problema en la sintaxis, te recomiendo no usar ese texto plano para que los usuarios al hacer copy to clipboard se puedan llevar el programa bien tabulado.

Que interesante conclusión Jorge, muchas gracias por comentarlo y por la perseverancia, esta será una buena solución para quien tenga este problema en el futuro. Voy a revisar lo del código para ver como se puede compartir de una mejor forma. Saludos!!

lo mas bonito de tu codigo es el efecto bakcspace y el efecto de los numeros en las esquinas……………alguien podria hacer un juego de ruleta o algo asi con ese efecto. Nos gustaria que ahondaras un poco mas en los efectos, por ejemplo los scroll y la forma de como crear caracteres especiales y almacenarlos en la misma memoria interna de la lcd, toda esta tematica es apasionante.