Différences entre versions de « Arduino SD CARD »
(Page créée avec « = Partie électronique = == Le composant == Le Shiled Ethernet embarque un contrôleur Wiznet 5100 qui est plus fiable que son homologue le contrôleur ENC28J60. Il existe... ») |
|||
(31 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
= Partie électronique = | = Partie électronique = | ||
== Le composant == | == Le composant == | ||
− | + | Pour intérargir avec une carte SD, il est possible d'utiliser un shield comme le ''shiled Ethernet'' ou d'utiliser un module pour carte SD monté sur une platine. | |
{| align=center | {| align=center | ||
Ligne 11 : | Ligne 11 : | ||
|align=center| Module pour carte micro SD | |align=center| Module pour carte micro SD | ||
|} | |} | ||
− | Peut importe que vous ayez le shield | + | Peut importe que vous ayez le shield ou le module pour carte micro SD, le montage est le même et utilise le protocole SPI ([https://fr.wikipedia.org/wiki/Serial_Peripheral_Interface Serial Port Interface]). |
+ | |||
== Le montage == | == Le montage == | ||
− | + | La plupart des modules pour carte SD embarquent des régulateurs de tension qui permettent d'utiliser 3.3v ou 5v sans problèmes. | |
+ | [[Fichier:sd_card_module_diagram.jpg|centré|350px]] | ||
+ | N'oubliez pas que la communication entre l'Arduino et le module se fait a travers certaines broches qu'il ne faut donc pas utiliser ! | ||
− | |||
− | |||
= Partie logicielle = | = Partie logicielle = | ||
== Les librairies == | == Les librairies == | ||
La librairies utilisée est déjà inclue de base : | La librairies utilisée est déjà inclue de base : | ||
+ | * SPI.h | ||
* SD.h | * SD.h | ||
+ | |||
+ | ==Préparation de la carte== | ||
+ | La plupart des cartes SD marchent directement avec l'Arduino mais, si ce n'est pas le cas, il faut passer par la casse formatage ! | ||
+ | |||
+ | Attention, formater trop souvent une carte SD réduit considérablement sa durée de vie ! | ||
+ | |||
+ | La librairie utilisée pour intérragir avec les cartes SD supporte le FAT16 et le FAT32 mais, il est préférable d'utiliser le FAT16. | ||
+ | ===Sous Windows=== | ||
+ | Sous Windows, les étapes sont déjà détaillées [[Iso_install_sdcard#Sous_Windows | ici]] | ||
+ | ===Sous Linux=== | ||
+ | Utilisez la commande ''df'' pour identifier le nom de périphérique de la carte SD, généralement ''/dev/sdb'' et donc ''/dev/sdb1'' pour la première partition. | ||
+ | Si la carte est montée automatiquement, il faut la démonter avec la commande ''umount'' sans la retirer de l'ordinateur. | ||
+ | |||
+ | Le formatage est effectué grâce à la commande suivante : | ||
+ | <pre> | ||
+ | # mkfs.vfat -F 16 /dev/sdb1 | ||
+ | </pre> | ||
+ | Si la commande n'existe pas, c'est que le paquetage ''dosfstools'' n'est pas installé. | ||
+ | |||
+ | Une fois l'opération terminée, il faut [[Gestion_des_disques#mount | monter]] la carte SD pour vérifier que le formatage s'est bien déroulé. | ||
+ | ===Convention de nommage=== | ||
+ | Lorsque l'on utilise le système de gestion de fichiers ''FAT16'', il faut respecter la [https://en.wikipedia.org/wiki/8.3_filename convention de nommage 8.3] qui oblige, dans les grandes lignes, à avoir des : | ||
+ | * noms de fichier à ne pas dépasser 8 caractères ; | ||
+ | * extensions à ne pas dépasser 3 caractères. | ||
+ | == Pré-requis pour utiliser la carte SD== | ||
+ | ===Vérification=== | ||
+ | Avant d'aller plus loin, il est intéressant d'utiliser le sketch ''CardInfo'' présent dans la liste d'exemple pour s'assurer du bon fonctionnement de la carte SD. | ||
+ | Après ouverture de la console, les lignes suivantes devraient s'afficher : | ||
+ | <pre> | ||
+ | Initializing SD card...Wiring is correct and a card is present. | ||
+ | |||
+ | Card type: SDHC | ||
+ | |||
+ | Volume type is FAT32 | ||
+ | |||
+ | Volume size (bytes): 3650486272 | ||
+ | Volume size (Kbytes): 3564928 | ||
+ | Volume size (Mbytes): 3481 | ||
+ | |||
+ | Files found on the card (name, date and size in bytes): | ||
+ | INDEX.HTM 2016-12-21 18:58:44 146 | ||
+ | WS.HTM 2016-12-29 11:37:10 1206 | ||
+ | </pre> | ||
+ | == Fonctions spécifiques à la classe SD== | ||
+ | ===begin()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Démarre la communication avec le module SD | ||
+ | *begin(pin) pin correspond au numéro de la broche ''SS'' (slave select) du module (à préciser si différent de la broche ''4'') | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | // Démarrage de la communication avec le module SD | ||
+ | if(SD.begin(4)){ | ||
+ | // Module OK | ||
+ | }else{ | ||
+ | // Problème de communication avec le module | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | |||
+ | ===exists()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Permet de tester si un répertoire ou un fichier existe | ||
+ | * exists(filepath) : filepath correspond au chemin du répertoire ou fichier | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | if(SD.exists("index.htm")){ | ||
+ | // Le fichier existe | ||
+ | }else { | ||
+ | // Le fichier n'existe pas | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | ===mkdir()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Permet de créer un répertoire | ||
+ | * mkdir(filepath) : filepath correspond au chemin à créer. La fonction créer tous les répertoires intermédiaires (comme ''mkdir -p'') | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | // Créer le répertoire html à la racine de la carte SD | ||
+ | if(SD.mkdir("/html")){ | ||
+ | // Création OK | ||
+ | }else{ | ||
+ | // Problème de création | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | ===open()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Permet d'ouvrir un fichier | ||
+ | * open(filepath, mode) : | ||
+ | **filepath correspond au chemin du fichier à ouvrir | ||
+ | **mode correspond au mode d'ouverture, ''FILE_READ'' pour un accès en lecture seule ou ''FILE_WRITE'' pour un accès en lecture/écriture (place le curseur d'écriture à la fin du fichier) | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | // Ouvre le fichier index.htm en lecture/écriture | ||
+ | File f = SD.open("index.htm", FILE_WRITE) | ||
+ | if(f){ | ||
+ | // Ouverture OK | ||
+ | }else{ | ||
+ | // Problème d'ouverture | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | ===remove()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Permet d'effacer un fichier | ||
+ | * remove(filepath) : filepath correspond au chemin du fichier à effacer | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | // Efface le fichier index.htm | ||
+ | if(SD.remove("index.htm")){ | ||
+ | // Effacement OK | ||
+ | }else{ | ||
+ | // Problème d'effacement | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | ===rmdir()=== | ||
+ | {| | ||
+ | |valign="top"| | ||
+ | Permet d'effacer un fichier | ||
+ | * remove(filepath) : filepath correspond au chemin du répertoire à effacer | ||
+ | |valign="top"| | ||
+ | <source lang="c"> | ||
+ | // Efface le dossier html | ||
+ | if(SD.rmdir("html")){ | ||
+ | // Effacement OK | ||
+ | }else{ | ||
+ | // Problème d'effacement | ||
+ | } | ||
+ | </source> | ||
+ | |} | ||
+ | |||
+ | == Fonctions spécifiques à la classe File== | ||
+ | ===Gestion des fichiers=== | ||
+ | *available() : retourne ''vrai'' s'il reste des octets à lire dans le fichier | ||
+ | *close() : écrit les données sur la carte SD et ferme le fichier | ||
+ | *flush() : écrit les données sur la carte SD | ||
+ | *peek() : retourne le prochain octet sans faire avancer le curseur ou ''-1'' si c'est la fin du fichier | ||
+ | *position() : retourne la position du curseur dans le fichier | ||
+ | *print() : écrit les données en ASCII dans le fichier et retourne le nombre de caractères écrits. | ||
+ | *println() : écrit les données en ASCII dans le fichier en sautant une ligne et retourne le nombre de caractères écrits. | ||
+ | *seek() : déplace le curseur dans le fichier | ||
+ | *size() : retourne la taille du fichier en octets | ||
+ | *read() : lit le prochain octet en faisant avancer le curseur | ||
+ | *write() : écrit un octet dans le fichier et retourne le nombre d'octets écrits. | ||
+ | |||
+ | ===Gestion des dossiers=== | ||
+ | *isDirectory() : retourne ''vrai'' si l'objet File désigne un dossier | ||
+ | *openNextFile() : retourne le prochain fichier ou répertoire de l'arborescence | ||
+ | *rewindDirectory() : retourne le premier fichier ou répertoire de l'arborescence | ||
+ | |||
+ | ==Exemple== | ||
+ | {|style="width:650px" align="center" | ||
+ | | | ||
+ | [[Fichier:Warning manual.jpg|centré|300px]] | ||
+ | |valign="top"| | ||
+ | Soyez sûr de comprendre la section sur [[Arduino_sketch_writing| comment écrire un sketch]] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée. | ||
+ | |} | ||
+ | Dans cet exemple, on prend les valeurs de l'entrée analogique pour les stocker dans un fichier de manière cyclique à la [https://fr.wikipedia.org/wiki/RRDTool RRD] | ||
+ | === Import === | ||
+ | <source lang="c"> | ||
+ | #include "SPI.h" | ||
+ | #include "SD.h" | ||
+ | </source> | ||
+ | ===Variables globales=== | ||
+ | <source lang="c"> | ||
+ | // Le nom du fichier | ||
+ | char fileName[] = "log.rrd"; | ||
+ | File database; | ||
+ | // Le temps en secondes entre chaques mesures | ||
+ | uint8_t mesureFreq = 1; | ||
+ | // La taille maximale du fichier en Ko | ||
+ | uint16_t maxFileSize = 1; | ||
+ | </source> | ||
+ | |||
+ | === Setup === | ||
+ | Pour utiliser la carte SD on doit démarrer la communication avec le module. Si la broche ''SS'' n'est pas la numéro ''4'', il faut l'indiquer en argument de la fonction ''begin()'' : | ||
+ | <source lang="c"> | ||
+ | Serial.begin(9600); | ||
+ | Serial.print(F("Starting logger on pin A1 : ")); | ||
+ | // On démarre la communication avec le module | ||
+ | if (!SD.begin(4)) { | ||
+ | // Problème avec le module | ||
+ | Serial.println(F("problem with SD card module !")); | ||
+ | while (true); | ||
+ | } | ||
+ | // On ouvre en écriture ou créer un fichier | ||
+ | database = SD.open(fileName, FILE_WRITE); | ||
+ | if (!database) { | ||
+ | // Problème avec la carte SD | ||
+ | Serial.println(F("problem creating file on SD card !")); | ||
+ | while (true); | ||
+ | } | ||
+ | // On passe la broche analogique 1 en entrée | ||
+ | pinMode(A1, INPUT); | ||
+ | Serial.println(F("OK")); | ||
+ | </source> | ||
+ | |||
+ | === loop === | ||
+ | <source lang="c"> | ||
+ | logValue(); | ||
+ | delay(mesureFreq*1000); | ||
+ | </source> | ||
+ | === Fonctions annexes=== | ||
+ | <source lang="c"> | ||
+ | void logValue() { | ||
+ | // Lecture de la valeur | ||
+ | uint16_t value = analogRead(A1); | ||
+ | // Vérification de la futur taille du fichier | ||
+ | if(database.position()+sizeof(value) > maxFileSize*1024){ | ||
+ | /** | ||
+ | * On arrive à la limite qu'on s'est fixée | ||
+ | * retour au début du fichier | ||
+ | */ | ||
+ | database.seek(0); | ||
+ | } | ||
+ | // Ecriture de la valeur dans le tampon | ||
+ | database.println(value); | ||
+ | // Ecriture de la valeur sur la carte SD | ||
+ | database.flush(); | ||
+ | // Message sur la console | ||
+ | Serial.print(F("Loggin at index ")); | ||
+ | Serial.print(database.position()); | ||
+ | Serial.print(F(" value ")); | ||
+ | Serial.println(value); | ||
+ | } | ||
+ | </source> |
Version actuelle datée du 16 janvier 2017 à 18:30
Partie électronique
Le composant
Pour intérargir avec une carte SD, il est possible d'utiliser un shield comme le shiled Ethernet ou d'utiliser un module pour carte SD monté sur une platine.
Wiznet 5100 version shield pour Mega/Uno | Module pour carte micro SD |
Peut importe que vous ayez le shield ou le module pour carte micro SD, le montage est le même et utilise le protocole SPI (Serial Port Interface).
Le montage
La plupart des modules pour carte SD embarquent des régulateurs de tension qui permettent d'utiliser 3.3v ou 5v sans problèmes.
N'oubliez pas que la communication entre l'Arduino et le module se fait a travers certaines broches qu'il ne faut donc pas utiliser !
Partie logicielle
Les librairies
La librairies utilisée est déjà inclue de base :
- SPI.h
- SD.h
Préparation de la carte
La plupart des cartes SD marchent directement avec l'Arduino mais, si ce n'est pas le cas, il faut passer par la casse formatage !
Attention, formater trop souvent une carte SD réduit considérablement sa durée de vie !
La librairie utilisée pour intérragir avec les cartes SD supporte le FAT16 et le FAT32 mais, il est préférable d'utiliser le FAT16.
Sous Windows
Sous Windows, les étapes sont déjà détaillées ici
Sous Linux
Utilisez la commande df pour identifier le nom de périphérique de la carte SD, généralement /dev/sdb et donc /dev/sdb1 pour la première partition. Si la carte est montée automatiquement, il faut la démonter avec la commande umount sans la retirer de l'ordinateur.
Le formatage est effectué grâce à la commande suivante :
# mkfs.vfat -F 16 /dev/sdb1
Si la commande n'existe pas, c'est que le paquetage dosfstools n'est pas installé.
Une fois l'opération terminée, il faut monter la carte SD pour vérifier que le formatage s'est bien déroulé.
Convention de nommage
Lorsque l'on utilise le système de gestion de fichiers FAT16, il faut respecter la convention de nommage 8.3 qui oblige, dans les grandes lignes, à avoir des :
- noms de fichier à ne pas dépasser 8 caractères ;
- extensions à ne pas dépasser 3 caractères.
Pré-requis pour utiliser la carte SD
Vérification
Avant d'aller plus loin, il est intéressant d'utiliser le sketch CardInfo présent dans la liste d'exemple pour s'assurer du bon fonctionnement de la carte SD. Après ouverture de la console, les lignes suivantes devraient s'afficher :
Initializing SD card...Wiring is correct and a card is present. Card type: SDHC Volume type is FAT32 Volume size (bytes): 3650486272 Volume size (Kbytes): 3564928 Volume size (Mbytes): 3481 Files found on the card (name, date and size in bytes): INDEX.HTM 2016-12-21 18:58:44 146 WS.HTM 2016-12-29 11:37:10 1206
Fonctions spécifiques à la classe SD
begin()
Démarre la communication avec le module SD
|
// Démarrage de la communication avec le module SD
if(SD.begin(4)){
// Module OK
}else{
// Problème de communication avec le module
}
|
exists()
Permet de tester si un répertoire ou un fichier existe
|
if(SD.exists("index.htm")){
// Le fichier existe
}else {
// Le fichier n'existe pas
}
|
mkdir()
Permet de créer un répertoire
|
// Créer le répertoire html à la racine de la carte SD
if(SD.mkdir("/html")){
// Création OK
}else{
// Problème de création
}
|
open()
Permet d'ouvrir un fichier
|
// Ouvre le fichier index.htm en lecture/écriture
File f = SD.open("index.htm", FILE_WRITE)
if(f){
// Ouverture OK
}else{
// Problème d'ouverture
}
|
remove()
Permet d'effacer un fichier
|
// Efface le fichier index.htm
if(SD.remove("index.htm")){
// Effacement OK
}else{
// Problème d'effacement
}
|
rmdir()
Permet d'effacer un fichier
|
// Efface le dossier html
if(SD.rmdir("html")){
// Effacement OK
}else{
// Problème d'effacement
}
|
Fonctions spécifiques à la classe File
Gestion des fichiers
- available() : retourne vrai s'il reste des octets à lire dans le fichier
- close() : écrit les données sur la carte SD et ferme le fichier
- flush() : écrit les données sur la carte SD
- peek() : retourne le prochain octet sans faire avancer le curseur ou -1 si c'est la fin du fichier
- position() : retourne la position du curseur dans le fichier
- print() : écrit les données en ASCII dans le fichier et retourne le nombre de caractères écrits.
- println() : écrit les données en ASCII dans le fichier en sautant une ligne et retourne le nombre de caractères écrits.
- seek() : déplace le curseur dans le fichier
- size() : retourne la taille du fichier en octets
- read() : lit le prochain octet en faisant avancer le curseur
- write() : écrit un octet dans le fichier et retourne le nombre d'octets écrits.
Gestion des dossiers
- isDirectory() : retourne vrai si l'objet File désigne un dossier
- openNextFile() : retourne le prochain fichier ou répertoire de l'arborescence
- rewindDirectory() : retourne le premier fichier ou répertoire de l'arborescence
Exemple
Soyez sûr de comprendre la section sur comment écrire un sketch avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée. |
Dans cet exemple, on prend les valeurs de l'entrée analogique pour les stocker dans un fichier de manière cyclique à la RRD
Import
#include "SPI.h"
#include "SD.h"
Variables globales
// Le nom du fichier
char fileName[] = "log.rrd";
File database;
// Le temps en secondes entre chaques mesures
uint8_t mesureFreq = 1;
// La taille maximale du fichier en Ko
uint16_t maxFileSize = 1;
Setup
Pour utiliser la carte SD on doit démarrer la communication avec le module. Si la broche SS n'est pas la numéro 4, il faut l'indiquer en argument de la fonction begin() :
Serial.begin(9600);
Serial.print(F("Starting logger on pin A1 : "));
// On démarre la communication avec le module
if (!SD.begin(4)) {
// Problème avec le module
Serial.println(F("problem with SD card module !"));
while (true);
}
// On ouvre en écriture ou créer un fichier
database = SD.open(fileName, FILE_WRITE);
if (!database) {
// Problème avec la carte SD
Serial.println(F("problem creating file on SD card !"));
while (true);
}
// On passe la broche analogique 1 en entrée
pinMode(A1, INPUT);
Serial.println(F("OK"));
loop
logValue();
delay(mesureFreq*1000);
Fonctions annexes
void logValue() {
// Lecture de la valeur
uint16_t value = analogRead(A1);
// Vérification de la futur taille du fichier
if(database.position()+sizeof(value) > maxFileSize*1024){
/**
* On arrive à la limite qu'on s'est fixée
* retour au début du fichier
*/
database.seek(0);
}
// Ecriture de la valeur dans le tampon
database.println(value);
// Ecriture de la valeur sur la carte SD
database.flush();
// Message sur la console
Serial.print(F("Loggin at index "));
Serial.print(database.position());
Serial.print(F(" value "));
Serial.println(value);
}