Foto­schau mit ESP32, TFT und SD-Kartenleser

Lese­zeit: 4 Minu­ten

Lösung

Zie­le des Projekts

  • Fotos von einem SD-Kar­ten­le­ser laden und auf einem TFT anzeigen
  • Beschrei­bung zum Foto anzeigen

Ver­wen­de­te Hardware

Pin­be­le­gung des TFT.Displays mit 480×320 Pixeln

Die Pins für den SD-Kar­ten­le­ser (im Bei­spiel: SD-CS und SDO) müs­sen in der Pin-Leis­te vor­han­den sein:

Pin­be­le­gung am ESP32-Wroom

SD_CS: 15 (SD-Kar­ten­le­ser)
SDO (MISO): 19 (SD-Kar­ten­le­ser)
LED: 5V
SCK: 18
SDI (MOSI): 23
LCD_RS (DC): 2
LCD_RST (RST): 4 
LCD_CS (CS): 5
GND
VCC: 5V

Die Rei­hen­fol­ge der Pins kann unter­schied­lich sein. Ach­te auf die Beschrif­tung der Pins.

Fotos erstel­len

Du benö­tigst eine Mini-SD-Kar­te, sie muss mit FAT-32 for­ma­tiert sein. Bei neu gekauf­ten SD-Kar­ten ist das in der Regel der Fall. Fotos dür­fen maxi­mal das For­mat von 480×320 Pixeln haben und müs­sen im For­mat bmp vor­lie­gen. Du kannst belie­bi­ge Fotos ska­lie­ren und ent­spre­chend abspeichern.

Ich ver­wen­de hier­zu das Pro­gramm GIMP. Beach­te die not­wen­di­gen Ein­stel­lun­gen beim Spei­chern des Bildes.

Natür­lich darf das Bild auch klei­ner als 480×320 Pixel sein. Bei der Funk­ti­on drawBMP kannst du die Start­po­si­ti­on auf der x- und y-Ach­se festlegen.

Fotos zum Download

koeln.bmpoverath_bahnhof.bmplindos.bmpbraunwald.bmpdresden_frauenkirche.bmp
chartres.bmpstrand.bmpberlin_olympia.bmpuni_bonn.bmpduenen.bmp
st_michelle.bmpijlst.bmpmonschau.bmpgaios.bmpkoeln_deutz.bmp

Sowohl das TFT-Dis­play als auch der SD-Kar­ten­le­ser ver­wen­den den SPI-Bus. Jedes Gerät benö­tigt aber eige­ne Daten­lei­tun­gen. Der ESP32-Wroom ver­fügt über zwei SPI-Bus­se, die gleich­zei­tig nutz­bar sind.

Benö­tig­te Bibliotheken

Die ver­wen­de­te Biblio­thek für das Dis­play mit 480×320 Pixeln kann nicht über die Biblio­theks­ver­wal­tung instal­liert wer­den. Sie muss her­un­ter gela­den wer­den:
https://​git​hub​.com/​p​r​e​n​t​i​c​e​d​a​v​i​d​/​A​d​a​f​r​u​i​t​_​S​T​7​7​9​6​S​_​kbv
und mit

Sketch -> Biblio­thek ein­bin­den -> zip-Biblio­thek hinzufügen

instal­liert werden.

Das Pro­gramm

Biblio­the­ken ein­bin­den und Varia­ble definieren

Die SPI-Pins für das TFT-Dis­play ent­spre­chen der Stan­dard­kon­fi­gu­ra­ti­on VSPI und müs­sen nicht dekla­riert wer­den.
Für den SD-Kar­ten­le­ser sind eini­ge Para­me­ter erforderlich:

  • der Typ der SD-Kar­te (3)
  • die Geschwin­dig­keit (SD_SCK_MHZ)
  • Der Daten­pin (CSPin)

Der Para­me­ter Beschrei­bung ent­schei­det dar­über, ob eine Beschrei­bung zum Foto ange­zeigt wird. Die Anzei­ge der Beschrei­bung nimmt einen klei­nen Teil des Fotos weg.

#include "SdFat.h"
#include "Adafruit_ST7796S_kbv.h"
#include "Adafruit_ImageReader.h"

// ESP32-WROOM
#define TFT_CS        5
#define TFT_RST       4 
#define TFT_DC        2

/* 
  SD VSPI Standard-Pins
  CLK    18
  MOSI   23
  MISO   19
  CS      5
*/

// Objekt tft der Bibliothek Adafruit_ST7796S_kbv erstellen
Adafruit_ST7796S_kbv tft = Adafruit_ST7796S_kbv(TFT_CS, TFT_DC, TFT_RST);

// Objekt SD der Bibliothek SdFat erstellen
SdFat SD;              

// Objekt des Kartenlesers wird an das Dateisystem der SD-Karte übertragen
Adafruit_ImageReader reader(SD);

Adafruit_Image Bild;  

// Farben
#define SCHWARZ     0x0000
#define WEISS       0xFFFF
#define BLAU        0x001F

// 3 = FAT32
#define SD_FAT_TYPE 3

// SPI-Geschwindigkeit
#define SPI_SPEED SD_SCK_MHZ(10)

// CSPin der SD-Karte
int CSPin = 15;

// Anzeigedauer
int Intervall = 6000;

bool Beschreibung = true;

Der set­up-Teil

Der set­up-Teil star­tet den SD-Kar­ten­le­ser und das TFT-Dis­play. Der erfolg­rei­che Start des SD-Kar­ten­le­sers wird im Seri­el­len Moni­tor und auf dem TFT-Dis­play angezeigt.

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

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);
 
  // TFT starten
  tft.begin();
  
  tft.invertDisplay(1);

  // Rotation anpassen
  tft.setRotation(3);

  // schwarzer Hintergrund
  tft.fillScreen(SCHWARZ);
  tft.setTextSize(3);
  tft.setTextColor(WEISS);
  tft.setCursor(1, 20);

  /*
     SD-Karte mit Angabe des CSPins und  der SPI-Geschwindigkeit starten
     wenn die Intialisierung fehlschlägt
     - keine SD-Karte vorhanden
     - falsche Pinbelegung
     -> es wird eine Fehlermeldung angezeigt
  */
  if (!SD.begin(CSPin, SPI_SPEED)) 
  {
    tft.println("Start der SD-Karte");
    tft.print("fehlgeschlagen!");
    Serial.println("Start der SD-Karte fehlgeschlagen!");
  } 
  else 
  {
    Serial.println("SD-Karte gestartet");
    tft.print("SD-Karte gestartet!");
  }

  delay(5000);
}

Der loop-Teil

Jedes Foto muss mit drawBMP an das TFT-Dis­play (tft) mit den x- und y-Koor­di­na­ten des Start­punk­tes über­ge­ben wer­den.
Je nach Zustand des Para­me­ter Beschrei­bung (true/false) wird eine Infor­ma­ti­on zum Foto ange­zeigt.
Die Umlau­te müs­sen mit tft.write() und ⇒hexa­de­zi­ma­len Code defi­niert werden.

void loop() 
{  
  reader.drawBMP("koeln.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.setCursor(10, 295);  
    tft.print("K");
    // ö = 0x94
    tft.write(0x94);
    tft.println("ln Blick vom Messeturm");
  }
  
  delay(Intervall);
 
  reader.drawBMP("duenen.bmp", tft, 0, 0);
  
  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("D");
    // ü = 0x81
    tft.write(0x81);
    tft.print("nen Ibiza");
  }

  delay(Intervall);  
 
  reader.drawBMP("overath_bahnhof.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Overath Bahnhof");
  }

  delay(Intervall);
 
  reader.drawBMP("rathaus.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Rathaus Bergisch Gladbach");
  }

  delay(Intervall);
 
  reader.drawBMP("dresden_frauenkirche.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Dresden Frauenkirche");
  }

  delay(Intervall);
 
  reader.drawBMP("chartres.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Chartres Dom");
  }

  delay(Intervall);

  reader.drawBMP("bonn_uni.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Bonn Uni");
  }

  delay(Intervall);

  reader.drawBMP("braunwald.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Braunwald Schweiz");
  }

  delay(Intervall);
   
  reader.drawBMP("koeln_deutz.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("K");
    // ö = 0x94
    tft.write(0x94);
    tft.println("ln Deutz");
  }

  delay(Intervall);

  reader.drawBMP("kloentaler_see.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Kl");
    // ö = 0x94
    tft.write(0x94);
    tft.println("ntaler See Schweiz");
    }

  delay(Intervall);  

  reader.drawBMP("sevilla.bmp", tft, 0, 0);
  
  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Sevilla Kathedrale");
  }

  delay(Intervall);

  reader.drawBMP("st_michelle.bmp", tft, 0, 0);
  
  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("St. Michelle Frankreich");
  }
  delay(Intervall);

  reader.drawBMP("dresden_bruecke.bmp", tft, 0, 0);

  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Dresden 'Blaues Wunder'");
  }

  delay(Intervall);

  reader.drawBMP("lindos.bmp", tft, 0, 0);
  
  if (Beschreibung)
  {
    tft.setCursor(10, 295);  
    tft.fillRect(1, 290, tft.width(), tft.height(), 0x0120); 
    tft.print("Lindos Rhodos");
  }

  delay(Intervall);
}

Quel­len


Letzte Aktualisierung: März 30, 2025 @ 12:25