Carte SD-Problème enregistrements avec la fonction END

Problème d’enregistrements avec une carte SD

Bonjour,

J’ai conçu un programme avec un arduino Nano qui utilise un lecteur de carte SD avec une horloge temps réel DS3231. Un fichier est créé avec pour nom la date du jour. Je souhaite effectuer des enregistrements toutes les min pour des essais.

J’intègre la fonction « SD.end() » pour pouvoir retirer sans risque la carte. Un tuto m’a permis de récupérer la broche 5 de la carte qui détecte ou non la présence de la carte (voir photo). Le pin 7 renseigne la variable associée « SDmissing ».

J’utilise la fonction millis() pour l’intervalle de 60s d’enregistrement. Ce système fonctionne d’habitude mais ici, le compteur du delta_T s’arrête au bout de quelques tours de loop. Mystère !

Quelqu’un voit-il la raison de ce phénomène ? Est-ce lié à l’utilisation du « SD.end » ? Merci pour votre aide.

Voici le sketch :

Blockquote

/*
Le programme :
  - avec Arduino Nano
  - verifie la connexion avec la carte SD - pin 10 pour CS
  - Vérifie la connexion au DS3231
  - Crée le nouveau fichier du jour à 00h:00min:00s
  - ferme toujours le fichier en fin d'enregistrement
*/

// Déclaration des bibliothèques
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>     // Declaration de DS3231
RTC_DS3231 rtc;

// Déclaration du pin de détection de présence de la carte SD en pin 7
#define SDmissing 7
boolean testCarteInseree;

// Declaration des types de variables à concatener pour afficher la date
String stringPoints = ":";
String dateActuelle;
String heureActuelle ="";

//File file;
File fichier;
File root;
int tailleFichier=0;
String nomFichier;

// Essais enregistrements
int x = 0;  //rang enregistrement
int data1 = 100;
int data2 = 0;
int data3 = 200;
String data4 = "Vent violent";
String data5 = "VR";
unsigned long tpsAct_10MIN = 0;
static unsigned long  tpsPrec_10MIN = 0;
unsigned long delta_T = 0.0;
unsigned long duree = 60000;

//-----------------------------------------------------------------------------------------------------
//                         ROUTINE REINITIALISATION DE LA CARTE
//-----------------------------------------------------------------------------------------------------
void initSDCard()
{
  while (!SD.begin())
  {
    Serial.print("---");
    Serial.print("Carte SD non disponible !");
    Serial.println("---");
    SD.end();           // Fonction non incluse dans la bib de l'IDE
    delay(100);
  }
  return;
}

//-----------------------------------------------------------------------------------------------------
//           SETUP                SETUP           SETUP                SETUP
//-----------------------------------------------------------------------------------------------------
void setup()
{

    Serial.begin(9600); //début de communication avec le moniteur série
    Serial.println("Initialisation");

    pinMode(SDmissing, INPUT_PULLUP);   // Pin détection Carte insérée oun noInterrupts()
    initSDCard();                       // Routine de détection de présence de la carte
    Serial.println("Communication etablie avec la carte SD !"); // Quand initSDCard est ok

    // ******************** INITIALISATION DS3231 ********************* 
    if (!rtc.begin()) 
    {
       Serial.println("Couldn't find RTC");
       Serial.flush();
       //while (1);
    }
    else
    {
        Serial.println("DS3231 OK !");
    }

}

//----------------------------------------------------------------------------
//         LOOP          LOOP         LOOP          LOOP         LOOP         
//----------------------------------------------------------------------------
void loop()
{
  // OPTION afichage état pin 7
  // testCarteInseree = digitalRead(SDmissing);
  // Serial.print("testCarteInseree = ");
  // Serial.println(testCarteInseree);

  //recuperation date et heure 
  DateTime now = rtc.now();

  heureActuelle = now.hour() + stringPoints + now.minute() + stringPoints + now.second();
  // Serial.println(heureActuelle);
  // Serial.println();

  // Pour création fichier date
  int jour= now.day();
  int mois = now.month();
  int an = now.year(); 


  //Si la carte est insérée (pin SDmissing à 0)
  if(!digitalRead(SDmissing))
  {   
      char datafile[14];

      //******************* CREATION FICHIER ***************************
      sprintf(datafile,"/%04d%02d%02d.txt",an,mois,jour);  //  %d pour un int

      delay(10);
      fichier = SD.open(datafile, FILE_WRITE);

      // Si le fichier existe
      if (fichier)
      {
          nomFichier = fichier.name();
          Serial.print("nomFichier : ");
          Serial.println(nomFichier);

          tailleFichier = fichier.size();
          if (tailleFichier == 0)   // Ecriture des en-tête
          {
              fichier.println("Rang;Heure;Vint;Vmax;Vmoy;Vent;Rafale");
              x = 0;
              fichier.close();
              delay(10); 
          }
          else
          {
              // Calcul durée pour 10 min
              tpsAct_10MIN =  millis();

              // Serial.print("tpsAct = ");
              // Serial.print(tpsAct_10MIN);
              // Serial.print("- tpsPrec = ");
              // Serial.println(tpsPrec_10MIN);

              delta_T = tpsAct_10MIN - tpsPrec_10MIN;
                  
              Serial.print("delta_T = ");
              Serial.println(delta_T);

              if (delta_T >= duree)
              {
                    // fichier = SD.open(datafile, FILE_WRITE);

                    // // Si le fichier existe
                    // if (fichier)
                    // {    
                        x++;
                        data1 = data1 -1;
                        data2 = data2 + 1;
                        data3 = data3 -1;
                        fichier.print(x),fichier.print(";"),fichier.print(heureActuelle),fichier.print(";"),fichier.print(data1),
                        fichier.print(";"),fichier.print(data2),fichier.print(";"),fichier.print(data3),fichier.print(";"),fichier.print(data4),fichier.print(";"),fichier.print(data5);
                        fichier.println();
                        fichier.close();
                        tpsPrec_10MIN = millis(); 
              } 
          }
      }
      else
      {

        initSDCard();
      }
  }
  else
  {
      initSDCard();
  }
}

Blockquote

Moniteur

Dans initSDCard(), avant de faire SD.begin(), il faudrait t'assurer qu'une carte est bien insérée.

Autrement, il faudrait peut-être regarder l'utilisation de la mémoire pour vérifier si par hasard il n'y aurait pas une fuite mémoire.

Bonjour fdufnews,
Merci pour cette réponse.
La présence d'une carte est vérifiée en ligne 112 grâce au lien de la broche 5 avec le pin7 du nano et le test "SDmissing". Cela marche très bien. Si j'enlève la carte, le message "Carte SD non disponible !" apparaît.
Par contre, comment contrôler l'utilisation de la mémoire et en détecter une fuite ?

Le delta_t est incrémenté mais tout s'arrête au bout de quelques loop avant d'atteindre la valeur donnée par "duree" (60000), sans raison apparente. J'utilise la fonction millis() habituellement sans problème. Le programme m'enregistre correctement la ligne d'entêtes au premier passage lorsque le fichier est vide.

Je vais faire un essai sans l'utilisation de la fonction "SD.End"
Merci pour ton aide.

Vous appelez cela quand begin na pas fonctionne donc ça ne sert à rien. (End fait juste un close sur la racine du file system mais si begin répond false c’est qu’il n’a pas pu ouvrir la racine)

Sinon (même si ce n’est pas votre souci) -Pourquoi static et pourquoi 0.0 dans un entier ??

Vous devriez faire une petite machine à état qui dit si la carte est présente ou pas etc quand elle est là, alors vous faites le dump des data

Justement, si elle est absente tu appelles initSDCard() et tu essaies d'établir le dialogue avec une carte sans vérifier s'il y en a une.
Avant de faire

while (!SD.begin())

ce serait judicieux de faire une boucle d'attente

while (!digitalRead(SDmissing))

En attendant qu'une carte soit insérée.


Autre chose qui me choque. Dans la boucle principale, tu ouvres le fichier et seulement après tu vérifies si le temps est venu de faire une écriture. Et surtout, si le temps n'est pas écoulé tu ne refermes pas le fichier.

Il serai quand même plus logique de vérifier que le temps s'est écoulé et qu'il va falloir faire une écriture avant d'ouvrir le fichier.
En l'état, si j'en crois ta copie d'écran, tu ouvres le fichier toutes les 44ms.

Au passage, il est préférable de faire un copié-collé du contenu de la fenêtre du moniteur série plutôt qu'une copie d'écran. C'est illisible pour les personnes qui répondent depuis leur téléphone.


une bonne habitude mettre le suffixe L aux constantes long

unsigned long duree = 60000L;

Plutôt UL suand il s’agit d’un unsigned :slight_smile: (et si elle ne varie pas, ne pas hésiter à rajouter const devant la définition)

Supers réactions bienvenues !
Je vais digérer toutes ces remarques et reprendre tranquillement mon programme. Sainte Logique ne m'a pas visiblement inspiré pour le coup.
Je reviens vers vous dès que je le peux.
Merci infiniment à tous.

Rebonjour fdufnews,
Je viens de reprendre le programme.
J'ai intégré tes deux remarques. J'avais en effet oublié de refermer le fichier. J'ai déplacé le ligne 169 en 172 :`

              if (delta_T >= duree)
              {
                    // fichier = SD.open(datafile, FILE_WRITE);

                    // // Si le fichier existe
                    // if (fichier)
                    // {    
                        x++;
                        data1 = data1 -1;
                        data2 = data2 + 1;
                        data3 = data3 -1;
                        fichier.print(x),fichier.print(";"),fichier.print(heureActuelle),fichier.print(";"),fichier.print(data1),
                        fichier.print(";"),fichier.print(data2),fichier.print(";"),fichier.print(data3),fichier.print(";"),fichier.print(data4),fichier.print(";"),fichier.print(data5);
                        fichier.println();

                        tpsPrec_10MIN = millis(); 
              } 
              fichier.close();

Ca marche du tonnerre !
Merci à toi. Je me doutais qu'une coquille s'était glissée quelque part.
Merci encore pour ta disponibilité.
Merci à tous.
A bientôt pour de nouvelles bourdes de ma part.
Bébert

Bonjour,
Pour ceux que cela pourrait intéresser, je vous joins la vidéo qui permet de détecter la présence ou non de la carte SD grâce à un fil à souder sur la broche 5 de la carte.

https://www.youtube.com/watch?v=GQjtG1MeVs4

Détection présence carte SD

Bonne bidouille à tous