Go Down

Topic: Carte SD - programmation [mettre en tableau key et val liées] - config.txt (Read 3 times) previous topic - next topic

Microbulle

Bon j'ai un autre problème :(

A prori je ne sort jamais de la boucle while(myFile.available()) {}

Même quand elle ne contient rien !!

Microbulle

Bon j'ai trouvé !

Effectivement pas bon les Strings  :smiley-mr-green: mais pas bon du tout  :smiley-red:

Bon, alors j'ai modifier mon code ainsi (et je ne vous met pas tout car c'est que la fin qui change !
Code: [Select]

/* FONCTION initSD() */
boolean initSD() {
 
  clearLcd();  //Effacer l'écran
  ecrireLcd("Init SD Card", 01);  //Ecrire
 
  //Si la carte n'est pas présente ou qu'elle est en défaut
  if(!SD.begin(4)) {
   
    ecrireLcd("Non presente", 21);  //Ecrire
    return false;
  }
 
  ecrireLcd("Sd card... Ok", 21);  //Ecrire
 
  delay(1000);
  return true;
}

/* FONCTION listerFichier() */
int listeFichier(String chemin) {
 
  int count = 0;
  char path[SIZE_BUFFER];
 
  //Conversion du chemin
  chemin.toCharArray(path, SIZE_BUFFER);
 
  //Ouvre ce qui est défini par le chemin
  myFile = SD.open(path);
 
  //Tant que c'est vrai
  while(true) {
   
    //Prend le nom du fichier
    File entry = myFile.openNextFile();
   
    //Si c'est la fin
    if(!entry) {
     
      break;  //Sortir de la boucle
    }
   
    //Si le nombre de fichier est plus important que le nombre de place en tableau
    if(count == SIZE_MODELE) {
     
      break;  //Sortir de la boucle
    }
   
    //Si c'est le répertoire /modeles/
    if(chemin == "/modeles/") {
   
        //Rentre le nom de fichier dans le tableau des noms de modèles
        tblFicMdle[count] = entry.name();
    }
   
    //Si c'est le répertoire /sauvegarde/
    if(chemin == "/svgde/") {
       
      //Rentre le nom de fichier dans le tableau des noms de sauvegarde
      tblFicSvg[count] = entry.name();
    }
   
    count++; //Compter le nombre de fichier
  }
 
  //Fermer le fichier
  myFile.close();
 
  //Retourner le nombre de fichier
  return count;
}

/* FONCTION qui ouvre un fichier */
void ouvrirFichier(String chemin, String fic) {
 
  //Variables
  char path[SIZE_BUFFER], bufferConf[SIZE_BUFFER];
  int i, bufferLenght, lineCounter = 0;
 
  clearLcd();  //Efface l'écran
  ecrireLcd("Fichier en lecture", 01);  //Ecrire
 
  //Crée le chemin
  chemin = chemin + fic;
 
  //Transforme le chemin
  chemin.toCharArray(path, SIZE_BUFFER);
 
  //Ouvre le fichier
  myFile = SD.open(path, FILE_READ);
 
  //Si le fichier est présent
  if(myFile) {
    //Tant que ce n'est pas la fin du fichier
    while(myFile.available()) {
     
      //Récupère la ligne
      i = 0;
      while((bufferConf[i++] = myFile.read()) != '\n') {
       
        //Si la ligne dépasse le buffer
        if(i == SIZE_BUFFER) {
          break;
        }
      }
     
      bufferLenght = i;  //Garder en mémoire le nombre de lettre
      bufferConf[--i] = '\0';  //Finir la ligne en retirant le saut de ligne
      lineCounter++; //Compter le nombre de lignes
     
      //Ne pas enregistrer les lignes vides ou les commentaires
      if(bufferConf[0] == '\0' || bufferConf[0] == '/' || bufferConf[0] == '#') {
        continue;
      }
     
      Serial.println(bufferConf);
     
    }
   
    //Fermer le fichier
    myFile.close(); 
  }
 
  return;
}


la ou je sort mon Serial.println(bufferConf); c'est là que je dois entrée en tableau. Ce que je cherche c'est à avoir
tbl[0] -> Robot Go
tbl[1] -> Robot
tbl[2] -> true
tbl[3] -> false

Il y aura des tests sur true et false au final. Donc c'est un point à étudier afin de ne pas le perdre de vue.

Microbulle

En fait ça fonctionne très bien. Beaucoup d'erreur ont été commise au niveau tableau.  :smiley-sad-blue:

La confusion entre un tableau de char ou x valait le nombre de possibilités et un tableau à deux dimensions qui lui a un nombre de possibilité de case contenant un nombre de caractères données.

L'incompréhension de strncpy qui après coup est effectivement une fonction rapide et pratique.

Je met ici la solution finale qui fonctionne.
Code: [Select]

#define SIZE_BUFFER 32  //Nombre de case du buffer
#define SIZE_CMDE 10  //Nombre de commandes

File myFile;  //Fichier
String tblFicMdle[SIZE_CMDE];  //Le tableau des noms des fichiers modèles
String tblFicSvg[SIZE_CMDE];  //Le tableau des noms des fichiers de sauvegardes
int nbFichierMdle;  //Nombre de fichier

char tblConfSvg[SIZE_CMDE][SIZE_BUFFER];  //Le tableau des configuration du fichier de sauvegarde
char tblConfMdle[SIZE_CMDE][SIZE_BUFFER]; //Le tableau des configurations du fichier de modèle

/* SETUP */
void setup() {
//Initialiser la carte SD
  if(initSD()) {
   
    //Lister les fichier de sauvegardes
    listeFichier("/svgde/");
   
    //Lister les fichiers de configuration modèle
    nbFichierMdle = listeFichier("/modeles/");
   
    //Ouvrir le fichier de sauvegarde
    //ouvrirFichier("/svgde/", tblFicSvg[0]);
   
    ouvrirFichier("/modeles/", tblFicMdle[2]);
  }
  else {
     
    //Charger les valeurs par défaut de la radio
  }
 
  Serial.println(tblConfMdle[0]);
  Serial.println(tblConfMdle[1]);
  Serial.println(tblConfMdle[2]);
  Serial.println(tblConfMdle[3]);
  Serial.println(tblConfMdle[4]);
}

/* LOOP */
void loop() {
}


/* FONCTION listerFichier() */
int listeFichier(String chemin) {
 
  int count = 0;
  char path[SIZE_BUFFER];
 
  //Conversion du chemin
  chemin.toCharArray(path, SIZE_BUFFER);
 
  //Ouvre ce qui est défini par le chemin
  myFile = SD.open(path);
 
  //Tant que c'est vrai
  while(true) {
   
    //Prend le nom du fichier
    File entry = myFile.openNextFile();
   
    //Si c'est la fin
    if(!entry) {
     
      break;  //Sortir de la boucle
    }
   
    //Si le nombre de fichier est plus important que le nombre de place en tableau
    if(count == SIZE_CMDE) {
     
      break;  //Sortir de la boucle
    }
   
    //Si c'est le répertoire /modeles/
    if(chemin == "/modeles/") {
   
        //Rentre le nom de fichier dans le tableau des noms de modèles
        tblFicMdle[count] = entry.name();
    }
   
    //Si c'est le répertoire /sauvegarde/
    if(chemin == "/svgde/") {
       
      //Rentre le nom de fichier dans le tableau des noms de sauvegarde
      tblFicSvg[count] = entry.name();
    }
   
    count++; //Compter le nombre de fichier
  }
 
  //Fermer le fichier
  myFile.close();
 
  //Retourner le nombre de fichier
  return count;
}

/* FONCTION qui ouvre un fichier */
void ouvrirFichier(String rep, String fic) {
 
  //Variables
  char path[SIZE_BUFFER], bufferConf[SIZE_BUFFER+1];
  int i, bufferLenght, lineCounter = 0;
  String chemin;
 
  clearLcd();  //Efface l'écran
  ecrireLcd("Fichier en lecture", 01);  //Ecrire
 
  //Crée le chemin
  chemin = rep + fic;
 
  //Transforme le chemin
  chemin.toCharArray(path, SIZE_BUFFER);
 
  //Ouvre le fichier
  myFile = SD.open(path, FILE_READ);
 
  //Si le fichier est présent
  if(myFile) {
    //Tant que ce n'est pas la fin du fichier
    while(myFile.available()) {
     
      //Récupère la ligne
      i = 0;
      while((bufferConf[i++] = myFile.read()) != '\n') {
       
        //Si la ligne dépasse le buffer
        if(i == SIZE_BUFFER) {
          break;
        }
      }
     
      bufferLenght = i;  //Garder en mémoire le nombre de lettre
      bufferConf[--i] = '\0';  //Finir la ligne en retirant le saut de ligne
     
      //Ne pas enregistrer les lignes vides ou les commentaires
      if(bufferConf[0] == '\0' || bufferConf[0] == '/' || bufferConf[0] == '#') {
        continue;
      }
     
     
     
      //Charger le tableau des configurations modèle
      if(rep == "/modeles/") {
       
        /*
          Copie le tableau contenant une commande, dans le tableau
          à deux dimensions qui est extérieur
        */
        strncpy(tblConfMdle[lineCounter], bufferConf, SIZE_BUFFER);
        bufferConf[SIZE_BUFFER] = '\0'; //Fini par un '\0'
      }
     
      //Charger le tableau des configurations sauvegardes
      if(rep == "/svgde/") {
       
        /*
          Copie le tableau contenant une commande, dans le tableau
          à deux dimensions qui est extérieur
        */
        strncpy(tblConfSvg[lineCounter], bufferConf, SIZE_BUFFER);
        bufferConf[SIZE_BUFFER] = '\0'; //Fini par un '\0'
      }
     
      lineCounter++; //Compter le nombre de lignes
    }
   
    //Fermer le fichier
    myFile.close(); 
  }
 
  return;
}


La prochaine étape va être de pouvoir charger les variables de tests. Avant je faisait des tests sur des strings. N'aurais-je pas intérêt à faire des tests sur des char fonction1, fonction2, fonction3... chargée par fonction1 = tbl1[0]; ... ?

Dans mon tableau j'ai entre autre du boolean (true ou false) qui doivent au final être tester. Je comprends bien qu'il me faudra faire de nouvelles conversions.

barbudor

Pour comparer des chaines de caractères : strcmp() ou strcasecmp()
Le premier prend en compte la différence minuscules/MAJUSCULES
Le 2nd ne prend pas en compte la différence
Renvoie 0 si égalité ou -1/+1 si différent (dépend si l'un est avant l'autre dans l'ordre alphabétique)

Si tu veux comparer qu'une partie de la chaîne il y a aussi strncmp() et strncasecmp() qui ne compare que les n premiers caractères
Tout est là : http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Microbulle

Et bien, c'est super cette page  8) J'ai encore appris des choses  :smiley-mr-green:

Alors, j'ai fait évoluer mon code et je doit en profiter pour vous citer dans mes soures  ;)
Je vous simplifie le code de façon à montrer que ce qui n'a de l'intérêt avec le sujet.
Code: [Select]

/*
  Auteur : Alexandre LABURE
 Aide DVP : Ragmaxone, sevyc64, Winjerome, Bousk
 Aide Arduino.cc : barbudor, SesechXP
 Création : le 30 octobre 2012
 Dernière modification : le 02 novembre 2012
 Version 1.0
*/

/* DEFINITIONS */
#define SIZE_BUFFER 32  //Nombre de case du buffer
#define SIZE_CMDE 10  //Nombre de commandes

File myFile;  //Fichier
String tblFicMdle[SIZE_CMDE];  //Le tableau des noms des fichiers modèles
String tblFicSvg[SIZE_CMDE];  //Le tableau des noms des fichiers de sauvegardes
int nbFichierMdle;  //Nombre de fichier

char tblConfSvg[SIZE_CMDE][SIZE_BUFFER];  //Le tableau des configuration du fichier de sauvegarde
char tblConfMdle[SIZE_CMDE][SIZE_BUFFER]; //Le tableau des configurations du fichier de modèle

//Configuration pour un modèle
String confNom, confType;
boolean confMix_V1V2, confMix_V3V4;

/* SETUP */
void setup() {
//Initialiser l'écran LCD
 initLcd();  //Initialiser l'écran LCD
 ecrireLcd("Telecommande 433Mhz", 01);  //Ecrire
 ecrireLcd("Version 1.0", 24);  //Ecrire
 ecrireLcd("Bonjour", 66);  //Ecrire
 
 delay(2000);
 
 
 //Initialiser la carte SD
 if(initSD()) {
   
   //Lister les fichier de sauvegardes
   listeFichier("/svgde/");
   
   //Lister les fichiers de configuration modèle
   nbFichierMdle = listeFichier("/modeles/");
   
   //Ouvrir le fichier de sauvegarde
   ouvrirFichier("/svgde/", tblFicSvg[0]);
   
   //ouvrirFichier("/modeles/", "model001.txt");
   ouvrirFichier("/modeles/", tblConfSvg[0]);
   
   //Charger les valeurs sauvegardés
   confNom = tblConfMdle[0];
   confType = tblConfMdle[1];
   
   //Compare la configuration
   if(strcmp(tblConfMdle[2], "true") == 0) {
     //Si c'est vrai
     confMix_V1V2 = true;
   }
   else {
     //Si c'est faux
     confMix_V1V2 = false;
   }
   
   //Compare la configuration
   if(strcmp(tblConfMdle[3], "true") == 0) {
     //Si c'est vraie
     confMix_V3V4 = true;
   }
   else {
     //Si c'est faux
     confMix_V3V4 = false;
   }
 }
 else {
   
   //Charger les valeurs par défaut de la radio
   confNom = "Aucun nom";
   confType = "Aucun";
   confMix_V1V2 = false;
   confMix_V3V4 = false;
 }
}

/* LOOP */
void loop() {
}

/* FONCTION initSD() */
boolean initSD() {
 
 clearLcd();  //Effacer l'écran
 ecrireLcd("Init SD Card", 01);  //Ecrire
 
 //Si la carte n'est pas présente ou qu'elle est en défaut
 if(!SD.begin(4)) {
   
   ecrireLcd("Non presente", 21);  //Ecrire
   return false;
 }
 
 ecrireLcd("Sd card... Ok", 21);  //Ecrire
 
 delay(1000);
 return true;
}

/* FONCTION listerFichier() */
int listeFichier(String chemin) {
 
 int count = 0;
 char path[SIZE_BUFFER];
 
 //Conversion du chemin
 chemin.toCharArray(path, SIZE_BUFFER);
 
 //Ouvre ce qui est défini par le chemin
 myFile = SD.open(path);
 
 //Tant que c'est vrai
 while(true) {
   
   //Prend le nom du fichier
   File entry = myFile.openNextFile();
   
   //Si c'est la fin
   if(!entry) {
     
     break;  //Sortir de la boucle
   }
   
   //Si le nombre de fichier est plus important que le nombre de place en tableau
   if(count == SIZE_CMDE) {
     
     break;  //Sortir de la boucle
   }
   
   //Si c'est le répertoire /modeles/
   if(chemin == "/modeles/") {
   
       //Rentre le nom de fichier dans le tableau des noms de modèles
       tblFicMdle[count] = entry.name();
   }
   
   //Si c'est le répertoire /sauvegarde/
   if(chemin == "/svgde/") {
       
     //Rentre le nom de fichier dans le tableau des noms de sauvegarde
     tblFicSvg[count] = entry.name();
   }
   
   count++; //Compter le nombre de fichier
 }
 
 //Fermer le fichier
 myFile.close();
 
 //Retourner le nombre de fichier
 return count;
}

/* FONCTION qui ouvre un fichier */
void ouvrirFichier(String rep, String fic) {
 
 //Variables
 char path[SIZE_BUFFER], bufferConf[SIZE_BUFFER+1];
 int i, bufferLenght, lineCounter = 0;
 String chemin;
 
 clearLcd();  //Efface l'écran
 ecrireLcd("Fichier en lecture", 01);  //Ecrire
 
 //Crée le chemin
 chemin = rep + fic;
 
 //Transforme le chemin
 chemin.toCharArray(path, SIZE_BUFFER);
 
 //Ouvre le fichier
 myFile = SD.open(path, FILE_READ);
 
 //Si le fichier est présent
 if(myFile) {
   //Tant que ce n'est pas la fin du fichier
   while(myFile.available()) {
     
     //Récupère la ligne
     i = 0;
     while((bufferConf[i++] = myFile.read()) != '\n') {
       
       //Si la ligne dépasse le buffer
       if(i == SIZE_BUFFER) {
         break;
       }
     }
     
     bufferLenght = i;  //Garder en mémoire le nombre de lettre
     bufferConf[--i] = '\0';  //Finir la ligne en retirant le saut de ligne
     
     //Ne pas enregistrer les lignes vides ou les commentaires
     if(bufferConf[0] == '\0' || bufferConf[0] == '/' || bufferConf[0] == '#') {
       continue;
     }
     
     //Charger le tableau des configurations modèle
     if(rep == "/modeles/") {
       
       /*
         Copie le tableau contenant une commande, dans le tableau
         à deux dimensions qui est extérieur
       */
       strncpy(tblConfMdle[lineCounter], bufferConf, SIZE_BUFFER);
       bufferConf[SIZE_BUFFER] = '\0'; //Fini par un '\0'
     }
     
     //Charger le tableau des configurations sauvegardes
     if(rep == "/svgde/") {
       
       /*
         Copie le tableau contenant une commande, dans le tableau
         à deux dimensions qui est extérieur
       */
       strncpy(tblConfSvg[lineCounter], bufferConf, SIZE_BUFFER);
       bufferConf[SIZE_BUFFER] = '\0'; //Fini par un '\0'
     }
     
     lineCounter++; //Compter le nombre de lignes
   }
 }
 else {
   clearLcd();  //Efface l'écran
   ecrireLcd("Fichier introuvable", 01);  //Ecrire
   for(;;);
 }
 
 //Fermer le fichier
 myFile.close();
 
 return;
}


Je vous ai épargné le loop() qui contient des choses qui n'ont plus rien à voir.

Je me suis fait un petit exemple avec strcmp() et qui fonctionne parfaitement. On test si c'est sur "true" et si oui, on en profite pour écrire true dans un boolean, sinon on écrit un false. C'est peut-être pas des plus optimisé mais ça fonctionne très bien.

Je profite d'aileur pour vous dire que je vais laisser tomber la carte SD quelques jours car j'aimerais nettoyé un peu mon code. Remplacer des strings inutiles par des char et revoir un peu l'architecture interne avec des classes. Par exemple créer une classe pour la partie LCD. Ainsi, je n'aurais plus à refaire initLcd(); planqué dans ma fonction. Elle sera directement dans la classe. Je pense qu'à terme ça peut faire gagner quelques octets et c'est pas non négligeable. Qu'en pensez-vous ?

Go Up