Pages: [1]   Go Down
Author Topic: SDFat Library  (Read 1890 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
hier wieder der Anfänger.

Arbeite gerade mit dem Codeschnitzel für einen SDCard-Webserver von dieser Seite http://www.ladyada.net/learn/arduino/ethfiles.html.
Alles läuft soweit gut.

Ich will das Programm jetzt auf meinem Mega laufen lassen. Da hab ich als Standard-PC Schnittstelle die Serial2.
Aber da gibts den Befehl "root.ls(LS_DATE | LS_SIZE);"
Der gibt normalerweise alle Dateien der Karte auf die serielle Schnittstelle. Leider auf die Standard-serielle
Gibts da eine Möglichkeit, den Befehl so umzuswitchen, daß er auf eine andere (Serial2) zugreift?

Code:
#include <SdFat.h>
#include <SdFatutil.h>
#include <SPI.h>
#include <Ethernet.h>
#define myserialPC Serial2  // Monitoring über "Serial-2"

/************ SDCARD STUFF ************/
const int CS_SD = 4;        // ChipSelect für SD-Karte auf PIN 4
const int CS_ETH = 10;      // ChipSelect für Ethernet auf PIN 10
const int CS_MEGA = 53;     // MEGA: Pin 53 fuer SD-Card
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

//----------------------------------------------------------------------
void setup() {
    pinMode(CS_SD, OUTPUT);
    pinMode(CS_ETH, OUTPUT);
    pinMode(CS_MEGA, OUTPUT);
  // initialize serial:
    myserialPC.begin(9600); // Serielle Schnittstelle 2 zum PC


    // make sure that the default chip select pin is set to
    // output, even if you don't use it:
    digitalWrite (CS_SD, LOW); // aktiviere SD-Karte
    digitalWrite (CS_ETH, HIGH); // deaktiviere Ethernet

                    // initialize SD-card
                      if (!card.init(SPI_HALF_SPEED,4)) error("card.init failed!");
                      // initialize a FAT volume
                      if (!volume.init(&card)) error("vol.init failed!");
                       
                      myserialPC.print("Volume is FAT");
                      myserialPC.println(volume.fatType(),DEC);
                      myserialPC.println();
                     
                      if (!root.openRoot(&volume)) error("openRoot failed");
                   
                      // list file in root with date and size
                      myserialPC.println("Files found in root:");
                      root.ls(LS_DATE | LS_SIZE);
                      myserialPC.println("Done");

    digitalWrite (CS_SD, HIGH); // deaktiviere SD-Karte

}

Bin um jede Idee dankbar.
Gruß/hk007
Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Germany
Offline Offline
Faraday Member
**
Karma: 56
Posts: 2983
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Schreib SDFat.h und SDFat.cpp um !

Am einfachsten, indem du in deinem Sketch in dieser Reihenfolge

#define SDSERIALLOG Serial2  // Monitoring über "Serial-2"
#include <SdFat.h>


und dann  in SdFat.h
Code:
#ifndef SDSERIALLOG
 #define SDSERIALLOG Serial
#endif
definierst, und danach in SDFile.cpp (oder überall) Serial durch SDSERIALLOG ersetzt.

Dadurch bleibt das bisherige Verhalten unverändert, und du kannst das der Community als super Verbesserung schenken.

Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK,
ich versteh den Sinn der neuen Definition.

Ich hätte jetzt aber in einer der Lib-Dateien nach dem "root.ls" Befehl gesucht. Fehlanzeige. Der ist nirgends zu finden.
Oder lieg ich da, mit meinen rudimentären C-Kenntnissen auf dem Holzweg.

gruß/hk007
Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Germany
Offline Offline
Faraday Member
**
Karma: 56
Posts: 2983
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das werden jetzt ganz rudimentäre c++ Kentnisse:

Methoden sind Funktionen eines Objektes und werden innerhalb einer Klasse definiert..

root ist ein Objekt der Klasse SDFile, und in der ist die Methode ls definiert.

Die Deklaration findest du in SDFat.h, die Definition ( der Programmcode ) in SDFile.cpp

Genauso wie du Serial2.print() schreibst, schreibst du auch root.ls(), wenn du eine solche Methode verwendest.

Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oh oh
Methoden, Klassen, Objekte.....
Viel Fachchinesisch für einen intuitiven Progammierer wie mich. LOL
Das ist dann mal was für langweilige Winterabende.

Aber jetzt noch mal was anderes zu obigem Code.
Das Beispiel mit dem Link aus Post#1 funktioniert ja sehr gut.

Ich hab auf der SD-Karte CSV-Dateien. Ich will jetzt den Code so ergänzen, daß ich auch auf eine der Dateien schreiben kann.
Als Vorlage hab ich mir das Beispiel ReadWriteSdFat genommen.

Aber ich fürchte beide kann ich nicht kombinieren.
Die beiden Init-Routinen sehen nämlich ganz anders aus:

Code:
Sd2Card card; 
if (!card.init(SPI_HALF_SPEED,4)) error("card.init failed!");
Code:
SdFat sd;
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

Wenn ich das richtig sehe, dann wird einmal die SdFat-Class und das andere mal die Sd2Card-Class verwendet.
Ziel wäre es schon die SD-Karte so wie in der Software in Post#1 laufen zu lassen, da hier die ganze Webroutine drinsteckt.
Aber in der Sd2Card-Klasse gibt es wohl keine Befehle wie file.open etc?

Das geht schon wieder langsam über meinen Horizont smiley-eek

gruß/hk007

Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Germany
Offline Offline
Faraday Member
**
Karma: 56
Posts: 2983
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

SdFat benutzt Sd2card ! ( Oder umgekehrt ? )
Das eine ist das Dateisystem, das andere die die SpeicherKarte selbst...

SdFat.begin() ruft Sd2Card.init() auf, und in einem SdFat Objekt ist auch ein Sd2Card Objekt enthalten. ( Fragt sich nur, ob du direkt drankommst, oder ob du die "Standard"-Bibliothek dafür wieder verbiegen musst ( irgendwas privates public machen oder so ) und ob das dir hilft..

Ausserdem gibt es noch File und SdFile, SdVolume und  evtl sind die bei LadyAda definierten Klassen andere als die von Sparkfun zum DataLogger empfohlenen. ...
Und es steht jedem frei, Erweiterungen einzubauen oder unnützen Ballast rauszuschmeissen ...

Ein Beispiel zeigt, was man direkt mit Sd2Card machen kann, das andere zeigt, wie du Dateien öffnest und liest oder schreibst.

Wenn ich mich recht entsinne, ist es nicht zu empfehlen, einfach zusätzlich zu dem in SDFat vorhandenen SD2Card Objekt ein zweites dazu zu definieren, vor allem wenn beide irgendwelche Veränderungen machen.

Aber seit ich einmal meine Funktionen ans Laufen gekriegt hab, habe ich mich nicht mehr näher für die Innereien von SDFat interessiert. Man kann eine Menge lernen ...  smiley-wink



 
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
danke für die geduldige Erklärung.
Hab jetzt noch ein paar Stunden gegoogelt und dann mit einem Codeschnipsel die Lösung für mein Problem gefunden.
Ich poste das mal hier. Evtl. hilfts mal jemand anderem:

Code:
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
SdFile myfile;     // das hier zusätzlich

 
// initialize SD-card
      if (!card.init(SPI_HALF_SPEED,4)) error("card.init failed!");
      // initialize a FAT volume
      if (!volume.init(&card)) error("vol.init failed!");
       
      Serial.print("Volume is FAT");
      Serial.println(volume.fatType(),DEC);
      Serial.println();
     
      if (!root.openRoot(&volume)) error("openRoot failed");
   
      // list file in root with date and size
      Serial.println("Files found in root:");
      root.ls(LS_DATE | LS_SIZE);
      Serial.println("Done");

und das hier zum Schreiben auf Fileebene

  if (myfile.open(&root,"test.csv", O_RDWR | O_CREAT | O_AT_END)) {
    myfile.print("test;1;2;3;4");
    myfile.close();
  }

Wenn mans weiss, dann ist es ganz einfach  smiley-razz
Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Schreib SDFat.h und SDFat.cpp um !
Am einfachsten, indem du in deinem Sketch in dieser Reihenfolge
#define SDSERIALLOG Serial2  // Monitoring über "Serial-2"
#include <SdFat.h>
und dann  in SdFat.h
Code:
#ifndef SDSERIALLOG
 #define SDSERIALLOG Serial
#endif
definierst, und danach in SDFile.cpp (oder überall) Serial durch SDSERIALLOG ersetzt.
Hi michael_x,

jetzt muss ich noch mal darauf zurückkommen:
Ich hab die Routine nicht in SDFile.cpp, sondern in SdFat.cpp gefunden. Ich bräuchte jetzt aber noch mal Hilfe von einem Profi.
Definiert ist die Routine so:
Code:
/** List the directory contents of the volume working directory to stdOut.
 * \param[in] flags The inclusive OR of
 * LS_DATE - %Print file modification date
 * LS_SIZE - %Print file size.
 * LS_R - Recursive list of subdirectories.
 */
void SdFat::ls(uint8_t flags) {
  vwd_.ls(stdOut_, flags);
}
und zu stdout finde ich am Anfang der SdFat-Library folgendes:
Code:
#if USE_SERIAL_FOR_STD_OUT || !defined(UDR0)
Print* SdFat::stdOut_ = &Serial;
#else  // USE_SERIAL_FOR_STD_OUT
class DefaultSerial : public Print {
 public:
  size_t write(uint8_t b);
};
size_t DefaultSerial::write(uint8_t b) {
  while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {}
  UDR0 = b;
  return 1;
}
//------------------------------------------------------------------------------
static DefaultSerial defaultStdOut;

Print* SdFat::stdOut_ = &defaultStdOut;
#endif  // USE_SERIAL_FOR_STD_OUT


Kann ich da irgendwas übergeben um die Ausgabe auf Serial2 umzuleiten?

Gruß/hk007

Edit:
ZU USE_SERIAL_FOR_STD_OUT hab ich noch das define in SdFatConfig.h gefunden:
Code:
/**
 * Set nonzero to use Serial (the HardwareSerial class) for error messages
 * and output from print functions like ls().
 *
 * If USE_SERIAL_FOR_STD_OUT is zero, a small non-interrupt driven class
 * is used to output messages to serial port zero.  This allows an alternate
 * Serial library like SerialPort to be used with SdFat.
 *
 * You can redirect stdOut with SdFat::setStdOut(Print* stream) and
 * get the current stream with SdFat::stdOut().
 */
#define USE_SERIAL_FOR_STD_OUT 0
« Last Edit: August 06, 2012, 01:32:53 pm by hk007 » Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

jetzt bin ich aber stolz auf mich:
Es gibt in der SdFat Class folgende Funktion "SdFat::setStdOut (Print* stream)"
>>You can redirect stdOut with SdFat::setStdOut(Print* stream) and get the current stdOut stream with SdFat::stdOut().<<

Also folgende Zeile ins Programm:
Code:
SdFat::setStdOut(&Serial2);  // redirect Standardausgabe für SdFat

Und schon purzeln die Zeichen auf die Serial2.

gruß/hk007
Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Germany
Offline Offline
Faraday Member
**
Karma: 56
Posts: 2983
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich zitiere mich gerne selbst:
Quote
Man kann eine Menge lernen ...  smiley-wink

Herzlichen Glückwunsch !

Das macht auch mehr Spass als unverstandene Schnipsel zu kopieren.

Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 353
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Das macht auch mehr Spass als unverstandene Schnipsel zu kopieren.

Ja, wenn man zu einem Ergebnis kommt dann schon.
Aber mit meinen aktuellen Programmierkenntnissen, ist es doch unumgänglich, im Internet Codeteile zusammenzusuchen und anzupassen.
Es ist eben wie bei jeder "neuen" Programmiersprache:
Ich weiss genau, was ich machen will, hab halt nur das Problem die richtigen Befehle zu finden und die Syntax einzuhalten.

Bis zum nächsten "Problem"  smiley-cool

Gruß/hk007
Logged

Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Pages: [1]   Go Up
Jump to: