Lopaka Basics 07: Animacje

Ten koń został sfotografowany w 1887 roku. Teraz jest GIF-em, galopującym na malutkim ekranie Arduino: piętnaście klatek i mieszczą się. Zrób go na cały ekran i trochę płynniejszego, a szkic w ogóle się nie zmieści.
W tym odcinku dowiesz się, jak działa animacja na małym ekranie i ile pamięci potrzebuje. Następnie zamienisz GIF w kod w Lopaka, uruchomisz go na symulowanym Arduino UNO i umieścisz cały miesiąc faz księżyca na ESP32.
Co zbudujesz: galopującego konia z GIF-a na OLED 128×64 z Arduino UNO oraz miesiąc faz księżyca z wideo na tym samym OLED z ESP32. Czego potrzebujesz: przeglądarki i konfiguracji symulatora z odcinka 1: OLED SSD1306 i biblioteki U8g2. W przypadku konia użyliśmy galopującego konia Eadwearda Muybridge’a (Animal Locomotion, 1887, domena publiczna); każdy krótki GIF działa.
Klatki i liczba klatek
Animacja to stos obrazków
Animacja to stos nieruchomych obrazków. Pokaż je jeden po drugim, wystarczająco szybko, a twoje oko przestanie widzieć obrazki i zacznie widzieć ruch.
Ta prędkość to liczba klatek na sekundę, w klatkach na sekundę (FPS). Przy dwóch klatkach na sekundę koń jest pokazem slajdów. Przy dziesięciu galopuje.

Pętla odtwarza ją klatka po klatce
Mikrokontroler odtwarza animację w ten sam sposób. Każde przejście loop() rysuje bieżącą klatkę, wysyła ją na ekran, czeka chwilę i przechodzi do następnej klatki. Po ostatniej klatce wraca do pierwszej.

Każda klatka kosztuje pamięć
Jedna klatka na cały ekran to 1024 bajty
OLED ma 128 na 64 piksele, a każdy piksel to jeden bit: włączony lub wyłączony. To 8192 bity, czyli 1024 bajty na jedną klatkę na cały ekran. Klatka o dowolnym rozmiarze zajmuje szerokość × wysokość ÷ 8 bajtów.

Arduino UNO przechowuje 23 klatki na cały ekran
Klatki żyją w pamięci flash, obok twojego programu. Arduino UNO ma 32 KB flash, a biblioteka U8g2 i szkic zajmują już około 8 KB z tego. Pozostawia to miejsce na 23 klatki na cały ekran. Sprawdziliśmy to kompilatorem: przy 23 klatkach szkic używa 99% flash UNO, a 24. klatka sprawia, że jest za duży.

Dlaczego koń się mieści, a cały ekran nie
Koń ma 96 na 64 piksele, więc klatka zajmuje 96 × 64 ÷ 8 = 768 bajtów. Piętnaście klatek to około 11 KB, a szkic mieści się w 62% flash.

Cały ekran przy dwudziestu klatkach na sekundę potrzebuje trzydziestu klatek po 1024 bajty, a szkic rośnie do 121% flash. Kompilator zatrzymuje się z komunikatem „Sketch too big”. Ale GIF ma tylko piętnaście rysunków. Aby odtworzyć go przy dwudziestu klatkach na sekundę, szkic pokazuje każdy rysunek dwa razy, więc połowa z tych trzydziestu klatek to kopie.

Trzy sposoby, aby animacja się zmieściła
- Mniej klatek. Zachowaj własną liczbę klatek GIF-a: wyższa dodaje tylko kopie.
- Mniejsze klatki. Każdy przycięty wiersz i kolumna oszczędza bajty w każdej klatce.
- Większa płytka. ESP32 ma 1,25 MB flash na twój program: miejsce na około tysiąc klatek na cały ekran.

Krok 1: zaimportuj GIF
Utwórz nowy projekt jak w odcinku 1: + Nowy projekt, platforma U8g2, rozmiar ekranu 128×64.
Biblioteka animacji
Otwórz kartę Animacje po lewej. Lopaka zawiera gotowe animowane ikony, a szacunkowy rozmiar znajduje się obok przycisków rozmiaru i jakości. Ikona 64×64 w jakości Wysoka zajmuje około 14 KB; przy 32×32 i jakości Niska to mniej niż jeden kilobajt. Wybierz tam ikonę, gdy potrzebujesz tylko małej animacji.
Prześlij swój GIF
W przypadku własnego GIF-a kliknij Prześlij u góry panelu i upuść plik w oknie. Wideo też działa, jak zobaczysz w kroku 5.
Lopaka dzieli GIF na klatki i otwiera okno importu. Klatki są po lewej, podgląd pośrodku, ustawienia po prawej:
- Dithering: przełącz go z Floyd-Steinberg na Brak ditheringu. Zdjęcie zamienia się w czystą białą sylwetkę zamiast chmury kropek. Dithering pomaga przy odcieniach, jak w odcinku 2; sylwetka go nie potrzebuje.
- Klatki na sekundę: zachowaj 10, własną prędkość GIF-a.
Wiersz na dole wykonuje za ciebie matematykę pamięci: 15 klatek źródłowych, 15 klatek wyjściowych, rozmiar klatki 96×64, około 11,3 KiB. Lopaka przeskalowała GIF 300×200 do wysokości ekranu, 64 pikseli, co daje mu szerokość 96 pikseli. Jedna klatka to 768 bajtów, liczba na górze ustawień.

Częstym błędem jest podnoszenie liczby klatek, aby GIF był płynniejszy. Przy 20 FPS okno pokazuje 15 klatek źródłowych, ale 30 klatek wyjściowych, a szacunek podwaja się do 22,5 KiB: tych samych piętnaście rysunków, każdy dwa razy.
Kliknij Importuj.
Krok 2: edytor klatek
Klatki otwierają się w edytorze klatek, ze wszystkimi piętnastoma na osi czasu na dole.
- Odtwórz (przycisk trójkąta) sprawdza pętlę.
- Przy włączonym przełączniku Cebula poprzednia klatka prześwituje na szaro, więc widzisz, jak daleko nogi przesuwają się z jednej klatki do następnej.
Stare zdjęcia mają liczby wzdłuż dolnej krawędzi, a import zamienił je w białe znaki. Usuń je ze wszystkich klatek naraz: kliknij rozmiar klatki obok liczby klatek (96×64 px), ustaw Wysokość na 60 i kliknij Zmień rozmiar. Piksele pozostają zakotwiczone w lewym górnym rogu, więc dolne cztery wiersze znikają na każdej klatce, a licznik pamięci spada z 11,3 do 10,6 KiB. Jeśli klatka nadal ma kilka kropek liczby na dolnej krawędzi, przejdź do niej i zetrzyj je gumką.

Kliknij Zapisz. Animacja znajduje się na ekranie jak każda inna warstwa, o nazwie horse, na X 16 i Y 0: (128 − 96) ÷ 2 = 16 umieszcza ją pośrodku.
Krok 3: kod
Klatki wprost do kodu
W przełącznikach obok kodu odznacz Pomocnicy animacji. Teraz Lopaka zapisuje klatki wprost do kodu, a twoje własne loop() decyduje, kiedy je narysować:
// [BEGIN lopaka generated]
static const unsigned char animation_horse_frames[15][720] U8X8_PROGMEM = {
{0x00,0x00,0x00, /* ... */ 0x00,0x00}, // frame 1: 720 bytes, shortened here
// ... 13 more frames ...
{0x00,0x00,0x00, /* ... */ 0xff,0xff} // frame 15
};
static int animation_horse_frame = 0;
void drawScreen_1(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
// horse
u8g2.drawXBMP(16, 0, 96, 60, animation_horse_frames[animation_horse_frame]);
animation_horse_frame = (animation_horse_frame + 1) % 15;
}
// [END lopaka generated]Co oznaczają liczby:
[15][720]: jedna tablica piętnastu klatek, po 720 bajtów każda. Wiersz 96 pikseli zajmuje 96 ÷ 8 = 12 bajtów, a 60 wierszy daje 720. Łącznie to 10 800 bajtów, te 10,6 KiB z edytora klatek.U8X8_PROGMEMprzechowuje klatki we flash, jak w przypadku obrazów w odcinku 2. Bez niego UNO próbowałoby skopiować je do swojego 2 KB RAM.drawXBMP(16, 0, 96, 60, ...)rysuje bieżącą klatkę na pozycji i rozmiarze warstwy.(animation_horse_frame + 1) % 15przechodzi do następnej klatki.% 15to reszta z dzielenia przez 15, więc po klatce 14 (piętnastej, licząc od zera) licznik wraca do 0.
Reszta szkicu
Wokół wygenerowanego bloku napisz resztę szkicu. Możesz wpisać ją w panelu kodu Lopaka: linie nad // [BEGIN lopaka generated] i pod // [END lopaka generated] są twoje, pozostają w projekcie, gdy zmienisz projekt, a opcja Kopiuj zabiera je ze sobą.
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
// Paste the Lopaka code here
void setup() {
u8g2.begin();
}
void loop() {
u8g2.clearBuffer();
drawScreen_1();
u8g2.sendBuffer();
delay(56);
}Każde przejście loop() to jedna klatka: wyczyść, narysuj, wyślij, poczekaj. To pętla z początku artykułu.
![Panel kodu w Lopaka z dyrektywą include i wyświetlaczem nad wygenerowanym blokiem, tablicą klatek animation_horse_frames[15][720] U8X8_PROGMEM, funkcją rysowania oraz setup i loop z delay(56) poniżej; Pomocnicy animacji odznaczeni](/pages/blog/assets/2026-11-03/animation-code.png)
Dlaczego opóźnienie wynosi 56 milisekund
Wysłanie pełnej ramki na OLED przez I2C zajmuje około 44 milisekund na symulowanym UNO. Dodaj opóźnienie 56 milisekund, a każda klatka zajmuje 100 milisekund: dziesięć klatek na sekundę, prędkość GIF-a. Na prawdziwej płytce czas wysłania ramki zależy od prędkości I2C; jeśli koń biegnie za szybko lub za wolno, zmień opóźnienie.
Kliknij Kopiuj.
Krok 4: uruchom to na Arduino UNO
Otwórz swój projekt symulatora z odcinka 1: Arduino UNO i OLED SSD1306 podłączony do GND, 5V, A5 (SCL) i A4 (SDA), z biblioteką U8g2. Wklej kod do sketch.ino i naciśnij Play.
Koń galopuje. Po skompilowaniu dla UNO szkic raportuje:
Sketch uses 19324 bytes (59%) of program storage space. Maximum is 32256 bytes.
Global variables use 1558 bytes (76%) of dynamic memory, leaving 490 bytes for local variables. Maximum is 2048 bytes.To 59% flash, mniej niż 62% sprzed przycięcia czterech wierszy. Jak w odcinku 1, większość RAM to bufor ramki o rozmiarze 1024 bajtów.
Krok 5: wideo na ESP32
Zaimportuj wideo
Lopaka importuje też wideo (MP4, MOV i WebM). Użyliśmy klipu NASA Scientific Visualization Studio, który pokazuje cały miesiąc faz księżyca w dziesięć sekund.
Utwórz kolejny projekt U8g2 na 128×64, otwórz Animacje i kliknij Prześlij. Okno importu wideo wykonuje obliczenia, gdy zmieniasz ustawienia:
- Przy 30 klatkach na sekundę wideo dziesięć sekund daje 300 klatek na 64×64: 150 KiB.
- Powolny księżyc wygląda dobrze przy 12 klatkach na sekundę: wpisz
12, a stanie się to 120 klatek, 60 KiB. - Włącz Odwróć wynik. Lopaka zapala ciemne części obrazka, dlatego ciemny koń na jasnym tle wyszedł biały. Księżyc jest odwrotny, jasny na ciemnym niebie, więc odwróć wynik: teraz księżyc się zapala, a niebo pozostaje ciemne.
Tym razem zachowaj dithering Floyd-Steinberg: kropki rysują cieniowanie powierzchni księżyca.

Kliknij Importuj, a następnie Zapisz w edytorze klatek. Lopaka wyśrodkowuje animację 64×64 na ekranie, na X 32. Ponownie odznacz Pomocników animacji, a kod otrzyma animation_moon_frames[120][512] oraz linię animation_moon_frame = (animation_moon_frame + 1) % 120;.
60 KB: dwa razy więcej niż UNO, poniżej 5% ESP32
Przy 64 na 64 piksele każda klatka to 64 × 64 ÷ 8 = 512 bajtów, więc 120 klatek zajmuje 61 440 bajtów, 60 KB. To około dwa razy więcej niż cały flash UNO.

ESP32 ma 1 310 720 bajtów flash na program, a ten sam klip zajmuje 4,7% z tego.
Uruchom to na ESP32
Użyj tego samego szkicu z kodem księżyca w jego miejscu i zmień opóźnienie na delay(32);. ESP32 wysyła ramkę w około 51 milisekund w symulatorze, więc każda klatka zajmuje około 83 milisekund: 12 klatek na sekundę.
W symulatorze utwórz projekt ESP32, dodaj OLED SSD1306 i bibliotekę U8g2 oraz podłącz wyświetlacz do pinów I2C ESP32: GND do GND, VCC do 3V3, SCL do GPIO 22 i SDA do GPIO 21. Wklej szkic i naciśnij Play. Kompilator raportuje 352 240 bajtów, 26% flash, a księżyc rośnie i kurczy się przez cały miesiąc.

Podsumowanie
- Animacja to stos klatek, pokazywanych wystarczająco szybko, aby wyglądały jak ruch. Każde przejście
loop()czyści, rysuje jedną klatkę, wysyła ją i czeka. - Każda klatka kosztuje szerokość × wysokość ÷ 8 bajtów flash. Klatka na cały ekran na tym OLED to kilobajt, a UNO mieści ich około dwudziestu.
- Aby GIF się zmieścił, użyj mniejszej liczby klatek, mniejszych klatek lub większej płytki.
Następny odcinek: Interfejs dotykowy z LVGL. Ekrany dotykowe, z przyciskami i suwakami, jak w telefonie. Przeczytaj odcinek 8 lub obejrzyj go na YouTube.
Gotowy, aby spróbować? Otwórz Lopaka i ożyw własny GIF.