Skyduino:~#
Articles
arduino, Corrigé, programmation

[Arduino] Traitement fichier par fichier d’un dossier d’une carte SD

Bonjour tout le monde !

Dans le cadre du forum arduino.cc j’ai réalisé (ou plutôt repris à ma sauce) un morceau de code pour aider un membre sur son projet.
Celui ci avait besoin de lire des fichiers texte situés à la racine d’une carte sd pour ensuite les transmettre à un serveur web (avec un code php pour réceptionner les infos).
Le but d’origine étant de faire un système de sauvegarde « offline » sur carte sd des informations en attente de transmission.

Comme le code en lui même est plutôt générique je pense qu’il peut servir d’exemple pour la réalisation d’un système de traitement fichier par fichier plus spécialisé.

Le code d’origine est conçu pour lire des fichiers textes structurés suivant un format proche du CSV.
Pour cet article j’ai re-modifié mon code pour le rendre un peu plus générique en partant du principe que les fichiers textes sont dans un format csv classique.

Remarque : Je n’ai pas fait de test pour vérifier les extensions des fichiers avant traitement mais ce n’est pas bien grave dans le cas présent.

Le code, avec commentaires comme d’habitude 😉

/* ----- Dépendances ----- */
#include <SD.h>        /* Pour la carte SD */
#include <Ethernet.h> /* Pour la shield ethernet */
#include <SPI.h>      /* Pour la communication bas niveau (carte SD et ethernet) */

/** Taille du buffer pour la lecture du fichier texte et l'envoi de la requête HTTP */
static const byte BUFFER_SIZE = 50;

/** Adresse IP du serveur distant */
static IPAddress serverIp(192, 168, 0, 135);

/** Adresse IP de l'ethernet shield */
static IPAddress ip(192, 168, 0, 35);

/** Adresse MAC de l'ethernet shield */
static byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF };

/** Objet File pointant sur le dossier "root" de la carte SD */
File rootDir;

/** Fonction d'initialisation hardware */
void setup() {

  /* Initialisation du port série */
  Serial.begin(115200);

  /* Initialisation de la shield ethernet */
  Ethernet.begin(mac, ip);

  /* Initialisation de la carte SD */
  Serial.print(F("Initialisation de la carte SD ... "));
  pinMode(10, OUTPUT); /* Obligatoire pour que la communication SPI fonctionne (10 UNO, 53 Mega)*/
  if (!SD.begin(4)) {  /* Broche "CS" de la carte SD sur D4 */
    Serial.println(F("Echec !"));
    for(;;);
  } 
  Serial.println(F("Ok !"));

  /* Ouverture du dossier "root" */
  rootDir = SD.open("/");
  Serial.println(F("Setup Termine !"));
}

/** Fonction de travail (appelé en boucle) */
void loop() {
  /* Buffer temporaire pour la lecture du fichier et la création de la requête HTTP */
  char buffer[BUFFER_SIZE];

  /* Variables contenant les résultats de la lecture du fichier texte */
  int valeur, heures, minutes, secondes, jours, mois, annees;

  /* Ouverture du prochain fichier disponible sur la carte SD */
  File entry =  rootDir.openNextFile();
  if (!entry) {
    Serial.println(F("Problème d'ouverture ou plus de fichier disponible !"));
    for(;;);
    /* On pourrait aussi faire un rootDir.rewindDirectory() pour reprendre au 1er fichier */
  }

  /* Test pour savoir s'il s'agit d'un répertoire */
  if(entry.isDirectory()) {
    /* Dans le cas d'un répertoire il est possible de faire un scan récursif.
     * Ici on ignore juste les dossiers */
    entry.close();
    return;
  }

  /* Affichage du nom du fichier en cours (pour debug) */
  /* Note: je ne fais pas de vérification sur l'extension des fichiers */
  Serial.print(F("Traitement de "));
  Serial.println(entry.name());

  /* Lecture des données du fichier */
  byte i = 0;
  while(entry.available() > 0) { /* Jusqu'à la fin du fichier */
    buffer[i] = entry.read(); /* Buffering */

    /* Sécurité anti buffer-overflow */
    if(++i == BUFFER_SIZE) {
      Serial.println(F("Fichier trop gros !"));
      entry.close();
      return;
    }
  }
  buffer[i] = '\0';

  /* Fermeture du fichier */
  entry.close();

  /* Pour debug */
  Serial.print(F("Buffer: "));
  Serial.println(buffer);

  /* Extraction des champs */
  if(sscanf(buffer, "%d ;%d ;%d ;%d ;%d ;%d ;%d", &valeur, &heures, &minutes, &secondes, &jours, &mois, &annees) != 7) {
    Serial.println(F("Fichier malforme !"));
    return;
  }

  /* Pour debug */
  Serial.print(F("Annees: "));
  Serial.println(annees);
  Serial.print(F("Mois: "));
  Serial.println(mois);
  Serial.print(F("Jours: "));
  Serial.println(jours);
  Serial.print(F("Heures: "));
  Serial.println(heures);
  Serial.print(F("Minutes: "));
  Serial.println(minutes);
  Serial.print(F("Secondes: "));
  Serial.println(secondes);
  Serial.print(F("Valeur: "));
  Serial.println(valeur);

  /* Ouverture de la connexion TCP */
  EthernetClient client;
  Serial.print(F("Connexion au serveur ... "));
  if (!client.connect(serverIp, 80)) {
    Serial.println(F("Echec !"));
    return;
  }
  Serial.println(F("Ok !"));

  /* Envoi de la requete HTTP */
  sprintf(buffer, "%04d%02d%02d%02d%02d%02d&val=%05d", annees, mois, jours, heures, minutes, secondes, valeur);
  client.print(F("GET /traitement.php?date="));
  client.print(buffer);
  client.println(F(" HTTP/1.0"));
  client.println();

  /* Fin de la requete HTTP */
  Serial.println(F("Fin envoi ..."));
  delay(10); /* Permet au serveur distant de recevoir les données avant de fermer la connexion*/
  client.stop();  
}

Pour les curieux voici le lien vers le topic d’origine sur le forum (pour voir le code dans son contexte d’origine) :
http://arduino.cc/forum/index.php?topic=138042.msg1036750#msg1036750

Bon WE et bon bidouillage à tous !

Advertisements

Discussion

4 réflexions sur “[Arduino] Traitement fichier par fichier d’un dossier d’une carte SD

  1. a ta place, je ferait un EthernetServer et je publierai tout sous une page web simple generée par l’arduino et qui permettrai : 1/de voir + avoir la possibilité de telecharger tes fichiers de l’arduino directement sur ton pc 2/de montrer (meme si c’est pas le but du tuto) comment lire les URL envoyées a l’arduino :p

    Publié par Zilators | 5 janvier 2013, 15 h 33 min

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Skyduino devient Carnet du Maker

Le site Carnet du Maker remplace désormais le blog Skyduino pour tout ce qui touche à l'Arduino, l'informatique et au DIY.