Timelapse avec ESP32 CAM "SD Card Mount Failed" [résolu]

Bonjour,
J'ai d'abord utilisé ce tuto ESP32-CAM Take Photo and Save to MicroSD Card | Random Nerd Tutorials
Cela fonctionne très bien, une photo est prise et enregistrée sur la carte SD à chaque appui sur le bouton reset.

J'ai ensuite utilisé ce tuto ESP32. Code Arduino pour mise en sommeil (Deep Sleep) et réveils (Timer, Touch Pad, GPIO...) • Domotique et objets connectés à faire soi-même (projetsdiy.fr) pour modifier la mise en veille profonde avec un réveil par minuteur en ajoutant :

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* Time ESP32 will go to sleep (in seconds) */

dans l'entête et en remplaçant en fin de setup :

     Serial.println("Going to sleep now");
    delay(2000);
    esp_deep_sleep_start();

par

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This message will never be printed");

Le réveil se fait bien au bout de 5 secondes, on le voit sur le moniteur série, résultat :

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Picture file name: /img17.jpg
Saved file to path: /img17.jpg
This will never be printed
Setup ESP32 to sleep for every 5 Seconds
Going to sleep now
ets Jun 8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
E (1548) sdmmc_sd: sdmmc_check_scr: send_scr returned 0xffffffff
SD Card Mount Failed
ets Jun 8 2016 00:22:57

Comment contourner ce problème lecteur SD qui ne s'initialise pas ?

Bonjour @achess

le site Random Nerd Tutorials est remarquable par la qualité et la quantité des tutoriels...

ça ne s'arrête pas l là , Sara et Rui Santos sont réactifs et proposent souvent tdes solutions dans le fil de discussion de chaque réallisation :+1: (aller voir en bas de page)

Il semble qu'en date des 24 et 24 août 2019 le problème que tu rencontres a été abordé , je n'ai pas été voir plus loin.....( la solution semble consister en une maitrise de l'état de GPIO4 pendant le deep-sleep)

Bonjour et merci al1,
Elle conseille d'utiliser une minuterie, c'est ce qui est proposé dans ce tuto Électronique en amateur: Time-lapse avec l'ESP32-CAM (electroniqueamateur.blogspot.com)(Électronique en amateur: ESP32-CAM: enregistrer des photos sur la carte microSD) mais comme c'est pour une utilisation longue sur batterie, j'aurais préféré utiliser la veille profonde entre chaque photo.

Le fait que dans ce cas ce ne soit pas un hard reset, peut-être ne faut-il pas réinitialiser certains éléments ?
Je ne comprends pas assez le fonctionnement pour aller plus loin...

au dates que j'ai indiqué Sara Rui propose une action spécifique sur GPIO4 censée permettre un bon reveil de deep-sleep pour la carte SD. Un des demandeurs semble valider sa proposition... je n'ai pas poursuivi la lecture...ni fait l'essai...

ajout dans le setup() :

pinMode(4, INPUT);
digitalWrite(4, LOW);
rtc_gpio_hold_dis(GPIO_NUM_4);

Rôle de la 3e ligne = imposer à GPIO4 la conservation de son dernier état durant le deep-sleep()

il se pourrait que , sans précaution particulière, le deep-sleep et les résistances de pull-up sur le GPIO desservant la carte SD produisent un signal intempestif qui perturbe la carte SD et empêche sa réinitialisation
Dans l'ESP32 le plus répandu en plus des deux coeurs XTENSA se trouve un petit processeur basse consommation pouvant effectuer des actions simples (programmation en assembleur) sur certains GPIOs, là on lui dit 'laisses GPIO4 dans l'état où tu l'as trouvé à la mise en sommeil profond'

i> Le fait que dans ce cas ce ne soit pas un hard reset, peut-être ne faut-il pas réinitialiser certains éléments ?
Je ne comprends pas assez le fonctionnement pour aller plus loin...

idem pour moi...d'où l'idée de tester d'abord ce qui est proposé !!

le schéma de la carte peut être trouvé ici :
https://preview.redd.it/yv050peu22p21.png?width=1222&format=png&auto=webp&s=6bda5db94ed155bb428e1bb02e1a362c447fa9eb

Cet ajout, c'est pour éviter que la led "flash" reste allumée entre 2 photos. il est inclus dans le code mis à jour.

Le programme de Électronique en amateur: Time-lapse avec l'ESP32-CAM fonctionne bien mais environ 130mA consommé en permanence.

:disappointed:

ici (mars et décembre 2020) est question de changer le mode de fonctionnement de la carte SD, qui sait en mode 1 bit elle sera plus lente pour les écritures mais par contre supportera peut être mieux les réveils de deep-sleep
https://randomnerdtutorials.com/esp32-cam-pir-motion-detector-photo-capture/

Eureka :wink:
En utilisant ce code modifié, ça fonctionne Détecteur de mouvement ESP32-CAM PIR avec capture de | Tutoriels Random Nerd (randomnerdtutorials.com)

/*********
 * Modifié en réveil périodique
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-cam-pir-motion-detector-photo-capture/

  IMPORTANT!!!
   - Select Board "AI Thinker ESP32-CAM"
   - GPIO 0 must be connected to GND to upload a sketch
   - After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h>            // read and write from flash memory
// define the number of bytes you want to access
#define EEPROM_SIZE 1

RTC_DATA_ATTR int bootCount = 0;

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

int pictureNumber = 0;
// timelapse
#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* durée de sommeil (in seconds) */



void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  Serial.begin(115200);

  Serial.setDebugOutput(true);

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  pinMode(4, INPUT);
  digitalWrite(4, LOW);
  rtc_gpio_hold_dis(GPIO_NUM_4);

  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Init Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  Serial.println("Starting SD Card");

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

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

  camera_fb_t * fb = NULL;

  // Take Picture with Camera
  fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);
  pictureNumber = EEPROM.read(0) + 1;

  // Path where new picture will be saved in SD Card
  String path = "/picture" + String(pictureNumber) + ".jpg";

  fs::FS &fs = SD_MMC;
  Serial.printf("Picture file name: %s\n", path.c_str());

  File file = fs.open(path.c_str(), FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file in writing mode");
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
    EEPROM.write(0, pictureNumber);
    EEPROM.commit();
  }
  file.close();
  esp_camera_fb_return(fb);

  delay(1000);

  // Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  rtc_gpio_hold_en(GPIO_NUM_4);

  // esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
  // réveil périodique
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

  Serial.println("Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {

}

:+1:
Merci du retour !!
Quelle est la valeur du courant de deep-sleep avec cette carte ?

4.5 mA/ 5V et 3 mA/3 V mais doit y avoir des choses à désactiver avant veille profonde, ou c'est la consommation du régulateur ?

en alimentant en 3V3 en sortie du régulateur linéaire 3V3 ce dernier n'absorbe presque plus de courant
reste la carte SD, la camera.... en plus de l'ESP32 , la mémoire Flash SPI et la PSRAM SPI.
......j'oubliais les régulateurs linéaires 2,8V et 1,2V pour la caméra si le signal CAM_PWR ne les désactive pas

Vu ce que cette carte embarque il n'est peut être pas certain qu'en deep-sleep, il soit possible de descendre beaucoup plus bas que 3mA.

Au delà il est possible de laisser tomber le deep-sleep de l'ESP32 et de n'alimenter la carte qu'à intervalle de temps réguliers avec un TPL5110 ou TPL5111. (20µA)
Adafruit produit des modules avec ces puces Texas Instruments et un mosfet
https://www.adafruit.com/product/3573

Je suis très satisfait en fait. J'avais cette carte depuis plusieurs mois et ne l'avais pas encore testée. J'aurais pu aussi utiliser un pro mini que j'ai dans mes tiroirs (6 µA en veille) pour le réveiller, mais vraiment pas nécessaire.

Ces derniers temps mes poules me font des infidélités... :japanese_goblin: Elles ont un grand terrain plein de cachettes et en profitent pour pondre chaque fois à des lieus différents, m'obligeant à faire la chasse aux oeufs . :grimacing:

Je compte poster l'espion dans un coin stratégique pendant les 2 à 3 heures de la journées ou elles déposent leur précieux tribu. :smiling_imp:

La cam pourra aussi servir avec PIR comme piège photographique.. vraiment utile, économe en batterie et pas cher :wink: