Pages: 1 2 [3]   Go Down
Author Topic: Carte SD - programmation [mettre en tableau key et val liées] - config.txt  (Read 2777 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

De retour à la maison, je me rend compte que key et val sont des char*.

Donc il me faut les convertir vers char ou String. Je cherche comment !
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 224
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Tout simplement avec le constructeur de la classe String :
Code:
char* charArray = "Hello world!";
String str = String(charArray);

++
Logged


Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
String str = String(charArray);

Voici un très bon exemple de mauvaise utilisation de String

A droite du signe = tu appelles le constructeur de la classe String. Ce qui crée un objet String temporaire, alloue de la mémoire pour stocker la chaine de caractère, copie la chaine de caractère dans l'espace mémoire ainsi alloué.
A gauche du signe égal tu a la définition d'une variable str de type String. Ce qui crée l'objet String appelé str.
Le signe égal signifie qu'il y a copié du membre de droite vers le membre de gauche.
L'objet temporaire est copié dans l'objet str.
La classe String va donc allouer de la mémoire pour stocker la chaine de caractère qui est contenue dans l'objet temporaire, puis copier les caractères.
Une fois la copie effectue, l'objet temporaire n'est plus utile donc il est détruit.

Bref :
- Perte d'efficacité car on copie 2 fois l'ensemble des caractères = perte de temps
- Fragmentation inutile de la mémoire car on alloue pour rien une mémoire temporaire qui est ensuite libérée mais crée un trou dans la zone d'allocation dynamique de mémoire.

Un meilleur code est tout simplement :
Code:
String str = "chaine initiale";
Qui ne fait que l'allocation de str et une seule copie.


Voilà pourquoi je considère qu'utiliser String c'est MAL  smiley-evil

Quand on est débutant et qu'on ne comprend pas trop les mécanismes qui sont derrière, les programmes plantent sans qu'on sache pourquoi : que croyez vous qu'il se passe si String essaye de redimensionner l'espace de stockage allouée à une String et qu'il n'y a plus de mémoire dispo : rien et le programme part dans les choux.
Sur un PC avec la mémoire virtuelle, peut de chance que cela arrive, mais au pire vous avez une jolie boite de dialogue : "Cette application s'est inopinément arretée : Pas assez de mémoire"

Malheureusement c'est quand on est débutant qu'on se laisse tenté par la facilité d'utilisation de String...

Par ailleurs sur PC, les classes String équivalents sont bien codées. On utilise ce genre de classe avec du try/catch pour pouvoir intercepter les exceptions. Ce qui n'est pas possible avec la classe String Arduino car les codeurs (ah ces artistes) ont allègrement oublié de lever des exceptions en cas d'erreur, se contentant de ne rien faire.

Sur un système à faible ressource mémoire tel qu'un ATmega, il vaut beaucoup mieux apprendre à gérer sa mémoire proprement en sachant ce que l'on fait plutôt que de laisser du mauvais code le faire dans son dos. A terme vous aurez des programmes plus fiables et plus économes en mémoire.

C'était la minute du Professeur Rollin smiley-lol

Logged

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 ?

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Très bonnes indications !
Justement je vais priofiter de ton cours pour rebondir. La mauvaise habitude que j'ai eu avec les String m'est resté  smiley-mr-green Honte à moi !

Donc vers quelle type de variable s'orienté au niveau du final ?

Je demande car e viens de changer un peu la donne. En fait je vais me permettre de simplifier un peu tout ça.
Mon vichier va évoluer comme suit:
Quote
//Modèle
Robot Go

//Type
Robot

//Mix_V1V2 / Mix_V3V4
true
false

Par contre, au retour j'obtiens:
Quote
Robot Go
Robot
fals
false

Il manque un true et j'obtiens un false incomplet qui prends la place du true  smiley-sad-blue

Au niveau code quelques changements pour essayer. Tant que j'en suis à tester, autant que je teste toutes les solutions avant de me jetter dans une version finale.
Code:
#define SIZE_CONF 10  //Nombre de configuration par fichier

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

/* 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
}

/* 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;
  String toto[SIZE_CONF];
 
  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) {
         
          //Finir la ligne et stopper la lecture
          while(myFile.read() != '\n') {
           
            break;
          }
        }
      }
     
     
      bufferLenght = i;  //Garder en mémoire le nombre de lettre
      bufferConf[--i] = '\0';  //Finir la ligne en retirant le saut de ligne
     
      //Serial.println(bufferConf[0]);
      //Ne pas enregistrer les lignes vides ou les commentaires
      if(bufferConf[0] == '\0' || bufferConf[0] == '/' || bufferConf[0] == '#') {
        continue;
      }
     
      toto[lineCounter] = bufferConf;
      ++lineCounter; //Compter le nombre de lignes
    }
   
   
    Serial.println(path);
    Serial.println(toto[0]);
    Serial.println(toto[1]);
    Serial.println(toto[2]);
    Serial.println(toto[3]);
    Serial.println(toto[4]);
    Serial.println(toto[5]);
    Serial.println(lineCounter);
   
   
  }
  else {
   
    clearLcd();  //Efface l'écran
    ecrireLcd("Fichier introuvable", 01);  //Ecrire
    for(;;);
  }
 
  //Fermer le fichier
  myFile.close();
 
  ecrireLcd("Fichier Ok", 01);  //Ecrire
 
  delay(1000);
}

Comme on le voie, si j'ai un commentaire, on saute, si j'ai un saut de ligne on saute.

Ne pas tenir compte de la sortie car je demande plus haut vers quoi je devrais évolué pour ne pas forcément utilisé un String  smiley-mr-green

Merci.
Logged

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

De mon point de vue, il vaut mieux utiliser des tableaux de char, de dimensions connues et maitrisées.
Utiliser les bonnes fonctions telles que strncpy() au lieu de strcpy() etc ... afin d'éviter les débordements de tableaux.

A la fin tu verra que finalement, les tableaux de char et la libC (stdio.h et string.h) offrent beaucoup de possibilités et un meilleur contrôle.
Logged

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 ?

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bon j'ai un autre problème smiley-sad

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

Même quand elle ne contient rien !!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/* 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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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.
Logged

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

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 ?

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Et bien, c'est super cette page  smiley-cool 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  smiley-wink
Je vous simplifie le code de façon à montrer que ce qui n'a de l'intérêt avec le sujet.
Code:
/*
  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 ?
Logged

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Planquer le code ne le fait pas disparaitre. DOnc tu ne gagnera pas d'octets.

Mais structurer ton code en modules, avec ou sans classes, te fera gagner en lisibilité et maintenabilité.
Logged

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 ?

Offline Offline
Full Member
***
Karma: 0
Posts: 113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, au temps pour moi ! Quand je parlais de réduire, le voulais dire augmenter la lisibilité.

Ceci dit, j'aimerais que les classes soit externe à mon programme principal. Comment ça se passe ?

In crée les classes puis un coup de require() suffit ? Ou bien, faut-t-il gardé dans le seul fichier à charger ?
Logged

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

require() c'est du Java(Script)

En C++ tu crée :
- Un fichier H de déclaration

Code:
#ifndef _MACLASSE_H_
#define _MACLASSE_H_

Class MaClasse
{
  public:
    MaClasse(); // Constructeur par défaut
    MaClasse( int p1, int p2 ); // Constructeur avec paramètres
    ~MaClasse(); // Destructeur

    int Toto( int p1 ); // Fonction membre publique Toto

  protected:
    void titi( int p2 ) ; fonction membre protégée

    int x;  // variable membre
    int y;
};

#endif

- Un fichier CPP d'implémentation

Code:

#include "MaClasse.h"

MaClasse::MaClasse()
{
  // code du constructeur par défaut
  x = 0;
  y = 0;
}

MaClasse::MaClasse( int p1, int p2 )
{
  // code du constructeur par défaut
  x = p1;
  y = p2;
}

MaClasse::~MaClasse()
{
  // code du destructeur
}

int MaClasse::Toto( int p1 )
{
  return (x + p1) / (y + 1);
}

void MaClasse::titi( int p1 )
{
  x++;
  y--;
}

Pour créer les fichiers dans l'IDE Arduino, tu cherche la petite fleche vers le bas à droite de la barre d'onglet et tu choisit "Ajouter un onglet"
Tu enregistre tous les fichiers dans le même répertoire que ton INO
Et normalement quand tu double-clique sur le INO, tout se charge

Au début du INO tu mets tous les #include "xxx.h"
Logged

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 ?

Offline Offline
Full Member
***
Karma: 0
Posts: 113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok pour tout ça  smiley-cool

Je propose d'utiliser une fonction dans l'éditeur qui est de cocher éditeur externe. J'ai un bon vieux Geany qui me sert pas mal comme éditeur. Par contre, je compilerais avec l'ide arduino.

Je te remercie pour tous ces conseils et infos. Par contre require') php et java le font, peut-être pas c++ en effet  smiley-sweat

Bon et bien, la semaine prochaine, je met mon soft par terre, j'externalise tout  smiley-mr-green

Logged

Pages: 1 2 [3]   Go Up
Jump to: