Go Down

Topic: Créer une suite de fichier avec une boucle for (Read 278 times) previous topic - next topic

Woxet

Feb 17, 2018, 11:54 am Last Edit: Feb 17, 2018, 12:10 pm by Woxet
Bonjour, bonjour,

J'ai un projet à réaliser d'une station météo avec l'Arduino accesible via Internet.

Pour cela j'aimerais faire un échantillonnage de la température, de la luminosité, ect... Enfin, j'aimerais stocker cet échantillonnage dans des fichiers .txt.

J'ai alors pensé à créer une suite de fichier .txt avec une boucle for, mais je ne sais pas trop si c'est possible. Voici ce que j'ai commencé à imaginier :

Code: [Select]
for(int i =0; i < ; i++){
          myFile = SD.open("relever "+[i]+".txt", FILE_WRITE);
          myFile.println(analogRead(A0));
          myFile.println(analogRead(A1));
          myFile.println(analogRead(A2));
          myFile.println(analogRead(A3));
          myFile.println(analogRead(A4));
          myFile.println(analogRead(A5));
          delay(10000);
        }


J'utilise une carte Arduino UNO et un shield Ethernet.
Merci d'avance pour vos réponses.

lesept

Mais quelle est ta question ? Savoir si ça marche ? Teste-le et reviens si ça ne marche pas...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

Woxet

Mais quelle est ta question ? Savoir si ça marche ? Teste-le et reviens si ça ne marche pas...
Ma question est d'abord est-ce que c'est possible ?
Et je sais que mon code ne marche pas sinon je ne l'aurais pas posté, c'était pour que ceux qui lisent ce post ont une idée de ce que je veux obtenir ^^'

J-M-L

#3
Feb 17, 2018, 01:12 pm Last Edit: Feb 17, 2018, 01:21 pm by J-M-L
pourquoi créer plein de fichiers plutôt qu'un seul qui contiendra la suite des échantillons (éventuellement avec l'heure de lecture) ?


dans votre code il y a des trucs louches:
Code: [Select]
for(int i =0; i < ; i++){
--> i inférieur à quoi ???



dans l'ouverture du fichier
Code: [Select]
myFile = SD.open("relever "+[i]+".txt", FILE_WRITE);
vous êtes en C++ mais la classe String n'est pas une classe par défaut du compilateur et il vaut mieux l'oublier. Donc il faut bâtir le nom du fichier dynamiquement dans un buffer - si vous êtes paresseux vous pouvez faire cela avec sprintf() (ça fait grossir fortement la mémoire), si vous êtes un peu moins paresseux vous pouvez utiliser un peu d'intelligence puisqu'il n'y a que 2 caractères (en imaginant que vos N° de fichiers vont de 00 à 99) à modifier et vous savez exactement où ils sont dans le buffer. Par exemple voici un petit code de démo qui crée un nom de fichier aléatoire toutes les secondes et qui l'affiche dans la console série (à 115200 bauds)
Code: [Select]
char nomDeFichier[] = "dataXX.txt"; // Le XX sera remplacé par 2 caractères
const byte indexDizaine = 4; // l'index du caractère représentant les dizaines dans le nom du fichier (le premier X)
const byte indexUnite = 5;   // l'index du caractère représentant les unités dans le nom du fichier (le second X)

// une fonction qui va remplacer les XX dans le nom de fichier par les 2 chiffres du nombre passé en paramètre
void remplaceXX(byte valeur)
{
  if (valeur <= 99) { // pour ne pas dépasser (on sait que c'est un byte donc toujours positif entre 0 et 255)
    byte dizaine = valeur / 10; // la division entière nous donne les dizaine (ça vire les chiffres après la virgule: 44 / 10 en entier ça fait 4, pas 4.4)
    byte unite = valeur - 10 * dizaine;
    nomDeFichier[indexDizaine] = '0' + dizaine; // on part du code ASCII de la lettre '0' et passe au bon caractère (fonctionne car les chiffres sont successifs en ASCII)
    nomDeFichier[indexUnite] = '0' + unite; // idem pour les unités
  }
  Serial.print("J'ai construit le nom de fichier: ");
  Serial.println(nomDeFichier);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  remplaceXX(random(0, 100));
  delay(1000); // on attend une seconde
}


Dans la console vous verrez un truc du genre

J'ai construit le nom de fichier: data49.txt
J'ai construit le nom de fichier: data07.txt
J'ai construit le nom de fichier: data49.txt
J'ai construit le nom de fichier: data73.txt
J'ai construit le nom de fichier: data58.txt
J'ai construit le nom de fichier: data30.txt
J'ai construit le nom de fichier: data72.txt




ATTENTION les noms de fichiers traditionnellement sont plutôt au format 8.3 (c'est à dire au maximum 8 caractères, un point et 3 caractères d'extension donc data1234.txt c'est ok mais relever 765.data risque de poser soucis suivant votre carte SD et les librairies utilisées


Enfin dans votre code vous ne fermez jamais je fichier, ce qui n'est pas du tout une bonne idée... tout fichier ouvert doit être fermé


Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

Woxet

Merci beaucoup, je vais essayer d'adapter à mon code :) je vous tiens au courant lorsque j'aurais terminé !

Woxet

J'ai modifié et ça me donne ceci:
Code: [Select]
#include <SD.h>
File myFile;

char nomDeFichier[] = "Relevé X.txt"; // Le X sera remplacé par un caractères
const byte indexUnite = 8; // l'index du caractère représentant sa position dans le nom du fichier (le X)

// une fonction qui va remplacer les XX dans le nom de fichier par les 2 chiffres du nombre passé en paramètre
void remplaceX(byte valeur)
{
  if (valeur < 6) {
    byte unite = valeur;
    nomDeFichier[indexUnite] = '0' + unite; // on part du code ASCII de la lettre '0' et passe au bon caractère (fonctionne car les chiffres sont successifs en ASCII)
  }
  Serial.println(nomDeFichier);
}

void setup() {
  Serial.begin(9600);
   for(int i=0; i<6; i++){
    myFile = SD.open(remplaceX(i), FILE_WRITE);
    myFile.close();
    delay(1000); // on attend une seconde
  }
}

void loop() {
 
}

Cependant, sur la ligne
Code: [Select]
myFile = SD.open(remplaceX(i), FILE_WRITE);il semblerait que j'ai une erreur qui est : "invalid use of void expression"
Est-ce que vous pouvez m'expliquer pourquoi ça ne marche pas svp  :3

J-M-L

#6
Feb 17, 2018, 11:44 pm Last Edit: Feb 17, 2018, 11:45 pm by J-M-L
Vous ne pouvez pas mettre d'accent dans le nom du fichier

Éviter aussi l'espace

L'index dans votre exemple doit être  7 parce qu'il faut compter à partir de 0 pour le premier élément du tableau

ça ne sert à rien d'avoir une variable unite dans
Code: [Select]
byte unite = valeur;autant utiliser directement valeur

La fonction replace() ne retourne pas le nom du fichier, elle ne retourne rien d'où votre erreur
 il faut appeler
Code: [Select]
replace(i); // on modifie le nom du fichierpuis ensuite
Code: [Select]
myFile = SD.open(nomDeFichier, FILE_WRITE);
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

Woxet

En réutilisant la partie de programme que vous m'avez envoyé et les exemples disponibles, j'ai amélioré le programme de façon à créer un fichier et inscrire mes 6 entrées (A0 -> A5). Voici ce que j'obtiens :

Code: [Select]
#include <SPI.h>
#include <SD.h>

File myFile;

char nomDeFichier[] = "ReleveX.txt"; // Le X sera remplacé par un caractères
const byte indexRang = 6; // l'index du caractère représentant sa position dans le nom du fichier (le X)
char nomDentree[] = "AX"; // Le XX sera remplacé par 2 caractères
const byte indexEntree = 1; // l'index du caractère représentant les dizaines dans le nom du fichier (le premier X)

// une fonction qui va remplacer les XX dans le nom de fichier par les 2 chiffres du nombre passé en paramètre
void remplaceXi(byte valeur)
{
  if (valeur < 6) {
    nomDeFichier[indexRang] = '0' + valeur; // on part du code ASCII de la lettre '0' et passe au bon caractère (fonctionne car les chiffres sont successifs en ASCII)
  }
  Serial.print(nomDeFichier);
}

void remplaceXq(byte valeur)
{
  if (valeur < 6) {
    nomDentree[indexEntree] = '0' + valeur;
  }
  Serial.println(nomDentree);
}
void setup() {
  Serial.begin(9600);
  while (!Serial) {;}
  Serial.print("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
 for(int i=0; i<6; i++){
    remplaceXi(i);
    myFile = SD.open(nomDeFichier, FILE_WRITE);
    if (myFile) {
      Serial.print("Writing to test.txt...");
      for(int q=0; q<6; q++){
        remplaceXq;
        myFile.println(analogRead(nomDentree));
      }
      myFile.close();
      Serial.println("done.");
    } else {
      Serial.println("error opening test.txt");
    }
    delay(30000); // on attend une seconde
  }
}

void loop() {
}



Merci infiniment pour votre aide !
Au passage, voyez vous une quelconque manière d'optimiser ce code car je vais devoir inclure une bibliothèque Ethernet donc si je peux économiser le maximum de place je suis preneur, merci encore !

lesept

Bonjour
je pense que tu as encore une erreur dans cette boucle :
Code: [Select]
for(int q=0; q<6; q++){
        remplaceXq;
        myFile.println(analogRead(nomDentree));
      }
où tu devrais avoir :
Code: [Select]
remplaceXq(q);

Sinon, les chiffres vont de 0 à 9, donc tu devrais tester avec <10 au lieu de <6.

On peut faire un analogRead dont l'argument est une chaîne de caractères ? As-tu testé le code que tu viens de publier ?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

Woxet

Merci de la remarque, je suis allé modifier et effectivement ça marche mieux ^^'

Je n'ai pas besoin d'allait au dessus de 6 car je fais un échantillonnage toutes les 10 mins pour 1h soit 60min/10 = 6 fichiers et de même pour les entrées qui sont de A0 à A5

Go Up