String in EEPROM schreiben und lesen

Hallo zusammen,

ich habe mir folgenden Code zusammengebaut um einen String im EEPROM ablegen und auslesen zu können, leider habe ich bei auslesen das Phänomen das zuviel gelesen wird.
Eigentlich sollte auf der ersten Position die Stringgröße abgespeichert sein, ich komme gerade nicht hinter den Fehler... wäre klasse wenn mir jemand auf die sprünge helfen könnt.

#include <String.h>
#include <EEPROM.h>




String MySaveString = "";



void setup() 
{
    Serial.begin(9600);
}


void loop() 
{
     // for (int i = 0 ; i < EEPROM.length() ; i++) {EEPROM.write(i, 0);}  // Schreibt in jede Adresse des EEPROM '0'

    StringToEEPROM(10,"HALLO_WELT");
    
    MySaveString = StringFromEEPROM(10);
    
    Serial.println(MySaveString);

    while(1){}
}


void StringToEEPROM(byte position, String ToWrite)
{
    byte Stringlaenge = ToWrite.length();
    Serial.println(Stringlaenge);
    EEPROM.write(position,Stringlaenge);
    Serial.println(EEPROM.read(position));
    for (byte b = 0 ; b < Stringlaenge; b++)
    {
        EEPROM.write(b + 2,ToWrite.charAt(b));
    }
    Serial.println("EEPROM schreiben abgeschlossen...");
}

String StringFromEEPROM(byte readposition)
{
    Serial.println("EINLESEN AB HIER!!!");
    String ToRead;
    Serial.println(EEPROM.read(readposition));
    byte Stringlaenge = EEPROM.read(readposition);
    Serial.println(Stringlaenge);    
    for (byte b = 0 ; b < Stringlaenge; b++)
    {
        Serial.print(b);
        char f = EEPROM.read(b+2);
        ToRead += (f);
    }
    Serial.println("EEPROM einlesen abgeschlossen...");
    return ToRead;
}

Dominator:
Eigentlich sollte auf der ersten Position die Stringgröße abgespeichert sein, ich komme gerade nicht hinter den Fehler... wäre klasse wenn mir jemand auf die sprünge helfen könnt.

"HALLO_WELT" hat 10 Buchstaben, aber am Ende wird dann '\0' nicht mit berücksichtigt. Dieser Abschluß einer Zeichenkette scheint Dir verloren zu gehen.

    byte Stringlaenge = ToWrite.length();
    Serial.println(Stringlaenge);
    EEPROM.write(position,Stringlaenge);

Die Variable position hat den wert 10, das ist nicht die erste Position, das wäre

EEPROM.write(0, Stringlaenge);

Hier hebt sich der Fehler mit der "ersten Position" scheinbar auf

byte Stringlaenge = EEPROM.read(readposition);

Müßte aber sein

byte Stringlaenge = EEPROM.read(0);

Sonst passt +2 nicht:

EEPROM.write(b + 2,ToWrite.charAt(b));
...
char f = EEPROM.read(b+2);

Die Variable position hat den wert 10, das ist nicht die erste Position, das wäre
Hier hebt sich der Fehler mit der "ersten Position" scheinbar auf

Damit möchte ich mir die ersten 10 Byte im EEPROM freihalten und dort anderes speichern.

Gewünscht ist folgendes:

Schreiben:
Angabe der Position ab der mit dem schreiben begonnen werden soll und der zu schreibende string.

  • Länge des Strings an die erste Position schreiben
  • 2 Positionen weiter mit dem string beginnen

Lesen:
Angabe der Position

  • Erstes Byte auslesen, das gibt die länge des Strings an
  • 2 Positionen weiter mit dem auslesen des Strings beginnen und aufhören zu lesen wenn der Wert aus der ersten Position erreicht ist.

Der string wird komplett geschrieben, kein Zeichen zu viel und auch kein Zeichen zu wenig.
Aber wenn ich ihn auslese, liest er mir immer zuviel aus! Der wert der aus der ersten Position gelesen
wird ist nicht der den ich dort erwarte.
Trage ich die auszulesende Länge fest ein, dann funktioniert es, ist aber nicht im Sinne des Erfinders.

Danke schon mal fürs drüber schauen.

Gruß Domi

Ich sehe da mehrere Probleme:

      char f = EEPROM.read(b+2);

berücksichtigt die Position nicht, besser wohl

      char f = EEPROM.read(readposition + b + 2);
              EEPROM.write(b + 2,ToWrite.charAt(b));

berücksichtigt die Position nicht, besser wohl

              EEPROM.write(position + b + 2, ToWrite.charAt(b));

Die Funktion

String StringFromEEPROM(byte readposition)

gibt eine lokale Variable zurück, die existiert nach dem Aufruf nicht mehr.

Warum überhaupt Strings?

Warum ist das Längenfeld 2 lang, mit einem unbenutzten Byte?

Warum nicht die normale End-'\0' benutzen (ist ein byte kürzer und viel kompatibler)?

Whandall:
Ich sehe da mehrere Probleme:

      char f = EEPROM.read(b+2);

berücksichtigt die Position nicht, besser wohl

      char f = EEPROM.read(readposition + b + 2);
              EEPROM.write(b + 2,ToWrite.charAt(b));

berücksichtigt die Position nicht, besser wohl

              EEPROM.write(position + b + 2, ToWrite.charAt(b));

Die Funktion

String StringFromEEPROM(byte readposition)

gibt eine lokale Variable zurück, die existiert nach dem Aufruf nicht mehr.

Warum überhaupt Strings?

Warum ist das Längenfeld 2 lang, mit einem unbenutzten Byte?

Warum nicht die normale End-'\0' benutzen (ist ein byte kürzer und viel kompatibler)?

Vielen Dank!
Strings um SMS-Text bzw. Passwort zu speichern.

Bin auch leider mit C nicht so vertraut, kann man die Funktion als Global deklarieren?
Weiter steige ich auch nicht ganz hinter Char-Array, ich bin das scripten mit Autoit "gewohnt", das scheint mein Verständniss versaut zu haben.
Das Längenfeld habe ich 2 byte lang gemacht um evtl. wenn alles funktioniert auch einen String speichern zu können der > 255 Zeichen ist.

Habe im Netz auch keine für mich funktionierende bereits bestehende Möglichkeit gefunden einen Text mit veränderlicher Länge im EEPROM ablegen zu können. Immer nur verweise Bibliotheken mit denen ich aber dann auch nicht klar gekommen bin :frowning:

Also vielen vielen dank an dieser Stelle!

Der Abschluss durch ein '\0' birgt keine Längenbegrenzung.

C(++), (char-)Arrays, Lebenszyklus von Variablen, etc wirst du besser lernen.

Lass die Finger ganz von Strings, sie werden dir keine Freude bereiten (auf einem 'normalen' Arduino).

Du findest keine Beispiele, weil man normalerweise Texte in ein Feld fester (maximal+1) Größe packt.

Whandall:
Der Abschluss durch ein '\0' birgt keine Längenbegrenzung.

Habe jetzt erst verstanden was du damit meinst...
Wenn ich vorher etwas anderes, also einen längeren Text im EEPROM hatte, dann würden diese Zeichen ja mit eingelesen, oder meinst du doch noch etwas anderes?

C(++), (char-)Arrays, Lebenszyklus von Variablen, etc wirst du besser lernen.

Habe mich mal an C# heran gewagt, aber mangels sinnvollem Projekt nicht weiter geübt.
Mir fällt es immer sehr schwer ohne eine wirklich sinnvolle Anwendung etwas zu programmieren oder generell etwas zu lernen

Gruß Domi

Ein super kurzes Testprogrämmchen:

char buf[50] = {"HALLO_WELT\0hallo welt"};
char ziel[50];

void setup() {
  Serial.begin(9600);
  Serial.println("Anfang");
  Serial.println(buf);
  for (byte j = 0; j < sizeof(buf); j++) {
    Serial.print(buf[j]);
  }
  Serial.println();
  for (byte j = 0; j < sizeof(buf); j++) {
    ziel[j] = buf[j];   // vor der Bedingung, da '\0' mit kopiert werden soll!
    if (buf[j] == '\0') break;
    Serial.print(buf[j]);
  }
  Serial.println();
  Serial.print("Ziel: ");
  Serial.println(ziel);
}

void loop() {}

Ausgabe (die § der dritten Zeile sind nicht druckbare Zeichen und werden eigentlich als Leerzeichen dargestellt):

Anfang
HALLO_WELT
HALLO_WELT§hallo welt§§§§§§§§§§§§§§§§§§§§§§§§§§§§
HALLO_WELT
Ziel: HALLO_WELT

Mit buf[50] reservierst Du 50 Bytes Speicher, der Inhalt wird aber durch '\0' für println terminiert.

Du kannst also von buf[0] bis zum Finden von '\0' die Zeichen in das EEPROM schreiben, aber einschließlich '\0'. Dann liest Dein Programm bis zum Finden von '\0' und schreibt die gefundenen Zeichen einschließlich '\0' in das Zeichenfeld.

Habe mich mal an C# heran gewagt, aber mangels sinnvollem Projekt nicht weiter geübt

Das macht nichts.
C# ist eher mit Java als mit C++ zu vergleichen. Gerade in Bezug auf Arduino hilft dir C# nichts.

Danke euch, nun komme ich mit meinem gebastel weiter.

Sagt mal, was für eine IDE nutzt ihr?
bin gerade mit "Programino" unterwegs, was für meine Bedürfnisse auch bis jetzt gut ausreicht,
bin aber noch nicht sicher ob ich es nach Ablauf der 14-Testtage kaufen werde oder doch noch etwas anderes versuche.

Schönen Gruß Domi

Sagt mal, was für eine IDE nutzt ihr? bin gerade mit "Programino" unterwegs

Wo sind wir denn hier? Natürlich arduino.cc

Ansonsten hat man mehr Komfort/Funktionalität mit dem VisualMicro-Plugin für VisualStudio (Community Version). Die nerven ein wenig, wenn man das free wörtlich nimmt, aber geht zeitlich unbeschränkt.

Um hier Hilfe zu bekommen, sollte ein Problem in der arduino.cc IDE zu produzieren sein.

Dominator:
Sagt mal, was für eine IDE nutzt ihr?

IDE 1.6.5, ich bin etwas faul, mir immer eine neue Version mit neuen Überraschungen zu installieren :slight_smile:

Wenn du statt die Länge am Anfang zu speichern, am Ende eine 0 anhängst, brauchst du immer nur 1 byte mehr als die Anzahl Buchstaben. Aber 255 Zeichen für einen Text im EEPROM ist schon viel.

jurs:
Ach ja?

Oben hast Du geschrieben, dass es zum Speichern von SMS und Passwörtern sein soll.

Wobei rechnest Du denn nun mit mehr als 255 Zeichen?

SMS länger als 255 Zeichen?
Oder Passwörter länger als 255 Zeichen?
Dass das EEPROM bei einem UNO überhaupt nur 1024 Zeichen groß ist, ist Dir aber schon klar, oder?
Nur mal so als Info, dass Du mit Software nicht mehr nutzen kannst als die Hardware bereitstellt.

Hast Du denn nun Deine Lösung? Oder noch nicht?

Wow, du scheinst einer von diesen Menschen zu sein die es immer wieder schaffen einen Beitrag so richtig unangenehm werden zu lassen.
Wenn du mit deinem Fahrzeug einen Ausflug machst, tankst du dann auch nur so viel Treibstoff
um Hin- und Rückweg bewältigen zu können?
Wenn man nichts, und damit meine ich ABSOLUT GARNICHTS sinnvolles beizutragen hat, abgesehen von der Größe des EEPROM, die jeder der überhaupt auf die Idee kommt etwas darin zu speichern schon beim recherchieren nach der Vorgehensweise dazu, zufällig aufgeschnappt hat, dann sollte man sich vielleicht überlegen ob man seine Zeit nicht auf etwas anders verwenden sollte.
Falschparker beim Ordnungsamt anschwärzen, denke ich wäre genau dein Ding!

Und ja, siehe Oben, Ich habe Meine Lösung.

@michael_x
Habe jetzt auch endlich Verstanden wie das mit der \0 funktioniert, da habe ich echt auf dem Schlauch
gestanden, wenn ich den Code das nächste mal anpacken muss, dann habe ich mir schon vorgenommen das dahingehend zu ändern.

Schöne Grüße

Domi