Pular para o conteúdo

Guia U8g2 para displays OLED e LCD com Arduino ​

Este guia leva um novo projeto U8g2 de uma tela vazia do Lopaka a um sketch Arduino funcional. O Lopaka cria o código de desenho; você conecta e inicializa o display, escolhe como ele é armazenado em buffer e decide quando cada tela é exibida.

O que é a U8g2? ​

A U8g2 é uma biblioteca gráfica para displays OLED e LCD monocromáticos. Ela oferece suporte a muitos controladores, primitivas de desenho, bitmaps e uma grande coleção de fontes. O Lopaka mira a API gráfica U8g2, não a API somente de texto U8x8.

Use o tutorial de configuração e a lista de construtores oficiais para confirmar que a U8g2 oferece suporte ao seu display exato.

Antes de começar ​

Você precisa de:

  • Um microcontrolador e um display monocromático compatível com a U8g2.
  • O nome do controlador do display, a resolução e a interface: por exemplo, SSD1306, 128×64, I2C por hardware.
  • A folha de dados do display ou o guia de fiação do fornecedor.
  • Um projeto compatível com Arduino que consiga compilar e enviar um sketch básico.

Atenção

O Lopaka não detecta seu hardware. Dois módulos parecidos podem usar controladores, endereços, pinagens ou deslocamentos de display diferentes.

Etapa 0: Instale e teste a U8g2 ​

No Arduino IDE, abra Tools → Manage Libraries, busque U8g2 e instale a biblioteca de olikraus. Esse é o método de instalação documentado pelo repositório oficial da U8g2.

Para uma instalação manual no Arduino, baixe a distribuição oficial da U8g2 para Arduino e adicione seu ZIP por Sketch → Include Library → Add .ZIP Library. Outras toolchains podem usar a mesma distribuição oficial por meio de seu fluxo de dependências de bibliotecas. Prefira uma versão lançada, a menos que você precise especificamente de uma alteração oficial ainda não lançada.

Antes de adicionar código do Lopaka, compile e envie um dos exemplos da U8g2 para o seu display. Um exemplo bem-sucedido prova que o construtor, a fiação e a instalação da biblioteca estão corretos.

Etapa 1: Escolha o construtor do display ​

O nome do construtor seleciona quatro coisas importantes:

ParteExemploSignificado
Controlador e displaySSD1306_128X64_NONAMEFamília de hardware e resolução
BufferF, 1 ou 2Buffer de tela cheia ou de página
InterfaceHW_I2C, SW_I2C, 4W_HW_SPI etc.Barramento e implementação
ArgumentosU8G2_R0, pinos de reset e de barramentoRotação e fiação

Por exemplo:

cpp
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
    U8G2_R0,
    U8X8_PIN_NONE
);

Esse é apenas um construtor representativo para um display SSD1306 128×64 com I2C por hardware. Substitua-o pelo construtor e pelos argumentos exatos da lista oficial de configuração em C++.

Buffer completo ou buffer de página? ​

  • Um construtor que contém _F_ mantém o quadro inteiro na RAM. Desenhe entre clearBuffer() e sendBuffer().
  • Um construtor que contém _1_ ou _2_ usa um buffer de página menor. Coloque a função de desenho completa dentro do loop de imagem firstPage() / nextPage().

O modo de buffer completo é mais simples e rápido, mas usa mais RAM. Para uma imagem de um bit de 128×64, o buffer de pixels sozinho tem 1.024 bytes. O modo de página usa menos RAM, mas redesenha a mesma imagem para cada página. Consulte o guia de modos de buffer da U8g2.

Etapa 2: Crie o projeto no Lopaka ​

  1. Abra lopaka.app e crie um projeto.
  2. Selecione U8g2 como a plataforma.
  3. Defina o Tamanho da tela com a largura e a altura lógicas do display. Para um display 128×64 sem rotação, use 128 × 64.
  4. Mantenha o fundo preto padrão. A saída da U8g2 tem um bit por pixel, então os designs do Lopaka são primeiro plano versus fundo, e não cores RGB.

O tamanho da tela de desenho do Lopaka define a superfície de design e a referência de coordenadas; ele não escolhe um construtor da U8g2 nem configura o display físico.

Etapa 3: Projete uma tela ​

Use o editor para posicionar textos, imagens e primitivas de desenho. A posição (0, 0) é o canto superior esquerdo da tela de desenho. Renomeie as camadas antes de exportar: os nomes viram comentários, identificadores de imagens, cabeçalhos de animações e nomes de variáveis opcionais.

Projetos U8g2 no Lopaka oferecem suporte a estes conceitos emitidos:

Camada do LopakaSaída U8g2 no Arduino
LinhadrawLine()
RetângulodrawFrame() / drawBox()
Retângulo arredondadodrawRFrame() / drawRBox()
ElipsedrawEllipse() / drawFilledEllipse()
TriângulodrawTriangle(); sempre preenchido no inspetor U8g2 do Lopaka
PolígonoUm auxiliar feito de chamadas fechadas de drawLine(); somente contorno
TextosetFont() mais drawStr() ou drawUTF8()
Pintura, ícone ou imagem importadaUm array XBM monocromático mais drawXBM() ou drawXBMP()
AnimaçãoDados/cabeçalho de quadros mais auxiliares de seleção e desenho de quadros

Primeiro plano, fundo e inversão ​

O projeto U8g2 é monocromático, então o Inspetor não mostra um seletor de cores RGB. Camadas normais acendem pixels; camadas invertidas usam a cor de desenho 2 (XOR) da U8g2. O Lopaka também emite modos transparentes de fonte e bitmap para que pixels vazios em textos e imagens não apaguem camadas abaixo.

A U8g2 observa que o XOR não é compatível com todas as primitivas, incluindo procedimentos de elipse. Verifique formas invertidas no display real; consulte setDrawColor.

Posição e linha de base do texto ​

As coordenadas das formas usam suas origens normais da U8g2. O texto usa a linha de base da fonte, não a borda superior das letras visíveis. Uma troca de fonte pode, portanto, alterar o alinhamento vertical aparente mesmo quando a camada de texto mantém a mesma posição.

O texto pode ser girado em 0°, 90°, 180° ou 270°. O Lopaka emite setFontDirection() quando necessário. Consulte a referência da API U8g2 para detalhes de coordenadas.

Etapa 4: Configure o código gerado ​

Abra Configurações de código e escolha Arduino (Cpp) para um sketch Arduino. A U8g2 também tem uma opção de sintaxe ESP-IDF (C) para projetos que já usam a interface C da U8g2; ela não é um aplicativo ESP-IDF completo nem uma portação de hardware.

ConfiguraçãoO que ela altera para a U8g2
Função wrapperEnvolve a tela ativa em void draw{ScreenName}(void)
Declarar como PROGMEMUsa U8X8_PROGMEM e drawXBMP() para declarações de bitmap no Arduino
Incluir fontesInclui cabeçalhos de fontes personalizadas baixados; fontes integradas da U8g2 não precisam de cabeçalho
Declarar imagensEmite arrays de bitmap usados por camadas de pintura e imagem
Incluir arquivos de imagemEmite #include "image_<Name>_bits.h" em vez dos arrays de bitmap em linha
Auxiliares de animaçãoInclui cabeçalhos de animações baixados e emite auxiliares de tempo/desenho
Declarar variáveisEmite declarações para propriedades de camadas marcadas como variáveis
Comentários, títulos das camadasAdiciona comentários com o nome da camada à saída estática
Limpar/preencher o displayInicia o bloco de desenho com u8g2.clearBuffer() (Arduino) ou u8g2_ClearBuffer() (ESP-IDF); consulte a nota abaixo

Mantenha todos os recursos ativados, exceto Limpar/preencher o display no Arduino.

Limpar/preencher o display no Arduino

No modelo Arduino, Limpar/preencher o display fica desativado por padrão. Quando você o ativa, draw{ScreenName}() começa com u8g2.clearBuffer(), que apaga qualquer coisa que seu sketch desenhou no buffer antes de chamá-la. Deixe desativado se o seu loop() já limpar o buffer ou desenhar outro conteúdo primeiro. Ele é ignorado quando os Auxiliares de animação estão ativados, porque o firstPage()/nextPage() do loop de animação já limpa cada página. O modelo ESP-IDF o mantém ativado por padrão.

Etapa 5: Exporte fontes e imagens ​

Fontes integradas ​

O Lopaka conhece a lista de fontes integradas da U8g2 e adapta o código gerado à fonte selecionada. Quando uma fonte é integrada à U8g2, o Lopaka emite seu símbolo de biblioteca diretamente e não gera nem oferece um cabeçalho de fonte separado para download. Por exemplo:

cpp
u8g2.setFont(u8g2_font_6x10_tr);

Para uma fonte que não está na lista de integradas, o Lopaka a trata como uma fonte personalizada, emite um include de cabeçalho correspondente e lista esse cabeçalho em Configurações de código → Fontes para download.

Os tamanhos das fontes integradas são fixos; selecione outra fonte para deixar o texto maior ou menor. Use a lista oficial de fontes da U8g2 para inspecionar a cobertura de caracteres.

Fontes personalizadas ​

Projetos U8g2 aceitam fontes BDF e podem importar TTF, OTF ou WOFF por meio do assistente de fontes de tamanho fixo do Lopaka. Em Configurações de código → Fontes:

  1. Baixe cada arquivo .h personalizado listado.
  2. Coloque os cabeçalhos ao lado do seu sketch ou do código-fonte gerado.
  3. Mantenha Incluir fontes ativado para que as linhas geradas #include "Font_Name.h" permaneçam presentes.

Renderizar somente os glifos usados cria um cabeçalho menor contendo os caracteres usados atualmente por camadas de texto correspondentes. Se um valor de texto for uma variável em tempo de execução, o Lopaka exporta a fonte personalizada completa porque não pode prever caracteres futuros.

Imagens e animações ​

Imagens estáticas são convertidas para dados XBM de um bit e podem ser declaradas diretamente no código-fonte copiado. Com Declarar como PROGMEM ativado, o Lopaka usa U8X8_PROGMEM e drawXBMP(), de acordo com a orientação de bitmap PROGMEM da U8g2.

Configurações de código → Imagens lista cada imagem como image_<Name>_bits.h, carregando exatamente os bytes XBM que a chamada de desenho recebe. Ative Incluir arquivos de imagem para emitir #include "image_<Name>_bits.h" em vez do array e manter os pixels no cabeçalho baixado.

As animações também são monocromáticas. Baixe cada arquivo .h listado em Animações, coloque-o com o sketch e mantenha o include e o código auxiliar gerados. O auxiliar do Arduino escolhe os quadros com millis(). Você ainda é responsável por chamar o auxiliar de atualização e redesenhar a tela completa pelo loop de buffer correto.

Atenção

A saída de animação pode incluir um código inicial setup() e loop(). Mescle seus includes, a atualização de quadros e os auxiliares de desenho no seu sketch e então use o padrão de atualização de buffer completo ou de buffer de página deste guia. Não mantenha um segundo setup() ou loop().

Etapa 6: Copie e integre o código ​

Crie uma tela chamada Main, adicione uma camada de texto e uma moldura, e então clique em Copiar no painel de código do Lopaka. Uma função de desenho gerada representativa fica assim:

cpp
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);
}

Seu código exato usará o nome da sua tela, suas camadas, fontes e coordenadas.

Sketch mínimo com buffer completo ​

Use este padrão somente com um construtor _F_:

cpp
#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 com buffer de página ​

Use este padrão de loop de imagem com um construtor _1_ ou _2_:

cpp
void loop(void) {
    u8g2.firstPage();
    do {
        drawMain();
    } while (u8g2.nextPage());
}

Não atualize o estado da interface dentro de drawMain() no modo de página. A U8g2 a chama mais de uma vez para construir um quadro, e cada passada precisa desenhar a mesma imagem. Atualize os valores dos sensores, o estado de navegação e a seleção de quadros de animação antes de firstPage().

Etapa 7: Adicione dados em tempo de execução e mais telas ​

Para tornar um valor dinâmico, selecione sua propriedade no Inspetor, ative seu alternador de variável e mantenha Declarar variáveis ativado. O Lopaka então substitui o literal por uma declaração nomeada baseada no nome da camada. Seu aplicativo pode atualizar esse valor antes do próximo redesenho.

Cada tela do Lopaka exporta separadamente, e seu título vira o nome da função de desenho. Copie a função de cada tela para o projeto, mescle os includes e recursos compartilhados para que sejam declarados apenas uma vez, e então escolha qual função chamar:

cpp
enum Screen { MAIN, DETAILS };
Screen currentScreen = MAIN;

void drawCurrentScreen(void) {
    if (currentScreen == MAIN) {
        drawMain();
    } else {
        drawDetails();
    }
}

O Lopaka não gera navegação entre telas, tratamento de botões, menus, leituras de sensores nem estado do aplicativo.

O que o Lopaka faz e o que você faz ​

O Lopaka fazVocê faz
Layout em pixels e ordem das camadasFiação do display, tensão e mapeamento de pinos
Chamadas de desenho da U8g2 para camadas compatíveisConstrutor exato de controlador/interface/buffer
Referências de fontes integradasInstalar a U8g2 e a toolchain da placa
Conversão de fontes personalizadas e cabeçalhos para downloadManter os cabeçalhos personalizados com o código-fonte
Declarações de bitmap de um bitOrçamento de RAM/flash e escolha do buffer
Variáveis opcionais e auxiliares de animaçãobegin(), loop de atualização, tempo e estado do aplicativo
Uma função de desenho nomeada por tela exportadaEntradas, navegação, sensores e quando redesenhar

Compile, envie e itere ​

  1. Compile antes de enviar. Resolva primeiro cada cabeçalho ou símbolo ausente.
  2. Envie e compare o display físico com a tela de desenho do Lopaka.
  3. Ajuste o construtor, a rotação, o tamanho da tela de desenho ou as posições das camadas conforme necessário.
  4. Quando o design mudar, substitua a seção gerada completa em vez de editar chamadas geradas individuais em vários lugares.

Mantenha o código de hardware e do aplicativo fora da seção gerada para que uma nova exportação não o sobrescreva:

cpp
// BEGIN LOPAKA GENERATED CODE
// Replace this entire block after exporting again.
// END LOPAKA GENERATED CODE

Solução de problemas ​

O display está em branco ​

  • Primeiro envie um exemplo oficial da U8g2 usando o mesmo construtor. Se ele também estiver em branco, verifique energia, terra, fiação, controlador, pino de reset e interface.
  • Confirme que u8g2.begin() é executado uma vez.
  • Confirme que o desenho acontece entre clearBuffer() / sendBuffer() para _F_, ou dentro do loop completo firstPage() / nextPage() para _1_ e _2_.
  • Para I2C, escaneie o barramento e compare o resultado com a documentação do módulo. Se você chamar setI2CAddress(), a U8g2 espera o endereço multiplicado por dois e a chamada precisa ocorrer antes de begin(); consulte a referência oficial.

A imagem está deslocada, cortada, espelhada ou girada ​

Verifique se a tela de desenho do Lopaka corresponde ao tamanho lógico do display do construtor. Selecione a variante exata de controlador/display: alguns módulos têm RAM do controlador mais larga que o painel visível. Use U8G2_R0 até U8G2_R3 no construtor para a rotação do display e então mantenha as dimensões do Lopaka consistentes com essa orientação.

Cores ou formas sobrepostas parecem invertidas ​

A saída da U8g2 tem um bit, não escala de cinza nem RGB. Desative invertido na camada se o XOR não era intencional. O XOR não é compatível com todas as primitivas da U8g2, então elipses invertidas devem ser verificadas no hardware.

Uma fonte ou símbolo não está definido ​

  • Os nomes integrados precisam existir na versão instalada da U8g2 e conter os glifos que você usa.
  • Para uma fonte personalizada, baixe seu .h, mantenha-o ao lado do código-fonte e mantenha Incluir fontes ativado.
  • Se os caracteres ficarem em branco, desative Renderizar somente os glifos usados e exporte a fonte personalizada de novo, especialmente quando o texto muda em tempo de execução.

O sketch fica sem memória ​

Experimente um construtor de buffer de página _1_ ou _2_, imagens menores, menos quadros de animação ou fontes personalizadas contendo apenas os glifos necessários. Fontes e recursos integrados consomem flash; o buffer completo do display consome RAM.

As imagens parecem ásperas ou invertidas ​

As imagens da U8g2 têm um bit, então as escolhas de redimensionamento, recorte, contraste, limiar e pontilhamento importam. Reabra o editor de imagens do Lopaka e pré-visualize no tamanho final em pixels. Mantenha Declarar como PROGMEM consistente com a declaração gerada e a chamada drawXBMP().

O modo de página pisca ou mostra apenas parte da tela ​

Chame a função de desenho completa dentro do loop de imagem do / while. Não desenhe algumas camadas antes de firstPage(), não altere valores entre páginas nem chame apenas firstPage() sem nextPage().

Perguntas frequentes ​

O Lopaka configura meu display SSD1306 ou SH1106? ​

Não. O Lopaka gera código de desenho. Você escolhe o construtor correspondente, o barramento, os pinos, o endereço, a rotação, o modo de buffer e a inicialização.

Posso usar a U8x8 em vez disso? ​

Não com a saída U8g2 do Lopaka. A U8x8 é uma API separada, somente de caracteres, e não oferece suporte às primitivas gráficas que o Lopaka emite.

O Lopaka pode gerar código U8g2 colorido? ​

Não. A plataforma U8g2 do Lopaka é monocromática. Escolha uma plataforma colorida, como TFT_eSPI ou ArduinoGFX, para um display RGB.

A exportação ESP-IDF (C) é um projeto de firmware completo? ​

Não. Ela emite código de desenho da interface C e recursos. Seu projeto ESP-IDF precisa configurar a estrutura da U8g2, os callbacks de GPIO/barramento, o loop de tarefas, a inicialização e a integração com a plataforma.

Onde posso aprender mais? ​