LVGL vs. desenho personalizado: por que os construtores de GUI vencem na produção
Publicado em Lopaka.app — O construtor de GUI LVGL gratuito e baseado na web para desenvolvedores embarcados
Introdução
Se você está criando uma GUI para um display embarcado, está diante de uma decisão fundamental: usar um framework como o LVGL ou escrever seu próprio código de desenho?
O debate surge o tempo todo nas comunidades embarcadas. De um lado, puristas defendem que o desenho personalizado oferece controle máximo e sobrecarga mínima. Do outro, pragmáticos apontam que reinventar a roda é um péssimo uso do tempo de engenharia.
Passei o último ano construindo o Lopaka — um construtor visual de GUI para LVGL — e observando dezenas de equipes lançarem produtos com ele. Os dados são claros, mas a resposta é mais nuançada do que você pode esperar.
Neste post, vou detalhar os verdadeiros compromissos entre LVGL e desenho personalizado, compartilhar benchmarks de desempenho e dizer exatamente quando usar cada abordagem.
O que é o LVGL?
O LVGL (Light and Versatile Graphics Library) é a biblioteca gráfica open-source mais popular para sistemas embarcados. Ele oferece:
- Widgets: Botões, rótulos, controles deslizantes, tabelas, medidores, teclados e mais de 35 outros
- Mecanismos de layout: Layouts flexbox e grid (sim, como o CSS)
- Sistema de estilos: Estilo no jeito CSS, com estados, transições e herança
- Tratamento de entrada: Suporte a toque, encoder, teclado e botões
- Animações: Mecanismo de animação integrado com funções de easing
- Gerenciamento de memória: Otimizado para MCUs com apenas 32KB de RAM
Ele roda em tudo, de ESP32 a STM32 a Raspberry Pi, e tem licença MIT.
O que é desenho personalizado?
Desenho personalizado significa que você escreve seu próprio código para renderizar pixels no display:
// Custom drawing approach
tft.fillScreen(TFT_BLACK);
tft.drawString("Temperature", 10, 10);
tft.drawNumber(25, 10, 30);
tft.drawRect(10, 60, 300, 40, TFT_WHITE);
// ... repeat for every element, every frameVocê cuida de tudo: posicionamento, redesenho, detecção de entrada, gerenciamento de estado, animações.
Comparação direta
Tempo de desenvolvimento
| Métrica | LVGL | Desenho personalizado |
|---|---|---|
| Tela simples (3-5 elementos) | 15-30 min | 1-2 horas |
| Tela complexa (10+ elementos) | 1-2 horas | 4-8 horas |
| App com várias telas (5 telas) | 4-6 horas | 20-40 horas |
| Adicionar animações | 10 min | 2-4 horas |
| Adicionar entrada por toque | 5 min | 1-2 horas |
Vencedor: LVGL por uma margem enorme.
Com um construtor visual como o Lopaka, esses tempos caem ainda mais — a maioria das telas simples leva menos de 10 minutos para projetar e exportar.
Manutenibilidade do código
Abordagem LVGL:
// Clear, semantic code
lv_obj_t *temp_label = lv_label_create(lv_scr_act());
lv_label_set_text(temp_label, "25°C");
lv_obj_align(temp_label, LV_ALIGN_CENTER, 0, -20);
// Easy to modify
void update_temp(float value) {
lv_label_set_text_fmt(temp_label, "%.1f°C", value);
}Abordagem de desenho personalizado:
// Manual pixel management
void draw_temp(int x, int y, float value) {
char buf[16];
sprintf(buf, "%.1f°C", value);
// Must clear old text first
tft.fillRect(x-5, y-5, 80, 20, TFT_BLACK);
tft.drawString(buf, x, y);
}Vencedor: LVGL. O código semântico de widgets se documenta sozinho. O código de desenho personalizado exige comentários para explicar o que cada retângulo faz.
Desempenho
É aqui que a coisa fica interessante. Vamos fazer benchmark em um ESP32 com display ILI9341:
| Métrica | LVGL | Desenho personalizado |
|---|---|---|
| Uso de RAM (UI simples) | 15-25 KB | 2-5 KB |
| Uso de RAM (UI complexa) | 40-80 KB | 10-20 KB |
| Tamanho em flash | 80-120 KB | 10-30 KB |
| Taxa de quadros (UI simples) | 30-60 fps | 50-60 fps |
| Taxa de quadros (UI complexa) | 20-40 fps | 30-50 fps |
| Uso de CPU (ocioso) | 2-5% | 0-1% |
| Uso de CPU (ativo) | 15-30% | 5-15% |
Vencedor: Desenho personalizado no desempenho bruto, mas a diferença é menor do que você imagina.
Para a maioria das aplicações, o desempenho do LVGL é mais do que suficiente. Os 20-40 fps que você obtém em UIs complexas são visualmente suaves, e o uso de CPU deixa bastante margem para a lógica da sua aplicação.
Onde o desenho personalizado vence:
- Dispositivos de consumo ultrabaixo (sensores alimentados por bateria que dormem 99% do tempo)
- MCUs extremamente limitados em recursos (< 64KB de RAM)
- Visualização de dados em alta velocidade (osciloscópios, gráficos em tempo real a mais de 100 fps)
Onde o LVGL vence:
- Qualquer coisa com interação do usuário (botões, menus, formulários)
- Aplicações com várias telas
- Produtos que precisam parecer profissionais
- Equipes com mais de um desenvolvedor
Experiência de desenvolvimento
Isso é subjetivo, mas importante. Pergunte a si mesmo:
- Você quer passar seu tempo nos recursos exclusivos do seu produto ou desenhando retângulos?
- Como você vai tratar a entrada por toque? Detecção de acerto? Antirrebote de botões?
- E a navegação por teclado para acessibilidade?
- Como você implementa transições suaves entre telas?
- Quem mantém esse código quando você sair?
Vencedor: LVGL. Ele resolve problemas nos quais você ainda nem pensou.
A análise de custo real
Vamos colocar isso em termos de negócio. Suponha que um desenvolvedor embarcado custe US$ 80/hora:
| Abordagem | Tempo de desenvolvimento | Custo | Manutenção contínua |
|---|---|---|---|
| Desenho personalizado (simples) | 40 horas | US$ 3.200 | US$ 400/mês |
| Desenho personalizado (complexo) | 160 horas | US$ 12.800 | US$ 800/mês |
| LVGL (codificado à mão) | 20 horas | US$ 1.600 | US$ 200/mês |
| LVGL + Lopaka | 8 horas | US$ 640 | US$ 100/mês |
A escolha de ferramenta que mais economiza dinheiro não é a de menor binário — é a que permite à sua equipe entregar mais rápido.
Quando usar cada abordagem
Use desenho personalizado quando:
- Você tem restrições extremas de recursos — < 32KB de RAM, < 128KB de flash
- Sua UI é estática — Uma única tela que nunca muda (por exemplo, uma leitura de temperatura)
- Você precisa de taxa de quadros máxima — Osciloscópios, analisadores lógicos, gráficos em tempo real
- Você está construindo uma biblioteca, não um produto — Você precisa de zero dependências
- Você gosta disso — Alguns desenvolvedores realmente gostam de escrever código de renderização
Use LVGL quando:
- Sua UI tem interação do usuário — Botões, menus, formulários, telas de configurações
- Você tem várias telas — Navegação, abas, modais
- Você precisa que pareça profissional — Demos de produto, dispositivos voltados ao cliente
- Você está com prazo — Entregar em semanas, não em meses
- Você é uma equipe — Vários desenvolvedores precisam trabalhar na UI
- Você quer que seja sustentável — Outra pessoa vai tocar nesse código
A abordagem híbrida
As equipes mais inteligentes com as quais trabalho usam uma abordagem híbrida:
- LVGL para a UI principal — Menus, configurações, telas de configuração
- Desenho personalizado para visualizações especializadas — Gráficos em tempo real, visualizações personalizadas
- Lopaka para prototipagem rápida — Projete as partes em LVGL visualmente, itere rápido
// Main screens use LVGL (designed in Lopaka)
lv_obj_t *main_screen = ui_MainScreen_create();
// Specialized view uses custom drawing
lv_obj_t *graph_canvas = lv_canvas_create(lv_scr_act());
lv_canvas_fill_bg(graph_canvas, lv_color_black(), LV_OPA_COVER);
// Custom rendering code for high-speed data visualization
draw_oscilloscope_trace(graph_canvas, samples, num_samples);Isso lhe dá o melhor dos dois mundos: desenvolvimento rápido para 90% da sua UI e controle máximo para os 10% que precisam.
Objeções comuns (e por que estão erradas)
“O LVGL é pesado demais”
A configuração mínima do LVGL roda com 32KB de RAM e 80KB de flash. Isso é menos do que a maioria dos sketches Arduino. A fama de “pesado” vem das configurações padrão que habilitam todos os recursos.
“Preciso de controle pixel a pixel”
O LVGL oferece controle pixel a pixel — você pode posicionar qualquer coisa exatamente onde quiser. A diferença é que você não é forçado a calcular cada coordenada manualmente.
“Código personalizado é mais eficiente”
Para renderização bruta, sim. Para a experiência completa do usuário (tratamento de entrada, gerenciamento de estado, animações, acessibilidade), o LVGL é dramaticamente mais eficiente porque já está escrito e testado.
“Não quero dependências externas”
O LVGL tem licença MIT, zero dependências e é usado em produção por milhares de empresas. É o mais próximo de “sem dependência” que você pode chegar para uma biblioteca gráfica.
A conclusão
| Critério | Vencedor |
|---|---|
| Velocidade de desenvolvimento | LVGL |
| Manutenibilidade do código | LVGL |
| Desempenho bruto | Desenho personalizado |
| Uso de recursos | Desenho personalizado |
| Aparência profissional | LVGL |
| Colaboração em equipe | LVGL |
| Manutenção de longo prazo | LVGL |
| Curva de aprendizado | Desenho personalizado (no início) |
Para 90% dos projetos de GUI embarcada, o LVGL é a escolha certa. O compromisso de desempenho é insignificante para a maioria das aplicações, e a economia de tempo de desenvolvimento é enorme.
Os 10% restantes — dispositivos ultra-restritos, visualizações em alta velocidade, displays estáticos — são melhor atendidos pelo desenho personalizado.
E para os projetos LVGL? Usar um construtor visual como o Lopaka torna a decisão ainda mais fácil. Você obtém o poder do LVGL com uma fração do tempo de desenvolvimento.
Recursos
- Lopaka.app — Construtor visual de GUI LVGL
- Documentação do LVGL — Documentação oficial do LVGL
- LVGL no GitHub — Código-fonte e exemplos
- Lopaka no Discord — Comunidade e suporte
Ainda em dúvida? Tente criar a mesma tela dos dois jeitos e cronometre. Acho que você vai se surpreender.