ESP32 écran, affichage d'un fond de carte

De Wiki de Mémoire Vive
Aller à la navigation Aller à la recherche

L'objectif serait de pouvoir afficher un fond de carte sur un module ESP32 écran, par exemple pour suivre des positions GPS.

Pour l'instant il ne s'agit que de la partie affichage, mais qui ne fonctionne pas. Le test porte sur la récupération d'une tuile (un morceau de carte), c'est à dire d'un fichier d'une image en format PNG. La récupération se fait bien, mais pas l'affichage. C'est la bibliothèque PNGdec qui est utilisée.

Voici le code, à ce stade,

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <TFT_eSPI.h>
#include <PNGdec.h>

const char* ssid = "2.4GHz-MEMOIRE-VIVE";
const char* password = "************";
TFT_eSPI tft = TFT_eSPI();
PNG png;

int pngDraw(PNGDRAW *pDraw) {
  static int offsetX = 0;
  static int offsetY = 0;
  if (pDraw->y == 0) {
    int width = pDraw->iWidth;
    int height = png.getHeight();
    offsetX = (tft.width() - width) / 2;
    offsetY = (tft.height() - height) / 2;
    Serial.printf("Image %dx%d centrée à (%d,%d)\n", width, height, offsetX, offsetY);
  }
  static uint16_t lineBuffer[512]; // en principe l'image est <= 256
  png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_LITTLE_ENDIAN, 0xFFFF);
  tft.pushImage(offsetX, offsetY + pDraw->y, pDraw->iWidth, 1, lineBuffer);
  return 1;
}

void showTile(int zoom, int x, int y) {
  Serial.printf("Free heap avant téléchargement: %d\n", ESP.getFreeHeap());

  WiFiClientSecure client;
  client.setInsecure();
  HTTPClient https;
  char url[128];
  sprintf(url, "https://tile.openstreetmap.org/%d/%d/%d.png", zoom, x, y);
  Serial.println(url);

  if (!https.begin(client, url)) {
    Serial.println("Erreur HTTPS.begin()");
    return;
  }

  https.addHeader("User-Agent", "Mozilla/5.0 (ESP32) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/604.1");
  int httpCode = https.GET();
  if (httpCode != HTTP_CODE_OK) {
    Serial.printf("Erreur HTTP: %d\n", httpCode);
    Serial.printf("Réponse: %s\n", https.getString().c_str());
    https.end();
    return;
  }

  int len = https.getSize();
  if (len <= 0 || len >= 50000) {
    Serial.println("Taille invalide !");
    https.end();
    return;
  }

  uint8_t *buf = (uint8_t*)malloc(len);
  if (!buf) {
    Serial.println("Erreur malloc !");
    https.end();
    return;
  }

  WiFiClient *stream = https.getStreamPtr();
  int index = 0;
  while (https.connected() && index < len) {
    int bytes = stream->read(buf + index, len - index);
    if (bytes <= 0) break;
    index += bytes;
  }
  Serial.printf("Téléchargé %d octets\n", index);

  // Calculer un checksum simple pour vérifier l'intégrité
  uint32_t checksum = 0;
  for (int i = 0; i < index; i++) {
    checksum += buf[i];
  }
  Serial.printf("Checksum du buffer: %u\n", checksum);

  // Afficher le "magic number"
  Serial.print("Magic number: ");
  for (int i = 0; i < 8; i++) {
    Serial.printf("%02X ", buf[i]);
  }
  Serial.println();

  // Essayer de décoder le PNG
  int rc = png.openRAM(buf, index, pngDraw);
  Serial.printf("Résultat openRAM = %d\n", rc);

  if (rc == PNG_SUCCESS) {
    tft.startWrite();
    tft.fillScreen(TFT_BLACK);
    png.decode(NULL, 0);
    tft.endWrite();
    Serial.println("Tuile affichée !");
  } else {
    Serial.printf("Erreur PNG (%d)\n", rc);
    // Afficher le début du buffer comme texte (pour voir s'il y a une erreur cachée)
    buf[min(index, len - 1)] = '\0';
    Serial.println("Contenu du buffer (début, 100 premiers octets):");
    for (int i = 0; i < min(100, index); i++) {
      Serial.printf("%02X ", buf[i]);
      if ((i + 1) % 20 == 0) Serial.println();
    }
    Serial.println();
  }

  free(buf);
  https.end();
  png.close();
  Serial.printf("Free heap après libération: %d\n", ESP.getFreeHeap());
}


void setup() {
  Serial.begin(115200);
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);

  Serial.printf("Connexion WiFi à %s...", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connecté !");
  Serial.println(WiFi.localIP());

  // Affichage du message de chargement
  tft.fillScreen(TFT_BLUE);
  tft.setTextColor(TFT_WHITE, TFT_BLUE);
  delay(1000);
  tft.fillScreen(TFT_RED);
  delay(1000);
  tft.fillScreen(TFT_GREEN);
  delay(1000);
  tft.fillScreen(TFT_WHITE);
  delay(1000);
  tft.setTextDatum(MC_DATUM);
  tft.drawString("Chargement carte...", tft.width()/2, tft.height()/2);

  showTile(15, 16614, 11304);
}

void loop() {
}