Przesyłanie obrazu z GIGA Display Shield przez WiFi
Pytanie
Jak przesłać obraz z GIGA Display Shield za pomocą WIFI do laptopa. Napisz program z wykorzystaniem #include "stm32h7xx.h"
#include "Arduino_H7_Video.h"
#include "lvgl.h"
#include "Arduino_GigaDisplayTouch.h"
Arduino_GigaDisplayTouch TouchDetector;
#include "Arduino_GigaDisplay_GFX.h"
zgłasza błąd //Compilation error: 'class GigaDisplay_GFX' has no member named 'getFramebuffer'; did you mean 'getBuffer'?
Arduino_GigaDisplay_GFX display;trzeba zamienić na
GigaDisplay_GFX display;
Odpowiedź Sztucznej Inteligencji
Bezpośrednia odpowiedź na pytanie
- Aby przesłać obraz z GIGA Display Shield do laptopa przez Wi‑Fi, najprościej uruchomić na GIGA R1 WiFi prosty serwer HTTP, który na żądanie zwróci zrzut ekranu jako plik BMP wygenerowany bezpośrednio z bufora ekranu (RGB565).
- Błąd kompilacji wynika z dwóch kwestii: należy utworzyć obiekt wyświetlacza jako GigaDisplayGFX display; (bez przedrostka Arduino) oraz użyć metody getBuffer(), a nie getFramebuffer(). Aktualne wersje biblioteki GigaDisplay_GFX udostępniają wskaźnik do bufora właśnie przez getBuffer(). (forum.arduino.cc)
- Upewnij się, że masz zainstalowaną bibliotekę Arduino_GigaDisplay_GFX (≥1.1.0) oraz core „Arduino Mbed OS GIGA Boards” w wersji co najmniej 4.0.6, jak wymaga to biblioteka. (arduinolibraries.info)
Szczegółowa analiza problemu
- Bufor ekranu GIGA Display Shield pracuje w formacie RGB565 (16 bit/piksel) i jest udostępniany przez GigaDisplay_GFX jako pamięć liniowa (uint16_t*) poprzez getBuffer(). To pozwala bezpośrednio wysłać 480×800×2 ≈ 768 kB danych bez kosztownej konwersji. Fragmenty kodu społeczności i przykłady operujące na pdisp->getBuffer() potwierdzają poprawny interfejs API. (forum.arduino.cc)
- W orientacji sprzętowej ekran ma 800×480, ale wewnętrzny canvas biblioteki jest 480×800 (portret). Dlatego najprościej wysłać BMP o wymiarach 480×800 zapisany „top‑down” (ujemna wysokość w nagłówku DIB), aby uniknąć odwracania wierszy. Przeglądarka poprawnie interpretuje RGB565, jeśli w nagłówku BMP użyjesz kompresji BI_BITFIELDS i masek 0xF800/0x07E0/0x001F.
- Błąd „has no member named getFramebuffer; did you mean getBuffer?” jest typowy, gdy kod bazuje na starszych/niewłaściwych przykładach (w Arduino_H7_Video istnieją funkcje dotyczące framebufferów, ale w GigaDisplay_GFX dostępny jest bufor przez getBuffer()). Dodatkowo, niewłaściwa deklaracja obiektu jako Arduino_GigaDisplay_GFX display; zamiast GigaDisplay_GFX display; prowadzi do dalszych konfliktów typów. Aktualna dokumentacja biblioteki GigaDisplay_GFX wymaga również zainstalowanego core’u GIGA 4.0.6+. (github.com)
Aktualne informacje i trendy
- Najnowsza znana wersja Arduino_GigaDisplay_GFX to 1.1.0 (wydana 9 maja 2025), a sama biblioteka wymaga core’u GIGA ≥4.0.6. Użytkownicy forum pokazują bieżące przykłady korzystania z getBuffer() do szybkich operacji na całych blokach pamięci. (arduinolibraries.info)
Wspierające wyjaśnienia i detale
- RGB565 w BMP: ustaw bpp=16 i BI_BITFIELDS z maskami R/G/B odpowiednio 0xF800/0x07E0/0x001F. Wysokość ujemna w DIB powoduje zapis „top‑down”, co odpowiada kolejności w buforze i eliminuje konieczność odwracania wierszy.
- Rozmiar przesyłanych danych: ~768 kB na żądanie. Wysyłaj w porcjach (np. 1024–1460 bajtów), aby nie zablokować stosu TCP.
Aspekty etyczne i prawne
- Zwracany strumień/obraz nie jest szyfrowany (HTTP). W sieciach współdzielonych uwzględnij prywatność i bezpieczeństwo – najlepiej pracować w zaufanej sieci lokalnej.
Praktyczne wskazówki
- Na GIGA R1 WiFi koniecznie podłącz do gniazda modułową antenę dostarczoną z płytką – bez niej transfer po Wi‑Fi może być niestabilny. (forum.arduino.cc)
- Do testów użyj przeglądarki (GET /frame.bmp) – nie potrzebujesz dodatkowego oprogramowania na laptopie.
- Jeśli chcesz pełny „stream”, pomyśl o MJPEG; pamiętaj jednak, że programowe kodowanie JPEG na STM32H7 jest kosztowne i spowolni GUI. Zacznij od pojedynczych zrzutów (on‑demand), a później ewentualnie dodaj prostą kompresję lub częściowe odświeżanie (delta).
Ewentualne zastrzeżenia lub uwagi dodatkowe
- Układ pamięci canvasa (480×800) może różnić się od aktualnej rotacji wyświetlacza; obraz BMP może być „portretowy”. Jeśli potrzebujesz 800×480 w „krajobrazie”, zrób transpozycję linii przy wysyłaniu (koszt CPU).
- Starsze wersje bibliotek/core’u mogły mieć różnice w API; aktualizacje przez Library Manager i Board Manager zwykle rozwiązują problemy. (arduinolibraries.info)
Sugestie dalszych badań
- Dokument „GIGA Display Shield – GFX Guide” oraz repozytorium Arduino_GigaDisplay_GFX (API, przykłady). (github.com)
- Wątki społeczności dotyczące optymalizacji kopiowania bufora i pracy z kamerą (przykłady użycia getBuffer()). (forum.arduino.cc)
Kod – serwer HTTP zwracający BMP (RGB565) z bufora ekranu
Uwaga: kompiluj dla Arduino GIGA R1 WiFi; wymaga zainstalowanego „Arduino Mbed OS GIGA Boards” i biblioteki Arduino_GigaDisplay_GFX (≥1.1.0).
// GIGA Display Shield -> WiFi -> BMP do przeglądarki
#include "stm32h7xx.h" // opcjonalnie
#include "Arduino_H7_Video.h" // opcjonalnie (wymagane przez ekosystem GIGA)
#include "lvgl.h" // jeśli używasz LVGL
#include "Arduino_GigaDisplayTouch.h"
#include "Arduino_GigaDisplay_GFX.h"
#include <WiFi.h>
GigaDisplay_GFX display; // POPRAWNIE: bez "Arduino_"
Arduino_GigaDisplayTouch TouchDetector;
#define BLACK 0x0000
#define WHITE 0xFFFF
// UWAGA: wewnętrzny canvas biblioteki ma 480x800 (portret)
static constexpr int CANVAS_W = 480;
static constexpr int CANVAS_H = 800;
static constexpr uint32_t BYTES_PER_PIXEL = 2;
static constexpr uint32_t IMAGE_SIZE = CANVAS_W * CANVAS_H * BYTES_PER_PIXEL;
const char* SSID = "Twoja_Siec";
const char* PASS = "Twoje_Haslo";
WiFiServer server(80);
static inline void write16(WiFiClient& c, uint16_t v) {
c.write((uint8_t)(v & 0xFF));
c.write((uint8_t)((v >> 8) & 0xFF));
}
static inline void write32(WiFiClient& c, uint32_t v) {
c.write((uint8_t)(v & 0xFF));
c.write((uint8_t)((v >> 8) & 0xFF));
c.write((uint8_t)((v >> 16) & 0xFF));
c.write((uint8_t)((v >> 24) & 0xFF));
}
void sendBMP(WiFiClient& client) {
// Nagłówki HTTP
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: image/bmp");
client.println("Connection: close");
client.println();
// BMP header (BITMAPFILEHEADER + BITMAPINFOHEADER + 3x bit masks)
const uint32_t fileHeader = 14;
const uint32_t dibHeader = 40;
const uint32_t masksSize = 12;
const uint32_t pixelDataOffset = fileHeader + dibHeader + masksSize;
const uint32_t fileSize = pixelDataOffset + IMAGE_SIZE;
// 'BM'
client.write('B'); client.write('M');
write32(client, fileSize);
write32(client, 0); // reserved
write32(client, pixelDataOffset); // offset do danych
// DIB (BITMAPINFOHEADER)
write32(client, dibHeader); // rozmiar DIB
write32(client, CANVAS_W); // szerokość
write32(client, (uint32_t)(-CANVAS_H)); // ujemna -> top-down
write16(client, 1); // planes
write16(client, 16); // bpp (RGB565)
write32(client, 3); // BI_BITFIELDS
write32(client, IMAGE_SIZE);
write32(client, 0); write32(client, 0); // ppm (X,Y)
write32(client, 0); write32(client, 0); // colorsUsed/Important
// Maski RGB565
write32(client, 0xF800); // R
write32(client, 0x07E0); // G
write32(client, 0x001F); // B
// Dane pikseli z bufora
uint8_t* fb = (uint8_t*)display.getBuffer(); // POPRAWNA metoda
if (!fb) return;
const size_t CHUNK = 1460; // przyjazne dla TCP/MTU
size_t sent = 0;
while (sent < IMAGE_SIZE) {
size_t n = IMAGE_SIZE - sent;
if (n > CHUNK) n = CHUNK;
client.write(fb + sent, n);
sent += n;
// pozwól stosowi TCP odetchnąć
delay(1);
}
}
void setup() {
Serial.begin(115200);
delay(500);
// Wyświetlacz
display.begin();
TouchDetector.begin();
// Prosta treść do testu
display.fillScreen(BLACK);
display.setTextColor(WHITE);
display.setTextSize(3);
display.setCursor(20, 40);
display.print("GIGA WiFi BMP demo");
// Wi-Fi
WiFi.begin(SSID, PASS);
Serial.print("Łączenie z Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print(".");
}
Serial.println();
Serial.print("IP: "); Serial.println(WiFi.localIP()); // otwórz w przeglądarce
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (!client) return;
// Prosta obsługa HTTP: czekaj na pustą linię (koniec nagłówków)
String req;
while (client.connected()) {
if (client.available()) {
char c = client.read();
req += c;
if (req.endsWith("\r\n\r\n")) break;
}
}
// Zwróć ramkę BMP niezależnie od ścieżki
sendBMP(client);
client.stop();
// prosty „heartbeat”: narysuj coś, by sprawdzić zmiany
static uint16_t col = 0x001F;
display.fillRect(20, 100, 200, 40, col);
col ^= 0x07E0; // zmieniaj kolor paska
}
Jak użyć:
- Wgraj szkic na GIGA R1 WiFi, podłącz antenę Wi‑Fi, odczytaj IP z Serial Monitora, otwórz w przeglądarce http://IP (np. http://192.168.1.50). Strona zwróci bezpośrednio obraz BMP będący zrzutem ekranu.
Jeśli wolisz klienta na laptopie:
- Możesz też wysyłać surowe RGB565 po TCP (bez BMP), a po stronie PC użyć prostego skryptu Python do odbioru i wyświetlenia – wówczas zredukujesz narzut nagłówka, ale przeglądarka nie otworzy takiego strumienia bezpośrednio.
Krótkie podsumowanie
- Zmień deklarację na GigaDisplay_GFX display; oraz pobieraj wskaźnik do obrazu przez display.getBuffer(); – tak przewiduje aktualne API. (forum.arduino.cc)
- Najprostsza transmisja do laptopa: jednorazowy zrzut w BMP przez HTTP (BI_BITFIELDS + RGB565).
- Zweryfikuj wersje: Arduino_GigaDisplay_GFX ≥1.1.0 i core GIGA ≥4.0.6, zgodnie z dokumentacją. (arduinolibraries.info)
Jeśli chcesz, przygotuję wariant „/stream” (MJPEG) oraz skrypt Pythona do odbioru surowego RGB565 i podglądu w czasie rzeczywistym.
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.
Zadaj dodatkowe pytanie Sztucznej Inteligencji