SD-Card initialisierung zurücknehmen

Hallo,
mit “beginn ()” initialisiere ich die SD-Bibliothek und Karte.
Wie nehme ich das zurück?
Hier mal der Code zum “einschalten” das funktioniert sehr gut.

Mega 2560

 #include <SPI.h>
#include <SD.h>

 if (digitalRead(S2) == HIGH)
{  
  if (!SD.begin(chipSelect)) {
    lcd.clear();
    lcd.setCursor(3, 1);
  
    lcd.print("SD-Card Fehler");
    delay(1000);
   lcd.clear(); 
    return;
  }
  lcd.clear();
    lcd.setCursor(4, 1);
     lcd.print("SD-Card i.O.");
     SDZL = 1;
  delay(1000); 
    lcd.clear();

Mit einem anderem Taster möchte ich das wieder “rückgängig” machen.

  if (digitalRead(S4) == HIGH)  
{
 SDZL = 0; 
 ExBoard.close();
 SPI.end (); 
}

Das funktioniert aber nicht, benutze ich jetzt S2 kommt “SD-Card Fehler”

Es muß doch möglich sein, die SD-Card wieder abzumelden um sie mit einem
anderen Taster wieder anzumelden.
Gruß und Dank
Andreas

vieleicht mit end()?
Grüße Uwe

Hallo uwefed,
was meinst Du denn, wo ich mit Deinem "end()" hin sollte?
Ist es möglich, das ich eine wenig "Bregenklöderich" bin?
Gruß und Dank
Andreas

mit "beginn ()" initialisiere ich die SD-Bibliothek und Karte.
Wie nehme ich das zurück?

Wieso solltest Du das zurücknehmen? Was willst Du damit erreichen? Die Karte wird damit nicht verändert, es wird nur die SPI-Schnittstelle aktiviert und die entsprechenden Leitungen auf Ein- bzw. Ausgang geschaltet. Wenn Du das rückgängig machen willst, musst Du zuvor die Konfiguration dieser Pins abspeichern und dann wieder aktivieren. Allerdings sehe ich praktisch keinen Grund, so etwas zu tun.

Die SD-Card abzumelden, wie man das bei einem PC machen sollte, ist bei einem Arduino nicht notwendig, denn die Schreibzugriffe werden immer sofort ausgeführt und nicht gepuffert, wie das bei PC-Betriebssystemen üblich ist.
Wenn Du einen neue SD-Card eingeschoben hast, kannst Du einfach die begin()-Methode wieder aufrufen, damit die internen Strukturen neu initialisiert werden.

pylon:
denn die Schreibzugriffe werden immer sofort ausgeführt und nicht gepuffert

So ganz stimmt das nicht. Die sdFat Lib (auf der auch die Standard SD Lib basiert), schreibt erst wenn close() oder sync() aufgerufen wird.

Siehe Doku:

bool SdBaseFile::close ()
Close a file and force cached data and directory information to be written to the storage device.

bool SdBaseFile::sync ()
The sync() call causes all modified data and directory fields to be written to the storage device.

close() ruft dabei selbst lediglich sync() auf

Hallo Ihr Beiden,
ich versuche einmal es zu erklären:
mit S2 (Code oben) starte ich das Aufzeichnen von Daten.
Entferne ich jetzt die SD-Card und setze sie wieder ein, dann werden
keine Daten mehr geschrieben.
"Resette" ich den Arduino und betätige S2 werden wieder Daten geschrieben.

Ich möchte mit S2 Daten schreiben und mit S4 das selbige beenden.
Dann die SD entfernen können, oder nur NICHT Datenschreiben.
Mit S2 soll es dann wieder weitergehen.
Einfach:
S2 - SD-Card on
S4 - SD-Card off
S2 - SD-Card on…u.s.w.

nachdem ich S2 betätigt habe, läuft folgendes ab- und funktioniert:

if ((seconds == 0) && (SDZL == 1))
   pinMode(SS, OUTPUT);
  
  ExBoard = SD.open("ExTemp.txt", FILE_WRITE);
  
  if (ExBoard)
 
  Serial.print("Writing to test.txt...");
    ExBoard.print(Datum);
    ExBoard.print(" ");
    ExBoard.print(Zeit);
    ExBoard.print(" ");
    ExBoard.print(INcT,1);
    ExBoard.print(" ");
    ExBoard.print(INrF,1);
    ExBoard.print(" ");
     ExBoard.print(EXcT,1);
    ExBoard.print(" ");
    ExBoard.println(EXrF,1);
	
    ExBoard.close();

dann betätige ich S4, das schreiben wird beendet.
SD raus, Daten sichern.
SD rein,
dann: mit S2 starten- kommt der Fehler...

 if (digitalRead(S2) == HIGH)
{  
  if (!SD.begin(chipSelect)) {
    lcd.clear();
    lcd.setCursor(3, 1);
  
    lcd.print("SD-Card Fehler");
    delay(1000);
   lcd.clear(); 
    return;

und nicht: hier soll wieder geschrieben werden:

lcd.clear();
    lcd.setCursor(4, 1);
     lcd.print("SD-Card i.O.");
     SDZL = 1;
  delay(1000); 
    lcd.clear();

Das muß doch möglich sein, das mit Tasten zu starten, beenden, zu starten?
Gruß und Dank
Andreas

Man müsste schauen, was genau schief geht.
Da steht aber leider die Programmierung der High-Level-Klasse SDClass etwas im Weg. Versuche mal in SD.h die folgende Passage:

private:
  // These are required for initialisation and use of sdfatlib
  Sd2Card card;
  SdVolume volume;
  SdFile root;

durch:

public:
  // These are required for initialisation and use of sdfatlib
  Sd2Card card;
  SdVolume volume;
  SdFile root;

zu ersetzen. Dann kannst Du nach einem schief gegangenen SD.begin() per SD.card.errorCode() den Grund für das Schiefgehen erfahren, zumindest, wenn es mit der Karte selbst zusammenhängt. Die Fehlercodes findest Du in Sd2Card.h (SD_CARD_ERROR_*).

In der Standard SD library hat SD.begin() kein passendes .end() oder so,
und kann einfach so leider auch nicht mehrfach aufgerufen werden.

Damit man begin() mehrfach aufrufen kann, hilft dieser patch:
http://forum.arduino.cc/index.php?topic=46969.msg339113#msg339113

Damit ruft man jedesmal begin() auf, wenn das Schreiben starten soll.
Man sollte das Ergebnis auswerten: false, solange keine Karte drin ist...

Hallo,
was wäre dieses Forum wohl ohne seine Profis…

Als erstes habe ich mal die externe Lib in die Tonne getreten. Das hat
mich gestört, das es nicht die Arduino original Lib ist.
Das hat aber nichts beracht, wie auch?

Die Geschichte mit der Fehlerabfrage ist ja eine nette Idee. Einen Fehler an
der Karte und an der r/w-Harware konnte ich von Anfang an ausschließen.

Der Fehler ist ja gewesen, das er die Karte nicht ein zweites Mal
initialisieren wollte.
Ich habe mir schon gedacht, das etwas nicht geschlossen/abgemeldet wird.
Es wird ja nur das File geschlossen, der Rest bleibt aber erhalten.
Ich habe mir die Lib´s einige Male angeschaut und so rechtes zum Karte
abmelden / neu initialisiere nicht gefunden.

Der Tip von michael_x ist dann der "ultimative Hammer" gewesen…
Hätte ich doch heute nur Blumen zur Hand :slight_smile:

Jetzt funktioniert es ohne Problem.

S2 ist betätigt worden, das Schreiben beginnt:

14.02.14 15:30 20.5 42.8 9.2 63.6
14.02.14 15:31 20.5 42.6 9.4 59.4
14.02.14 15:32 20.5 42.3 9.5 60.6
14.02.14 15:33 20.5 42.2 9.5 63.2
14.02.14 15:34 20.5 42.2 9.5 60.2
14.02.14 15:35 20.5 42.7 9.5 60.2

S4 ist betätigt worden, das Schreiben endet:
Karte in PC, fummel, fummel…

Karte in Arduino
S2 ist betätigt worden, das Schreiben beginnt wieder:

14.02.14 15:40 20.5 42.3 9.2 63.9
14.02.14 15:41 20.5 42.3 9.2 63.2
14.02.14 15:42 20.5 42.6 9.1 63.8
14.02.14 15:43 20.5 42.6 9.1 63.6
14.02.14 15:44 20.5 42.7 9.1 63.4
14.02.14 15:45 20.5 42.4 9.1 60.7

S4 ist betätigt worden, das Schreiben endet wieder:
u.s.w.

Jetzt macht auch der "HardwareSchalter" Sinn. Was nützt es mir, wenn gemeldet
wird "Karte drinn"- Ich aber nicht auf sie schreiben kann?
Ich kann jetzt auch per SoftwareSchaltUhr zu ganz bestimmten Zeiten Daten
schreiben. Dabei ist es möglich die Karte zu jeder Zeit zu ziehen, die Daten
auf den PC zu kopieren und die Karte wieder einstecken um weiter Daten
zu schreiben. OHNE- den Arduino neu starten zu müssen. Das ganze System
bleibt erhalten. AllerErsteSahne!
Andreas sagt, Danke schön.

Die Arduino SD Lib ist eine Wrapper Klasse einer alten Version von sdFat. Sie enthält deshalb auch entsprechend viele Bugs. Wenn man mit was anderem zurecht kommt, ist ein Umstieg daher ratsam.

Außerdem bildet sie nur einen Bruchteil der Funktionalität ab. Ich bin mit sdFat sehr zufrieden, aber man sollte sich schon mehr mit Programmieren auskennen, die sich die Syntax stark in C++ anlehnt. Es gibt z.B. echte I/O Streams, was aber optional ist.

Hallo,

das interessiert mich auch.
Du hast in der SD.h Library den Code für die Funktion

SDClass.begin

mit dem Code im Link ganz unten ersetzt?

Damit wird sie zuerst geschlossen und dann gleich wieder geöffnet?

Habe auch mal ne Frage zur Geschwindigkeit der Karten-Detektion.

Ich verwende sdFat und da dauert es ziemlich lange bis sd.begin() false zurück liefert. Etwa 2,5 Sekunden. Ist das normal? Eine positive Rückmeldung dauert ein paar ms.

Für die Anwendung ist das egal, aber wirklich schön ist es auch nicht. Oder muss man da auch was ändern?

Hallo,
"aber man sollte sich schon mehr mit Programmieren auskennen"
"echte I/O Streams"

Ja, ich habe mich da schon "schlau gelesen" Diese KartenGeschichte funktioniert
auch ohne Lib`s. Ich fummel gerade mal 3 Monate mit dem Arduino und das was
ich bislang zum "laufen" bekommen habe- finde ich beachtlich.
Uhr und 2 HYT939 laufen ohne Lib. Die Sache mit den Karten übersteigt aber
noch meinen beschränkten Horizont.


Ich habe die sd.beginn Meldung in ca. 1 Sek. (wahrscheinlich weniger)
auf dem LCD.
Es ist dieses Gerät:

am Arduino Mega 2560/Rev3. An den Pin´s 50, 51, 52 und 53 mit
original Arduino Lib.


ich habe die einfach eingefügt.
Es wird die SD.cpp gepatcht. Hier Original und Fälschung:
Beide aus IDE 1.0.5/MacOSX

Original:

boolean SDClass::begin(uint8_t csPin) {
/*

Performs the initialisation required by the sdfatlib library.

Return true if initialization succeeds, false otherwise.

*/
return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);
}

und Fälschung:

boolean SDClass::begin(uint8_t csPin) {
/*

Performs the initialisation required by the sdfatlib library.

Return true if initialization succeeds, false otherwise.

*/
if (root.isOpen()) root.close(); // allows repeated calls
return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);

return card.init(SPI_HALF_SPEED, csPin) &&
volume.init(card) &&
root.openRoot(volume);

}

Gruß und Spaß dabei
Andreas

P.S. ich habe gerade mal geschaut- die sd.beginn Meldung habe ich in "Echtzeit" auf dem LCD
also S2 drücken, Meldung erscheint (mit delay() bleibt sie 1Sek. stehen, ohne delay() ist sie fast nicht wahrnehmbar.

Wobei es da schon Unterschiede gibt, wie man das macht. SdFat ist auch wesentlich performanter als die normale SD Lib falls sich da inzwischen nichts geändert hat:
http://forum.arduino.cc/index.php/topic,49649.0.html

Diese Änderung geht da allerdings nicht. begin() ist in SdFat.cpp und da gibt es keine Variable root. Aber man kann auch so immer wieder begin() aufrufen. Das habe ich bisher schon gemacht.

Hallo,

muß nochmal nachfragen. Ist das jetzt nicht irgendwie doppelt?

boolean SDClass::begin(uint8_t csPin) {
  /*
    Performs the initialisation required by the sdfatlib library.
    Return true if initialization succeeds, false otherwise.
   */
if (root.isOpen()) root.close();      // allows repeated calls
  return card.init(SPI_HALF_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);

  return card.init(SPI_HALF_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);
}

Ich dachte das wird komplett ersetzt und müßte dann so aussehen?

boolean SDClass::begin(uint8_t csPin) {
  /*
    Performs the initialisation required by the sdfatlib library.
    Return true if initialization succeeds, false otherwise.
   */
if (root.isOpen()) root.close();      // allows repeated calls
  return card.init(SPI_HALF_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);
}

Hallo,
Serenifly, das ist ja eine hoch interesante Sache. Wenn mein "neues" "sicher"
läuft, dann probiere ich die andere Lib mal aus. Schönen Dank für die Info.

Doc_Arduino, ja- das sieht doppeltgemoppelt aus. In dem Beitrag wird gesagt
"hinzufügen". Habe ich gemacht.

Wenn das so längere Zeit ohne Probleme läuft, dann werde ich den doppelten
Teil mal löschen. Ich bin heil-froh das es so erst einmal läuft. Im
Moment "übe" ich Fehler abfangen.
Gruß und Spaß
Andreas

Hallo,

dann bist Du mir schon weit voraus. Ich traue mich immer nicht so recht ran und frage lieber hier und da nochmal nach. Ich probiere immer noch mit Kleinigkeiten herum und wenn es klappt freue ich mich wie ein kleiner Schneekönig. :slight_smile: