Zahlen von Sd-Karte lesen

Hi,

ich möchte mehrere Zahlen von einer Sd-Karte lesen und in meinem Code einbinden. Kennt jemand ein Tutorial, wo das anschaulich erklärt wird? In Eng ist auch gut. Der Playground hat mir leider nicht weitergeholfen und in den ganzen Tutorials wird hauptsächlich die Installation erklärt und der Code nicht genauer erläutert.
Vllt. seh ich ja den Wald vor lauter Bäumen nicht, aber bis jetzt hab ich nix gefunden. :sweat_smile:

dlca:
ich möchte mehrere Zahlen von einer Sd-Karte lesen und in meinem Code einbinden. Kennt jemand ein Tutorial, wo das anschaulich erklärt wird?

Gibt es ein Tutorial, in dem Deine Frage etwas anschaulicher erklärt wird?

Bei "Zahlen von SD-Karte lesen" schaue ich zuerst auf die SD-Karte, lese "Samsung MicroSD 2 GB".
Die 2 als Zahl wird es wohl nicht sein, die Du lesen möchtest.

Als nächstes denke ich an Datei- und Verzeichnisnamen, die man von der Karte lesen kann. Sehr beliebt bei Log-Dateien. Da könnte man Dateinamen haben wie "20130615.TXT", und die 8 Stellen des Dateinamens entsprechen Jahr, Monat, Tag und man könnte diese Dateinamen einlesen und daraus die Zahlen für Jahr, Monat, Tag zurückerhalten wollen.

Oder es könnte sich bei den Zahlen um Daten aus Dateien handeln. Aber verschiedene Dateiformate gibt es tausende, wenn nicht zigtausende, aus denen man irgendwas auslesen kann. Vielleicht könnten binär codierte Dateien gemeint sein. Oder vielleicht könnten auch Textdateien gemeint sein, in denen menschenlesbare Zahlen als Text drinstehen? In dem Fall könnte vielleicht ein kleines Beispiel nicht schaden zu erklären, wie die Datei aufgebaut sein soll, aus der irgendwelche Zahlen ausgelesen werden sollen.

Ein Satz mit "Erklär dein Problem etwas genauer" hätts auch getan :stuck_out_tongue:

Ich möchte ein Arduino zur Temperaturreglung verwenden. Allerdings sollen die Regelwerte ohne Neuprogrammierung geändert werden können. Dafür hab ich mir ein Sd-Modul besorgt. Das Arduino soll also eine Datei (.txt oder sowas in der Richtung) öffnen und Zahlen z.B. eine pro Zeile einlesen und in eine Variable (z.B. float) eintragen. Gut wäre es, wenn in der Datei auch noch Text stehen dürfte, muss aber nicht sein.
Ich bekomme es hin, dass die Sd-Karte erkannt wird und Dateien und Ordner angezeigt werden. Nur fehlt mir der Ansatz, wie man in einer geöffneten Datei einzelne Zahlen herauspicken kann um diese dann zu verwenden.

Vllt. hat ja jemand schonmal sowas ähnliches gemacht und kann eine ungefähre Vorlage posten. (Nein, ich bitte nicht darum, dass mir hier wer ne Lösung schreibt)

Bin für jede Hilfe Dankbar.

dlca:
Das Arduino soll also eine Datei (.txt oder sowas in der Richtung) öffnen und Zahlen z.B. eine pro Zeile einlesen und in eine Variable (z.B. float) eintragen. Gut wäre es, wenn in der Datei auch noch Text stehen dürfte, muss aber nicht sein.
Ich bekomme es hin, dass die Sd-Karte erkannt wird und Dateien und Ordner angezeigt werden. Nur fehlt mir der Ansatz, wie man in einer geöffneten Datei einzelne Zahlen herauspicken kann um diese dann zu verwenden.

Also eine "lesbare Textdatei" mit von Menschenhand in einem per Editorprogramm eingetippten Initialisierungsdaten im Klartext, die ausgelesen werden sollen.

Wenn Du Dir ein Datenformat für so eine Textdatei frei aussuchen darfst, suchst Du Dir am besten eins aus, das sich leicht verarbeiten läßt.

Beispiel:
23.5 Solltemperatur-1
27.2 Alarmtemperatur-1-High
20.2 Alarmtemperatur-1-Low
9.15 Schaltzeit-1-Ein
18.30 Schaltzeit-1-Aus

Zum Einlesen von Gleitkommazahlen denke ich zunächst mal an die Funktion atof ("array to float"):
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga689c9d3c4c04463aa31d329937789d06

Mit dieser Funktion läßt sich eine Gleitkommazahl direkt "ab Zeilenanfang" einlesen, wenn der Text vorher als Zeile in ein char-Array eingelesen wurde. Mal angenommen Du hast die Zeile aus der SD-Karte eingelesen und es steht die Zahl und ein nachfolgender Text drin:
char test[100]="23.5 Solltemperatur-1";
Dann weist Du die Zahl an eine Variable wie folgt zu:
float f=atof (test);

Wenn Du die Variablen abhängig vom Text innerhalb der Zeile an ganz bestimmte Variablen zuweisen möchtest, könntest Du mit der "strstr" Funktion prüfen, ob ein bestimmter Text in einer Zeile steht und dann mittels if-Vergleichen abhängig vom Text in der Zeile den Zahlenwert an ganz bestimmte Variablen zuweisen.

Woran hapert es denn hauptsächlich?
Weißt Du nicht, wie Du aus einer Datei eine Zeile in eine char-Array Variable einliest?
Oder kennst Du Dich nicht mit den AVR libc Library-Funktionen aus, mit denen Dir hunderte fertiger Funktionen zur Verwendung in Deinen Programmen bereitgestellt werden, z.B. die Funktion "atof()" zur Umwandlung einer Gleitkommazahl aus einem char-Array?

Falls es die vielen hundert Funktionen der AVR libc Library sind, die Du nicht kennst, findest Du hier die Library-Referenz:
http://www.nongnu.org/avr-libc/user-manual/modules.html
Fast alle der dort genannten Funktionen der AVR libc kannst Du unter Arduino verwenden, ohne dass eine "#include" Zeile im Programm-Sketch stehen braucht.

jurs:
Woran hapert es denn hauptsächlich?
Weißt Du nicht, wie Du aus einer Datei eine Zeile in eine char-Array Variable einliest?
Oder kennst Du Dich nicht mit den AVR libc Library-Funktionen aus, mit denen Dir hunderte fertiger Funktionen zur Verwendung in Deinen Programmen bereitgestellt werden, z.B. die Funktion "atof()" zur Umwandlung einer Gleitkommazahl aus einem char-Array?

Beides. Ich hab Programmieren mit dem Map-Editor von Warcraft 3(altes Computerspiel) gelernt. Von daher sind Schleifen, if-Abfragen usw. kein Problem. Nur mit Textverarbeitung hab ich mich vorher noch nicht befasst. Gleichzeitig ist die Informationslage im Gegensatz zu anderen Themen eher schlecht.
Deinen Vorschlag werde ich heute Abend nochmal genau durchgehen und ein bissl rumprobieren. Dann kann ich auch präzisere Fragen stellen.

Also ich hab jetzt doch einige Beispiele dazu gefunden, aber ich verstehe sie einfach nicht

Im Moment hapert es sogar daran einzelne Zeilen einzulesen. Im prinzip soll es so ablaufen:

read(zeile1) until char 5 = convert into float1
read(zeile2) until char 5 = convert into float2

Bin echt ratlos :confused:

Ps: Der Dateiinhalt sieht so aus:

24		// Soll-Temp
0.5		// Abweichung
1.5		// Warnung
22		// Soll-Temp2

dlca:
Also ich hab jetzt doch einige Beispiele dazu gefunden, aber ich verstehe sie einfach nicht

Democode anbei.

#include <SD.h>

#define FILENAME "dlca.txt"
File myFile;

float tempSoll_One, tempAbweichung, tempWarnung, tempSoll_Two;

void initSD()
{
  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(10, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
}

void writeSD()
{
  // Die Datei auf die SD-Karte schreiben
  myFile = SD.open(FILENAME, FILE_WRITE);
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.println("Datei bereit zum Schreiben");
    myFile.println("24 // Soll-Temp1");
    myFile.println("0.5 // Abweichung");
    myFile.println("1.5	// Warnung");
    myFile.println("22 // Soll-Temp2");
    myFile.close(); // close the file:
    Serial.println("Datei wurde auf SD-Karte erstellt.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file for writing");
  }
}

void readOneLine()
// Hinweis: Datei muss bereits zum Lesen geöffnet sein,
// wenn diese Funktion aufgerufen wird.
{
  char linebuf[40]; // 40 reicht für Zeilen bis 37 Zeichen Länge + CR+LF+\0
  int counter=0;
  memset(linebuf,0,sizeof(linebuf)); // ausnullen des Zeilenspeichers
  while (myFile.available()) {
    linebuf[counter]=myFile.read();
    if (linebuf[counter]=='\n') break; // Zeilenende, Schleife verlassen
    if (counter<sizeof(linebuf)-1) counter++;
  }
  // Jetzt wurde bis zum Zeilenende oder bis zum Dateiende gelesen
  // und nun nachschauen, was gelesen wurde und in Variablen packen
  // Achtung, es kommt auf exakte Gross- und Kleinschreibung an!
  if (strstr(linebuf,"Soll-Temp1")) tempSoll_One=atof(linebuf);
  else if (strstr(linebuf,"Soll-Temp2")) tempSoll_Two=atof(linebuf);
  else if (strstr(linebuf,"Soll-Temp2")) tempSoll_Two=atof(linebuf);
  else if (strstr(linebuf,"Abweichung")) tempAbweichung=atof(linebuf);
  else if (strstr(linebuf,"Warnung")) tempWarnung=atof(linebuf);
  else
  {
    Serial.print("Zeile ohne Variablen: ");
    Serial.println(linebuf); 
  }
}


void readSD()
{
  // re-open the file for reading:
  myFile = SD.open(FILENAME);
  if (myFile) {
    Serial.println("Datei bereit zum Lesen:");
    // Bis zum Dateiende zeilenweise auslesen
    while (myFile.available()) {
      readOneLine();
    }
    // close the file:
    myFile.close();
    Serial.println("Datei wurde gelesen");
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}




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
  }
  initSD();
  writeSD(); // Diese Zeile muss nur einmal laufen und kann dann auskommentiert werden
  readSD();
  // Mal nachschauen ob etwas gelesen wurde:
  Serial.print("Soll-1: ");Serial.println(tempSoll_One);
  Serial.print("Soll-2: ");Serial.println(tempSoll_Two);
  Serial.print("Abweichung: ");Serial.println(tempAbweichung);
  Serial.print("Warnung: ");Serial.println(tempWarnung);
}

void loop()
{
	// nothing happens after setup
}

Die Zeile "writeSD();", mit der die Datei auf der SD-Karte angelegt wird, braucht natürlich nur einmal ausgeführt werden und kann gelöscht oder auskommentiert werden, wenn die Datei angelegt wurde und existiert.

Wenn irgendwas unklar ist, einfach fragen.

ein riesen Danke für den Code! Bei den anderen Beispielen war das Problem, dass nur Teilabschnitte gepostet wurden und teilweise auch andere Librarys zum Einsatz kamen.
Jetzt mit den Erklärungen hab ich kapiert, was die einzelnen Teile bewirken.

E: Code funktioniert perfekt