SD-Karte zeilenweise auslesen

Hallo zusammen im Forum,

ich hab ein Problem mit dem Zeilenweise auslesen einer SD-Karten (*.txt) Datei.

Für mein Projekt hab ich einen Arduino UNO, ein DEBO MICROSD 2 Board für MicroSD-Karten und eine 2GB MicroSD-Karte gekauft. Den Arduino habe ich dann der Beispieldokumentation entsprechend mit dem SD-Board verkabelt und die SD-Karte eingesetzt.

Die SD und SPI Bibliotheken in der Arduino IDE eingebunden und die Beispiel-Datei: SD\ReadWrite hochgeladen. Alles funktioniert prima, der String wird auf die SD-Karte geschrieben, dieser wird anschließend ausgelesen und im Seriellen Monitor angezeigt.
Soweit alles gut.

Nun zu meinem Problem:
Ich möchte gerne ein Sketch erstellen, dem ich im Setup, Programmparameter die ich mit einem externem Text-Editor Zeile für Zeile aud die SD-Karte schreibe, dem Hauptprogramm übergebe.

Beispiel einer TXT-Datei:

             D1,LOW
             D2,HIGH
             D3,1234
             D4,LOW
             ...
             usw.

D1... dient dem Zuordnungsverständnis, dem nach einem Trennzeichen(hier ein ",") der String folgt, der entsprechender Variablen zugeordnet werden soll(HIGH,LOW oder Zeichenfolge).

weitere SD-Karten mit anderen Programmparametern führen zu veränderten Sketch-Funktionen.

Ich hab schon mehrere private Projekte realisiert komme aber hier, was die Zeilenweise-Kommunikation mit einem SD-Datenträger betrifft an meine Grenze. Ich hab hier im Forum und darüber hinaus schon viele Beiträge zur Kommunikation mit SD-Karten gelesen aber wie gesagt komm da einfach nicht weiter.

Ich würde mich daher sehr freuen, wenn ich hierzu Hilfe bekommen könnte, aber bitte, Hilfe die ich als Dummi auch verstehen kann, Danke.

Ich hoffe und danke schon jetzt für eure Aufmerksamkeit.

Das Beispiel ReadCsvFile.ino der Bibliothek SdFat macht recht genau, was Du möchtest, ist aber erstmal recht unübersichtlich. Du kannst die Bibliothek nutzen oder Dir das Prinzip abschauen.

Dateien werden grundsätzlich immer zeichenweise gelesen. Wenn dabei ein NeueZeile-Zeichen ('\n') vorkommt, kann man das ausnutzen, um das bisherige als komplette Zeile zu interpretieren.

Der Text "HIGH" ist übrigens relativ schwierig auszuwerten, da z.B. "HIGH " etwas anderes ist, ganz zu schweigen von gröberen Zweifelsfällen wie " HIGH" oder "high"

Und ob du nach "D1," nur einen von zwei möglichen Werten, oder nach "D3," eine beliebige (?) Ganzzahl erwartest, muss dein Sketch auch selbst wissen.


Nachtrag: je nachdem wie die Datei erzeugt wurde, kann "Neue Zeile" auch eine Kombination der Zeichen '\r' und '\n' sein. Am einfachsten, Leerzeichen und '\r' vor '\n' ignorieren...

Nichts besonderes.
Ich würde die SDFAT-Lib nehmen.
Dort ist das Beispiel getline drin. Das macht schon fast, was Du willst.
In buffer ist Deine Zeile - die musst nur noch (inhaltlich) auswerten.
Wenn Du kannst, versuch Dich an bestehendem zu orientieren. # als erstes Zeichen z.B. macht daraus eine Kommentarzeile
Je Zeile nur einen Wert; Und zu guter Letzt die Beschreibung mit einem = vom Wert trennen.

Hallo agmue, vielen Dank für deine Aufmerksamkeit und dein schreiben.
Hab den Sketch-ReadCsvFile.ino aus der SdFat Bibliothek angesehen, ist leider nicht das was ich suche, denn der Sketch liest einfach nur den gesamten Dateiinhalt aus und gibt diesen komplett an den Seriellen Monitor.
Ich möchte aber jeweils den Inhalt einer Datei-Zeile in Form eines String einer Variablen zuordnen, den Inhalt der nächsten Zeile einer weiteren Variabel zuweisen usw.

Hallo michael_x, auch dier vielen Dank für deine Aufmerksamkeit und dein schreiben.
Wenn HIGH oder high schwierigkeiten bereitet kann ich auch EIN und AUS verwenden.
Mein Problem ist aber wie komm ich an die erste Zeile der SD-Textdatei und wie kann ich den String nach dem Trennzeichen(im Beispiel ein Komma als Trennzeichen) einer Variabel zuweisen, dann die zweite, dritte usw. Zeile.

Besser 1 und 0

Gruß Tommy

Hallo my_xy_projekt, auch dier vielen Dank für deine Aufmerksamkeit und dein schreiben.
Bin gerade dabei mir das getline-Beispiel anzusehen, danke für den Hinweis.

Na das ist gar nicht schwer.
DAs geht auch mit SD...
Schon ein wenig älter und sehr umfangreich mit viel Kram drum rum:

Da ist eine ino mit dran - nicht erschrecken, aber die wird geparst....

Das Einlesen einer Zeile von der SD Karte geht übrigens genauso wie das Einlesen einer Zeile von der seriellen Schnittstelle. Dafür kann man sogar die gleiche Funktion verwenden wenn man alles per Hand macht.
Aber es gibt auch fertige Funktionen dazu.

Das Trennen von Zeichenketten ist einfacher wenn man C Strings (char Arrays) statt Arduino String Objekte verwendet. Dann kann man das bequem mit strtok() erledigen

Dann lies meine Antwort genau (Jeden Buchstaben). Und erkenne, dass du an einem "EIN " in der Datei verzweifeln wirst, weil es nicht das gleiche wie "EIN" ist, was aber der Datei kaum anzusehen ist.
Ob 1 / 0 oder T / F oder + / - : Da Dateien zeichenweise gelesen werden, ist der Vergleich eines einzelnen Zeichens auch wesentlich einfacher, als ein Vergleich von Texten. Und wenn diese gar von unbekannter Länge sind...

Hallo michael_x,
aber ich möchte doch nichts vergleichen, es soll doch "nur" ein String, von einer SD-Datei-Zeile, mal egal wie der aussiet ob "HIGH" oder "Ein" oder "XYZ" einer Varibel zugewiesen werden.

Hallo Serenifly, auch dier vielen Dank für deine Aufmerksamkeit und dein schreiben.
Aber ich möchte doch mehrere String's von mehreren Zeilen bestimmten Variablen zuweisen.

Und nach dem Einlesen soll dann nichts gemacht werden? Das hört sich doch so an als ob die einen Pin und einen Zustand einlesen willst und diese dann auch setzen willst. Wenn du da "High" oder "Low" schreibst muss man vergleichen (solche Strings erst mal zuweisen ist etwas unsinnig). Wenn man nur "0" oder "1" nimmt kann man direkt in Integer konvertieren. Aber so oder so muss man mit den Teil-Strings was tun.

Und auch wenn man nichts vergleicht sollte man wissen wie das geht.

Aber wie gesagt sollte man bei sowas wenn überhaupt Zahlen zuweisen (als z.B. Pin-Nummern, oder 0/1 für den Zustand) und nicht Strings. Das ist wesentlich einfacher und sparsamer. Und für die nachfolgende Verwendung praktischer.
Eingelesen wird es erst mal als String natürlich. Aber beim Trennen der Teil-Strings kann man das sofort in praktischere Datentypen konvertieren.

Das ändert nichts an der Vorgehensweise. Man liest Zeilenweise an. Wenn man mehrere Zeilen hat kann man das einer Schleife tun bis die Datei zu Ende ist.

Natürlich möchte ich wie du sagst im Sketch-Hauptteil durch die String-Variabeln bedingt schalten und steuern zB. if (String(D1) == "HIGH") { dann ... Ausführung}; dabei ist String(D1) die Variabel- die den String von SD-Datei aus Zeile eins beinhaltet.

Das ist eine recht teure Variante.
Zudem funktioniert das nicht weil "1"!= "HIGH"

Ich rate dir von String ab.
Bei größeren µC mag das ja ok sein...

Evtl. kannst du dir ja beim CMDMessenger was abschauen.
Der tuts übrigens auch mit Dateien und anderen Ablegern von Stream.

Wenn er dir zuviel Speicher benötigt, kannst du ihn hier einschränken.
z.B. die Buffer kleiner machen, oder weniger Callbacks

Hallo combie, auch Dir herzlichen Dank für deine Aufmerksamkeit und schreiben.
Tut mir leid, ich hab das mit if(String(D1)) =="HIGH") etwas hingewurschtelt, ich werde es letztlich mit
--- int strcmp(char *str1, char *str2) -- wie bei C-HowTo.de unter "String vergleichen" beschrieben ausführen.

Man kann sich das Vergleichen komplett sparen wenn man es gleich vernünftiger abspeichert (sowohl auf der SD Karte als auch im RAM):

void setup ()
{
  Serial.begin(115200);

  char str1[] = "12,0";
  char str2[] = "5,1";

  parseString(str1);
  parseString(str2);
}

void loop ()
{  
}

void parseString(char* str)
{
  byte pin = atoi(strtok(str, ","));
  byte state = atoi(strtok(NULL, ","));

  Serial.print(pin);
  Serial.print(" - ");
  Serial.println(state);
}

Pin-Nummer nur mit Ziffern (also kein D1, A1, etc.) und den Status als 0 oder 1. pin und state kann man auch direkt in digitalWrite() einsetzen

Klar man das auch als Wörter speichern und dann mit Vergleichen umsetzen. Aber wozu den Aufwand betreiben?

Ähnlich ist es z.B. bei Kommandos. Statt "Temperatur:20" kann man "T20" oder "T:20" machen. Dann kann man auf das 'T' mit switch/case abfragen statt mit strcmp() ein ganzes Wort zu vergleichen.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.