Sainsmart TFT 1,8" Display Anzeige Bilder

Hallo,

das Programm zur Anzeige von ca. 2.000 Bildern im bmp - Format von der Mini SD Card läuft bestens, nicht zuletzt dank der Hilfe in diesem Forum.

Das Programm habe ich auf einem ATmega328P-PU gespeichert.

Die Bilder haben alle das gleiche Format, 128 x 160 Pixel, 61 KB, durchnummeriert von Bild0001.bmp bis Bild2000.bmp, aufwärts sortiert und so gespeichert auf der SD Card.

Bei jedem Start des Programms erscheint jedoch ein Bild von irgendeiner Stelle der SD Card, die folgende Reihenfolge ist nicht erkennbar, aber nach dem letzten Bild, Bild 2000.bmp, geht das
Programm zum ersten Bild Bild0001.bmp und fährt dann in der gewünschten Reihenfolge fort.

Bei jedem Neustart erscheint immer das gleiche Bild mit der gleichen nachfolgenden Reihenfolge.

Frage: Wie kann ich das Programm ergänzen, damit immer mit dem ersten Bild auf der SD Card gestartet wird?

Frage: Beim Bildwechsel flackert das Display ( Streifen), nach dem Bildaufbau jedoch steht das Bild ruhig. Wie kann ich die Störung beseitigen?

Im Voraus vielen Dank für Eure Hilfe.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <SD.h>


#define SD_CS    4  // Chip select line for SD card
#define TFT_CS  10  // Chip select line for TFT display
#define TFT_DC   9  // Data/command line for TFT
#define TFT_RST  8  // Reset line for TFT (or connect to +5V)

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

File dir;

void setup(void) {
  Serial.begin(9600);  

  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab

  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!");
    return;    
       
  }
  Serial.println("OK!");
  dir = SD.open("/");
  dir.rewindDirectory();
}
void loop() {  
  
   File entry = dir.openNextFile();
   if ( ! entry ) {
      dir.rewindDirectory();
      Serial.println( F(" Von vorne! "));
      return;
   }
   Serial.print(entry.name());
   // skip directories
   if (entry.isDirectory()) {
      Serial.println("/");
   } else {
      if( bmpDraw(entry.name(),0,0) ) delay(30000);
   }
   entry.close();
}

// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates.  It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel).  Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster.  20 pixels seems a
// good balance.

#define BUFFPIXEL 20

boolean bmpDraw(char *filename, uint8_t x, uint8_t y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();

  if((x >= tft.width()) || (y >= tft.height())) return false;

  Serial.println();
  Serial.print("Loading image '");
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.print("File not found");
    return false;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: "); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: "); Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print("Bit Depth: "); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print("Image size: ");
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...

          // Seek to start of scan line.  It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding.  Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            tft.pushColor(tft.Color565(r,g,b));
          } // end pixel
        } // end scanline
        Serial.print("Loaded in ");
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  
  if(!goodBmp)Serial.println("BMP format not recognized.");
  
  return goodBmp;
}

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

Leider kann ich Dein Problem nicht reproduzieren:

#include <SPI.h>
#include <SD.h>
#define SD_CS    53  // Chip select line for SD card

File dir;

void setup(void) {
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!");
    return;
  }
  Serial.println("OK!");
  dir = SD.open("/");
  dir.rewindDirectory();
}
void loop() {
  File entry = dir.openNextFile();
  if ( ! entry ) {
    dir.rewindDirectory();
    Serial.println( F(" Von vorne! "));
    return;
  }
  Serial.print(entry.name());
  Serial.print('\t');
  delay(2000);
}
Initializing SD card...OK!
BILD0001.BMP	BILD0002.BMP	BILD0003.BMP	BILD0004.BMP	 Von vorne! 
BILD0001.BMP	BILD0002.BMP	BILD0003.BMP	BILD0004.BMP	 Von vorne! 
BILD0001.BMP	BILD0002.BMP	BILD0003.BMP	BILD0004.BMP	 Von vorne!

Liegt es an der geringeren Zahl Dateien?

Die DOS-basierten Filesysteme bringen in der Regel die Fileliste in der Reihenfolge ihres Aufspielens/Anlegens.
Das könnte das Problem sein.

Gruß Tommy

...aber nach dem letzten Bild, Bild 2000.bmp, geht das
Programm zum ersten Bild Bild0001.bmp und fährt dann in der gewünschten Reihenfolge fort

Das macht mich allerdings stutzig.
Ist ja in beiden Fällen der gleiche rewindDirectory() Aufruf.

Tommy56:
Die DOS-basierten Filesysteme bringen in der Regel die Fileliste in der Reihenfolge ihres Aufspielens/Anlegens.

Da ich aus der DOS-Zeit stamme, habe ich alle Dateien in numerischer Reihenfolge auf die SD-Karte geschrieben, das schien mir selbstverständlich.

michael_x:
Das macht mich allerdings stutzig.

Da bist Du nicht alleine. Kann DOS womöglich nur 256 Dateien im Verzeichnis verwalten und lernt dann nach 2000 Dateien, daß auch mehr möglich sind? ;D

Eine spekulative Idee wäre, in setup erst eine Datei, beispielesweise BILD2000.BMP, zu öffnen und erst dann rewindDirectory() aufzurufen. Das klärt nicht die Gründe, hätte ich aber mal probiert, wenn ich den Fehler hätte reproduzieren können.

Hallo,

danke für Eure Hinweise.

Ich habe die SD Card formatiert und die 2000 Dateien in aufsteigender Folge auf ihr gespeichert, so wie ich es vorher auch gemacht habe. Jetzt startet die Anzeige mit dem letzten Bild und geht dann zum ersten Bild. Die nachfolgende Anzeige ist jetzt so, wie sie auf der SD Card gespeichert ist.

Also bin ich es jetzt zufrieden und forsche nicht weiter nach.

Gruß
Tron23