Przewodnik U8g2 po wyświetlaczach OLED i LCD dla Arduino
Ten przewodnik prowadzi nowy projekt U8g2 od pustego obszaru rysowania w Lopaka do działającego szkicu Arduino. Lopaka tworzy kod rysowania; ty podłączasz i inicjujesz wyświetlacz, wybierasz sposób jego buforowania i decydujesz, kiedy pokazywany jest każdy ekran.
Czym jest U8g2?
U8g2 to biblioteka graficzna dla monochromatycznych wyświetlaczy OLED i LCD. Obsługuje wiele kontrolerów, prymitywy rysowania, bitmapy oraz dużą kolekcję czcionek. Lopaka korzysta z graficznego API U8g2, a nie z tekstowego API U8x8.
Skorzystaj z oficjalnego samouczka konfiguracji oraz listy konstruktorów, aby potwierdzić, że U8g2 obsługuje dokładnie twój wyświetlacz.
Zanim zaczniesz
Potrzebujesz:
- Mikrokontrolera i monochromatycznego wyświetlacza obsługiwanego przez U8g2.
- Nazwy kontrolera wyświetlacza, rozdzielczości i interfejsu: na przykład SSD1306, 128×64, sprzętowe I2C.
- Arkusza danych wyświetlacza lub przewodnika okablowania od producenta.
- Projektu zgodnego z Arduino, który potrafi skompilować i wgrać podstawowy szkic.
Uwaga
Lopaka nie wykrywa twojego sprzętu. Dwa moduły, które wyglądają tak samo, mogą mieć różne kontrolery, adresy, wyprowadzenia pinów lub przesunięcia wyświetlacza.
Krok 0: Zainstaluj i przetestuj U8g2
W Arduino IDE otwórz Tools → Manage Libraries, wyszukaj U8g2 i zainstaluj bibliotekę autorstwa olikraus. Jest to metoda instalacji opisana w oficjalnym repozytorium U8g2.
Aby zainstalować ręcznie w Arduino, pobierz oficjalną dystrybucję U8g2 dla Arduino i dodaj jej plik ZIP przez Sketch → Include Library → Add .ZIP Library. Inne środowiska (toolchain) mogą korzystać z tej samej oficjalnej dystrybucji w ramach swojego procesu zarządzania zależnościami bibliotek. Preferuj wydaną wersję, chyba że potrzebujesz konkretnej, jeszcze niewydanej zmiany z repozytorium.
Zanim dodasz kod z Lopaka, skompiluj i wgraj jeden z przykładów U8g2 dla swojego wyświetlacza. Działający przykład potwierdza, że konstruktor, okablowanie i instalacja biblioteki są poprawne.
Krok 1: Wybierz konstruktor wyświetlacza
Nazwa konstruktora określa cztery ważne rzeczy:
| Część | Przykład | Znaczenie |
|---|---|---|
| Kontroler i wyświetlacz | SSD1306_128X64_NONAME | Rodzina sprzętu i rozdzielczość |
| Bufor | F, 1 lub 2 | Pełny bufor ekranu lub bufor stronicowy |
| Interfejs | HW_I2C, SW_I2C, 4W_HW_SPI itd. | Magistrala i implementacja |
| Argumenty | U8G2_R0, piny reset i magistrali | Obrót i okablowanie |
Na przykład:
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(
U8G2_R0,
U8X8_PIN_NONE
);Jest to tylko przykładowy konstruktor dla jednego wyświetlacza SSD1306 128×64 ze sprzętowym I2C. Zastąp go dokładnym konstruktorem i argumentami z oficjalnej listy konfiguracji C++.
Pełny bufor czy bufor stronicowy?
- Konstruktor zawierający
_F_przechowuje całą klatkę w pamięci RAM. Rysuj pomiędzyclearBuffer()asendBuffer(). - Konstruktor zawierający
_1_lub_2_używa mniejszego bufora stronicowego. Umieść kompletną funkcję rysowania wewnątrz pętli obrazufirstPage()/nextPage().
Tryb pełnego bufora jest prostszy i szybszy, ale zużywa więcej pamięci RAM. Dla obrazu jednobitowego 128×64 sam bufor pikseli zajmuje 1 024 bajty. Tryb stronicowy zużywa mniej pamięci RAM, ale rysuje ten sam obraz dla każdej strony. Zobacz przewodnik po trybach bufora biblioteki U8g2.
Krok 2: Utwórz projekt w Lopaka
- Otwórz lopaka.app i utwórz projekt.
- Wybierz U8g2 jako platformę.
- Ustaw Rozmiar ekranu na logiczną szerokość i wysokość wyświetlacza. Dla nieobróconego wyświetlacza 128×64 użyj
128 × 64. - Pozostaw domyślne czarne tło. Wyjście U8g2 ma jeden bit na piksel, więc projekty Lopaka opierają się na kontraście pierwszoplanowym i tła, a nie na kolorach RGB.
Rozmiar obszaru rysowania w Lopaka określa powierzchnię projektową i układ współrzędnych; nie wybiera konstruktora U8g2 ani nie konfiguruje fizycznego wyświetlacza.
Krok 3: Zaprojektuj ekran
Użyj edytora, aby umieścić tekst, obrazy i prymitywy rysowania. Pozycja (0, 0) to lewy górny róg obszaru rysowania. Zmień nazwy warstw przed eksportem: nazwy stają się komentarzami, identyfikatorami obrazów, nagłówkami animacji i opcjonalnymi nazwami zmiennych.
Projekty U8g2 w Lopaka obsługują następujące generowane elementy:
| Warstwa Lopaka | Wyjście Arduino U8g2 |
|---|---|
| Linia | drawLine() |
| Prostokąt | drawFrame() / drawBox() |
| Zaokrąglony prostokąt | drawRFrame() / drawRBox() |
| Elipsa | drawEllipse() / drawFilledEllipse() |
| Trójkąt | drawTriangle(); w inspektorze U8g2 w Lopaka zawsze wypełniony |
| Wielokąt | Funkcja pomocnicza zbudowana z zamkniętych wywołań drawLine(); tylko kontur |
| Tekst | setFont() oraz drawStr() lub drawUTF8() |
| Malowanie, ikona lub zaimportowany obraz | Monochromatyczna tablica XBM oraz drawXBM() lub drawXBMP() |
| Animacja | Dane/nagłówek klatek oraz funkcje pomocnicze wyboru i rysowania klatek |
Pierwszy plan, tło i odwrócenie
Projekt U8g2 jest monochromatyczny, więc inspektor nie pokazuje selektora kolorów RGB. Zwykłe warstwy ustawiają piksele; warstwy odwrócone używają koloru rysowania U8g2 2 (XOR). Lopaka generuje również przezroczyste tryby czcionek i bitmap, aby puste piksele w tekście i obrazach nie wymazywały warstw znajdujących się pod nimi.
U8g2 zaznacza, że XOR nie jest obsługiwany przez każdy prymityw, w tym procedury elips. Sprawdź odwrócone kształty na prawdziwym wyświetlaczu; zobacz setDrawColor.
Pozycja i linia bazowa tekstu
Współrzędne kształtów używają ich normalnych punktów początkowych U8g2. Tekst używa linii bazowej czcionki, a nie górnej krawędzi widocznych liter. Zmiana czcionki może więc zmienić pozorne wyrównanie w pionie, nawet gdy warstwa tekstowa zachowuje tę samą pozycję.
Tekst można obracać o 0°, 90°, 180° lub 270°. Lopaka w razie potrzeby generuje setFontDirection(). Szczegóły dotyczące współrzędnych znajdziesz w dokumentacji API U8g2.
Krok 4: Skonfiguruj wygenerowany kod
Otwórz Ustawienia kodu i wybierz Arduino (Cpp) dla szkicu Arduino. U8g2 ma również opcję składni ESP-IDF (C) dla projektów, które już używają interfejsu C biblioteki U8g2; nie jest to kompletna aplikacja ESP-IDF ani port sprzętowy.
| Ustawienie | Co zmienia w U8g2 |
|---|---|
| Funkcja opakowująca | Opakowuje aktywny ekran w void draw{ScreenName}(void) |
| Deklaruj jako PROGMEM | Używa U8X8_PROGMEM i drawXBMP() dla deklaracji bitmap Arduino |
| Dołącz czcionki | Dołącza pobrane nagłówki czcionek niestandardowych; wbudowane czcionki U8g2 nie wymagają nagłówka |
| Deklaruj obrazy | Generuje tablice bitmap używane przez warstwy malowania i obrazów |
| Dołącz pliki obrazów | Generuje #include "image_<Name>_bits.h" zamiast tablic bitmap w kodzie |
| Funkcje pomocnicze animacji | Dołącza pobrane nagłówki animacji i generuje funkcje pomocnicze czasu/rysowania |
| Deklaruj zmienne | Generuje deklaracje dla właściwości warstw oznaczonych jako zmienne |
| Komentarze, tytuły warstw | Dodaje komentarze z nazwami warstw do statycznego wyjścia |
| Wyczyść/wypełnij wyświetlacz | Rozpoczyna blok rysowania od u8g2.clearBuffer() (Arduino) lub u8g2_ClearBuffer() (ESP-IDF); zobacz uwagę poniżej |
Pozostaw wszystkie funkcje włączone, z wyjątkiem Wyczyść/wypełnij wyświetlacz w Arduino.
Wyczyść/wypełnij wyświetlacz w Arduino
W szablonie Arduino opcja Wyczyść/wypełnij wyświetlacz jest domyślnie wyłączona. Gdy ją włączysz, funkcja draw{ScreenName}() rozpoczyna się od u8g2.clearBuffer(), co wymazuje wszystko, co twój szkic narysował w buforze przed jej wywołaniem. Pozostaw ją wyłączoną, jeśli twój loop() już czyści bufor lub najpierw rysuje inną treść. Opcja jest pomijana, gdy włączone są Funkcje pomocnicze animacji, ponieważ pętla animacji firstPage()/nextPage() już czyści każdą stronę. Szablon ESP-IDF pozostawia ją domyślnie włączoną.
Krok 5: Eksportuj czcionki i obrazy
Wbudowane czcionki
Lopaka zna listę wbudowanych czcionek U8g2 i dostosowuje wygenerowany kod do wybranej czcionki. Gdy czcionka jest wbudowana w U8g2, Lopaka bezpośrednio generuje jej symbol biblioteki i nie tworzy ani nie oferuje osobnego nagłówka czcionki do pobrania. Na przykład:
u8g2.setFont(u8g2_font_6x10_tr);W przypadku czcionki, której nie ma na liście wbudowanych, Lopaka traktuje ją jako czcionkę niestandardową, generuje jeden pasujący include nagłówka i umieszcza ten nagłówek w sekcji Ustawienia kodu → Czcionki do pobrania.
Rozmiary wbudowanych czcionek są stałe; wybierz inną czcionkę, aby powiększyć lub pomniejszyć tekst. Skorzystaj z oficjalnej listy czcionek U8g2, aby sprawdzić pokrycie znaków.
Czcionki niestandardowe
Projekty U8g2 akceptują czcionki BDF i mogą importować TTF, OTF lub WOFF za pomocą kreatora czcionek o stałym rozmiarze w Lopaka. W sekcji Ustawienia kodu → Czcionki:
- Pobierz każdy wymieniony niestandardowy plik
.h. - Umieść nagłówki obok swojego szkicu lub wygenerowanego kodu źródłowego.
- Pozostaw opcję Dołącz czcionki włączoną, aby wygenerowane linie
#include "Font_Name.h"pozostały obecne.
Opcja Renderuj tylko używane glify tworzy mniejszy nagłówek zawierający znaki aktualnie używane przez pasujące warstwy tekstowe. Jeśli wartość tekstowa jest zmienną w czasie wykonywania, Lopaka eksportuje pełną czcionkę niestandardową, ponieważ nie może przewidzieć przyszłych znaków.
Obrazy i animacje
Obrazy statyczne są konwertowane na jednobitowe dane XBM i mogą być deklarowane bezpośrednio w kopiowanym kodzie źródłowym. Przy włączonej opcji Deklaruj jako PROGMEM Lopaka używa U8X8_PROGMEM i drawXBMP(), zgodnie z wytycznymi dotyczącymi bitmap PROGMEM biblioteki U8g2.
Sekcja Ustawienia kodu → Obrazy wymienia każdy obraz jako image_<Name>_bits.h, zawierający dokładnie te bajty XBM, które otrzymuje wywołanie rysowania. Włącz opcję Dołącz pliki obrazów, aby generować #include "image_<Name>_bits.h" zamiast tablicy i przechowywać piksele w pobranym nagłówku.
Animacje również są monochromatyczne. Pobierz każdy plik .h wymieniony w sekcji Animacje, umieść go wraz ze szkicem i zachowaj wygenerowany include oraz kod pomocniczy. Funkcja pomocnicza Arduino wybiera klatki za pomocą millis(). Nadal odpowiadasz za wywoływanie funkcji pomocniczej aktualizacji i ponowne rysowanie kompletnego ekranu w prawidłowej pętli bufora.
Uwaga
Wyjście animacji może zawierać startowy kod setup() i loop(). Połącz jego include'y, aktualizację klatek i funkcje pomocnicze rysowania ze swoim szkicem, a następnie użyj wzorca odświeżania z pełnym buforem lub buforem stronicowym z tego przewodnika. Nie zachowuj drugiego setup() ani loop().
Krok 6: Skopiuj i zintegruj kod
Utwórz ekran o nazwie Main, dodaj warstwę tekstową i ramkę, a następnie kliknij Kopiuj w panelu kodu Lopaka. Przykładowa wygenerowana funkcja rysowania wygląda tak:
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);
}Twój dokładny kod będzie używał nazwy twojego ekranu, warstw, czcionek i współrzędnych.
Minimalny szkic z pełnym buforem
Używaj tego wzorca tylko z konstruktorem _F_:
#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();
}Alternatywa z buforem stronicowym
Użyj tego wzorca pętli obrazu z konstruktorem _1_ lub _2_:
void loop(void) {
u8g2.firstPage();
do {
drawMain();
} while (u8g2.nextPage());
}Nie aktualizuj stanu interfejsu użytkownika wewnątrz drawMain() w trybie stronicowym. U8g2 wywołuje ją więcej niż raz, aby zbudować jedną klatkę, a każde przejście musi narysować ten sam obraz. Aktualizuj wartości czujników, stan nawigacji i wybór klatek animacji przed firstPage().
Krok 7: Dodaj dane w czasie wykonywania i więcej ekranów
Aby wartość była dynamiczna, wybierz jej właściwość w inspektorze, włącz jej przełącznik zmiennej i pozostaw opcję Deklaruj zmienne włączoną. Lopaka zastąpi wtedy literał nazwaną deklaracją opartą na nazwie warstwy. Twoja aplikacja może zaktualizować tę wartość przed następnym przerysowaniem.
Każdy ekran Lopaka eksportuje się osobno, a jego tytuł staje się nazwą funkcji rysowania. Skopiuj funkcję każdego ekranu do projektu, połącz wspólne include'y i zasoby tak, aby były deklarowane tylko raz, a następnie wybierz, którą funkcję wywołać:
enum Screen { MAIN, DETAILS };
Screen currentScreen = MAIN;
void drawCurrentScreen(void) {
if (currentScreen == MAIN) {
drawMain();
} else {
drawDetails();
}
}Lopaka nie generuje nawigacji między ekranami, obsługi przycisków, menu, odczytów czujników ani stanu aplikacji.
Co robi Lopaka, a co robisz ty
| Lopaka robi | Ty robisz |
|---|---|
| Układ pikseli i kolejność warstw | Okablowanie wyświetlacza, napięcie i mapowanie pinów |
| Wywołania rysowania U8g2 dla obsługiwanych warstw | Dokładny konstruktor kontrolera/interfejsu/bufora |
| Odniesienia do wbudowanych czcionek | Instalację U8g2 i środowiska (toolchain) płytki |
| Konwersję czcionek niestandardowych i nagłówki do pobrania | Przechowywanie nagłówków niestandardowych wraz z kodem źródłowym |
| Jednobitowe deklaracje bitmap | Budżet RAM/flash i wybór bufora |
| Opcjonalne zmienne i funkcje pomocnicze animacji | begin(), pętlę odświeżania, taktowanie i stan aplikacji |
| Nazwaną funkcję rysowania dla każdego wyeksportowanego ekranu | Wejścia, nawigację, czujniki i moment przerysowania |
Kompiluj, wgrywaj i iteruj
- Kompiluj przed wgraniem. Najpierw rozwiąż każdy problem brakującego nagłówka lub symbolu.
- Wgraj i porównaj fizyczny wyświetlacz z obszarem rysowania Lopaka.
- W razie potrzeby dostosuj konstruktor, obrót, rozmiar obszaru rysowania lub pozycje warstw.
- Gdy projekt się zmieni, zastąp kompletną wygenerowaną sekcję, zamiast edytować pojedyncze wygenerowane wywołania w kilku miejscach.
Przechowuj kod sprzętowy i aplikacyjny poza wygenerowaną sekcją, aby świeży eksport nie mógł go nadpisać:
// BEGIN LOPAKA GENERATED CODE
// Replace this entire block after exporting again.
// END LOPAKA GENERATED CODERozwiązywanie problemów
Wyświetlacz jest pusty
- Najpierw wgraj oficjalny przykład U8g2 używający tego samego konstruktora. Jeśli on też jest pusty, sprawdź zasilanie, masę, okablowanie, kontroler, pin reset i interfejs.
- Potwierdź, że
u8g2.begin()jest wykonywane raz. - Potwierdź, że rysowanie odbywa się pomiędzy
clearBuffer()/sendBuffer()dla_F_lub wewnątrz kompletnej pętlifirstPage()/nextPage()dla_1_i_2_. - W przypadku I2C przeskanuj magistralę i porównaj wynik z dokumentacją modułu. Jeśli wywołujesz
setI2CAddress(), U8g2 oczekuje adresu pomnożonego przez dwa, a wywołanie musi nastąpić przedbegin(); zobacz oficjalną dokumentację.
Obraz jest przesunięty, przycięty, odbity lub obrócony
Sprawdź, czy obszar rysowania Lopaka odpowiada logicznemu rozmiarowi wyświetlacza konstruktora. Wybierz dokładny wariant kontrolera/wyświetlacza: niektóre moduły mają pamięć RAM kontrolera szerszą niż widoczny panel. Użyj U8G2_R0 do U8G2_R3 w konstruktorze do obrotu wyświetlacza, a następnie utrzymuj wymiary Lopaka zgodne z tą orientacją.
Kolory lub nakładające się kształty wyglądają na odwrócone
Wyjście U8g2 jest jednobitowe, nie w skali szarości ani RGB. Wyłącz opcję odwrócone na warstwie, jeśli XOR był niezamierzony. XOR nie jest obsługiwany przez każdy prymityw U8g2, więc odwrócone elipsy należy zweryfikować na sprzęcie.
Czcionka lub symbol jest niezdefiniowana
- Nazwy wbudowane muszą istnieć w zainstalowanym wydaniu U8g2 i zawierać używane przez ciebie glify.
- W przypadku czcionki niestandardowej pobierz jej plik
.h, przechowuj go obok kodu źródłowego i pozostaw opcję Dołącz czcionki włączoną. - Jeśli znaki są puste, wyłącz opcję Renderuj tylko używane glify i wyeksportuj czcionkę niestandardową ponownie, zwłaszcza gdy tekst zmienia się w czasie wykonywania.
Brakuje pamięci w szkicu
Wypróbuj konstruktor bufora stronicowego _1_ lub _2_, mniejsze obrazy, mniej klatek animacji lub czcionki niestandardowe zawierające tylko wymagane glify. Wbudowane czcionki i zasoby zużywają pamięć flash; pełny bufor wyświetlacza zużywa pamięć RAM.
Obrazy wyglądają szorstko lub odwrócone
Obrazy U8g2 są jednobitowe, więc wybory dotyczące rozmiaru, przycinania, kontrastu, progu i ditheringu mają znaczenie. Otwórz ponownie edytor obrazów w Lopaka i zobacz podgląd w docelowym rozmiarze pikseli. Utrzymuj opcję Deklaruj jako PROGMEM zgodną z wygenerowaną deklaracją i wywołaniem drawXBMP().
Tryb stronicowy migocze lub pokazuje tylko część ekranu
Wywołuj kompletną funkcję rysowania wewnątrz pętli obrazu do / while. Nie rysuj niektórych warstw przed firstPage(), nie zmieniaj wartości pomiędzy stronami ani nie wywołuj tylko firstPage() bez nextPage().
Częste pytania
Czy Lopaka konfiguruje mój wyświetlacz SSD1306 lub SH1106?
Nie. Lopaka generuje kod rysowania. Ty wybierasz pasujący konstruktor, magistralę, piny, adres, obrót, tryb bufora i inicjowanie.
Czy mogę zamiast tego użyć U8x8?
Nie z wyjściem U8g2 z Lopaka. U8x8 to osobne API, wyłącznie tekstowe, i nie obsługuje prymitywów graficznych generowanych przez Lopaka.
Czy Lopaka może generować kolorowy kod U8g2?
Nie. Platforma U8g2 w Lopaka jest monochromatyczna. Dla wyświetlacza RGB wybierz kolorową platformę, taką jak TFT_eSPI lub ArduinoGFX.
Czy eksport ESP-IDF (C) jest kompletnym projektem oprogramowania układowego?
Nie. Generuje kod rysowania interfejsu C oraz zasoby. Twój projekt ESP-IDF musi skonfigurować strukturę U8g2, wywołania zwrotne GPIO/magistrali, pętlę zadań, inicjowanie i integrację z platformą.