Lopaka Basics 05: del navegador a la placa

Dibujaste una pantalla, subiste el código y la pantalla se queda en negro. La pantalla rara vez está rota. Suele ser una de cinco cosas, y cuando corriges la correcta, la pantalla se enciende.
En este episodio llevarás el tablero matutino del episodio 2 del navegador a una placa: instalarás la biblioteca en el IDE de Arduino, crearás el sketch alrededor del código de Lopaka y comprobarás cuánta memoria usa. Después recorrerás las cinco razones por las que una pantalla nueva se queda en negro, y la corrección para cada una.
Lo que vas a crear: un sketch de Arduino que muestra las pantallas Morning y Night del episodio 2 en un OLED SSD1306 de 128×64, más una lista de comprobación para una pantalla en negro. Lo que necesitas: un navegador, el IDE de Arduino gratuito y el proyecto Morning Dashboard del episodio 2. Un Arduino UNO y un módulo OLED son opcionales; ejecutamos el sketch en el simulador del episodio 1.
Cómo habla la placa con la pantalla
Cuatro cables: energía, reloj y datos
Un OLED pequeño como el nuestro necesita cuatro cables. Dos son energía: VCC y GND. Los otros dos son un bus llamado I2C:
- SCL es el reloj. La placa envía un tic constante en él.
- SDA lleva los datos, un bit por tic.

Cada mensaje empieza con una dirección
Otras piezas pueden compartir los mismos dos cables: un sensor de temperatura, un reloj en tiempo real y la pantalla pueden colgar todos de SCL y SDA. Así que cada mensaje empieza con una dirección, y solo la pieza con esa dirección responde.
La mayoría de estas pantallas responden a 0x3C. Algunas responden a 0x3D. En muchos módulos una resistencia diminuta en la parte trasera pone la dirección, junto a una etiqueta como «IIC ADDRESS SELECT 0x78 / 0x7A». Esos dos números son las mismas direcciones duplicadas: 0x3C × 2 = 0x78 y 0x3D × 2 = 0x7A. Tenlo presente para la razón 2 de abajo.

Las pantallas en color más grandes usan SPI
Las pantallas en color como el TFT del episodio 4 suelen usar SPI en su lugar: más cables (MOSI, SCK, CS, DC y RST), mucho más rápido, y un cable de selección, CS, en lugar de una dirección.

Paso 1: copia el código desde Lopaka
Abre el Morning Dashboard del episodio 2: un OLED de 128×64 con la biblioteca U8g2 y dos pantallas, Morning y Night.
Lopaka escribe las funciones de dibujo, una por pantalla: drawMorning() y drawNight(). El sketch alrededor de ellas, con la configuración de pantalla y loop(), lo escribes una vez en el IDE de Arduino.
Haz clic en Copy en la pestaña Morning del panel de código, después cambia a la pestaña Night y copia también eso. Copy toma el código de la pestaña abierta. El código generado es el mismo que en el episodio 2.

Paso 2: instala U8g2
En el IDE de Arduino, abre el Library Manager (el ícono de libros a la izquierda), busca U8g2 y haz clic en INSTALL en la biblioteca U8g2 de oliver. El episodio usó la versión 2.36.19.
Paso 3: elige la placa
Haz clic en Select Board arriba, elige Select other board and port, escribe uno y elige Arduino UNO. Sin una placa conectada, el IDE aún puede compilar el sketch; solo necesitas el puerto para subirlo.
Paso 4: crea el sketch
Un sketch nuevo ya tiene setup() y loop(). Pega el código de Lopaka arriba y después añade tres líneas: incluye la biblioteca, crea la pantalla y arráncala en setup(). En loop(), limpia el búfer, dibuja y envía el búfer a la pantalla:
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
// Paste the Lopaka code here: drawMorning() and drawNight()
void setup() {
// put your setup code here, to run once:
u8g2.begin();
}
void loop() {
// put your main code here, to run repeatedly:
u8g2.clearBuffer();
if (millis() / 3000 % 2) drawNight(); else drawMorning();
u8g2.sendBuffer();
}setup() se ejecuta una vez, cuando la placa arranca. loop() se ejecuta una y otra vez. La línea if muestra cada pantalla durante tres segundos, como en el episodio 2, y el orden limpiar, dibujar, enviar es el búfer de fotogramas del episodio 1.

La línea del constructor describe tu pantalla
La línea larga bajo el #include es el constructor. Describe tu pantalla y cada parte de su nombre significa algo:
- SSD1306: el chip controlador en el módulo.
- 128X64: el tamaño en píxeles.
- NONAME: un módulo genérico, no una marca concreta.
- F: el modo de búfer.
Fes un búfer de fotogramas completo, 1.024 bytes de RAM.1dibuja la pantalla por páginas y necesita solo 128 bytes. - HW_I2C: el cableado, I2C por hardware en los pines SDA y SCL de la placa.
U8G2_R0 significa sin rotación y U8X8_PIN_NONE dice que no hay un pin de reinicio cableado. La biblioteca U8g2 tiene un constructor para cada combinación de chip, tamaño, búfer y cableado. Elige el equivocado y la pantalla se queda en negro.

Paso 5: verifica y ejecuta
Verifica
Haz clic en Verify, la marca de verificación arriba a la izquierda. El IDE compila el sketch e informa:
Sketch uses 15394 bytes (47%) of program storage space. Maximum is 32256 bytes.
Global variables use 1600 bytes (78%) of dynamic memory, leaving 448 bytes for local variables. Maximum is 2048 bytes.El sketch ocupa menos de la mitad de la flash y más de tres cuartos de la RAM. Solo el búfer de fotogramas son 1.024 de los 2.048 bytes del UNO; todo lo demás ocupa 576. Vigila ese 78%: vuelve en la razón 5.

Sube el código, o ejecútalo en el simulador
Con una placa conectada, elige su puerto en el mismo diálogo Select Board y haz clic en Upload, la flecha junto a Verify.
¿Sin placa? Abre el proyecto de simulador del episodio 1: un Arduino UNO con una pantalla SSD1306 cableada GND a GND, VCC a 5V, SDA a A4 y SCL a A5, y la biblioteca U8g2. Pega el sketch y pulsa Play. La pantalla muestra la pantalla Morning y cambia a Night cada tres segundos.

Cinco razones por las que una pantalla se queda en negro
Las comprobaciones van de fuera hacia dentro: cables, dirección, chip, código y memoria. En cada una rompemos la configuración que funciona en el simulador, vemos la pantalla ponerse negra y la arreglamos.
1. Los cables
En un UNO, SDA va a A4 y SCL va a A5. Intercámbialos y la placa está hablando con nadie: la pantalla se queda en negro.
Comprueba también energía y tierra. Otras placas usan otros pines: en la mayoría de placas ESP32, SDA es el pin 21 y SCL es el pin 22.

2. La dirección
La mayoría de los módulos responden a 0x3C, algunos a 0x3D. U8g2 habla a 0x3C a menos que le digas otra cosa. Si el módulo está en 0x3D, nada responde y la pantalla se queda en negro.
Para averiguar cuál tienes, ejecuta un sketch escáner I2C. Pregunta a cada dirección del bus e imprime las que responden:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("Scanning I2C...");
for (byte a = 1; a < 127; a++) {
Wire.beginTransmission(a);
if (Wire.endTransmission() == 0) {
Serial.print("Found a device at 0x");
Serial.println(a, HEX);
}
}
Serial.println("Done.");
}
void loop() {}Súbelo y abre el Serial Monitor a 9600 baudios.

Después pon la dirección en tu sketch de tablero, antes de begin():
void setup() {
u8g2.setI2CAddress(0x3D * 2);
u8g2.begin();
}U8g2 quiere la dirección duplicada, así que 0x3D se convierte en 0x3D * 2, 0x7A: el mismo número impreso en la parte trasera del módulo.

3. El chip
Dos módulos pueden parecer exactamente iguales y usar controladores distintos. La mayoría de las pantallas pequeñas de 0,96 pulgadas usan el SSD1306. Muchas de 1,3 pulgadas usan el SH1106. Ejecuta código SSD1306 en un SH1106 y obtienes una pantalla en blanco o una franja de ruido en el borde.
La corrección es el nombre del chip en el constructor:
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
4. El código
U8g2 dibuja en un búfer en memoria y solo sendBuffer() mueve la imagen a la pantalla. Olvida esa línea, u olvida u8g2.begin() en setup(), y la pantalla se queda oscura. El sketch sigue compilando sin error, así que comprueba primero estas líneas:
u8g2.begin(); // in setup()
u8g2.clearBuffer(); // in loop()
drawMorning();
u8g2.sendBuffer();
5. La memoria
¿Recuerdas ese 78%? Un UNO tiene 2.048 bytes de RAM y el búfer de fotogramas ocupa la mitad.
Lopaka mantiene las imágenes en flash con PROGMEM: el interruptor Declare as PROGMEM junto al código está activado por defecto y los arrays reciben U8X8_PROGMEM. Desactívalo y las imágenes se mueven a la RAM. Solo la luna son 48 × 48 / 8 = 288 bytes y las cuatro imágenes del tablero ocupan 416. Ahora el sketch usa 2.016 bytes, el 98% de la RAM, con 32 bytes libres para todo lo que el programa hace mientras se ejecuta. Sigue compilando, pero la pantalla se deshace: en el simulador, el texto desaparece y las imágenes se rompen.

Deja PROGMEM activado. Si aún te falta RAM, cambia a modo por páginas: pon un 1 en lugar de la F en el constructor y el búfer se reduce de 1.024 bytes a 128.
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);En modo por páginas la biblioteca dibuja la pantalla en ocho tiras, una tras otra, así que loop() también cambia. En lugar de clearBuffer() y sendBuffer(), el dibujo va dentro de un bucle firstPage() / nextPage():
void loop() {
u8g2.firstPage();
do {
if (millis() / 3000 % 2) drawNight(); else drawMorning();
} while (u8g2.nextPage());
}Con el modo por páginas, el mismo tablero usa 704 bytes, el 34% de la RAM.

Resumen
- Lopaka dibuja la pantalla, el IDE crea el sketch alrededor: instala U8g2, elige la placa, pega las funciones de dibujo y añade el include, el constructor,
begin()y el bucle limpiar, dibujar, enviar. - Una línea de constructor describe tu pantalla: chip, tamaño, búfer y cableado.
- ¿Pantalla en negro? Comprueba cinco cosas: los cables, la dirección, el chip, el código y la memoria.
Próximo episodio: Screens & Menus. Más de una pantalla, con menús y un botón. Lee el episodio 6 o míralo en YouTube.
¿Listo para probar? Abre Lopaka y pon tu pantalla en una placa real.