Saltar al contenido
Control Automático Educación

LCD I2C Raspberry Pi Pico

En esta entrada aprenderemos a programar un LCD I2C con la Raspberry Pi Pico usando MicroPython y adicionalmente veremos que el mismo código y la misma librería puede ser empleada en un NodeMCU ESP8266 o ESP32.

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:

I2C con MicroPython en Raspberry Pi Pico / ESP8266/32

Una de las fomas más fáciles y prácticas de utilizar un display LCD con Raspberry Pi Pico, con NodeMCU ESP8266 o ESP32 es usando directamente un módulo I2C para la conexión de un LCD16x2, LCD20x4 o cualquier otro LCD.

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

Si estamos empleando en nuestro proyecyo un LCD con la Raspberry Pi Pico o si usamos un esp8266 empleando un lcd programado en micropython, necesitamos determinar la dirección del dispositivo.

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 que tendrás tres archivos con extensión .py, y para que funcione la librería, debes pasar el archivo lcd_api.py y pico_i2c_lcd.py a la memoria de la Raspberry Pi Pico. Eso lo puedes hacer con el IDE de Thonny, dando click en VIEW/FILES

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
Display 7 Segmentos MicroPython

Display 7 Segmentos

LCD Arduino

LCD Arduino

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.

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

Comentarios (18)

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.