Forum: Mikrocontroller und Digitale Elektronik Arduino: SD-Library - Karte entfernen


von Manfred (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mir heftig den Wolf gesucht und Stunden im Google zugebracht, 
das Problem scheint bekannt, aber keine Lösung:

Ich kann eine SD-Karte beschreiben und lesen. Wenn diese beim Start 
meiner Software nicht eingesteckt ist, wird das erkannt. Nun will ich 
aber auch erkennen, wenn diese im laufenden Betrieb gezogen wird oder 
verreckt.

Ob die SD-Library aus der IDE 1.7.4 oder jene aus der 1.8.5 eingesetzt 
wird, mach keinerlei Unterschied.

Die angehängte Software erfüllt keinen produktiven Sinn, lässt lediglich 
4 LEDs als Lauflicht tackern und schreibt alle paar Sekunden Daten auf 
die Karte. Nach jeweils sechs geschriebenen Datensätzen wird der Inhalt 
der Datei gelesen und seriell ausgegeben, auch da passiert Unfug.
1
/*
2
  SD card test
3
  Hardware: Nano
4
5
 This example shows how use the utility libraries on which the'
6
 SD library is based in order to get info about your SD card.
7
 Very useful for testing a card when you're not sure whether its working or not.
8
9
 ** MOSI - pin 11
10
 ** MISO - pin 12
11
 ** CLK -  pin 13
12
 ** CS -   pin 2
13
14
 created  28 Mar 2011
15
 by Limor Fried
16
 modified 9 Apr 2012
17
 by Tom Igoe
18
 */
19
// include the SD library:
20
#include <SPI.h>
21
#include <SD.h>
22
23
String Version = "V 2018-02-10";
24
25
// set up variables using the SD utility library functions:
26
Sd2Card card;
27
SdVolume volume;
28
SdFile root;
29
30
const int chipSelect = 2; // 31.12.2015 
31
File myFile;
32
33
void setup()
34
{
35
  pinMode(6, OUTPUT);
36
  digitalWrite (6, LOW);
37
  pinMode(7, OUTPUT);
38
  digitalWrite (7, LOW);
39
  pinMode(8, OUTPUT);
40
  digitalWrite (8, LOW);
41
  pinMode(9, OUTPUT);
42
  digitalWrite (9, LOW);
43
  pinMode(10, OUTPUT);
44
//  digitalWrite (10, LOW);
45
  
46
  // Open serial communications and wait for port to open:
47
  Serial.begin(57600); // 31.12.2015
48
  Serial.println(F("Test SD-Card"));
49
  Serial.print(F("Version "));
50
  Serial.print(Version);
51
  Serial.println(F(" gestartet"));
52
  Serial.print(F("Initializing SD card..."));
53
54
  // we'll use the initialization code from the utility libraries
55
  // since we're just testing if the card is working!
56
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
57
    Serial.println(F("initialization failed. Things to check:"));
58
    Serial.println(F("* is a card is inserted?"));
59
    Serial.println(F("* Is your wiring correct?"));
60
    return;
61
  } else {
62
    Serial.println(F("Wiring is correct and a card is present."));
63
  }
64
65
  // print the type of card
66
  Serial.print(F("\nCard type: "));
67
  switch (card.type()) {
68
    case SD_CARD_TYPE_SD1:
69
      Serial.println(F("SD1"));
70
      break;
71
    case SD_CARD_TYPE_SD2:
72
      Serial.println(F("SD2"));
73
      break;
74
    case SD_CARD_TYPE_SDHC:
75
      Serial.println(F("SDHC"));
76
      break;
77
    default:
78
      Serial.println(F("Unknown"));
79
  }
80
81
  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
82
  if (!volume.init(card)) {
83
    Serial.println(F("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"));
84
    return;
85
  }
86
87
  // print the type and size of the first FAT-type volume
88
  uint32_t volumesize;
89
  Serial.print(F("Volume type is FAT"));
90
  Serial.println(volume.fatType(), DEC);
91
92
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
93
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
94
  volumesize *= 512;                            // SD card blocks are always 512 bytes
95
  Serial.print(F("Volume size (bytes): "));
96
  Serial.println(volumesize);
97
  Serial.print(F("Volume size (Kbytes): "));
98
  volumesize /= 1024;
99
  Serial.println(volumesize);
100
  Serial.print(F("Volume size (Mbytes): "));
101
  volumesize /= 1024;
102
  Serial.println(volumesize);
103
104
  Serial.println(F("\nFiles found on the card (name, date and size in bytes): "));
105
  root.openRoot(volume);
106
107
  // list all files in the card with date and size
108
  root.ls(LS_R | LS_DATE | LS_SIZE);
109
  
110
  Serial.println(F("Pause 1 Sek"));
111
  delay(1000);
112
  
113
  if (!SD.begin(chipSelect)) {
114
    Serial.println(F("initialization failed!"));
115
    return;
116
  }
117
  Serial.println(F("initialization done."));
118
  
119
  SD.remove("test.txt");  // debug Datei loeschen
120
  myFile = SD.open("test.txt", FILE_WRITE);
121
122
  // if the file opened okay, write to it:
123
  if (myFile) {
124
    Serial.print(F("Writing to test.txt..."));
125
    myFile.println(F("** write started in setup **"));
126
    myFile.println(Version);
127
    myFile.print(millis());
128
    myFile.println(F(" ms"));
129
    // close the file:
130
    myFile.close();
131
    Serial.println(F("first write done / myFile = "));
132
    Serial.print(myFile);
133
  } else {
134
    // if the file didn't open, print an error:
135
    Serial.println(F("error opening test.txt for write"));
136
  }
137
  Serial.println(F(" ")); // Leerzeile erzeugen
138
    // open a file for reading:
139
  myFile = SD.open("test.txt");
140
  if (myFile) {
141
    Serial.println(F("test.txt"));
142
143
    // read from the file until there's nothing else in it:
144
    while (myFile.available()) {
145
      Serial.write(myFile.read());
146
    }
147
    // close the file:
148
    myFile.close();
149
  } else {
150
    // if the file didn't open, print an error:
151
    Serial.println(F("error opening test.txt for read"));
152
  }
153
  
154
} // Ende Setup
155
156
int Loopct = 0;
157
158
void loop(void) {
159
 digitalWrite (6, HIGH);
160
 delay(300);
161
 digitalWrite (7, HIGH);
162
 delay(300);
163
 digitalWrite (8, HIGH);
164
 delay(300);
165
 digitalWrite (9, HIGH);
166
 delay(300);
167
 // digitalWrite (10, HIGH);
168
 // delay(2000);
169
 // digitalWrite (10, LOW);
170
 // delay(300);
171
 digitalWrite (9, LOW);
172
 delay(300);
173
 digitalWrite (8, LOW);
174
 delay(300);
175
 digitalWrite (7, LOW);
176
 delay(300);
177
 digitalWrite (6, LOW);
178
 delay(2000);
179
180
  if (!SD.exists("test.txt")) {
181
    Serial.println(F("** SD.exists negativ **"));
182
    return;
183
  }
184
185
 myFile = SD.open("test.txt", FILE_WRITE);
186
 Serial.print(F("return myFile = "));
187
 Serial.println(myFile);
188
  if (myFile) {
189
    Serial.print(F("Loop writing to test.txt... "));
190
    myFile.println(F("testing 1, 2, 3."));
191
    myFile.println(Version);
192
    myFile.print(millis());
193
    int lastwrite = myFile.println(F(" ms Zeile zwei"));
194
    // close the file:
195
    myFile.close();
196
    Serial.println(F("done."));
197
    Serial.print(F("return myFile closed = "));
198
    Serial.print(myFile);
199
    Serial.print(F(" / return from write = "));
200
    Serial.println(lastwrite);
201
202
  } else {
203
    // if the file didn't open, print an error:
204
    Serial.println(F("error"));
205
  }
206
 Loopct ++;
207
 if (Loopct > 5) {
208
   Loopct = 0;
209
   readfile();
210
 }   
211
212
} // Ende loop
213
214
void readfile() {
215
  myFile = SD.open("test.txt");
216
  if (myFile) {
217
    Serial.println(F("read test.txt"));
218
    // read from the file until there's nothing else in it:
219
    while (myFile.available()) {
220
      Serial.write(myFile.read());
221
    }
222
    myFile.close();
223
  } else {
224
    // if the file didn't open, print an error:
225
    Serial.println(F("error opening test.txt for read"));
226
  }
227
} // Ende readfile

In Zeile 180 frage ich, ob die Datei existiert - das Ergebnis bleibt 
wahr, wenn die Karte nach ein paar Schreibzyklen gezogen wird.

In Zeile 202 sollte das Programm aussteigen, wenn sd.open false liefert 
- egal, das ist immer true, auch wenn die Karte gezogen wird.

In Zeile 193 hole ich mir den Rüchgabewert des write-Befehls, der wird 
tatsächlich null, wenn die Karte fehlt - mein derzeit einziger Ansatz.

Ideen dazu?

---

Ein weiteres Problem habe ich beim Lesen: Wenn die Karte gezogen wurde, 
findet die Leseroutine offenbar kein Ende und gibt per Serial.print 
tagelang unsinnige Zeichen aus. Tut nicht wirklich weh, da ich in der 
beabsichtigten Endanwendung nicht lesen muß, eine Lösung hätte ich 
dennoch gerne.

von Stefan F. (Gast)


Lesenswert?

Ich glaube, da musst Du Dir mal den Quelltext der SD Library genau 
anschauen. Du brauchst ein harmloses Kommando, dass du an die Karte 
schicken kannst und welches sich im Fehlerfall nicht in eine 
Endlosschleife aufhängt.

Manche SD Karten Slots enthalten einen Schaltkontakt, der durch das 
Einstecken der Karte betätigt wird.

von Manfred (Gast)


Lesenswert?

Stefan U. schrieb:
> Du brauchst ein harmloses Kommando, dass du an die Karte
> schicken kannst und welches sich im Fehlerfall nicht in eine
> Endlosschleife aufhängt.

Jetzt ist mein Gerät so weit, dass ich mich um die Karte kümmern muß. 
Einzig zuverlässig scheint der Rückgabewert geschriebener Bytes: "int 
BytesWritten = myFile.print(" ms");"

Ist dieser Null, kann ich "card.init" wiederholen - eine nachträglich 
gesteckte Karte wird dann erkannt und beschrieben.

---------

Jetzt treibt mich aber eine andere Sache um: Aus Gründen der Verdrahtung 
habe ich CS auf D2 gelegt und D10 als Steuerausgang benutzt. Sobald ich 
den SPI anfasse, wird D10 high :-(

Weder in SPI.h noch SD.h bzw. *.cpp finde ich Zugriffe auf D10, wohl 
aber im Internet, dass diese Verknüfung im AT328 fest vorgegeben sei. 
Mist, muss ich wohl den Lötkolben nehmen und umpfuschen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.