ich versuche seit ein paar tagen eine Zeile in meine SD Karte zu modifizieren. Also die Zeile sieht so aus: Spannung: 13.012V. Auf meinem TFT Display kann ich der Wert der Spannung lesen und auch verringern oder erhöhen. Aber ich habe nicht geschafft diese Änderung in meiner SD-Karte zu speichern (Z.b : Statt Spannung: 13.012V, Spannung: 12.011V).
Um der Spannungswert zu lesen habe ich diese code geschrieben:
File myFile = SD.open("Def_File.txt"); //datei öffnen
if (myFile) { //öffnen erfolgreich
String ausgabe;
while (myFile.available()) { //solange noch zeichen zu lesen sind
char line[64]; //buffer für eine Zeile
int n = 0; //position in der zeile
while (n < 64) { //solange nicht am zeilenende
if (!myFile.available()) break; //failsafe
line[n] = myFile.read(); //lese nächstes zeichen
if (line[n] == '\n') { //überprüft nach zeilenende
line[n] = 0; // remove '\n'
break;
}
n++;
}
//Serial.println(String(line)); //serielle ausgabe der aktuellen zeile
char search[15] = "Versuchsnummer:"; //zu findener Begriff
int test3 = 0; //anzahl übereinstimmender Zeichen
for (int i = 0; i < 15; i++) {
if (line[i] == search[i]) test3++;
else break;
}
if (test3 >= 14) { //begint die zeile mit "Versuchsnummer"
ausgabe = String(line).substring(16); //substring ignoriert die ersten 16 zeichen von line
Serial.println(ausgabe);
}
myFile.close();
}
Ich warte eure baldige Ideen.
Ich danke euch schon im Voraus.
Wie ist die Datei aufgebaut?
Sind alle Zeilen gleich lang? Wie lang ist die Datei (wegen evtl. zwischenspeichern)?
Der einfachste Weg (bei ungleich langen Zeilen) wäre die alte Datei zeilenweise zu lesen, die Werte zu ändern und in eine neue Datei zu schreiben. Danach die alte Datei löschen und die neue umbenennen.
Die Lib SdFat kann mit mehreren gleichzeitig geöffneten Files arbeiten.
Dein Sketch liest ja nur, wie Du bereits selbst anmerkst.
Wie sollen wir dann herausfinden, was an Deinem Code zum schreiben nicht funktioniert?
Es gibt zwei Beispiele, die Du in der Arduino IDE unter Datei->Beispiele->SD findest.
Datalogger
ReadWrite
Beide sollten Dir zeigen wie man das bewerkstelligen kann.
Wenn Du immer nur eine Zeile dort stehen haben möchtest, kannst Du unelegant die Datei jedes mal wieder löschen, oder Dir den 2. Parameter in SD.Open("Def_File.txt", O_WRITE | O_CREAT | O_TRUNC) anschauen.
Wie ist der Fileaufbau von deinem File?
Welche Stellen sollen geändert werden, fix format oder abhängig von bestimmt Start-Stop Zeichen, bestimmte Zeile, hast du mehrere Zeilen im File?
Hier ist der Code um der neue Spannungswert in der SD karte zu Speichern:
// um die eingesellte SPannung zu dem Netzteil zu schicken
if (((x < 300) && (x > 260)) && ((y < 240) && (y > 220))) { //with Time reset
sprintf(buf1, "GPV %01d%01d.01%d01%d01%d", A, B, C, D, E);
sprintf(buf, "%01d%01d.%01d%01d%01d", A, B, C, D, E);
if (Serial1.print("ADR 6\r"))
{
delay(200);
Serial.print("ADR 6 ");
while (Serial1.available() > 0) {
cInput = Serial1.read();
//Serial.print("receiving: ");
Serial.print(cInput);
}
Serial.println();
if ((Serial1.print(buf1)) && (Serial1.print("\r")))
{
delay(200);
Serial.print(buf1);
while (Serial1.available() > 0) {
cInput = Serial1.read();
//Serial.print("receiving: ");
Serial.print(cInput);
}
}
Serial.println();
}
//--------------------------------------------------------------------------------------------
// Um der neue Spannungswert in der SD Karte zu Speichern
File myFile = SD.open("Def_File.txt"); //datei öffnen
if (myFile) { //öffnen erfolgreich
String ausgabe1;
while (myFile.available()) { //solange noch zeichen zu lesen sind
char line[64]; //buffer für eine Zeile
int n = 0; //position in der zeile
while (n < 64) { //solange nicht am zeilenende
if (!myFile.available()) break; //failsafe
line[n] = myFile.read(); //lese nächstes zeichen
if (line[n] == '\n') { //überprüft nach zeilenende
line[n] = 0; // remove '\n'
break;
}
n++;
}
//Serial.println(String(line)); //serielle ausgabe der aktuellen zeile
myFile = SD.open("Def_File.txt", FILE_WRITE);
if (myFile) {
char search[9] = "Spannung:"; //zu findener Begriff
int test5 = 0; //anzahl übereinstimmender Zeichen
for (int i = 0; i < 9; i++) {
if (line[i] == search[i]) test5++;
else break;
}
if (test5 >= 8) { //begint die zeile mit "Versuchsnummer"
ausgabe1=buf;
ausgabe1 = String(line).substring(10);//substring ignoriert die ersten 10 zeichen von line
myFile.println(ausgabe1);
}
//Serial.println(ausgabe);
myFile.close();
}
myFile.close();
}
}
//----------------------------------------------------------------------------------------------------------
aaaah, pro Zeile quasi ein Wert.
Frage: Muss das wirklich sein? Kannst nicht einfach für jeden Wert ein separates File schreiben. ich denke das macht dir die Sache wesentlich einfacher.
auch bei einem File ist Grundsätzlich ist die Logik auch zu Fuß zu schaffen:
FileA = source;
FileB = tempTarget;
While not EOF:
{
FileA Zeile n in buffer einlesen
WENN die Zeile n zu ändern ist, neue Zeile in FileB schreiben SONST buffer in FileB schreiben
n++;
}
FileA löschen
FileB auf FileA umbennen.
noiasca:
ich denke das macht dir die Sache wesentlich einfacher.
Wieso? Wenn die Werte eine konstante Breite haben ist das simpel
Mit seek() kann man auf eine Position in der Datei springen. Und diese Position ist durch die festgelegte Formatierung bekannt
Man kann es auch allgemein machen und wie oben gesagt zeilenweise auslesen. Dann kann man z.B. im Text nach Schlüsselwörtern suchen um eine gewünschte Zeile zu finden. Das ist aber nicht unbedingt nötig.
wer garantiert, dass nicht mal Strom 10.123 oder Spannung nur 9.14 war, dann greifst mit Seek in den Gatsch oder es bleiben noch Zeichen dahinter stehen.
Ich schreibe hier nicht dass es nicht auch geht, aber für mich wäre ein fixes File je Wert einfacher.
File X auswählen, File X öffnen, neuen Wert reinschreiben.
vs
File C öffnen, seek an die richtige Stelle, neuen Wert reinschreiben.
sprintf() kennt er schon. Damit muss er nur die Werte beim Schreiben richtig formatieren
Und für float gibt es dtostrf() dafür
Sowas ist übrigens Unsinn:
ausgabe1 = String(line).substring(10)
C Strings sind Arrays. Array-Variablen entsprechen Zeigern auf das erste Element. Damit geht einfach Zeiger-Arithmetik:
Serial.println(line + 10);
Und das muss man auch nicht per Hand machen:
char search[9] = "Spannung:"; //zu findener Begriff
int test5 = 0; //anzahl übereinstimmender Zeichen
for (int i = 0; i < 9; i++) {
if (line[i] == search[i]) test5++;
else break;
Um Teil-Strings am Anfang zu finden gibt es strncmp(). Um Teil-Strings irgendwo in einem C String zu finden gibt es strstr(). Beschreibungen dazu gibt es massig im Internet