micropython-displays-lcd-i2c-oled-ssd1306

Pantallas LCD I2C y OLED SSD1306 con MicroPython

  • 5 min

Una pantalla en MicroPython es un periférico que muestra texto o gráficos sin depender del USB.

Hasta ahora, la única forma que tenía nuestro microcontrolador de decirnos algo era mediante print() a través del cable USB. Pero si queremos hacer un termostato de pared, un reloj o un tamagotchi, necesitamos una pantalla.

En el ecosistema maker existen dos estándares que dominan sobre el resto por su precio y facilidad de uso:

  1. LCD de Caracteres (1602 / 2004): Ideales para mostrar texto simple. Robustas y muy legibles.
  2. OLED Gráficos (SSD1306): Pequeñas, nítidas y capaces de dibujar gráficos, logotipos y texto de varios tamaños.

Ambas se manejan cómodamente mediante el protocolo I2C que vimos en capítulos anteriores.

Pantallas LCD con adaptador I2C (PCF8574)

Las pantallas LCD clásicas (basadas en el controlador Hitachi HD44780) son una pesadilla de cables: necesitan 6 o más pines GPIO para funcionar.

Por suerte, casi todas las que compramos hoy vienen con una “mochila” negra soldada detrás: un chip PCF8574. Este chip convierte el bus I2C (2 cables) en las múltiples señales que necesita la pantalla.

Conexión

  • VCC: 5V (La mayoría de LCDs se ven muy tenues si las alimentas a 3.3V).
  • GND: Tierra.
  • SDA / SCL: A los pines I2C de tu placa.

Precaución con los voltajes Aunque alimentemos la pantalla a 5V (desde el pin VIN/V5), las líneas SDA y SCL también trabajarán a 5V debido a las resistencias pull-up de la pantalla. El ESP32 suele ser tolerante, pero es recomendable usar un Level Shifter si quieres estar 100% seguro. En la práctica, mucha gente las conecta directamente y funciona, pero conviene conocer el riesgo.

Librería y código

MicroPython no incluye driver para estas LCD por defecto. Necesitamos instalar una librería. La más común es la combinación de lcd_api.py y esp8266_i2c_lcd.py (cuyo nombre engaña, sirve para ESP32 y Pico también).

Podemos instalarla fácilmente si tenemos mip:

import mip
mip.install("github:dhylands/python_lcd_driver/libs/esp8266_i2c_lcd.py")
mip.install("github:dhylands/python_lcd_driver/libs/lcd_api.py")
Copied!

Una vez instaladas, usarlas es muy sencillo:

from machine import SoftI2C, Pin
from esp8266_i2c_lcd import I2cLcd
import time

# Configuración I2C (Ajusta los pines a tu placa)
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=100000)

# Escaneamos para buscar la dirección (suele ser 0x27 o 0x3F)
devices = i2c.scan()
if len(devices) == 0:
    print("No se encontró la pantalla LCD")
else:
    lcd_address = devices[0]
    
    # Inicializamos la LCD (dirección, filas, columnas)
    lcd = I2cLcd(i2c, lcd_address, 2, 16) # 2 filas, 16 columnas

    # Escribir texto
    lcd.putstr("Hola Mundo!")
    
    # Mover el cursor (columna, fila) -> Fila 1 (la de abajo), Columna 0
    lcd.move_to(0, 1)
    lcd.putstr("MicroPython :D")
    
    time.sleep(3)
    
    # Borrar pantalla
    lcd.clear()
    
    # Control de la luz de fondo
    lcd.backlight_off()
    time.sleep(1)
    lcd.backlight_on()
Copied!

Pantallas OLED (SSD1306)

Si buscas algo más moderno, las pantallas OLED son la respuesta. No necesitan luz de fondo (cada píxel emite su propia luz), por lo que consiguen un negro puro y un contraste espectacular.

La mayoría de las baratas (0.96 pulgadas) usan el controlador SSD1306 y tienen una resolución de 128x64 píxeles.

El concepto de framebuffer

A diferencia de la LCD donde enviamos caracteres (“A”, “B”…), la OLED es una matriz de puntos.

MicroPython maneja esto usando un Framebuffer.

  1. Creamos una imagen en la memoria RAM del microcontrolador.
  2. Dibujamos ahí (puntos, líneas, texto).
  3. Cuando terminamos, enviamos toda la imagen de golpe a la pantalla con el comando .show().

Código

El driver ssd1306 sí suele venir incluido en el firmware estándar de MicroPython, así que no hay que instalar nada.

from machine import Pin, SoftI2C
import ssd1306
import time

# Configuración I2C
i2c = SoftI2C(scl=Pin(22), sda=Pin(21))

# Dimensiones de la pantalla
WIDTH = 128
HEIGHT = 64

# Inicializamos el objeto OLED
oled = ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c)

# 1. Limpiar pantalla (llenar de negro)
oled.fill(0) 

# 2. Dibujar cosas en memoria
oled.text("Hola OLED!", 0, 0)      # Texto en (x=0, y=0)
oled.text("Temp: 25.4 C", 0, 10)   # Texto más abajo

# Dibujar formas geométricas
oled.rect(10, 30, 50, 20, 1)       # Rectángulo (x, y, w, h, color)
oled.fill_rect(70, 30, 20, 20, 1)  # Rectángulo relleno
oled.pixel(100, 40, 1)             # Un punto suelto

# 3. ¡IMPORTANTE! Enviar los datos a la pantalla
oled.show()
Copied!

¿Se ve píxelado? La fuente de texto por defecto es de 8x8 píxeles y no se puede cambiar de tamaño fácilmente con el driver básico. Si necesitas fuentes grandes o bonitas, tendrás que usar librerías gráficas avanzadas (como writer.py de Peter Hinch), aunque consumen más memoria.

Invertir colores y trucos

Una característica genial de los OLED es que podemos jugar con los bits.

# Invertir colores (Fondo blanco, texto negro)
oled.fill(1) # Llenamos todo de blanco (encendido)
oled.text("Texto Negro", 0, 0, 0) # El último 0 indica color "apagado"
oled.show()
Copied!

Qué pantalla elegir

CaracterísticaLCD 1602 / 2004OLED SSD1306
TipoCaracteres (Texto)Gráfico (Píxeles)
TamañoGrande y aparatosaMuy pequeña (0.96”)
VisibilidadBuena con luz ambienteExcelente en oscuridad, mala al sol
ConsumoAlto (por la luz de fondo)Muy bajo (depende de píxeles encendidos)
UsoMenús industriales, debugWearables, interfaces modernas
VoltajePreferible 5V3.3V (Perfecta para ESP32/Pico)

Ya tenemos la capacidad de visualizar datos. Ahora podemos combinar lo aprendido: leer un sensor de temperatura (DHT22) y mostrar el valor en una pantalla OLED en tiempo real. ¡Eso ya es un proyecto completo!