[SD] Problème écriture fichier csv

Bonjour

J’ai un problème problématique.

J’ai un programme qui actionne ou non des relais en boucle en fonction d’un fichier setup en scv:

 void loop() {
  

  iCycle = 0; // Initialisation du compteur de cycle à 0
  btnPlayPressed = digitalRead(etatbtnPlay); // Lecture de l'état  du bouton START
  //Serial.println(btnPlayPressed);



//--------------Attente de l'appuye sur le bonton START
  lcd.setCursor(0,0); 
  lcd.print("Appuye sur START");
  lcd.setCursor(0,1);
  lcd.print("                    ");
 
  while (btnPlayPressed == HIGH && iCycle <= nbCycle) // On boucle tant que le nombre de cycle du compteur est inférieur au nombre de cycle lu dans le csv
  {                                                   
    lcd.clear();
    
    //--------------On démarre le cyclage par les conditions Initiales
    Serial.println("Mise en conditions initiales");
    iEtape = 0;
    digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
    digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);

    iCycle = 1;

    for (iCycle = 1; iCycle <= nbCycle; iCycle++)
    {
      // affichage du nb de cycle éffectué
      lcd.setCursor(0, 0);
      lcd.print("Cycle = ");
      lcd.setCursor(8, 0);
      lcd.println(iCycle);
      lcd.setCursor(9, 0);
      lcd.print("  ");

      nbEtape=8;
      for (iEtape = 1; iEtape <= nbEtape; iEtape++) // le compteur nbEtape est définie ligne (113) à 8
      {
        // afficher l'étape en cours
        lcd.setCursor(0, 1);
        lcd.print("Etape = ");
        lcd.setCursor(8, 1);
        lcd.println(iEtape);
        lcd.setCursor(9, 1);
        lcd.print("  ");
        
 
        
        digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
        digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);
DateTime now = rtc.now();
fichierlog = SD.open(FileName, FILE_WRITE);

    fichierlog.print(now.year());
    fichierlog.print("/");
    fichierlog.print(now.month());
    fichierlog.print("/");
    fichierlog.print(now.day());
    fichierlog.print(";");
    
    fichierlog.print(now.hour());
    fichierlog.print(":");
    fichierlog.print(now.minute());
    fichierlog.print(":");
    fichierlog.print(now.second());
    fichierlog.print(";");

    fichierlog.print(iCycle);
    fichierlog.print(";");
    
    fichierlog.print(iEtape);
    fichierlog.println();
    fichierlog.close();
    

                /* tant que le bouton pause es tappuyé, on attends
         
         */
        
        // afficher la transition en cours

        Serial.println(tabTransition[iEtape].etatCondition1);
       
        delay(tabTransition[iEtape].etatCondition1);
        
        //delay(1000);

        /* tant que le bouton pause es tappuyé, on attends
         */
      }
    }
//--------------Animation : Clignotement du texte "Termine !!"--------------
    Serial.println("Termine !!");
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);

  }

}

Il fonctionne très bien (dans l’exemple aucun relai ne doit s’allumer)

Mais dès que je rajoute du code pour faire un fichier log, tout les 4 relais s’actionne et ce relache a chaque étape

code pour le log :

DateTime now = rtc.now();
fichierlog = SD.open(FileName, FILE_WRITE);

    fichierlog.print(now.year());
    fichierlog.print("/");
    fichierlog.print(now.month());
    fichierlog.print("/");
    fichierlog.print(now.day());
    fichierlog.print(";");
    
    fichierlog.print(now.hour());
    fichierlog.print(":");
    fichierlog.print(now.minute());
    fichierlog.print(":");
    fichierlog.print(now.second());
    fichierlog.print(";");

    fichierlog.print(iCycle);
    fichierlog.print(";");
    
    fichierlog.print(iEtape);
    fichierlog.println();
    fichierlog.close();

code avec log:

void loop() {
  

  iCycle = 0; // Initialisation du compteur de cycle à 0
  btnPlayPressed = digitalRead(etatbtnPlay); // Lecture de l'état  du bouton START
  //Serial.println(btnPlayPressed);



//--------------Attente de l'appuye sur le bonton START
  lcd.setCursor(0,0); 
  lcd.print("Appuye sur START");
  lcd.setCursor(0,1);
  lcd.print("                    ");
 
  while (btnPlayPressed == HIGH && iCycle <= nbCycle) // On boucle tant que le nombre de cycle du compteur est inférieur au nombre de cycle lu dans le csv
  {                                                   
    lcd.clear();
    
    //--------------On démarre le cyclage par les conditions Initiales
    Serial.println("Mise en conditions initiales");
    iEtape = 0;
    digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
    digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);

    iCycle = 1;

    for (iCycle = 1; iCycle <= nbCycle; iCycle++)
    {
      // affichage du nb de cycle éffectué
      lcd.setCursor(0, 0);
      lcd.print("Cycle = ");
      lcd.setCursor(8, 0);
      lcd.println(iCycle);
      lcd.setCursor(9, 0);
      lcd.print("  ");

      nbEtape=8;
      for (iEtape = 1; iEtape <= nbEtape; iEtape++) // le compteur nbEtape est définie ligne (113) à 8
      {
        // afficher l'étape en cours
        lcd.setCursor(0, 1);
        lcd.print("Etape = ");
        lcd.setCursor(8, 1);
        lcd.println(iEtape);
        lcd.setCursor(9, 1);
        lcd.print("  ");
        
 
        
        digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
        digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);
DateTime now = rtc.now();
fichierlog = SD.open(FileName, FILE_WRITE);

    fichierlog.print(now.year());
    fichierlog.print("/");
    fichierlog.print(now.month());
    fichierlog.print("/");
    fichierlog.print(now.day());
    fichierlog.print(";");
    
    fichierlog.print(now.hour());
    fichierlog.print(":");
    fichierlog.print(now.minute());
    fichierlog.print(":");
    fichierlog.print(now.second());
    fichierlog.print(";");

    fichierlog.print(iCycle);
    fichierlog.print(";");
    
    fichierlog.print(iEtape);
    fichierlog.println();
    fichierlog.close();
    

                /* tant que le bouton pause es tappuyé, on attends
         
         */
        
        // afficher la transition en cours

        Serial.println(tabTransition[iEtape].etatCondition1);
       
        delay(tabTransition[iEtape].etatCondition1);
        
        //delay(1000);

        /* tant que le bouton pause es tappuyé, on attends
         */
      }
    }
//--------------Animation : Clignotement du texte "Termine !!"--------------
    Serial.println("Termine !!");
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);

  }

}

tabEtape et tabTransition viennent d'où? Mettez tout le code

Partie 1 :

// librairie utilie pour le code:
#include <SD.h> // carte SD
#include <SPI.h> // Liaison Série
#include <string.h>
#include "Wire.h"  //Liaison I2C
#include "Adafruit_LiquidCrystal.h" // Ecran LCD I2C
#include "RTClib.h"

// Connection de l'écran LCD en I2C
Adafruit_LiquidCrystal lcd(0x20);
RTC_DS1307 rtc;


File fichiersetup; // Fichier pour la lecture du ficher de setu
File fichierlog; // Fichier pour enregistrer les données


static char buf[50]; // buffer pour la lecture de la linge
char FileName[20];


int ligne = 0; // Compteur pour la lecture de la ligne
int paraBloquant; // Variable pour la coversion du paramètre bloquant ou non
int IndexEtape; // Compteur pour le nombre d'étape (raz à chaque cycle)
int nbEtape; // Nombre d'étape 
int nbCycle; // Nombre de cycle dans le fichier csv
int Nombredecycle; // Nombre de cycle lancer (par le bouton start
int iCycle; // Compteur pour le nombre de cycle éffectué
int iEtape; // Compteur pour le nombre d'étape éffectué
int iTransition; // Compteur pour le nombre de transition
int btnPlayPressed; 
int etatbtnPlay = 11; // variable pour vérifier l'état du btnPlayPressed


// Pins Relais
const int NUM_R1 = 4;
const int NUM_R2 = 5;
const int NUM_R3 = 6;
const int NUM_R4 = 7;


// Pour chaque ligne du csv on a : 
char *p1; // Cellule 1
char *p2; // Cellule 2 pas besoin d'être séparé (soit N soit B)
char *p3; // Cellule 3
char *p12; // Partie à gauche du "+"
char *p22; // Partie à droite du "+"
char *p121; // Partie à gauche du "=" à gauche du "+"
char *p122; // Partie à droite du "=" à gauche du "+"
char *p221; // Partie à gauche du "=" à droite du "+"
char *p222; // Partie à droite du "=" à droite du "+"

// Fonctions pour le numéro et l'etat d'un relai
int funcDonneNumRelai (char *cParamLu);
int funcDonneEtatRelai (char *cParamLu);

// déclaration des structures
struct typRelai {
  int numRelai1;  // numéro du relai1 (à gauche du "+")
  int etatRelai1;  // état du relai (à gauche du "+")
  int numRelai2;  // numéro du relai (à droite du "+")
  int etatRelai2;  // état du relai (à droite du "+")
};
typRelai rVariable {0, 0};

struct typTransition {
 // int numCondition1; // numéro de la condition (à gauche du "+")
  int etatCondition1; // état de la condition (à gauche du "+")
 // int numCondition2; // numéro de la condition (à droite du "+")
 // int etatCondition2; // état de la condition (à droite du "+")
  int bloquant;
};
typTransition tVariable {0, 0};



// déclaration du tableau
typRelai tabEtape[8];
typTransition tabTransition[8];

Partie 2 :

void setup() {



// Démarrage de la RTC
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();

  if (! rtc.isrunning()) {
    Serial.println("RTC ne fonctionne PAS!");
    // La ligne qui suit ajuste le RTC à la date et time du moment de compilation
     //rtc.adjust(DateTime(__DATE__, __TIME__));  // décommenter pour mettre a l'heure
  }
 DateTime now = rtc.now();

// Pin pour les Relais
  pinMode(NUM_R1, OUTPUT); // pin de sortie du Relai 1
  pinMode(NUM_R2, OUTPUT); // pin de sortue du Relai 2
  pinMode(NUM_R3, OUTPUT); // pin de sortie du Relai 3
  pinMode(NUM_R4, OUTPUT); // pin de sortie du Relai 4
  pinMode(etatbtnPlay, INPUT); // pin du bouton Start (Entrée)

  lcd.begin(20, 4); // démarrage du LCD en 20*4
  lcd.setBacklight(HIGH); // allumage du rétroéclairage


  // Ouverture du port série
  Serial.begin(9600); //démarage de la liaison série
  while (!Serial) {}; // a commenter si cycleur sur pile


  // -----------------------Initialisation de la carte SD------------------------------
  Serial.print("Initialisation de la carte SD ...");
  if (!SD.begin(4)) {
    Serial.println("initialisation echouee !");
    return;
  }
  Serial.println("initialisation reussie.");






// Nom du fichier log 
sprintf(FileName,"%02d%s%02d%s",now.hour(),"h",now.minute(),".csv");


// Ecriture de la date et heure dans le fichier
fichierlog = SD.open(FileName, FILE_WRITE);
  if (fichierlog) {
    Serial.print("Writing to test.txt...");
    fichierlog.print(now.year());
    fichierlog.print("/");

    fichierlog.print(now.month());
    fichierlog.print("/");

    fichierlog.print(now.day());
    fichierlog.print("  ");

    fichierlog.print(now.hour());
    fichierlog.print(":");

    fichierlog.print(now.minute());
    fichierlog.print(":");

    fichierlog.println(now.second());
    fichierlog.close();

    
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

    




  //------------------------Ouverture du fichier setup csv-----------------------------------
  fichiersetup = SD.open ("READTEST.csv", FILE_READ);
  
  




  //----------------------Lecture du fichier csv ligne par ligne-----------------------

  while (fichiersetup.available())
  {

    int i;
    for (i = 0; fichiersetup.available() && i < sizeof buf - 1; i++)
    {
      buf[i] = fichiersetup.read();
      if (buf[i] == '\n')
        break;  // fin de ligne
    }
    buf[i] = 0;  // fin de la chaine




    ligne++;
    //  }


    nbEtape = 8;


    //--------------séparation des données d'une ligne (ici 3 cellules Max)---------------
    // Séparation des cellules
    p1 = strtok(buf, ";");
    p2 = strtok(NULL, ";");
    p3 = strtok(NULL, ";");
    //Serial.println(p3);
    // Séparation au niveau du "+"
    p12 = strtok(p2, "+");
    p22 = strtok(NULL, ";");

    // Séparation de la partie a gauche du "+" au niveau du "="
    p121 = strtok(p12, "=");
    p122 = strtok(NULL, ";");

    // Séparation de la partie a droite du "+" au niveau du "="
    p221 = strtok(p22, "=");
    p222 = strtok(NULL, ";");

    if (strstr(p1, "CYCLES"))
    {
      nbCycle = atoi(p2); // conversion de la valeur lu dans le csv a un integer
      Serial.print("Nombre de cycles="); // Affichage du resultat de la conversion
      Serial.println (nbCycle); // Affichage du resultat de la conversion
    }



if(strstr(p1, "CYCLES"))
{
  nbCycle=atoi(p2);
  Serial.print("Nombre de cycles=");
  Serial.println (nbCycle);
}



if (strstr(p1, "CONDITION")) // Si on lit CONDITION
  {
    IndexEtape=0;
    //---------------------conversion du numéro du 1er relai----------------------------

  rVariable.numRelai1 = funcDonneNumRelai(p121);
  //Serial.println(rVariable.numRelai1);
  
//----------------------conversion de l'etat du 1er relai----------------------------

  rVariable.etatRelai1 = funcDonneEtatRelai(p122);
//Serial.println(rVariable.etatRelai1);
 


//********************************2ème Relai*****************************************

 //---------------------conversion du numéro du 2ème relai----------------------------
  

  rVariable.numRelai2 = funcDonneNumRelai(p221);
  //Serial.println(rVariable.numRelai2);

//----------------------conversion de l'etat du 2ème relai----------------------------

  rVariable.etatRelai2 = funcDonneEtatRelai(p222);
  //Serial.println(rVariable.etatRelai2);

    tabEtape[IndexEtape]=rVariable;

  }
  else if (strstr(p1, "ETAPE")) // Si on lit ETAPE 
  {
    IndexEtape++;
    //---------------------conversion du numéro du 1er relai----------------------------

  rVariable.numRelai1 = funcDonneNumRelai(p121);
  //Serial.println(rVariable.numRelai1);

  
//----------------------conversion de l'etat du 1er relai----------------------------


  rVariable.etatRelai1 = funcDonneEtatRelai(p122);
  //Serial.println(rVariable.etatRelai1);

 


//********************************2ème Relai*****************************************

 //---------------------conversion du numéro du 2ème relai----------------------------


  rVariable.numRelai2 = funcDonneNumRelai(p221);
  //Serial.println(rVariable.numRelai2);

//----------------------conversion de l'etat du 2ème relai----------------------------

     rVariable.etatRelai2 = funcDonneEtatRelai(p222);
     //Serial.println(rVariable.etatRelai2);

     
    tabEtape[IndexEtape]=rVariable;
    
  }
  else if (strstr(p1, "TRANSITION")) // Si on lit TRANSITION
  {

    tVariable.etatCondition1=atoi(p122);
    Serial.println(tVariable.etatCondition1);


  }
//ecriture du titre du programme
else if(strstr(p1, "ENTETE")){
fichierlog = SD.open(FileName, FILE_WRITE);
    fichierlog.println(p2);
    fichierlog.close();
                        
                             }






    //------------------Verification de la lecture et du découpage--------------------
    //Serial.println(p1); // Cellule 1
    //Serial.println(p2); // Cellule 2
    //Serial.println(p12); // Partie à gauche du "+"
    //Serial.println(p22); // Partie à droite du "+"
    //Serial.println(p121); // Partie à gauche du "=" à gauche du "+"
    //Serial.println(p122); // Partie à droite du "=" à gauche du "+"
    //Serial.println(p221); // Partie à gauche du "=" à droite du "+"
    //Serial.println(p222); // Partie à droite du "=" à droite du "+"






    //********************************1er Relai*****************************************





    //-------------------conversion paramètre bloquant ou non---------------------------
    if (strcmp(p3, "N") == 0)
      paraBloquant = 0; // Si on lit N , on affecte à paraBloquant la valeur 0
    else
      paraBloquant = 1; // Sinon on affecte à paraBloquant la valeur 1

    tVariable.bloquant = paraBloquant;

    tabTransition[IndexEtape] = tVariable;


  }

 }

Partie 3 :

void loop() {
  

  iCycle = 0; // Initialisation du compteur de cycle à 0
  btnPlayPressed = digitalRead(etatbtnPlay); // Lecture de l'état  du bouton START
  //Serial.println(btnPlayPressed);



//--------------Attente de l'appuye sur le bonton START
  lcd.setCursor(0,0); 
  lcd.print("Appuye sur START");
  lcd.setCursor(0,1);
  lcd.print("                    ");
 
  while (btnPlayPressed == HIGH && iCycle <= nbCycle) // On boucle tant que le nombre de cycle du compteur est inférieur au nombre de cycle lu dans le csv
  {                                                   
    lcd.clear();
    
    //--------------On démarre le cyclage par les conditions Initiales
    Serial.println("Mise en conditions initiales");
    iEtape = 0;
    digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
    digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);

    iCycle = 1;

    for (iCycle = 1; iCycle <= nbCycle; iCycle++)
    {
      // affichage du nb de cycle éffectué
      lcd.setCursor(0, 0);
      lcd.print("Cycle = ");
      lcd.setCursor(8, 0);
      lcd.println(iCycle);
      lcd.setCursor(9, 0);
      lcd.print("  ");

      nbEtape=8;
      for (iEtape = 1; iEtape <= nbEtape; iEtape++) // le compteur nbEtape est définie ligne (113) à 8
      {
        // afficher l'étape en cours
        lcd.setCursor(0, 1);
        lcd.print("Etape = ");
        lcd.setCursor(8, 1);
        lcd.println(iEtape);
        lcd.setCursor(9, 1);
        lcd.print("  ");
        
 
        
        digitalWrite(tabEtape[iEtape].numRelai1, tabEtape[iEtape].etatRelai1);
        digitalWrite(tabEtape[iEtape].numRelai2, tabEtape[iEtape].etatRelai2);
DateTime now = rtc.now();
fichierlog = SD.open(FileName, FILE_WRITE);

    fichierlog.print(now.year());
    fichierlog.print("/");
    fichierlog.print(now.month());
    fichierlog.print("/");
    fichierlog.print(now.day());
    fichierlog.print(";");
    
    fichierlog.print(now.hour());
    fichierlog.print(":");
    fichierlog.print(now.minute());
    fichierlog.print(":");
    fichierlog.print(now.second());
    fichierlog.print(";");

    fichierlog.print(iCycle);
    fichierlog.print(";");
    
    fichierlog.print(iEtape);
    fichierlog.println();
    fichierlog.close();
    

                /* tant que le bouton pause es tappuyé, on attends
         
         */
        
        // afficher la transition en cours

        Serial.println(tabTransition[iEtape].etatCondition1);
       
        delay(tabTransition[iEtape].etatCondition1);
        
        //delay(1000);

        /* tant que le bouton pause es tappuyé, on attends
         */
      }
    }
//--------------Animation : Clignotement du texte "Termine !!"--------------
    Serial.println("Termine !!");
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("          ");
    delay(300);
    lcd.setCursor(0, 2);
    lcd.print("Termine !");
    delay(300);

  }

}


//---------Fonction pour le numéro du relai-----------

int funcDonneNumRelai (char *cParamLu)
{
const int NUM_R1 = 4;
const int NUM_R2 = 5;
const int NUM_R3 = 6;
const int NUM_R4 = 7;

int iNumRelai;

  if (strcmp(cParamLu,"R1")==0)
    iNumRelai=NUM_R1; // Si on lit R1, on affecte à numRelai la valeur 1
  else if (strcmp(cParamLu,"R2")==0)
    iNumRelai=NUM_R2; // Si on lit R2, on affecte à numRelai la valeur 2
  else if (strcmp(cParamLu,"R3")==0)
     iNumRelai=NUM_R3; // Si on lit R3, on affecte à numRelai la valeur 3 
  else if (strcmp(cParamLu,"R4")==0)
     iNumRelai=NUM_R4; // Si on lit R4, on affecte à numRelai la valeur 4                              
  else 
     iNumRelai=0;  // Si on lit ni R1 ni R2 ni R3 ni R4, le numéro du relai est 0
     //Serial.println(rVariable.numRelai2); // affiche le résultat de la conversion
   
  return iNumRelai;

}


//---------Fonction pour l'état du relai-----------

int funcDonneEtatRelai (char *cParamLu)
{
const int ON_R = 1;
const int OFF_R = 0;


int iEtatRelai;

  if (strcmp(cParamLu,"OFF")==0)
    iEtatRelai=OFF_R; // Si on lit R1, on affecte à numRelai la valeur 1                         
  else 
     iEtatRelai=ON_R;  // Si on lit ni R1 ni R2 ni R3 ni R4, le numéro du relai est 0
     //Serial.println(rVariable.numRelai2); // affiche le résultat de la conversion
   
  return iEtatRelai;

}

J'ai trouver la solution :

Mon setup de la carte SD est sur le port 4 :

  Serial.print("Initialisation de la carte SD ...");
  if (!SD.begin(4)) {
    Serial.println("initialisation echouee !");
    return;
  }
  Serial.println("initialisation reussie.");

Et j'ai un relai de branché sur ce pin. C'est ça qui possait problème.

J'ai changer les pins de mes relais et tous marche comme il faut !!