Une des faiblesses du microcontrôleur Arduino est qu’il a peu de mémoire. Lorsqu’on veut traiter un nombre important de données (enregistrer des mesures ou écrire ou lire des fichiers, etc.), il est nécessaire de rajouter de la mémoire. Pour cela, on peut utiliser un carte Secure Digital ou carte SD qui permet d’allouer de la mémoire supplémentaire tout en conservant un encombrement réduit.
Matériel
- Ordinateur
- Arduino UNO x1
- câble USB pour connecter l’Arduino à l’ordinateur x1
- Shield ou module pour carte SD
Présentation du shield SD Card
Quelque soit le module que vous choisissez, il se présentera de la même façon: un emplacement pour la carte SD et des pins pour pouvoir s’y interfacer.
Le module de carte SD présente 6 broches pour permettre d’établir la connexion. 2 connexions pour l’alimentation et 4 pour établir la liaison SPI (Serial Peripheral Interface)
- 5V ou 3.3V pour l’alimentation du module
- GND la masse du module
- CS ou ChipSelect pour activer la communication
- MISO (Master Input, Slave Output) broche de transmission. Sortie du module.
- MOSI (Master Output, Slave Input) broche de réception. Entrée du module.
- SCK (Clock) horloge permettant de synchroniser la communication
Dans le cas d’un shield les branchements sont prédéfinis. Vérifiez bien dans la documentation technique du composant comment l’utiliser.
Schéma de câblage
- 3.3V sur 3.3V
- GND sur GND
- CS généralement sur 4 (ici sur 10)
- MISO sur 12
- MOSI sur 11
- SCK sur 13
Code pour récupérer les info d’une carte SD
Pour interagir avec votre carte SD, il existe un librairie dans l’IDE Arduino : SD.h. Des exemples sont disponibles sur le logiciel et sur internet.
#include <SPI.h> #include <SD.h> Sd2Card card; SdVolume volume; SdFile root; const int chipSelect = 10; void setup() { Serial.begin(9600); while (!Serial) { } Serial.print("\nInitializing SD card..."); if (!card.init(SPI_HALF_SPEED, chipSelect)) { Serial.println("initialization failed"); return; } else { Serial.println("Wiring is correct and a card is present."); } Serial.print("\nCard type: "); switch (card.type()) { case SD_CARD_TYPE_SD1: Serial.println("SD1"); break; case SD_CARD_TYPE_SD2: Serial.println("SD2"); break; case SD_CARD_TYPE_SDHC: Serial.println("SDHC"); break; default: Serial.println("Unknown"); } if (!volume.init(card)) { Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); return; } uint32_t volumesize; Serial.print("\nVolume type is FAT"); Serial.println(volume.fatType(), DEC); Serial.println(); volumesize = volume.blocksPerCluster(); // clusters are collections of blocks volumesize *= volume.clusterCount(); // we'll have a lot of clusters volumesize *= 512; // SD card blocks are always 512 bytes Serial.print("Volume size (bytes): "); Serial.println(volumesize); Serial.print("Volume size (Kbytes): "); volumesize /= 1024; Serial.println(volumesize); Serial.print("Volume size (Mbytes): "); volumesize /= 1024; Serial.println(volumesize); Serial.println("\nFiles found on the card (name, date and size in bytes): "); root.openRoot(volume); root.ls(LS_R | LS_DATE | LS_SIZE); } void loop(void) {}
Code pour lire et écrire des données dans un fichier stocké sur la carte SD
#include <SPI.h> #include <SD.h> File myFile; String buffer; String filename = "test"; 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."); myFile = SD.open(filename + ".txt", FILE_WRITE); if (myFile) { Serial.print("Writing to " + filename + ".txt..."); myFile.println("testing 1, 2, 3."); myFile.close(); Serial.println("done."); } else { Serial.println("error opening " + filename + ".txt"); } //Read file byte by byte myFile = SD.open(filename + ".txt"); if (myFile) { Serial.println("Read " + filename + ".txt byte by byte:"); while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); } else { Serial.println("error opening " + filename + ".txt"); } //Read file line by line myFile = SD.open(filename + ".txt"); if (myFile) { Serial.println("Read " + filename + ".txt line by line:"); while (myFile.available()) { buffer = myFile.readStringUntil('\n'); Serial.println(buffer); } myFile.close(); } else { Serial.println("error opening " + filename + ".txt"); } } void loop() { }
Il est possible d’effacer le fichier en utilisant la fonction:
SD.remove("test.txt");
Attention: Si vos fichiers ne sont pas reconnus, essayez d’utiliser un nom court pour le fichier enregistré sur la carte SD (max 8 caractères). En effet, le nombre de caractères pour un fichier sur une carte SD est limité avec Arduino.
Testez et mélangez ces exemples pour obtenir les fonctionnalités que vous désirez. Si vous rencontrez un soucis pour utiliser votre carte SD avec le microcontrôleur Arduino, n’hésitez pas à nous laisser un commentaire ou à nous envoyer un message.
Bonus: Affichez les fichiers stockés sur la carte SD
Pour vérifier que les fichiers sont bien enregistrés sur la carte SD, il est possible d’afficher les fichiers stockés à la racine. Il suffit pour cela d’utiliser l’objet File qui permet de parcourir les répertoires de la carte SD.
//Libraries #include <SD.h>//https://www.arduino.cc/en/reference/SD #include <SPI.h>//https://www.arduino.cc/en/Reference/SPI //Constants #define SD_ChipSelectPin 4 //Objects File root; void setup() { //Init Serial USB Serial.begin(9600); Serial.println(F("Initialize System")); //Init sd shield if (!SD.begin(SD_ChipSelectPin)) { Serial.println(F("SD fail")); return; } printFilenames(); } void loop() { } void printFilenames(void ) { /* function printFilenames */ ////find files in SD card root = SD.open("/"); while (true) { File entry = root.openNextFile(); if (! entry) { break;// no more files } Serial.println(entry.name()); entry.close(); } root.close(); }
Application
- Ajoutez de la mémoire à votre robot
- Donner une voix à votre projet
Source
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie
bonjour
1 – y a t il un truc pour dater le ficher (par défaut 01/01/2000 01:00) avec comme source un module genre ds3231 ?
2 – j’ai réussie a concaténer la date du module ds3231 mais pas a l’intégrè dans le nom du ficher pour le moment . (une histoire de char et string)
merci
cordialement
Bonjour,
1- Oui c’est possible il faut rechercher la librairie SdFat
2- Vous pouvez tester cette fonction en remplaçant par vos valeurs
long counter=0;
void getFilename(char *filename) {
long seconds = millis() / 1000;
long minutes = seconds / 60;
counter+=1;
long hours = counter;//minutes / 60;
long days = hours / 24;
filename[0] = 19/10 + ‘0’;
filename[1] = 19%10 + ‘0’;
filename[2] = 1/10 + ‘0’;
filename[3] = 1%10 + ‘0’;
filename[4] = 31/10 + ‘0’;
filename[5] = 31%10 + ‘0’;
filename[6] = hours/10 + ‘0’;
filename[7] = hours%10 + ‘0’;
filename[8] = ‘.’;
filename[9] = ‘t’;
filename[10] = ‘x’;
filename[11] = ‘t’;
}
Ce serait possible de lire le fichier texte ligne par ligne?
J’ai un code qui interprète le G code ligne par ligne à partir de la connexion série. je veux me passer de la connexion série donc je pensais mettre le fichier G code dans une sd et lire ligne par ligne le programme pour ne pas avoir de trop lourdes modifications à faire sur le programme d’interprétation de G code qui, même si il est assez clair est tout de même un peu au dessus de mon niveau en programmation Arduino.
ça m’intéresserait de voir le code pour interpréter un Gcode avec Arduino. Peux-tu me l’envoyer?
Pour lire un fichier ligne par ligne, tu peux écrire:
avec buffer un String
while (printFile.available()) {
buffer = printFile.readStringUntil('\n');
Serial.println(buffer);
}
Bonjour.
svp je voudrais enregistrer des données de comptage dans la carte sd car j’ai besoin de pouvoir les retrouver lors de la réinitialisation de mon microcontroleur. Je ne vois pas clairement comment insérer le code que vous avez donné dans le mien
En fait j’ai un programme qui gère l’incrémentation d’un compteur. Or lorsque le microcontrôleur se réinitialise, je perds la valeur du compteur parce que le comptage se fait dans la RAM. J’aimerais donc sauvegarder à une cette fréquence cette valeur du compteur dans la carte sd mais je ne sais pas comment faire
Bonjour, si tu ne veux conserver que la dernière valeur du capteur, il te faut d’abord:
//Read file line by line
myFile = SD.open(« test.txt »);
if (myFile) {
Serial.println(« Read test.txt line by line: »);
while (myFile.available()) {
buffer = myFile.readStringUntil(‘\n’);
Serial.println(buffer);
}
myFile.close();
} else {
Serial.println(« error opening test.txt »);
}
counter=buffer.toInt()+1
SD.remove(« test.txt »);
myFile = SD.open(« test.txt », FILE_WRITE);
if (myFile) {
Serial.print(« Writing to test.txt… »);
myFile.println(counter);
myFile.close();
Serial.println(« done. »);
} else {
Serial.println(« error opening test.txt »);
}
Je pense qu’il te faudra lire le fichier dans l’initialisation (setup) et définir une fonction d’écriture writeToFile() exécutée toutes les x secondes en utilisant la fonction millis() ou la librairie Timer.h
Tu peux aussi regarder la librairie EEPROM
Merci pour votre réponse mais ça ne fonctionne toujours pas…
La communication est impossible
Bonjour, qu’avez-vous essayé de faire? pouvez-vous communiquer avec la carte SD?
Bonjour,
j’arrive pas à reconnaître ma carte sd sur arduino uno, pourtant mes branchements semblent correctes, je suis sur du 5v, ma micro card est de 16GB, je me demande si je dois pas utiliser une carte de 8 Gb max ?
Vous avez une idée ?!
Merci de votre attention en tout cas,
Cahrlotte
Bonjour,
Quel module utilisez-vous?
Avez-vous testé les différents exemples de l’Arduino IDE pour la carte SD?
Vous pouvez effectivement essayé de carte pour voir si ça fonctionne mieux
Comment changer le nom du fichier dans lequel est enregistrer les données ? Par exemple en utilisant une variable nommée File_Name et le fichier s’appelerait File_Name.txt (avec File_Name = « Test » => cela donnera Test.txt)
Bonjour,
comme ceci
String filename= »Test »
myFile = SD.open(filename+ ».txt », FILE_WRITE);
Bonjour, je cherche une fonction me permettant de lire la première ligne d’un fichier, puis de l’effacer. De cette manière le nouveau fichier commencera par la seconde ligne du fichier initial. Cette opération sera ensuite répétée jusqu’à la fin du fichier, afin de « sortir » les lignes une par une.
Cette méthode me semble plus rapide que de compter les ‘\n’ à chaque fois, du moins si on souhaite accéder aux données de manière systématique et séquentielle, ligne par ligne.
Une idée?
Bonjour, pour moi la seule manière d’effectuer cette opération avec Arduino, sans utiliser toute la ressource mémoire, c’est d’écrire le reste du fichier dans un nouveau fichier, d’effacer le fichier d’origine puis de renommer le nouveau fichier.
Cette solution n’est-elle pas « aussi lente » qu’une recherche des ‘\n’ pour chaque ligne à sélectionner?
Oui, plus lente même je pense. J’ai peut-être mal compris votre besoin. En quoi, l’exemple du tutoriel, de lecture ligne par ligne ne vous convient pas?
Il n’ai pas possible d’effacer une ligne dans un fichier.
Il est possible de:
–
Je cherche à optimiser la vitesse d’exécution. Je voudrais aussi que la durée de la recherche d’une ligne ne dépende pas de sa position dans le fichier de données (début du texte ou fin du texte par-exemple). Du coup, votre idée d’un curseur qui mémorise la position du résultat de la recherche précédente me semble excellente!
Merci!
Bonjour, serait-il possible de d »placer un fichier .csv vers un dossier?? Si oui, je suis preneur de toutes solutions 😉 Merci!
Cordialement…
Bonjour,
vous pouvez créer un dossier en utilisant la fonction SD.mkdir().
Vous pouvez ensuite écrire le fichier csv dans le dossier créé en utilisant SD.open(filepath). Avec filepath, la concaténation du nom du dossier et du nom du fichier « foldername/filename ».
bonjour, je souhaite faire avec un BP en appuyant 3sec enregistrer des données pris sur un capteur de température, mais je sait pas du tout comment faire, quelqu’un pourrais m’aider ?
Bonjour, je voudrais enregistrer des données sur une plage de temps comment on fait ?
je n’arrives pas à initialiser ma carte SD malgré que j’ai bien fais toutes les configurations. J’ai besoin d’aide
Bonjour, comment peut-on savoir le nombre de fichiers sur une carte SD ? existe t’il une fonction
simple ?. Merci d’avance pour vos réponses…
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) { Serial.print('\t'); } Serial.print(entry.name()); // for each file count it fileCountOnSD++; if (entry.isDirectory()) { Serial.println("/"); printDirectory(entry, numTabs + 1); } else { // files have sizes, directories do not Serial.print("\t\t"); Serial.println(entry.size(), DEC); } entry.close(); } }
Bonjour, un peu tardivement mais je vous remercie pour votre réponse…
avec plaisir!
Bonjour,
Je sais écrire et lire des données sur une carte SD. Mais est-il possible d’écrire de nouvelles données à la suite d’un fichier existant qui a été fermé pour être lu ? Je voudrais pouvoir lire les données déjà enregistrées dans un fichier puis continuer à l’alimenter sans avoir à créer un nouveau fichier. Y a-t-il une solution ?
Merci d’avance pour votre aide.
Dans ce cas, vous pouvez lire tout le texte ajouter une ligne et réécrire le texte.
Ou essayer le flag O_APPEND de la lirbairie SD.h
File outputFile = SD.open(LOG_FILE, FILE_WRITE);
outputFile.seek(EOF);
outputFile.println(« Appended to the EOF »);
Great tutorial! I’ve been looking for a way to write text to an SD card with Arduino for a while now, and this post provided clear and concise instructions. I’m excited to try it out and use it for my own projects. Thanks for sharing!