Esp32 Cam, SD Karte konnte nicht initialisiert werden

Guten Tag.
Weiss irgend jemand wieso ich bei meinem ESP32-Cam Board keine SD Karte mehr nutzen kann? Ich habe ein ESP32-Cam Board von Berrybase, und am Anfang konnte ich auch mal zum testen ein Foto machen und darauf speichern, doch ich weiss nicht mehr mit welchem Code und welcher SD Karte. Dann lag die ESP32 Cam nur herum in einem Karton, und wenn ich jetzt das SD_Test Example aus der Arduino IDE auf die ESP32-Cam schreibe, dann kommt immer: Card Mount Failed.
Egal ob ich eine 32GB SD Karte nehme und mit Fat32 oder Fat16 auf Ubuntu mit gparted formatiere, oder auf Windows mit Fat32 formatiere, oder es mit einer 128MB Karte und Fat32 versuche, es kann nie die Karte nutzen. Und die Karten funktionieren auch normal am PC.

Weiss irgend jemand wieso das einfach nicht mehr geht? Habe ich irgend etwas falsch gemacht?
Das Example Script ist das:

/*
 * pin 1 - not used          |  Micro SD card     |
 * pin 2 - CS (SS)           |                   /
 * pin 3 - DI (MOSI)         |                  |__
 * pin 4 - VDD (3.3V)        |                    |
 * pin 5 - SCK (SCLK)        | 8 7 6 5 4 3 2 1   /
 * pin 6 - VSS (GND)         | ▄ ▄ ▄ ▄ ▄ ▄ ▄ ▄  /
 * pin 7 - DO (MISO)         | ▀ ▀ █ ▀ █ ▀ ▀ ▀ |
 * pin 8 - not used          |_________________|
 *                             ║ ║ ║ ║ ║ ║ ║ ║
 *                     ╔═══════╝ ║ ║ ║ ║ ║ ║ ╚═════════╗
 *                     ║         ║ ║ ║ ║ ║ ╚══════╗    ║
 *                     ║   ╔═════╝ ║ ║ ║ ╚═════╗  ║    ║
 * Connections for     ║   ║   ╔═══╩═║═║═══╗   ║  ║    ║
 * full-sized          ║   ║   ║   ╔═╝ ║   ║   ║  ║    ║
 * SD card             ║   ║   ║   ║   ║   ║   ║  ║    ║
 * Pin name         |  -  DO  VSS SCK VDD VSS DI CS    -  |
 * SD pin number    |  8   7   6   5   4   3   2   1   9 /
 *                  |                                  █/
 *                  |__▍___▊___█___█___█___█___█___█___/
 *
 * Note:  The SPI pins can be manually configured by using `SPI.begin(sck, miso, mosi, cs).`
 *        Alternatively, you can change the CS pin and use the other default settings by using `SD.begin(cs)`.
 *
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | SPI Pin Name | ESP8266 | ESP32 | ESP32‑S2 | ESP32‑S3 | ESP32‑C3 | ESP32‑C6 | ESP32‑H2 |
 * +==============+=========+=======+==========+==========+==========+==========+==========+
 * | CS (SS)      | GPIO15  | GPIO5 | GPIO34   | GPIO10   | GPIO7    | GPIO18   | GPIO0    |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | DI (MOSI)    | GPIO13  | GPIO23| GPIO35   | GPIO11   | GPIO6    | GPIO19   | GPIO25   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | DO (MISO)    | GPIO12  | GPIO19| GPIO37   | GPIO13   | GPIO5    | GPIO20   | GPIO11   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 * | SCK (SCLK)   | GPIO14  | GPIO18| GPIO36   | GPIO12   | GPIO4    | GPIO21   | GPIO10   |
 * +--------------+---------+-------+----------+----------+----------+----------+----------+
 *
 * For more info see file README.md in this library or on URL:
 * https://github.com/espressif/arduino-esp32/tree/master/libraries/SD
 */

#include "FS.h"
#include "SD.h"
#include "SPI.h"

/*
Uncomment and set up if you want to use custom pins for the SPI communication
#define REASSIGN_PINS
int sck = -1;
int miso = -1;
int mosi = -1;
int cs = -1;
*/

void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if (levels) {
        listDir(fs, file.path(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void createDir(fs::FS &fs, const char *path) {
  Serial.printf("Creating Dir: %s\n", path);
  if (fs.mkdir(path)) {
    Serial.println("Dir created");
  } else {
    Serial.println("mkdir failed");
  }
}

void removeDir(fs::FS &fs, const char *path) {
  Serial.printf("Removing Dir: %s\n", path);
  if (fs.rmdir(path)) {
    Serial.println("Dir removed");
  } else {
    Serial.println("rmdir failed");
  }
}

void readFile(fs::FS &fs, const char *path) {
  Serial.printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(fs::FS &fs, const char *path, const char *message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char *path, const char *message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char *path1, const char *path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char *path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char *path) {
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  if (file) {
    len = file.size();
    size_t flen = len;
    start = millis();
    while (len) {
      size_t toRead = len;
      if (toRead > 512) {
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    end = millis() - start;
    Serial.printf("%u bytes read for %lu ms\n", flen, end);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }

  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  for (i = 0; i < 2048; i++) {
    file.write(buf, 512);
  }
  end = millis() - start;
  Serial.printf("%u bytes written for %lu ms\n", 2048 * 512, end);
  file.close();
}

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    delay(10);
  }

#ifdef REASSIGN_PINS
  SPI.begin(sck, miso, mosi, cs);
  if (!SD.begin(cs)) {
#else
  if (!SD.begin()) {
#endif
    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);

  listDir(SD, "/", 0);
  createDir(SD, "/mydir");
  listDir(SD, "/", 0);
  removeDir(SD, "/mydir");
  listDir(SD, "/", 2);
  writeFile(SD, "/hello.txt", "Hello ");
  appendFile(SD, "/hello.txt", "World!\n");
  readFile(SD, "/hello.txt");
  deleteFile(SD, "/foo.txt");
  renameFile(SD, "/hello.txt", "/foo.txt");
  readFile(SD, "/foo.txt");
  testFileIO(SD, "/test.txt");
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}

void loop() {}

Der Code kompiliert und lädt fehlerfrei hoch, ich stecke die Cam kurz aus und wieder ein, und im Serial Monitor kommt immer Card Mount Failed.
Ausserdem habe ich AI Thinker ESP32 Cam als Board ausgewählt, ich hoffe das stimmt. Das Web Server Test Script hat funktioniert.

Bei Berrybase gibt es mehrer ESP32-Cams. Die die von M5, die von AI-Thinker, die Seeed XIAO ESP32S3 Sense und noch mehr.

Welche genau, denn so kann dir keiner helfen. Ein Bild sagt meistens mehr als SEHR viele Worte.

Es ist dieses Board:

Ich nehme an das ist die AI Thinker Cam, es funktioniert auch das Webserver Example wenn ich am anfang AI Thinker Cam definiere.

Irgendwie denke ich langsam, es ist einfach kaputt...
Denn es sollte ja wahrscheinlich einfach funktioneren mit einer SD Karte in Fat32 formatiert, mit dem Test Script? Egal ob 32GB oder 128MB, oder?

schau mall hier

Mit diesem Script aus dem Link funktioniert es jetzt... ?
Das Foto ist zwar praktisch unbrauchbar, weil es viel zu dunkel ist und grün verfärbt, aber es nimmt Fotos auf und speichert sie auf der 128MB SD Karte.
Doch das SD Test Script aus der Arduino IDE funktioniert immer noch nicht.
Und ich hatte vor diesem SD Test Script noch ein anderes von irgendwo aus dem Internet ausprobiert, was auch nicht funktioniert hatte.
Wieso funktioniert denn das SD Test Script nicht, doch dieses aus dem Link von fony funktioniert?

Muss mir das ansehen, weiß nur das die SD aus der ESP hat bei mir auch Probleme gemacht.

Wenn du beide Sketche (funktionieren und nicht funktionierend) vergleichst und die Unterschiede hier postest, macht es eine Hilfe für dich deutlich leichter.

Die nehmen zwei Lib um auf die SD schreiben

#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32

Gas mit dem Grünstich bekommst nicht weg es muss schon sehr hell sein damit der ein wenig verschwindet, anderseits was willst du für 10€ es ist keine Nikon oder Canon für min 300€

Ja, das habe ich jetzt auch gesehen...
Aber das bedeutet ja irgendwie, nicht jede Bibliothek die normalerweise mit einem Arduino kompatibel ist, ist auch mit einem ESP kompatibel. Nicht mal das SD Test Example aus der IDE selbst.
Also möglicherweise funktioniert irgend etwas das eigentlich normal funktionieren sollte auf dem Arduino, bei der ESP32-Cam einfach nicht...

Und das Bild von der Esp32-Cam war aber mit dem Webserver Test Script viel besser, und nicht grün verfärbt...

Scheint irgendwie schon etwas speziell zu sein mit diesem Esp32...

Aber immerhin weiss ich jetzt 1 Möglichkeit für die SD Karte und 1 Möglichkeit für die Kamera.

Dann muss das halt irgendwie so gemacht werden...

Vielen Dank für die Hilfe

Ist doch eigentlich logisch. Das sind ja auch total unterschiedliche Controller. Und in der IDE findest du für jeden Controller auch die passenden Beispiele.

Ist doch eigentlich logisch. Das sind ja auch total unterschiedliche Controller.

Ja aber ich dachte der Code ist der selbe...

in der IDE findest du für jeden Controller auch die passenden Beispiele

Ah das hat bei Esp auch nochmals so viele Exampels, habe ich irgendwie nicht bemerkt bis jetzt.

Viele Sachen funktionieren aber auch auf der Esp32-Cam genau gleich wie auf dem Arduino.
Und unter der SD Zeile bei Examples hat es auch SD_MMC, ich nehme an das hätte funktioniert, da es die gleichen Bibliotheken verwendet. War mir jetzt nicht grad ersichtlich dass ich das nehmen muss, das z.B. steht ja jetzt nicht unter Esp...
Aber egal, ich muss die neuen Esp Examples mal anschauen, und dann halt in Zukunft darauf achten dass ich Scripte für den ESP verwende, und vielleicht Arduino Scripte nicht funktionieren...

Danke für den Hinweis

Ja, aber eben nur teilweise. Wegen der Unterschiede des Controllers.
Aber vieles passt und funktioniert auch.
Und beim ESP32-CAM ist das nochmal was anderes. Auch weil ESP32 nicht unbedingt ESP32 ist. Da gibt es mittlerweile auch sehr viel verschiedene Typen. Die dann auch wieder nicht 100% kompatibel sind. Da hängt das dann aber wieder an den "inneren Werten" :wink: oder an den Pins.

Ja, aber eben nur teilweise. Wegen der Unterschiede des Controllers.

Aha, ok...

Und beim ESP32-CAM ist das nochmal was anderes. Auch weil ESP32 nicht unbedingt ESP32 ist. Da gibt es mittlerweile auch sehr viel verschiedene Typen. Die dann auch wieder nicht 100% kompatibel sind

Ja :slight_smile: nicht grad einfach...
Dann schaue ich halt in Zukunft dass ich genau für mein Board den Code habe.

Das ist richtig und gut so.
Und wenn du mehr (andere Controller) machst, gewöhnst du dich daran. :wink:

Am besten immer im Sketch dokumentieren:
Welcher Controller
Welche IDE Version
Welche core Version
Welche Library Version
und was noch so alles wichtig ist.

Ja das sollte ich machen :slight_smile:
Danke für den Tipp

Ergänzung: Link zu den Libs.

Gruß Tommy

Ja stimmt. Steht bei mir unter "was noch so alles wichtig ist". :wink:

Und ja, steht bei mir auch bei externen Libs mit drin.

Und noch wichtiger und aufwändiger wird es, wenn du eine "portable IDE 1.8.19" verwendest und mehrere core-Versionen sowie ESP8266 und ESP32 Installationen nutzt.

Lass die Kamera mal 3 Fotos hintereinander (ohne Pause dazwischen) machen, das 3. Bild ist dann brauchbar. Hängt damit zusammen wie die Cam das vorhandene Licht misst und die Belichtungszeit danach einstellt.

Ich habe 4 portable IDE 1.8.19 mit den ESP8266-Cores 2.7.4, 3.0.2, 3.1.1 und 3.1.2
Das ist kein Problem.

Gruß Tommy