eine Zeile in der SD Karte modifizieren

Hello Zusammen,

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.

Da fehlen ein paar Infos.

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.

Gruß Tommy

Hallo Pass6,

Dein Sketch liest ja nur, wie Du bereits selbst anmerkst.
Wie sollen wir dann herausfinden, was an Deinem Code zum schreiben nicht funktioniert? :slight_smile:

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?

Ich warte auf deine baldige Antworten. (wtf)

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();
          }
        }

          //----------------------------------------------------------------------------------------------------------

So sieht der File in der SD Karte:

Versuchsnummer: P17-041-007
Strom: 0.940
Spannung: 13.12
Laufzeit_Soll: 500:00:00
Anzahl_Netzeile: 01

Hast Du mehrere derartige Messungen in der Datei, von denen Du eine nachträglich ändern willst?
Wenn ja, wie willst Du diese ermitteln?

Ich verstehe Dein Anliegen noch nicht wirklich.

Gruß Tommy

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.

eine Datei pro Wert

Serenifly:
Wieso? Wenn die Werte eine konstante Breite haben ist das simpel

wenn. ja wenn...

Schau dir aber mal sein Musterfile an:

Versuchsnummer: P17-041-007
Strom: 0.940
Spannung: 13.12
Laufzeit_Soll: 500:00:00
Anzahl_Netzeile: 01

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