Codificar JPG en bucle con ILI9488 y ESP32

Hola Buenos días, soy un nuevo usuario de microcontroladores, en concreto el ESP32.
Estoy empezando con estos dispositivos y me llama lo relacionado con la lectura desde SD y pantallas, así que quería empezar montando un visualizador de imágenes JPG.
Por ahora estoy haciendo uso de los ejemplos de las librerías y tutoriales de Youtube, pero he llegado a un punto en el que necesito pedir ayuda.
Primero me gustaría argumentar mi proyecto:
Estoy intentando que mediante una pantalla ILI9488 con SD, el ESP32 codifique JPG mediante la librería TJpg_Decoder.
Para ello he tirado de un ejemplo denominado SD_Jpg, que se encuentra dentro de la librería, lo he modificado para que me de información de la SD y para que lea los archivos de la misma y los pase haciendo loop cada 2s.
El problema es que si pruebo solo con el ejemplo sin hacer cambios, me muestra una imagen predeterminada, pero mi objetivo es que me de algo mas de información por el monitor serie y ademas que muestre todas las imagenes JPg que tenga en la SD.
Pero al hacer los cambios que yo necesito el Monitor serie me dice que la imagen no funciona:

12:12:26.582 -> ����SD Card Type: SDHC

12:12:26.755 -> SD Card Size: 7680MB

12:12:26.755 -> initialisation done.

12:12:27.668 -> Jpeg file not found

12:12:27.668 -> 770 ms

12:12:29.987 -> Jpeg file not found

12:12:29.987 -> 3383 ms

12:12:32.274 -> Jpeg file not found

12:12:32.274 -> 3078 ms

Como se ve en el LOG, la SD la inicializa bien, encuentra las imágenes y me da los ms, pero no muestra nada en pantalla.

Les dejo el código (siento el desastre soy bastante novato) por si alguien puede orientarme donde puede estar el problema, por que necesito entender que esta sucediendo o que estoy haciendo mal, para poder solucionarlo:

// Example for library:
// https://github.com/Bodmer/TJpg_Decoder

// Include the jpeg decoder library
#include <TJpg_Decoder.h>

#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
  #include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
   // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}


void setup()
{
  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

 if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  Serial.println("initialisation done.");
}

void loop()
{
  tft.fillScreen(TFT_RED);

  // Time recorded for test purposes
  uint32_t t = millis();
  File file;
  File root = SD.open("/");
  if(!root){
      Serial.println("Failed to open root directory");
      return;
  }
  file = root.openNextFile();  // Opens next file in root
  while(file)
{
    if(!file.isDirectory())
    {

  // Get the width and height in pixels of the jpeg if you wish
  uint16_t w = 0, h = 0;
 // TJpgDec.getSdJpgSize(file.name(),&w, &h, "/panda.jpg");
 // Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);

  // Draw the image, top left at 0,0
  TJpgDec.drawSdJpg(0, 0, file.name());

  // How much time did rendering take
  t = millis() - t;
  Serial.print(t); Serial.println(" ms");

  // Wait before drawing again
  delay(2000);
}

    file = root.openNextFile();  // Opens next file in root
  }
  
  root.close();
}

Les agradezco enormemente su ayuda.
Un saludo.

Quizás algo como esto podría funcionar (no probado, escrito aquí basado en tu código)

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");

  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Opens next file in root
  while (file) {
    if (!file.isDirectory()) {
      // Get the width and height in pixels of the jpeg if you wish
      uint16_t w = 0, h = 0;
      TJpgDec.getSdJpgSize(&w, &h, file.name());
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, file.name());     // Draw the image, top left at 0,0
      chrono = millis() - chrono;               // How much time did rendering take
      Serial.print("Width = "); Serial.print(w);
      Serial.print(", height = "); Serial.println(h);
      Serial.print(t); Serial.println(" ms");
      delay(2000);                              // Wait before drawing again
    }
    file = root.openNextFile();  // Opens next file in root
  }
  root.close();
}

void loop() {}

Le agradezco muchísimo que se haya tomado su tiempo para revisar el código, pero no muestra nada en pantalla, continua diciendo que file not found:

13:59:35.057 -> �?�Jpeg file not found
13:59:35.722 -> Jpeg file not found
13:59:35.722 -> Width = 0, height = 0
13:59:38.013 -> Jpeg file not found
13:59:38.013 -> Jpeg file not found
13:59:38.052 -> Width = 0, height = 0

¿Podría orientarme explicándome el motivo de los cambios que ha echo? estoy interesado mas en saber donde esta mi fallo y el porque, de que no funcione bien.
Un saludo.

Simplemente puse el código en la configuración y modifiqué la llamada para obtener el tamaño usando el nombre del archivo.

¿Puedes imprimir el nombre tal como lo ve la función?

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");

  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Opens next file in root
  while (file) {
    if (!file.isDirectory()) {
      Serial.print("file.name() = ");  Serial.println(file.name());  // <=========
      // Get the width and height in pixels of the jpeg if you wish
      uint16_t w = 0, h = 0;
      TJpgDec.getSdJpgSize(&w, &h, file.name());
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, file.name());     // Draw the image, top left at 0,0
      chrono = millis() - chrono;               // How much time did rendering take
      Serial.print("Width = "); Serial.print(w);
      Serial.print(", height = "); Serial.println(h);
      Serial.print(t); Serial.println(" ms");
      delay(2000);                              // Wait before drawing again
    }
    file = root.openNextFile();  // Opens next file in root
  }
  root.close();
}

void loop() {}

Si, aparecen los nombres de las imágenes:

14:15:52.612 -> Jpeg file not found

14:15:52.612 -> Width = 0, height = 0

14:15:54.939 -> file.name() = tiger.jpg

14:15:54.939 -> Jpeg file not found

14:15:54.939 -> Jpeg file not found

14:15:54.939 -> Width = 0, height = 0

14:15:57.230 -> file.name() = lena20k.jpg

14:15:57.230 -> Jpeg file not found

14:15:57.230 -> Jpeg file not found

14:15:57.230 -> Width = 0, height = 0

14:15:59.541 -> file.name() = Baboon40.jp

Eso si obtengo un error al compilar por la linea:

107 Serial.print(t); Serial.println(" ms");

La he comentado por que es algo que por ahora no me preocupa. Solo es por reportar todos los fallos a modo de documentación.

➜ chrono...

¿Puedes intentar esto para ver si es la función de dibujo la que no puede encontrar el archivo o la que calcula el tamaño?

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");

  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Opens next file in root
  while (file) {
    if (!file.isDirectory()) {

      Serial.print("El archivo actual:");  Serial.println(file.name());

      // Get the width and height in pixels of the jpeg if you wish
      uint16_t w = 0, h = 0;
      Serial.print("Image size"); Serial.flush();
      TJpgDec.getSdJpgSize(&w, &h, file.name());
      Serial.print("ancho = "); Serial.print(w);
      Serial.print(", alto = "); Serial.println(h); Serial.flush();


      Serial.print("tiempo de visualización = "); Serial.flush();
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, file.name());     // Draw the image, top left at 0,0
      chrono = millis() - chrono;               // How much time did rendering take
      Serial.print(t); Serial.println(" ms");
      delay(2000);                              // Wait before drawing again
    }
    file = root.openNextFile();  // Opens next file in root
  }
  root.close();
}

void loop() {}

He solucionado el error de compilación, no había definido "t" error mio.
También he compilado con sus correcciones:

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");

  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Opens next file in root
  while (file) {
    if (!file.isDirectory()) {

      Serial.print("El archivo actual:");  Serial.println(file.name());

      // Get the width and height in pixels of the jpeg if you wish
      uint16_t w = 0, h = 0;
      Serial.print("Image size"); Serial.flush();
      TJpgDec.getSdJpgSize(&w, &h, file.name());
      Serial.print("ancho = "); Serial.print(w);
      Serial.print(", alto = "); Serial.println(h); Serial.flush();

uint32_t t = millis();
      Serial.print("tiempo de visualización = "); Serial.flush();
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, file.name());     // Draw the image, top left at 0,0
      chrono = millis() - chrono;               // How much time did rendering take
      t = millis() - t;
      Serial.print(t); Serial.println(" ms");
      
      delay(2000);                              // Wait before drawing again
    }
    file = root.openNextFile();  // Opens next file in root
  }
  root.close();
}

void loop() {}

Ya calcula los ms pero continua con "file not found"

 �JF�El archivo actual:cats.jpg
Image sizeJpeg file not found
ancho = 0, alto = 0
tiempo de visualización = Jpeg file not found
2 ms
El archivo actual:girl.jpg
Image sizeJpeg file not found
ancho = 0, alto = 0
tiempo de visualización = Jpeg file not found
2 ms

La biblioteca podría necesitar el "/" delante del nombre de archivo.

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              // Hardware-specific library
TFT_eSPI tft = TFT_eSPI();         // Invoke custom library


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT.  If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Stop further decoding as image is running off bottom of screen
  if ( y >= tft.height() ) return 0;

  // This function will clip the image block rendering automatically at the TFT boundaries
  tft.pushImage(x, y, w, h, bitmap);

  // This might work instead if you adapt the sketch to use the Adafruit_GFX library
  // tft.drawRGBBitmap(x, y, bitmap, w, h);

  // Return 1 to decode next block
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Initialise SD before TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Initialise the TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

  // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setJpgScale(1);

  // The decoder must be given the exact name of the rendering function above
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");

  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Opens next file in root
  while (file) {
    if (!file.isDirectory()) {
      char filepath[strlen(file.name()) + 2] = "/";
      strlcat(filepath, file.name(), sizeof filepath); // Se pone "/" delante del nombre del archivo para obtener la ruta completa.

      Serial.print("El archivo actual:");  Serial.println(filepath);

      // Get the width and height in pixels of the jpeg if you wish
      uint16_t w = 0, h = 0;
      Serial.print("Image size"); Serial.flush();
      TJpgDec.getSdJpgSize(&w, &h, filepath);
      Serial.print("ancho = "); Serial.print(w);
      Serial.print(", alto = "); Serial.println(h); Serial.flush();


      Serial.print("tiempo de visualización = "); Serial.flush();
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, filepath);     // Draw the image, top left at 0,0
      chrono = millis() - chrono;            // How much time did rendering take
      Serial.print(t); Serial.println(" ms");
      delay(2000);                              // Wait before drawing again
    }
    file = root.openNextFile();  // Opens next file in root
  }
  root.close();
}

void loop() {}
1 Like

Muchas gracias por su tiempo y paciencia, efectivamente faltaba "/" delante del nombre, le estoy muy agradecido.
Ahora solo queda limpiar el código y ordenarlo bien, también tengo que ver por que no hace loop, pero entiendo que es por que todo esta en "void setup()".
De nuevo gracias por la inestimable ayuda.

Sí, he colocado todo en el setup() para que las imágenes se muestren solo una vez. Si mueves el bucle que recorre el directorio raíz de la tarjeta SD dentro de loop(), entonces tus imágenes se mostrarán en un ciclo "infinito".

1 Like

Buenos días.
El otro tuve un problema con el proyecto en el que estoy liado "VER":

Por fin di con el error gracias al compañero J-M-L Jackson.
El problema que me encuentro ahora es que quiero trasladar este mismo proyecto de una placa ESP32 a una ESP8266, pero con otro pantalla, una ST7789.
En el archivo de configuración User_Setup.h de la librería TFT_eSPI, he descomentado la linea que corresponde a la pantalla:

#define ST7789_DRIVER      // Full configuration option, define additional parameters below for this display

Y también las lineas que corresponde al ESP8266:

// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######

// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
#define TFT_MISO  PIN_D6  // Automatically assigned with ESP8266 if not defined
#define TFT_MOSI  PIN_D7  // Automatically assigned with ESP8266 if not defined
#define TFT_SCLK  PIN_D5  // Automatically assigned with ESP8266 if not defined

#define TFT_CS    PIN_D8  // Chip select control pin D8
#define TFT_DC    PIN_D3  // Data Command control pin
#define TFT_RST   PIN_D4  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1     // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

Por supuesto he comentado las que corresponden al ESP32, para que no de conflictos.

// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP   ######

// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins

//#define TFT_MISO 19
//#define TFT_MOSI 23
//#define TFT_SCLK 18
//#define TFT_CS   15  // Chip select control pin
//#define TFT_DC    2  // Data Command control pin
//#define TFT_RST   4  // Reset pin (could connect to RST pin)
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

El problema que estoy teniendo es que al compilar el código, este me da errores solo en las lineas que tienen que ver con la SD, y no se si hay que definir esa parte de manera diferente en el ESP8266, ya que he seguido las siguientes instrucciones:

Las lineas que dan error son las siguientes

if (!SD.begin()) {

  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {

  if (cardType == CARD_MMC) {
    
  } else if (cardType == CARD_SD) {
    
  } else if (cardType == CARD_SDHC) {

 cardSize = SD.cardSize() / (1024 * 1024);

Sospecho que tiene algo que ver con las librerías del ESP8266, que tenga que definir de otra manera las lineas comentas anteriormente, pero me encuentro completamente perdido, ya que soy bastante novato.

Les pongo la salida al compilar:

In file included from C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SD\src/SD.h:25,
                 from c:\Users\xxx\Documents\Arduino\libraries\TJpg_Decoder\src/TJpg_Decoder.h:36,
                 from C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:1:
C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SDFS\src/SDFS.h: In member function 'virtual int sdfs::SDFSFileImpl::availableForWrite()':
C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SDFS\src/SDFS.h:279:31: error: 'using element_type = class File32' {aka 'class File32'} has no member named 'availableSpaceForWrite'; did you mean 'availableForWrite'?
  279 |         return _opened ? _fd->availableSpaceForWrite() : 0;
      |                               ^~~~~~~~~~~~~~~~~~~~~~
      |                               availableForWrite
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino: In function 'void setup()':
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:63:17: error: no matching function for call to 'SDClass::begin()'
   63 |   if (!SD.begin()) {
      |                 ^
In file included from c:\Users\xxx\Documents\Arduino\libraries\TJpg_Decoder\src/TJpg_Decoder.h:36,
                 from C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:1:
C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SD\src/SD.h:68:10: note: candidate: 'bool SDClass::begin(uint8_t, uint32_t)'
   68 |     bool begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED) {
      |          ^~~~~
C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SD\src/SD.h:68:10: note:   candidate expects 2 arguments, 0 provided
C:\Users\xx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:67:25: error: 'class SDClass' has no member named 'cardType'
   67 |   uint8_t cardType = SD.cardType();
      |                         ^~~~~~~~
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:69:19: error: 'CARD_NONE' was not declared in this scope
   69 |   if (cardType == CARD_NONE) {
      |                   ^~~~~~~~~
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:75:19: error: 'CARD_MMC' was not declared in this scope
   75 |   if (cardType == CARD_MMC) {
      |                   ^~~~~~~~
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:77:26: error: 'CARD_SD' was not declared in this scope
   77 |   } else if (cardType == CARD_SD) {
      |                          ^~~~~~~
C:\Users\xxx\AppData\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:79:26: error: 'CARD_SDHC' was not declared in this scope
   79 |   } else if (cardType == CARD_SDHC) {
      |                          ^~~~~~~~~
C:\Users\xxx\Local\Temp\.arduinoIDE-unsaved2024225-17792-1k0ub2u.wcx6\sketch_mar25a\sketch_mar25a.ino:85:17: error: 'class SDClass' has no member named 'cardSize'
   85 |   cardSize = SD.cardSize() / (1024 * 1024);
      |                 ^~~~~~~~
Se encontraron varias bibliotecas para "SD.h"
  Usado: C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SD
  No utilizado: C:\Users\xxx\Documents\Arduino\libraries\SD
Se encontraron varias bibliotecas para "SdFat.h"
  Usado: C:\Users\xxx\Documents\Arduino\libraries\SdFat
  No utilizado: C:\Users\xxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266SdFat
exit status 1

Compilation error: no matching function for call to 'SDClass::begin()'

Y este es el codigo sobre el que estoy trabajando, son ejemplos modificados y adaptados a lo que necesito:

#include <TJpg_Decoder.h>
#include <SD.h>
#define FS_NO_GLOBALS
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h" // Solo ESP32
#endif

#define SD_CS   5

// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h>              
TFT_eSPI tft = TFT_eSPI();         // Llama a la libreria


// Esta siguiente función se llamará durante la decodificación del archivo jpeg para
// renderiza cada bloque en TFT. Si utiliza una biblioteca TFT diferente
// necesitarás adaptar esta función a tu medida.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  // Detener la decodificación ya que la imagen se está ejecutando en la parte inferior de la pantalla
  if ( y >= tft.height() ) return 0;

  // Esta función recortará el bloque de imagen renderizado automáticamente en los límites de TFT
  tft.pushImage(x, y, w, h, bitmap);

    // Devuelve 1 para decodificar el siguiente bloque
  return 1;
}

void setup()
{
  uint32_t chrono;
  uint64_t cardSize ;
  File file;

  Serial.begin(115200);
  Serial.println("\n\n Testing TJpg_Decoder library");

  // Inicializa SD antes que TFT
  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }
  Serial.println("\r\nInitialisation done.");

  // Inicializa TFT
  tft.begin();
  tft.setTextColor(0xFFFF, 0x0000);
  tft.fillScreen(TFT_BLACK);
  tft.setSwapBytes(true); // Intercambiar los bytes de color (endianess)
  tft.setRotation(2);   //Rota la pantalla
  // La imagen jpeg se puede escalar en un factor de 1, 2, 4 u 8
  TJpgDec.setJpgScale(1);

  // Al decodificador se le debe dar el nombre exacto de la función de renderizado anterior
  TJpgDec.setCallback(tft_output);

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  Serial.println("initialisation done.");
  
  }
  

void loop() 
{
uint32_t chrono;
  uint64_t cardSize ;
  File file;
File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory");
    return;
  }

  file = root.openNextFile();  // Abre el siguiente archivo en la raíz
  while (file) {
    if (!file.isDirectory()) {
      char filepath[strlen(file.name()) + 2] = "/";
      strlcat(filepath, file.name(), sizeof filepath); // Se pone "/" delante del nombre del archivo para obtener la ruta completa.

      Serial.print("El archivo actual:");  Serial.println(filepath);

      // Obténer el ancho y alto en píxeles del jpeg
      uint16_t w = 0, h = 0;
      Serial.print("Image size"); Serial.flush();
      TJpgDec.getSdJpgSize(&w, &h, filepath);
      Serial.print("ancho = "); Serial.print(w);
      Serial.print(", alto = "); Serial.println(h); Serial.flush();

uint32_t t = millis();
      Serial.print("tiempo de visualización = "); Serial.flush();
      chrono = millis();
      TJpgDec.drawSdJpg(0, 0, filepath);     // Dibuja la imagen, arriba a la izquierda en 0,0
      chrono = millis() - chrono;            // Tiempo de renderizado 
      t = millis() - t;
      Serial.print(t); Serial.println(" ms");
      delay(4000);                              
    }
    file = root.openNextFile();  //Abre el siguiente archivo en la raíz
//root.close();
}
}

Agradezco de antemano la ayuda que puedan proporcionarme.
Un saludo.

Prueba mover

#include <SPI.h>

antes de

#include <SD.h>

ya que SD necesita de la librería SPI.


Si ocurre

  if (!SD.begin(SD_CS)) {
    Serial.println(F("SD.begin failed!"));
    while (1) delay(0);
  }

entonces

  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }

no puede ocurrir nunca porque el código quedó bloqueado en el while()
Además de que falta asignar el pin CS en begin(), la tarjeta ya estaría inicializada si el código llegó hasta aquí, no debes hacer una nueva inicialización.
Quita esas 3 sentencias que no tienen sentido.


Tengo mis dudas con la inclusión de la librería FS, creo que no es necesario incluirla.
Prueba comentando la línea

#include <FS.h>
1 Like

Hola MaximoEsfuerzo, lo primero agradecerte el tiempo que as dedicado a entender mi galimatias de código, entiendo que tiene que ser un lio.
Veo lo que me quieres decir, he inicializado dos veces la SD, eso no tiene sentido y es error mio, gracias por ver algo que no vi yo mismo.
También he movido:
#include "SPI.h"
antes de:
#include <SD.h>
También he comentado la librería "FS.h", pero al compilar continua dándome error en las mismas lineas, menos al inicializar la SD, claro esta.

  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {

  if (cardType == CARD_MMC) {
    
  } else if (cardType == CARD_SD) {
    
  } else if (cardType == CARD_SDHC) {

 cardSize = SD.cardSize() / (1024 * 1024);

He probado a comentar esas lineas por probar y termina de compilar pero con este error:

error using element_type = class File32

He comprobado por internet que ese error es un conflicto de librerías, en concreto mi caso era entre la librería SdFat.h y la SD.h que se encuentra dentro de las librerías del ESP8266. He desinstalado SdFat.h y lo he solucionado, ya compila.
Con respecto a definir el pin CS, lo tengo definido al inicio como:

#define SD_CS   5

¿No tendría que hacer nada mas en este sentido, no?
Solo me queda saber por que me da error en las lineas descritas anteriormente, pero eso ya es algo menor, con tiempo y haciendo pruebas tiene que salir.

Gracias por orientarme.

En esta línea faltaba pasar SD_CS como parámetro

if (!SD.begin()) {

Igual ya no va así que despreocupate.

Si, si, esa linea la tengo así, muchas gracias.

Creo que no nos entendemos...
Esa línea que hago mención es la primera de las 3 que eliminaste, por eso te digo que ya no importa.
¿Se entiende?

Agrego:
Respecto a cardType() y cardSize(), por lo que entiendo del código de la librería para el 8266, y si estoy en lo correcto, deberías usar type() y size(), respectivamente.
Prueba, no cuesta nada. :wink:

1 Like

Disculpa me explique fatal, las lineas que comentaste que estaban redundando las elimine, las reescribí de nuevo y colo que bien el código, por supuesto añadí SD_CS.
Lo que comentas de type() y size() lo voy a probar estos días de fiesta que tengo tiempo y puedo trastear tranquilamente.
Muchas gracias por tu tiempo.

Buenos días.

Efectivamente el problema estaba en definir cardType() y cardSize() por type() y size().
El problema que sigo teniendo al compilar son las lineas:

  if (cardType == CARD_NONE) {

  if (cardType == CARD_MMC) {
    
  } else if (cardType == CARD_SD) {
    
  } else if (cardType == CARD_SDHC) {

El problema debe estar en como se definen esas lineas en la librería SD de ESP8266, ya que he visto algún ejemplo y no son así.
Una pregunta ¿Sabríais donde puedo ver la documentación de esa librería o librerías? he visto el Github pero no veo nada parecido a "Arduino Reference - Arduino Reference".

Gracias por toda la ayuda, de verdad lo digo.

He encontrado la documentación del ESP8266, se encuentra aquí:

https://esp8266-arduino-spanish.readthedocs.io/es/latest/index.html

También he visto que gracias a varios ejemplo,s las lineas que me daban error al compilar era producido por que la librería SD del ESP8266, se definían de otra manera:

uint8_t cardType = SD.type();

 if (cardType) // mirar esta linea que aunque funciona no se si esta bien 
  {
    Serial.println("No SD card attached"); 
   return;
     Serial.print("SD Card Type: ");
 if (cardType == SD_CARD_TYPE_SD2) {
    Serial.println("MMC");
  } else if (cardType == SD_CARD_TYPE_SD2) {
    Serial.println("SDSC");
 } else if (cardType == SD_CARD_TYPE_SDHC) {
  Serial.println("SDHC");
 } else {
  Serial.println("UNKNOWN");

No estoy muy seguro todavía de si he definido bien cada tipo de tarjeta, pero por lo menos ahora no falla.
Aun así necesito encontrar alguna documentación que me indique correctamente como saber que tipo de tarjeta es la que corresponde a SD1 o SD2.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.