Przejdź do treści

LVGL kontra rysowanie własne: dlaczego kreatory GUI wygrywają w produkcji ​

Opublikowano na Lopaka.app — bezpłatnym internetowym kreatorze GUI LVGL dla deweloperów embedded

Wprowadzenie ​

Jeśli budujesz GUI dla wyświetlacza embedded, stajesz przed fundamentalną decyzją: użyć frameworka takiego jak LVGL czy napisać własny kod rysowania?

Ta debata ciągle wraca w społecznościach embedded. Z jednej strony puryści twierdzą, że rysowanie własne daje maksymalną kontrolę i minimalny narzut. Z drugiej pragmatycy wskazują, że wynajdywanie koła na nowo to straszne wykorzystanie czasu inżynierskiego.

Ostatni rok spędziłem na budowaniu Lopaka — wizualnego kreatora GUI dla LVGL — i obserwowaniu, jak dziesiątki zespołów wypuszczają z nim produkty. Dane są jasne, ale odpowiedź jest bardziej niuansowa, niż możesz się spodziewać.

W tym wpisie rozbiorę prawdziwe kompromisy między LVGL a rysowaniem własnym, podzielę się benchmarkami wydajności i powiem ci dokładnie, kiedy używać każdego podejścia.

Czym jest LVGL? ​

LVGL (Light and Versatile Graphics Library) to najpopularniejsza otwarta biblioteka graficzna dla systemów embedded. Zapewnia:

  • Widżety: przyciski, etykiety, suwaki, wykresy, mierniki, klawiatury i ponad 35 kolejnych
  • Silniki układu: układy Flexbox i siatki (tak, jak CSS)
  • System stylów: style podobne do CSS ze stanami, przejściami i dziedziczeniem
  • Obsługę wejścia: dotyk, enkoder, klawiaturę, przyciski
  • Animacje: wbudowany silnik animacji z funkcjami easing
  • Zarządzanie pamięcią: zoptymalizowane pod MCU z zaledwie 32 KB RAM

Działa na wszystkim, od ESP32 po STM32 i Raspberry Pi, i jest na licencji MIT.

Czym jest rysowanie własne? ​

Rysowanie własne oznacza, że piszesz własny kod, żeby renderować piksele na wyświetlaczu:

c
// 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 frame

Obsługujesz wszystko: pozycjonowanie, odrysowywanie, wykrywanie wejścia, zarządzanie stanem, animacje.

Porównanie bezpośrednie ​

Czas tworzenia ​

MetrykaLVGLRysowanie własne
Prosty ekran (3-5 elementów)15-30 min1-2 godziny
Złożony ekran (ponad 10 elementów)1-2 godziny4-8 godzin
Aplikacja wieloekranowa (5 ekranów)4-6 godzin20-40 godzin
Dodawanie animacji10 min2-4 godziny
Dodawanie wejścia dotykowego5 min1-2 godziny

Zwycięzca: LVGL z ogromną przewagą.

Z wizualnym kreatorem takim jak Lopaka te czasy spadają jeszcze bardziej — większość prostych ekranów zajmuje poniżej 10 minut na zaprojektowanie i wyeksportowanie.

Utrzymywalność kodu ​

Podejście LVGL:

c
// 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);
}

Podejście rysowania własnego:

c
// 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);
}

Zwycięzca: LVGL. Semantyczny kod widżetów sam się dokumentuje. Kod rysowania własnego wymaga komentarzy, żeby wyjaśnić, co robi każdy prostokąt.

Wydajność ​

Tu robi się ciekawie. Zróbmy benchmark na ESP32 z wyświetlaczem ILI9341:

MetrykaLVGLRysowanie własne
Zużycie RAM (prosty interfejs)15-25 KB2-5 KB
Zużycie RAM (złożony interfejs)40-80 KB10-20 KB
Rozmiar flash80-120 KB10-30 KB
Liczba klatek (prosty interfejs)30-60 fps50-60 fps
Liczba klatek (złożony interfejs)20-40 fps30-50 fps
Zużycie CPU (bezczynność)2-5%0-1%
Zużycie CPU (aktywność)15-30%5-15%

Zwycięzca: rysowanie własne pod względem surowej wydajności, ale różnica jest mniejsza, niż myślisz.

W większości zastosowań wydajność LVGL jest więcej niż wystarczająca. 20-40 fps, które dostajesz na złożonych interfejsach, jest wizualnie gładkie, a zużycie CPU zostawia dużo zapasu na logikę aplikacji.

Gdzie wygrywa rysowanie własne:

  • Urządzenia o ultra niskim poborze mocy (czujniki bateryjne, które śpią przez 99% czasu)
  • MCU o skrajnie ograniczonych zasobach (poniżej 64 KB RAM)
  • Wizualizacja danych z dużą prędkością (oscyloskopy, wykresy w czasie rzeczywistym przy ponad 100 fps)

Gdzie wygrywa LVGL:

  • Wszystko z interakcją użytkownika (przyciski, menu, formularze)
  • Aplikacje wieloekranowe
  • Produkty, które muszą wyglądać profesjonalnie
  • Zespoły z więcej niż jednym deweloperem

Doświadczenie tworzenia ​

To subiektywne, ale ważne. Zapytaj siebie:

  • Czy chcesz spędzać czas na unikalnych funkcjach produktu, czy na rysowaniu prostokątów?
  • Jak obsłużysz wejście dotykowe? Wykrywanie trafień? Debouncing przycisków?
  • A co z nawigacją klawiaturą dla dostępności?
  • Jak zaimplementujesz gładkie przejścia między ekranami?
  • Kto będzie utrzymywał ten kod, gdy odejdziesz?

Zwycięzca: LVGL. Rozwiązuje problemy, o których jeszcze nawet nie pomyślałeś.

Analiza prawdziwych kosztów ​

Ujmijmy to w kategoriach biznesowych. Załóż, że deweloper embedded kosztuje 80 USD za godzinę:

PodejścieCzas tworzeniaKosztBieżące utrzymanie
Rysowanie własne (proste)40 godzin3200 USD400 USD/miesiąc
Rysowanie własne (złożone)160 godzin12 800 USD800 USD/miesiąc
LVGL (kodowane ręcznie)20 godzin1600 USD200 USD/miesiąc
LVGL + Lopaka8 godzin640 USD100 USD/miesiąc

Wybór narzędzi, który oszczędza najwięcej pieniędzy, to nie ten z najmniejszym plikiem binarnym — to ten, który pozwala zespołowi szybciej wypuszczać produkt.

Kiedy używać każdego podejścia ​

Używaj rysowania własnego, gdy: ​

  1. Masz skrajne ograniczenia zasobów — poniżej 32 KB RAM, poniżej 128 KB flash
  2. Twój interfejs jest statyczny — jeden ekran, który nigdy się nie zmienia (np. odczyt temperatury)
  3. Potrzebujesz maksymalnej liczby klatek — oscyloskopy, analizatory logiczne, wykresy w czasie rzeczywistym
  4. Budujesz bibliotekę, a nie produkt — potrzebujesz zero zależności
  5. Lubisz to — niektórzy deweloperzy naprawdę lubią pisać kod renderujący

Używaj LVGL, gdy: ​

  1. Twój interfejs ma interakcję użytkownika — przyciski, menu, formularze, ekrany ustawień
  2. Masz wiele ekranów — nawigacja, karty, okna modalne
  3. Potrzebujesz profesjonalnego wyglądu — dema produktu, urządzenia dla klientów
  4. Masz harmonogram — wypuść w tygodnie, nie miesiące
  5. Jesteś zespołem — wielu deweloperów musi pracować nad interfejsem
  6. Chcesz, żeby dał się utrzymywać — ktoś inny dotknie tego kodu

Podejście hybrydowe ​

Najmądrzejsze zespoły, z którymi pracuję, używają podejścia hybrydowego:

  1. LVGL dla głównego interfejsu — menu, ustawienia, ekrany konfiguracji
  2. Rysowanie własne dla wyspecjalizowanych widoków — wykresy w czasie rzeczywistym, własne wizualizacje
  3. Lopaka do szybkiego prototypowania — projektuj części LVGL wizualnie, szybko iteruj
c
// 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);

Daje ci to najlepsze z obu światów: szybkie tworzenie 90% interfejsu i maksymalną kontrolę nad 10%, które jej potrzebuje.

Popularne zastrzeżenia (i dlaczego są błędne) ​

„LVGL jest za ciężkie” ​

Minimalna konfiguracja LVGL działa w 32 KB RAM i 80 KB flash. To mniej niż większość szkiców Arduino. Reputacja „ciężkości” pochodzi z domyślnych konfiguracji, które włączają każdą funkcję.

„Potrzebuję kontroli co do piksela” ​

LVGL daje ci kontrolę co do piksela — możesz ustawić wszystko dokładnie tam, gdzie chcesz. Różnica polega na tym, że nie jesteś zmuszony ręcznie obliczać każdej współrzędnej.

„Własny kod jest wydajniejszy” ​

Przy surowym renderowaniu tak. Przy pełnym doświadczeniu użytkownika (obsługa wejścia, zarządzanie stanem, animacje, dostępność) LVGL jest dramatycznie wydajniejsze, bo jest już napisane i przetestowane.

„Nie chcę zewnętrznych zależności” ​

LVGL jest na licencji MIT, ma zero zależności i jest używane w produkcji przez tysiące firm. To najbliżej „braku zależności”, jak możesz być przy bibliotece graficznej.

Podsumowanie ​

KryteriumZwycięzca
Szybkość tworzeniaLVGL
Utrzymywalność koduLVGL
Surowa wydajnośćRysowanie własne
Zużycie zasobówRysowanie własne
Profesjonalny wyglądLVGL
Współpraca zespołowaLVGL
Długoterminowe utrzymanieLVGL
Krzywa uczenia sięRysowanie własne (początkowo)

Dla 90% projektów GUI embedded LVGL to właściwy wybór. Kompromis wydajnościowy jest pomijalny w większości zastosowań, a oszczędności czasu tworzenia są ogromne.

Pozostałe 10% — urządzenia o skrajnych ograniczeniach, wizualizacje z dużą prędkością, wyświetlacze statyczne — lepiej obsłuży rysowanie własne.

A przy projektach LVGL? Użycie wizualnego kreatora takiego jak Lopaka sprawia, że decyzja jest jeszcze łatwiejsza. Dostajesz moc LVGL za ułamek czasu tworzenia.

Zasoby ​

Wciąż się wahasz? Spróbuj zbudować ten sam ekran na oba sposoby i zmierz czas. Myślę, że będziesz zaskoczony.