SD

Will man sein Programm mit Datenlogger Funktionen ausstatten, ist es sehr wahrscheinlich, daß die 1Kb internes EEPROM schnell zu klein werden. Das zu umgehen, gibt es nun mehrere Möglichkeiten. Man kann ein externes serielles EEPROM einsetzen, daß z.B. mit SPI angekoppelt wird. MAn kann die Daten direkt senden, entweder über die serielle Schnittstelle, oder über eine Funkstrecke. Oder aber man speichert die Daten auf eine exerne Flashkarte. UN genau dafür gibt es diese Bibliothek. Sie kann das Filesystem einer SD Karte bedienen und Dateien lesen und Schreiben. ALlerdings muss man ein paar EInschränkungen in Kauf nehmen. Die Bibliothek kann SD -Karten mit FAT16 und FAT32 benutzen. FAT16 ist aber zu bevorzugen. Dadurch kann man aber leider nicht alle Karten verwenden. Nur Karten ⇐2GB lassen sich noch ohne weiteres mit FAT16 formatieren. Ansonsten muss ein Zusatzprogramm verwendet werden. Der Rest der Karte ist dann aber trotzdem ungenutzt. FAT32 würde zwar auch gehen, ist aber relativ langsam. (Das ist meine perönliche Erfahrung) Die Bibliothek kann keine Karten formatieren, d.h. man muss die Karten an einem PC schon formatieren. Weiterhin können nur Dateien, die der 8.3 Namenskonvention folgen, verwendet werden.
Und nicht erschrecken, die Bibliothek macht den Sketch um ca. 12kb größer…

Zum Anschluss muss man die Pins 11,12,13 mit den entsprechenden Pins des Kartenmodules verbinden. Pin 11 ist MOSI, Pin 12 ist MISO, Pin 13 ist SCLK. Weiterhin ist es ratsam einen CS (ChipSelect) Pin zu benutzen. Ich hab den Pin 10 genommen.

In der Bibliothek gibt es 2 Bereiche. Einmal der Bereich der Verzeichnisse und einmal der Bereich der Dateien.

Gundfunktionen:

SD.begin()
SD.begin(CS-Pin) 

Damit wird sowohl die Bibliothek, wie auch die Karte initialisiert. Zurück kommt ein Wahr (true), wenn alles funkioniert hat, oder ein Falsch (false), wenn ein Fehler vorliegt.

SD.exists(Dateiname) 

Prüft, ob eine Datei vorhanden ist. Zurück kommt ein Wahr (true), wenn die Datei existiert, oder ein Falsch (false), wenn die Datei nicht da ist. Pfade werden mit „/“ angegeben.

SD.mkdir(Pfadname) 

Erzeugt einneues Verzeichniss. Es können auch direkt Verzeichnissstrukturen angelegt werden. Also z.B. SD.mkdir(„a/b/c“) würde auch die Verzeichniss a und b anlegen, fallse diese nicht existieren sollten.

file = SD.open(Dateiname mit Pfad)
file = SD.open(Dateiname mit Pfad, Modus)

Öffnet eine Datei. Der Dateiname kann direkt mit Pfad angegeben werden. Ist der Modus Schreiben gewählt, wird die Datei, wenn Sie nicht existiert, automatisch angelegt. Modus kann folgende Werte annehmen:

SD.remove(Dateiname);

Löscht eine Datei. <a class=„wikilink“>Zurück kommt ein Wahr (true), wenn die Datei gelöscht werden konnte, oder ein Falsch (false), wenn die Datei nicht gelöscht werden konnte.</a>

SD.rmdir(Pfadname);

Löscht ein Verzeichniss. Zurück kommt ein Wahr (true), wenn das Verzeichniss gelöscht werden konnte, oder ein Falsch (false), wenn nicht. Das Verzeichniss muss leer sein.

Hat man erst mal eine Datei oder ein Verzeichniss geöffnet gibt es nun verschiedene Funktionen, um mit der Datei/Verzeichniss zu arbeiten.

file.name();

Gibt den Namen der Datei zurück. (Aus welchen Gründen auch immer, in der Referenz fehlt diese Methode…)

file.available();

Gibt die Anzahl an Bytes an, die man aus der Datei (noch) lesen kann.

file.close();

Schliesst die Datei. Falls noch Daten geschrieben werden müssen, wird das jetzt gemacht.

file.flush();

Stellt sicher, daß alle anstehenden Daten auf die Karte geschrieben werden.

file.peek();

Ließt ein Byte ohne den Zeiger weiter zu bewegen.

file.position();

Gibt die aktuelle Position in der Datei an. (unsigned long)

file.print(Daten);
file.print(Daten, Basis);

file.println();
file.println(Daten);
file.println(Daten, Basis); 

Wie bei allen Print Befehlen bisher, schreibt die angegeben Daten auf die Karte. Die Daten können von den Typen char, byte, int, long, oder string sein. Basis dient der Formatierung von numerischen Daten. BIN für die binäre Darstellung, DEC für Dezimal, OCT für Oktal, HEX für Hexadezimal. (Es wird erst nach flush() sicher gestellt, daß alle Daten auch auf der Karte sind.) Die println Befehle hängen noch ein Zeilenende und Zeilenvorschub an. (CRLF)

file.seek(Position);

Hiermit wird eine bestimmte Position innerhalb der Datei angefahren. Ab dort wird dann gelesen, bzw. geschrieben. Die Position muss schon existieren. Also ein Seek über das Ende der Datei hinaus geht leider nicht.

file.size();

Gibt die Größe der Datei. (unsigned long)

file.read();

Liest das nächste Byte. (Wenn da eine -1 rauskommt, ist das Ende der Datei erreicht.)

file.write(Daten);
file.write(Puffer, Länge);

Schreibt Daten auf die Datei.

file.isDirectory();

ist wahr, wenn das Dateiobjekt ein Verzeichniss ist.

file.openNextFile();

Öffnet die nächste Datei in dem Vater-Verzeichniss. Zurück kommt ein Dateiobjekt. Hiermit kann sich quasi einmal durch alle Dateien hangeln.

file.rewindDirectory();

Geht nach einem openNextFile wieder zurück auf die erste Datei in dem Verzeichniss.

Hier mal ein Beispiel, daß eine Datei von der Karte ausliest und auf die serielle Schnittstelle schreibt. Die Datei liegt im Unterverzeichniss 1 und heißt test.txt.

/*
  SD card file dump
 
 This example shows how to read a file from the SD card using the
 SD library and send it over the serial port.
   
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 
 created  22 December 2010
 by Limor Fried
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
     
 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("1/test.txt");

  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening test.txt");
  }
}

void loop()
{
}