Guía de U8g2 para pantallas OLED y LCD con Arduino
Esta guía lleva un proyecto U8g2 nuevo desde un lienzo vacío de Lopaka hasta un sketch de Arduino que funciona. Lopaka crea el código de dibujo; tú conectas e inicializas la pantalla, eliges cómo se gestiona el búfer y decides cuándo se muestra cada pantalla.
¿Qué es U8g2?
U8g2 es una biblioteca gráfica para pantallas OLED y LCD monocromáticas. Admite muchos controladores, primitivas de dibujo, mapas de bits y una gran colección de fuentes. Lopaka genera código para la API gráfica de U8g2, no para la API U8x8, que solo maneja texto.
Usa el tutorial de configuración y la lista de constructores oficiales para confirmar que U8g2 es compatible con tu pantalla exacta.
Antes de empezar
Necesitas:
- Un microcontrolador y una pantalla monocromática compatibles con U8g2.
- El nombre del controlador de la pantalla, la resolución y la interfaz: por ejemplo, SSD1306, 128×64, I2C por hardware.
- La hoja de datos de la pantalla o la guía de cableado del fabricante.
- Un proyecto compatible con Arduino que pueda compilar y subir un sketch básico.
Advertencia
Lopaka no detecta tu hardware. Dos módulos que parecen iguales pueden usar controladores, direcciones, asignaciones de pines u offsets de pantalla distintos.
Paso 0: Instalar y probar U8g2
En Arduino IDE, abre Tools → Manage Libraries, busca U8g2 e instala la biblioteca de olikraus. Este es el método de instalación que documenta el repositorio oficial de U8g2.
Para una instalación manual en Arduino, descarga la distribución oficial de U8g2 para Arduino y agrega su ZIP con Sketch → Include Library → Add .ZIP Library. Otras toolchains pueden usar la misma distribución oficial mediante su sistema de dependencias de bibliotecas. Prefiere una versión publicada, salvo que necesites específicamente un cambio que todavía no se haya publicado.
Antes de agregar código de Lopaka, compila y sube uno de los ejemplos de U8g2 para tu pantalla. Si el ejemplo funciona, el constructor, el cableado y la instalación de la biblioteca son correctos.
Paso 1: Elegir el constructor de la pantalla
El nombre del constructor define cuatro aspectos importantes:
| Parte | Ejemplo | Significado |
|---|---|---|
| Controlador y pantalla | SSD1306_128X64_NONAME | Familia de hardware y resolución |
| Búfer | F, 1 o 2 | Búfer de pantalla completa o de página |
| Interfaz | HW_I2C, SW_I2C, 4W_HW_SPI, etc. | Bus e implementación |
| Argumentos | U8G2_R0, pines de reset y del bus | Rotación y cableado |
Por ejemplo:
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
U8G2_R0,
U8X8_PIN_NONE
);Este es solo un constructor de ejemplo para una pantalla SSD1306 de 128×64 con I2C por hardware. Reemplázalo por el constructor y los argumentos exactos de la lista de configuración para C++ oficial.
¿Búfer completo o búfer de página?
- Un constructor que contiene
_F_guarda la imagen completa de la pantalla en la RAM. Dibuja entreclearBuffer()ysendBuffer(). - Un constructor que contiene
_1_o_2_usa un búfer de página más pequeño. Coloca la función de dibujo completa dentro del bucle de imagenfirstPage()/nextPage().
El modo de búfer completo es más simple y rápido, pero usa más RAM. Para una imagen de 128×64 a un bit, el búfer de píxeles ocupa por sí solo 1024 bytes. El modo de página usa menos RAM, pero vuelve a dibujar la misma imagen para cada página. Consulta la guía de modos de búfer de U8g2.
Paso 2: Crear el proyecto de Lopaka
- Abre lopaka.app y crea un proyecto.
- Selecciona U8g2 como plataforma.
- Ajusta Tamaño de pantalla al ancho y alto lógicos de la pantalla. Para una pantalla de 128×64 sin rotar, usa
128 × 64. - Mantén el fondo negro predeterminado. La salida de U8g2 es de un bit por píxel, así que los diseños de Lopaka distinguen entre primer plano y fondo en lugar de usar colores RGB.
El tamaño del lienzo de Lopaka define la superficie de diseño y la referencia de coordenadas; no elige un constructor de U8g2 ni configura la pantalla física.
Paso 3: Diseñar una pantalla
Usa el editor para colocar texto, imágenes y primitivas de dibujo. La posición (0, 0) es la esquina superior izquierda del lienzo. Cambia el nombre de las capas antes de exportar: los nombres se convierten en comentarios, identificadores de imágenes, encabezados de animaciones y nombres opcionales de variables.
Los proyectos U8g2 de Lopaka generan estos elementos:
| Capa de Lopaka | Salida de U8g2 para Arduino |
|---|---|
| Línea | drawLine() |
| Rectángulo | drawFrame() / drawBox() |
| Rectángulo redondeado | drawRFrame() / drawRBox() |
| Elipse | drawEllipse() / drawFilledEllipse() |
| Triángulo | drawTriangle(); siempre relleno en el inspector de U8g2 de Lopaka |
| Polígono | Una función auxiliar hecha con llamadas drawLine() cerradas; solo contorno |
| Texto | setFont() más drawStr() o drawUTF8() |
| Capa de pintura, ícono o imagen importada | Un arreglo XBM monocromático más drawXBM() o drawXBMP() |
| Animación | Datos o encabezado de fotogramas más funciones auxiliares para elegir y dibujarlos |
Primer plano, fondo e inversión
El proyecto U8g2 es monocromático, así que el inspector no muestra un selector de color RGB. Las capas normales encienden píxeles; las capas con Invertido (XOR) usan el color de dibujo 2 (XOR) de U8g2. Lopaka también genera modos transparentes de fuente y de mapa de bits, para que los píxeles vacíos del texto y de las imágenes no borren las capas que están debajo.
U8g2 advierte que no todas las primitivas admiten XOR, incluidas las de elipse. Comprueba las formas invertidas en la pantalla real; consulta setDrawColor.
Posición y línea base del texto
Las coordenadas de las formas usan los orígenes habituales de U8g2. El texto usa la línea base de la fuente, no el borde superior de las letras visibles. Por eso, cambiar de fuente puede alterar la alineación vertical aparente aunque la capa de texto mantenga la misma posición.
El texto puede girarse 0°, 90°, 180° o 270°. Lopaka genera setFontDirection() cuando hace falta. Consulta la referencia de la API de U8g2 para los detalles de las coordenadas.
Paso 4: Configurar el código generado
Abre Ajustes de código y elige Arduino (Cpp) para un sketch de Arduino. U8g2 también tiene la opción de sintaxis ESP-IDF (C) para proyectos que ya usan la interfaz en C de U8g2; no es una aplicación ESP-IDF completa ni un port de hardware.
| Ajuste | Qué cambia en U8g2 |
|---|---|
| Función contenedora | Envuelve la pantalla activa en void draw{ScreenName}(void) |
| Declarar como PROGMEM | Usa U8X8_PROGMEM y drawXBMP() en las declaraciones de mapas de bits para Arduino |
| Incluir fuentes | Incluye los encabezados descargados de las fuentes personalizadas; las fuentes integradas de U8g2 no necesitan encabezado |
| Declarar imágenes | Genera los arreglos de mapa de bits que usan las capas de pintura y de imagen |
| Incluir archivos de imagen | Genera #include "image_<Name>_bits.h" en lugar de los arreglos de mapa de bits en línea |
| Funciones auxiliares de animación | Incluye los encabezados de animación descargados y genera funciones auxiliares de temporización y dibujo |
| Declarar variables | Genera declaraciones para las propiedades de capa marcadas como variables |
| Comentarios, títulos de capas | Agrega comentarios con el nombre de cada capa a la salida estática |
| Borrar/rellenar pantalla | Empieza el bloque de dibujo con u8g2.clearBuffer() (Arduino) o u8g2_ClearBuffer() (ESP-IDF); consulta la nota de más abajo |
En Arduino, mantén activadas todas las opciones excepto Borrar/rellenar pantalla.
Borrar/rellenar pantalla en Arduino
En la plantilla de Arduino, Borrar/rellenar pantalla está desactivada de forma predeterminada. Si la activas, draw{ScreenName}() empieza con u8g2.clearBuffer(), que borra todo lo que tu sketch haya dibujado en el búfer antes de llamarla. Déjala desactivada si tu loop() ya limpia el búfer o dibuja otro contenido antes. Se omite cuando Funciones auxiliares de animación está activada, porque el bucle firstPage()/nextPage() de la animación ya limpia cada página. La plantilla de ESP-IDF la mantiene activada de forma predeterminada.
Paso 5: Exportar fuentes e imágenes
Fuentes integradas
Lopaka conoce la lista de fuentes integradas de U8g2 y adapta el código generado a la fuente seleccionada. Cuando una fuente viene integrada en U8g2, Lopaka usa directamente su símbolo de la biblioteca y no genera ni ofrece para descargar un encabezado de fuente aparte. Por ejemplo:
u8g2.setFont(u8g2_font_6x10_tr);Si una fuente no está en la lista de integradas, Lopaka la trata como fuente personalizada, genera un único include para su encabezado y muestra ese encabezado en Ajustes de código → Fuentes para que lo descargues.
Los tamaños de las fuentes integradas son fijos; elige otra fuente para agrandar o achicar el texto. Usa la lista oficial de fuentes de U8g2 para revisar qué caracteres incluye cada una.
Fuentes personalizadas
Los proyectos U8g2 aceptan fuentes BDF y pueden importar TTF, OTF o WOFF con el asistente de fuentes de tamaño fijo de Lopaka. En Ajustes de código → Fuentes:
- Descarga todos los archivos
.hpersonalizados de la lista. - Coloca los encabezados junto a tu sketch o al código fuente generado.
- Mantén activada Incluir fuentes para que se conserven las líneas
#include "Font_Name.h"generadas.
Incluir solo los glifos usados crea un encabezado más pequeño con los caracteres que usan en ese momento las capas de texto con esa fuente. Si el valor de un texto es una variable en tiempo de ejecución, Lopaka exporta la fuente personalizada completa, porque no puede prever qué caracteres se usarán.
Imágenes y animaciones
Las imágenes estáticas se convierten en datos XBM de un bit y pueden declararse directamente en el código copiado. Con Declarar como PROGMEM activada, Lopaka usa U8X8_PROGMEM y drawXBMP(), de acuerdo con las indicaciones de U8g2 sobre mapas de bits en PROGMEM.
Ajustes de código → Imágenes muestra cada imagen como image_<Name>_bits.h, con exactamente los bytes XBM que recibe la llamada de dibujo. Activa Incluir archivos de imagen para generar #include "image_<Name>_bits.h" en lugar del arreglo y dejar los píxeles en el encabezado descargado.
Las animaciones también son monocromáticas. Descarga todos los archivos .h de la lista Animaciones, colócalos junto al sketch y conserva el include y el código auxiliar generados. La función auxiliar de Arduino elige los fotogramas con millis(). Sigues siendo responsable de llamar a la función auxiliar de actualización y de volver a dibujar la pantalla completa con el bucle de búfer correcto.
Advertencia
La salida de animación puede incluir código inicial de setup() y loop(). Incorpora a tu sketch sus includes, la actualización de fotogramas y las funciones auxiliares de dibujo, y luego usa el patrón de refresco con búfer completo o con búfer de página de esta guía. No dejes un segundo setup() ni un segundo loop().
Paso 6: Copiar e integrar el código
Crea una pantalla llamada Main, agrega una capa de texto y un marco, y haz clic en Copiar en el panel de código de Lopaka. Una función de dibujo generada típica se ve así:
void drawMain(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(8, 18, "Hello!");
u8g2.drawFrame(0, 0, 128, 64);
}Tu código usará el nombre de tu pantalla y tus propias capas, fuentes y coordenadas.
Sketch mínimo con búfer completo
Usa este patrón solo con un constructor _F_:
#include <Arduino.h>
#include <Wire.h>
#include <U8g2lib.h>
// Hardware-specific: replace with the constructor for your display.
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
U8G2_R0,
U8X8_PIN_NONE
);
// Paste Lopaka asset declarations, custom-font includes, helpers,
// and the generated drawMain() function here.
void drawMain(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(8, 18, "Hello!");
u8g2.drawFrame(0, 0, 128, 64);
}
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.clearBuffer();
drawMain();
u8g2.sendBuffer();
}Alternativa con búfer de página
Usa este patrón de bucle de imagen con un constructor _1_ o _2_:
void loop(void) {
u8g2.firstPage();
do {
drawMain();
} while (u8g2.nextPage());
}En modo de página, no actualices el estado de la interfaz dentro de drawMain(). U8g2 la llama más de una vez para construir un fotograma, y cada pasada debe dibujar la misma imagen. Actualiza los valores de los sensores, el estado de navegación y la selección del fotograma de animación antes de firstPage().
Paso 7: Agregar datos en tiempo de ejecución y más pantallas
Para que un valor sea dinámico, selecciona su propiedad en el inspector, activa su interruptor de variable y mantén activada Declarar variables. Lopaka reemplaza entonces el literal por una declaración con un nombre basado en el de la capa. Tu aplicación puede actualizar ese valor antes del siguiente redibujado.
Cada pantalla de Lopaka se exporta por separado, y su título se convierte en el nombre de la función de dibujo. Copia la función de cada pantalla en el proyecto, combina los includes y recursos compartidos para que se declaren una sola vez y luego elige qué función llamar:
enum Screen { MAIN, DETAILS };
Screen currentScreen = MAIN;
void drawCurrentScreen(void) {
if (currentScreen == MAIN) {
drawMain();
} else {
drawDetails();
}
}Lopaka no genera navegación entre pantallas, manejo de botones, menús, lecturas de sensores ni estado de la aplicación.
Qué hace Lopaka y qué haces tú
| Lopaka se encarga de | Tú te encargas de |
|---|---|
| Distribución de píxeles y orden de las capas | Cableado, voltaje y asignación de pines de la pantalla |
| Llamadas de dibujo de U8g2 para las capas compatibles | Constructor exacto de controlador, interfaz y búfer |
| Referencias a fuentes integradas | Instalar U8g2 y la toolchain de la placa |
| Conversión de fuentes personalizadas y encabezados descargables | Mantener los encabezados personalizados junto al código fuente |
| Declaraciones de mapas de bits de un bit | Presupuesto de RAM y flash, y elección del búfer |
| Variables opcionales y funciones auxiliares de animación | begin(), bucle de refresco, temporización y estado de la aplicación |
| Una función de dibujo con nombre por cada pantalla exportada | Entradas, navegación, sensores y cuándo volver a dibujar |
Compilar, subir e iterar
- Compila antes de subir. Resuelve primero cada encabezado o símbolo que falte.
- Sube el sketch y compara la pantalla física con el lienzo de Lopaka.
- Ajusta el constructor, la rotación, el tamaño del lienzo o la posición de las capas según haga falta.
- Cuando cambie el diseño, reemplaza toda la sección generada en lugar de editar llamadas generadas sueltas en varios lugares.
Mantén el código de hardware y de la aplicación fuera de la sección generada, para que una nueva exportación no lo sobrescriba:
// BEGIN LOPAKA GENERATED CODE
// Replace this entire block after exporting again.
// END LOPAKA GENERATED CODESolución de problemas
La pantalla está en blanco
- Primero sube un ejemplo oficial de U8g2 con el mismo constructor. Si también queda en blanco, revisa la alimentación, la tierra, el cableado, el controlador, el pin de reset y la interfaz.
- Confirma que
u8g2.begin()se ejecuta una sola vez. - Confirma que el dibujo ocurre entre
clearBuffer()/sendBuffer()con_F_, o dentro del bucle completofirstPage()/nextPage()con_1_y_2_. - Con I2C, escanea el bus y compara el resultado con la documentación del módulo. Si llamas a
setI2CAddress(), U8g2 espera la dirección multiplicada por dos y la llamada debe hacerse antes debegin(); consulta la referencia oficial.
La imagen aparece desplazada, recortada, reflejada o girada
Comprueba que el lienzo de Lopaka coincida con el tamaño lógico de la pantalla definido por el constructor. Elige la variante exacta de controlador y pantalla: algunos módulos tienen una RAM de controlador más ancha que el panel visible. Usa de U8G2_R0 a U8G2_R3 en el constructor para rotar la pantalla y luego mantén las dimensiones de Lopaka acordes con esa orientación.
Los colores o las formas superpuestas se ven invertidos
La salida de U8g2 es de un bit, no en escala de grises ni RGB. Desactiva Invertido (XOR) en la capa si no querías usar XOR. No todas las primitivas de U8g2 admiten XOR, así que comprueba las elipses invertidas en el hardware.
Una fuente o un símbolo no está definido
- Los nombres de las fuentes integradas deben existir en la versión de U8g2 instalada y contener los glifos que usas.
- Para una fuente personalizada, descarga su
.h, guárdalo junto al código fuente y mantén activada Incluir fuentes. - Si algunos caracteres salen en blanco, desactiva Incluir solo los glifos usados y vuelve a exportar la fuente personalizada, sobre todo si el texto cambia en tiempo de ejecución.
El sketch se queda sin memoria
Prueba un constructor con búfer de página _1_ o _2_, imágenes más pequeñas, menos fotogramas de animación o fuentes personalizadas que contengan solo los glifos necesarios. Las fuentes integradas y los recursos ocupan flash; el búfer completo de la pantalla ocupa RAM.
Las imágenes se ven toscas o invertidas
Las imágenes de U8g2 son de un bit, así que el tamaño, el recorte, el contraste, el umbral y el tramado que elijas importan. Vuelve a abrir el asistente de imágenes de Lopaka y revisa la vista previa al tamaño final en píxeles. Mantén Declarar como PROGMEM coherente con la declaración generada y la llamada drawXBMP().
El modo de página parpadea o muestra solo parte de la pantalla
Llama a la función de dibujo completa dentro del bucle de imagen do / while. No dibujes algunas capas antes de firstPage(), no cambies valores entre páginas y no llames solo a firstPage() sin nextPage().
Preguntas frecuentes
¿Lopaka configura mi pantalla SSD1306 o SH1106?
No. Lopaka genera código de dibujo. Tú eliges el constructor, el bus, los pines, la dirección, la rotación, el modo de búfer y la inicialización que correspondan.
¿Puedo usar U8x8 en su lugar?
No con la salida U8g2 de Lopaka. U8x8 es una API aparte, solo de caracteres, y no admite las primitivas gráficas que genera Lopaka.
¿Puede Lopaka generar código U8g2 a color?
No. La plataforma U8g2 de Lopaka es monocromática. Para una pantalla RGB, elige una plataforma a color como TFT_eSPI o ArduinoGFX.
¿La exportación ESP-IDF (C) es un proyecto de firmware completo?
No. Genera código de dibujo para la interfaz en C y los recursos. Tu proyecto ESP-IDF debe configurar la estructura de U8g2, los callbacks de GPIO y del bus, el bucle de tareas, la inicialización y la integración con la plataforma.