Lopaka Basics 05: do navegador à placa

Você desenhou uma tela, enviou o código, e o display fica preto. O display raramente está quebrado. Geralmente é uma de cinco coisas, e quando você corrige a certa, a tela acende.
Neste episódio, você vai levar o painel matinal do episódio 2 do navegador para uma placa: instalar a biblioteca na Arduino IDE, montar o sketch ao redor do código do Lopaka e conferir quanta memória ele usa. Depois você vai passar pelos cinco motivos para um display novo ficar preto, e a correção para cada um.
O que você vai construir: um sketch do Arduino que mostra as telas Morning e Night do episódio 2 em um OLED SSD1306 de 128×64, além de uma lista de verificação para uma tela preta. Do que você precisa: um navegador, a Arduino IDE gratuita e o projeto Morning Dashboard do episódio 2. Um Arduino UNO e um módulo OLED são opcionais; executamos o sketch no simulador do episódio 1.
Como a placa conversa com a tela
Quatro fios: energia, clock e dados
Um OLED pequeno como o nosso precisa de quatro fios. Dois são energia: VCC e GND. Os outros dois são um barramento chamado I2C:
- SCL é o clock. A placa envia um tique constante nele.
- SDA carrega os dados, um bit por tique.

Cada mensagem começa com um endereço
Outras peças podem compartilhar os mesmos dois fios: um sensor de temperatura, um relógio de tempo real e o display podem todos ficar em SCL e SDA. Então cada mensagem começa com um endereço, e só a peça com aquele endereço responde.
A maioria desses displays responde a 0x3C. Alguns respondem a 0x3D. Em muitos módulos, um resistor minúsculo na parte de trás define o endereço, ao lado de uma etiqueta como "IIC ADDRESS SELECT 0x78 / 0x7A". Esses dois números são os mesmos endereços dobrados: 0x3C × 2 = 0x78 e 0x3D × 2 = 0x7A. Lembre disso para o motivo 2 abaixo.

Telas coloridas maiores usam SPI
Telas coloridas como o TFT do episódio 4 geralmente usam SPI: mais fios (MOSI, SCK, CS, DC e RST), muito mais rápido, e um fio de seleção, CS, em vez de um endereço.

Etapa 1: copie o código do Lopaka
Abra o Morning Dashboard do episódio 2: um OLED de 128×64 com a biblioteca U8g2 e duas telas, Morning e Night.
O Lopaka escreve as funções de desenho, uma por tela: drawMorning() e drawNight(). O sketch ao redor delas, com a configuração do display e loop(), você escreve uma vez na Arduino IDE.
Clique em Copiar na guia Morning do painel de código, depois mude para a guia Night e copie aquela também. O Copiar pega o código da guia aberta. O código gerado é o mesmo do episódio 2.

Etapa 2: instale a U8g2
Na Arduino IDE, abra o Library Manager (o ícone de livros à esquerda), busque U8g2 e clique em INSTALL na biblioteca U8g2 de oliver. O episódio usou a versão 2.36.19.
Etapa 3: escolha a placa
Clique em Select Board no topo, escolha Select other board and port, digite uno e escolha Arduino UNO. Sem uma placa conectada, a IDE ainda consegue compilar o sketch; você só precisa da porta para enviar.
Etapa 4: monte o sketch
Um sketch novo já tem setup() e loop(). Cole o código do Lopaka no topo e depois adicione três linhas: inclua a biblioteca, crie o display e inicie ele em setup(). Em loop(), limpe o buffer, desenhe e envie o buffer para a tela:
#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() executa uma vez, quando a placa começa. loop() executa de novo e de novo. A linha if mostra cada tela por três segundos, como no episódio 2, e a ordem limpar, desenhar, enviar é o buffer de quadro do episódio 1.

A linha do construtor descreve o seu display
A linha longa sob o #include é o construtor. Ela descreve o seu display, e cada parte do nome dela significa algo:
- SSD1306: o chip controlador no módulo.
- 128X64: o tamanho em pixels.
- NONAME: um módulo genérico, e não uma marca específica.
- F: o modo de buffer.
Fé um buffer de quadro completo, 1.024 bytes de RAM.1desenha a tela em páginas e precisa de só 128 bytes. - HW_I2C: a fiação, I2C de hardware nos pinos SDA e SCL da placa.
U8G2_R0 significa sem rotação, e U8X8_PIN_NONE diz que nenhum pino de reset está ligado. A biblioteca U8g2 tem um construtor para cada combinação de chip, tamanho, buffer e fiação. Escolha o errado, e a tela fica preta.

Etapa 5: verifique e execute
Verifique
Clique em Verify, a marca de seleção no canto superior esquerdo. A IDE compila o 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.O sketch ocupa menos da metade da flash e mais de três quartos da RAM. O buffer de quadro sozinho tem 1.024 dos 2.048 bytes do UNO; todo o resto ocupa 576. Fique de olho nesses 78%: eles voltam no motivo 5.

Envie ou execute no simulador
Com uma placa conectada, escolha a porta dela na mesma caixa de diálogo Select Board e clique em Upload, a seta ao lado de Verify.
Sem placa? Abra o projeto do simulador do episódio 1: um Arduino UNO com um display SSD1306 ligado GND ao GND, VCC ao 5V, SDA ao A4 e SCL ao A5, e a biblioteca U8g2. Cole o sketch e pressione Play. O display mostra a tela Morning e muda para Night a cada três segundos.

Cinco motivos para uma tela ficar preta
As verificações vão de fora para dentro: fios, endereço, chip, código e memória. Em cada uma, quebramos a configuração que funciona no simulador, vemos a tela ficar preta e corrigimos.
1. Os fios
Em um UNO, SDA vai para A4 e SCL vai para A5. Troque eles, e a placa está falando com ninguém: a tela fica preta.
Confira energia e terra também. Outras placas usam outros pinos: na maioria das placas ESP32, SDA é o pino 21 e SCL é o pino 22.

2. O endereço
A maioria dos módulos responde a 0x3C, alguns a 0x3D. A U8g2 conversa com 0x3C, a menos que você diga o contrário. Se o módulo estiver definido como 0x3D, nada responde, e a tela fica preta.
Para descobrir qual você tem, execute um sketch scanner I2C. Ele pergunta a cada endereço no barramento e imprime os que respondem:
#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() {}Envie ele e abra o Serial Monitor a 9600 baud.

Depois defina o endereço no seu sketch do painel, antes de begin():
void setup() {
u8g2.setI2CAddress(0x3D * 2);
u8g2.begin();
}A U8g2 quer o endereço dobrado, então 0x3D vira 0x3D * 2, 0x7A: o mesmo número impresso na parte de trás do módulo.

3. O chip
Dois módulos podem parecer exatamente iguais e usar controladores diferentes. A maioria das telas pequenas de 0,96 polegada usa o SSD1306. Muitas de 1,3 polegada usam o SH1106. Execute código SSD1306 em um SH1106, e você obtém uma tela em branco ou uma faixa de ruído na borda.
A correção é o nome do chip no construtor:
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
4. O código
A U8g2 desenha em um buffer na memória, e só sendBuffer() move a imagem para a tela. Esqueça essa linha, ou esqueça u8g2.begin() em setup(), e a tela fica escura. O sketch ainda compila sem erro, então confira estas linhas primeiro:
u8g2.begin(); // in setup()
u8g2.clearBuffer(); // in loop()
drawMorning();
u8g2.sendBuffer();
5. A memória
Lembra daqueles 78%? Um UNO tem 2.048 bytes de RAM, e o buffer de quadro ocupa metade.
O Lopaka mantém imagens na flash com PROGMEM: o interruptor Declare as PROGMEM ao lado do código vem ativado por padrão, e os arrays recebem U8X8_PROGMEM. Desative ele, e as imagens se movem para a RAM. A lua sozinha tem 48 × 48 / 8 = 288 bytes, e as quatro imagens do painel ocupam 416. Agora o sketch usa 2.016 bytes, 98% da RAM, com 32 bytes restantes para tudo o que o programa faz enquanto executa. Ele ainda compila, mas a tela desmorona: no simulador, o texto some e as imagens quebram.

Deixe o PROGMEM ativado. Se mesmo assim faltar RAM, mude para o modo por páginas: coloque um 1 em vez do F no construtor, e o buffer encolhe de 1.024 bytes para 128.
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);No modo por páginas, a biblioteca desenha a tela em oito faixas, uma depois da outra, então loop() também muda. Em vez de clearBuffer() e sendBuffer(), o desenho vai dentro de um loop firstPage() / nextPage():
void loop() {
u8g2.firstPage();
do {
if (millis() / 3000 % 2) drawNight(); else drawMorning();
} while (u8g2.nextPage());
}Com o modo por páginas, o mesmo painel usa 704 bytes, 34% da RAM.

Recapitulação
- O Lopaka desenha a tela, a IDE monta o sketch ao redor dela: instale a U8g2, escolha a placa, cole as funções de desenho e adicione o include, o construtor,
begin()e o loop limpar, desenhar, enviar. - Uma linha de construtor descreve o seu display: chip, tamanho, buffer e fiação.
- Tela preta? Confira cinco coisas: os fios, o endereço, o chip, o código e a memória.
Próximo episódio: Screens & Menus. Mais de uma tela, com menus e um botão. Leia o episódio 6 ou assista no YouTube.
Pronto para testar? Abra o Lopaka e coloque sua tela em uma placa real.