Pantalla OLED con ESP32 e I2C

Resumen

Programar una pantalla OLED con ESP32 es más sencillo de lo que parece cuando aprovechas los componentes que ofrece ESP-IDF. Aquí aprendes a configurar la librería SSD1306, establecer la comunicación I2C y mostrar tu primer mensaje Hola, mundo en una pantalla de 128x64 píxeles.

Este flujo te sirve si estás iniciando con microcontroladores ESP32 y quieres dominar el control de displays embebidos paso a paso.

Qué necesitas saber sobre la pantalla OLED y el protocolo I2C

La tarjeta de desarrollo usa una pantalla OLED de 128x64 píxeles controlada por el chip SSD1306. Si tu pantalla tiene otras dimensiones, revisa la documentación técnica para ajustar la configuración.

La comunicación entre el microcontrolador y el chip de la pantalla se hace mediante I2C, un protocolo que utiliza dos líneas de voltaje (SDA y SCL) para enviar y recibir datos en binario. También existe la opción de usar SPI si tu hardware lo requiere [02:30].

¿Qué es el protocolo I2C? Es un protocolo de comunicación entre chips que usa dos líneas de señal, una para datos (SDA) y otra para el reloj (SCL), permitiendo que un chip principal controle a otros dispositivos como pantallas o sensores.

Cómo se estructura la librería SSD1306 en ESP-IDF

La librería que instalaste en la clase anterior trae varios archivos clave que vale la pena entender antes de codear.

Qué archivos componen el componente SSD1306

  • CMakeLists.txt: define los archivos de C que se compilan e incluyen en el proyecto.
  • font8x8_basic.h: contiene la tipografía usada para dibujar caracteres en la pantalla [03:45].
  • Kconfig.projbuild: agrega un menú dentro de menuconfig llamado SSD1306 Configuration donde defines tipo de conexión (I2C o SPI), tamaño del panel (128x64 o 128x32), orientación de pantalla y los pines de comunicación [04:10].
  • ssd1306_i2c.c y ssd1306_spi.c: implementan la comunicación según el protocolo elegido.
  • ssd1306.h y ssd1306.c: exponen las funciones públicas y las constantes de configuración.

Qué funciones ofrece la librería

La función estrella es la de inicialización, que recibe un puntero del tipo SSD1306_t, el ancho y el alto en píxeles. Además tienes funciones para leer dimensiones, paginar píxeles agrupándolos en renglones y mucho más [05:30].

Las más útiles para empezar son tres:

  • display_text: muestra un texto en pantalla.
  • clear_screen: limpia toda la pantalla.
  • clear_line: limpia un renglón específico.

También puedes hacer scroll horizontal cuando un texto no cabe completo y dibujar imágenes en píxeles, lo cual amplía mucho lo que puedes lograr.

Cómo programar el Hola Mundo paso a paso

Con la librería entendida, el código se vuelve directo. Aquí va la receta completa.

Cómo importar la librería e inicializar la pantalla

Lo primero es incluir la cabecera. Como ya configuraste la carpeta components, no debería marcar errores al compilar.

c #include "ssd1306.h"

Luego defines un puntero del tipo SSD1306_t que almacenará toda la configuración de la pantalla. Este puntero te sirve para enviar órdenes y leer datos.

c SSD1306_t screen;

Antes de dibujar nada, configura el canal I2C indicándole al ESP32 que actúe como master y leyendo los pines desde la configuración:

c i2c_master_init(&screen, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO); ssd1306_init(&screen, 128, 64);

La variable CONFIG_SDA_GPIO corresponde al pin de datos, CONFIG_SCL_GPIO al pin de reloj, y CONFIG_RESET_GPIO al pin de reinicio de la pantalla [10:15].

Cómo limpiar la pantalla y ajustar el contraste

Siempre que inicies, conviene limpiar la pantalla porque puede traer píxeles encendidos de un proceso anterior. La función ssd1306_clear_screen recibe el puntero y un booleano que indica si la pantalla está invertida.

c ssd1306_clear_screen(&screen, false); ssd1306_contrast(&screen, 0xFF);

El valor 0xFF representa en hexadecimal todos los bits encendidos, equivalente a 255, el contraste máximo. Esto asegura que los píxeles blancos se vean nítidos y los apagados queden completamente oscuros.

¿Por qué usar 0xFF para el contraste? Porque representa el byte completo lleno de unos, es decir, el porcentaje más alto de contraste posible para la pantalla.

Cómo escribir un texto en una línea específica

Antes de escribir un texto, limpia el renglón con ssd1306_clear_line. Esto evita que caracteres viejos se mezclen con los nuevos cuando el texto nuevo es más corto que el anterior.

c ssd1306_clear_line(&screen, 0, false); ssd1306_display_text(&screen, 0, "Hola, mundo", 11, false);

La función display_text recibe el puntero, la página o renglón donde dibujar (empezando en cero), la cadena, su longitud en caracteres y si la pantalla está invertida. Sin el largo correcto, la librería no sabe cuántos píxeles iluminar [13:50].

¿Por qué hay que limpiar la línea antes de escribir? Porque la librería solo sobrescribe los caracteres nuevos. Si antes había un texto más largo, los caracteres sobrantes permanecen y se mezclan con el nuevo mensaje.

Por qué este flujo se reutiliza con LoRa y otros componentes

Una vez compilas y no aparecen errores, confirmas que el módulo se enlazó correctamente y que tu código está listo para grabarse en la tarjeta. La belleza de los componentes de ESP-IDF es que la estructura se repite: importas la librería, defines variables de control, inicializas el protocolo y llamas a las funciones disponibles.

Esta misma lógica te servirá para programar el módulo LoRa en las próximas clases, ya que sigue exactamente la misma filosofía de componentes reutilizables. ¿Qué animaciones o pantallas creativas se te ocurren probar primero? Compártelo en los comentarios.