Problem beim schreiben in eeprom

Hallo
Ich habe ein kleines Problem mit dem schreiben eines Strings ins eeprom.
Mit meinem code tippe ich zum Beispiel 9 zahlen ein und speichern tut er nur 8.
Oder er liest nur 8 beim einschalten wenn er stromlos war.
Das weiss ich nicht genau. Vielleicht fällt es jemandem auf wo der Fehler sitzt.

String nummer;                         // Nummer enthält die Nummer an den die SMS geht
int meinStringlaenge;                 // Länge des Strings
int eeprom_addresse = 0;           // Startadresse zum schreiben im eeprom
int eeprom_groesse = 17;           // Grösse des verwendeten speichers
                                             // Also 16 stellige Nummer möglich + terminierung
void nummer_speichern()
{

  meinStringlaenge = nummer.length();

  char neuerString[meinStringlaenge];

  if (meinStringlaenge > 0)
  {
    nummer.toCharArray(neuerString, meinStringlaenge);

    for (eeprom_addresse = 0; eeprom_addresse < meinStringlaenge;)
    {
      EEPROM.write(eeprom_addresse, neuerString[eeprom_addresse]);
      eeprom_addresse++;
    }

    EEPROM.write(eeprom_addresse, '\0');
  }
  EEPROM.write(36, auswahl);                    // Merker in eeprom schreiben ob sms(1) oder telefonanruf(0)ausgewählt wurde
}
void nummer_loeschen()
{

  for (int i = 0 ; i < 17 ; i++)
  {
    EEPROM.put(i, 0);
  }
}

Und so wird wieder ausgelesen.

char neuerString;

  for (eeprom_addresse = 0; eeprom_addresse < eeprom_groesse;) // Liest bis zur 17ten stelle
  {
    neuerString = EEPROM.read(eeprom_addresse);
    if (neuerString != '\0')
    {
      nummer += char(neuerString);         // Gespeicherte Nummer aus dem eeprom an variable nummer übergeben
    }
    eeprom_addresse++;
  }

Ich hoffe jemand kann mir weiter helfen, ich dreh mich im kreis und komm doch nicht da hinter :frowning:

Hi

Schuss ins Blaue:
.length(); gibt Dir die Länge des String OHNE terminierende \0 zurück, ein leerer String würde also 0 liefern, obwohl Du ein Zeichen (\0) schreiben müsstest.
(meine ich, heute in der Arduino-Referenz gelesen zu haben)

MfG

Ohne kompletten Sketch, modell des Arduino ist es schwer was zu sagen.
Mit eeprom meinst Du das interne eeprom?
Grüße Uwe

Vielleicht fällt es jemandem auf wo der Fehler sitzt.

Mir fällt auf, dass du es dir viel komplizierter machst, als nötig!
Mal benutzt du write, mal put.
Das String Objekt scheint dich eher zu behindern, als zu helfen.
Auch verwaltest du die Adressen händisch.

Vielleicht hilft dir dieses: Umgang mit dem AVR EEPROM

@postmaster-ino
Warum schreibst du nicht gleich ....mach + 1 dahinter dann gehts :-)))))))
Ich habs einfach nicht geblickt, betriebsblind.
Aber dein "Tip ins Blaue" hat natürlich geholfen.
vielen Dank !!!!

@uwefed
Ja genau im Internen will ich schreiben.
Den ganzen sketch wollte ich nicht hochladen weil alles was mit Variablen, Löschen, Speichern, Lesen,
zu tun hat war in den schnipseln. Der ganze code ist schon recht gross(für mich).
Hätte euch bestimmt ermüdet das alles zu durchforsten. :slight_smile:
Und was am wichtigsten ist, ich wollte nicht das ihr mich in der luft zerreist für das kunstwerk....LOL.

@combie
Siehste in deinem vierzeiler waren 4 mal kritik versteckt :-)))))
Darum habe ich nur das was zum eeprom gehört hochgeladen :-)))))
Aber hast schon recht bin erst mit get und put angefangen was nicht gut ging.
Beim löschen funktionierte put also habe ich es recht schnell vergessen.(schon geändert)
String war recht schnell gemacht weil erst nie die rede vom eeprom war und das ding komplett vom strom zu trennen für 2 stunden. Und dann wieder zu wecken. Aber weil es im akkubetrieb keine 24 stunden durchhält musste ich mir was einfallen lassen. Und die 36 benutz ich nur für die betriebsart und speicher nur 0 oder 1.
Wie gesagt der stetch war komplett fertig und jetzt muss ich so einiges ändern zb. gsm modul muss noch
beim auslösen abgefragt werden ob er hochgelaufen ist und ob er ein Netz hat. Alles wegen dem Stromlos machen aber ich hoffe am ende lohnt es sich.

Auf jeden Fall dank ich euch und hoffe das ich nochmal auf eure Hilfe zählen kann,
wenn ich mit dem gsm modul abfragen nicht klar komme.
bye

Hallo
Ich muss den Thread nochmal bemühen weil ich wieder ein kleines problem habe.
Ich wollte beim start eine Pin abfrage einfügen.
Dazu muss erstmal ein Pin angelegt werden im eeprom.
Das versuche ich so:

Verwendete variablen.

String pin_1;                            // Pin der eingegeben wurde
String pinnummer;                     // Soll den beim start ausgelesenen Pin enthalten
int pin_laenge;                          // Länge des Strings (Pin_1) 4 zahlen
int pin_eeprom_addresse = 40;    // Startadresse zum schreiben des Pin im eeprom
int pin_eeprom_groesse = 44;      // Pinnummer belegt 4 stellen im eeprom + Terminierungszeichen

Hiermit Speicher ich ab adresse 40.

pin_laenge = pin_1.length() + 1;

    char neuerPin[pin_laenge];

    pin_1.toCharArray(neuerPin, pin_laenge);

    for (pin_eeprom_addresse = 40; pin_eeprom_addresse < pin_eeprom_groesse;)
    {
      EEPROM.write(pin_eeprom_addresse, neuerPin[pin_eeprom_addresse]);
      pin_eeprom_addresse++;
    }

    EEPROM.write(pin_eeprom_addresse, '\0');        // Terminierungszeichen schreiben

Und hiermit lese ich ihn beim start wieder aus.

 char pinString;

    for (pin_eeprom_addresse = 40; pin_eeprom_addresse < pin_eeprom_groesse;)               // Liest eeprom stelle 40 bis 44 den Pin aus.
    {
      pinString = EEPROM.read(pin_eeprom_addresse);
      if (pinString != '\0')
      {
        pinnummer += char(pinString);                                       // Gespeicherte Nummer aus dem eeprom an variable pinnummer übergeben
      }
       pin_eeprom_addresse++;
    }

Merkwürdiger weise geht es ja mit der selben vorgehensweise bei der Telefonnummer.
Hier sind nur die namen der Variablen geändert und nicht ab adresse 0 sondern ab 40.
Aber egal welche nummer ich eingebe, beim auslesen bekomme ich immer “A456”.
Jetzt ist die frage wo kommt das her ?
Schon beim speichern was falsch oder beim lesen vom eeprom ?
pin_1 enthält immer die richtige nummer.

Hallo
Weil der code zu viele vergleiche mit string und den längen hat.
Und ich mich am anfang entscheiden musste wo ich hin will get und put oder read und write.
Ich kann nur nicht verstehen warum es mit dem selben aufbau bei einer längeren nummer geht ab adresse 0.
Aber bei einer 4 stelligen nummer ab adresse 40 nicht.
Das möchte ich natürlich verstehen was ich falsch gemacht habe.

So ich bin etwas weiter gekommen :slight_smile:
Wenn ich es an jeder adresse einzelnd schreibe zb.

 if (pin_1.length() == 1)
        {
        EEPROM.write(20, pressedKey);
        }
        if (pin_1.length() == 2)
        {
        EEPROM.write(21, pressedKey);
        }
        if (pin_1.length() == 3)
        {
        EEPROM.write(22, pressedKey);
        }
        if (pin_1.length() == 4)
        {
        EEPROM.write(23, pressedKey);
        }

Dann liest mein oben beschriebener code alles korrekt aus.
Also liegt der fehler in der speicherung. Jetzt könnte ich etwas hilfe brauchen :slight_smile:

Jetzt könnte ich etwas hilfe brauchen

Wenn du die vorige Hilfe “Vergiss den Mist mit String” ignorierst, wird es wohl dünn mit der Hilfe.

eigentlich alles ganz simple Methoden von Arduino - EEPROM

EEPROM::put:
Write any data type or object to the EEPROM.

“any” ist etwas übertrieben, gilt z.B. NICHT für String Objekte.
( put macht nur eine kleine Schleife über sizeof(String), der eigentliche Text des Strings ist da gar nicht dabei. )

Total-Newby:
@combie
Siehste in deinem vierzeiler waren 4 mal kritik versteckt :-)))))
Darum habe ich nur das was zum eeprom gehört hochgeladen :-)))))

Dann kommt jetzt noch eine Kritik:
Du postest untestbaren Code. Ohne die wichtigen Definitionen.

Wie soll man dir da helfen?

Desweiteren bist du auf folgende dinge nur mit Rechtfertigungen eingegangen:
Mir fällt auf, dass du es dir viel komplizierter machst, als nötig!
Das String Objekt scheint dich eher zu behindern, als zu helfen.
Auch verwaltest du die Adressen händisch.

Ihr habt es nicht anders gewollt :confused:
Ich weiss echt nicht wie ich den code von String befreien soll !
Keine ahnung wo ich da anfangen sollte. Und der code ist testbar mit einem:
UNO
LCD 20x4
Keypad
Und einem schalter mit mindestens 2 schaltkreisen.
Meiner hat 9 Pins 3 Positionen

Wenn pin A0 high ist sollte es ohne schalter gehen

P.S
Der code ist zu gross zum einfügen darum als rar.

sketch_dec17a.zip (5.2 KB)

Du hast recht...
Mir wird etwas schwindelig, bei deinem Code!

Ein Beispiel:

loop(); // Alles beenden und zurück in den loop springen
Das ist völlig überflüssig.
Denn: Passiert automatisch.

Dann, hast du da viele blockierende Schleifen.
Das tut eigentlich keinen Not.
Für jeden dieser Bereiche, kann, oder besser sollte, man einen endlichen Automaten einsetzen.
Das würde den Code aufräumen.
Klarheit schaffen. (bis jetzt sehe ich den roten Faden noch nicht)

Und in Sachen EEPROM, was dir ja wohl am stärksten auf der Leber liegt...
Verzichte doch bitte auf die händische Adressierung.
Die EEPROM Daten kannst du alle in eine Struktur stopfen.
Das erleichtert das lesen und schreiben ungemein.

Die keypad habe ich angehängt !

Seht ihr genauso wie ihr probleme habt den roten faden zu finden. Habe ich probleme dort auf string zu verzichten. Das ist ja das delämmer ich würds ja gerne.

Keypad.zip (30.1 KB)

könnte man machen war aber nicht so geplant !
Stellt die 0 ein Problem da ?
Ach ja wahrscheinlich wenn er gespeichert wurde und er bis zu einer 0 lesen soll würde er immer abbrechen richtig ?

Ach ja wahrscheinlich wenn er gespeichert wurde und er bis zu einer 0 lesen soll würde er immer abbrechen richtig ?

Warum sollte es?
Weil du String verwendet für die Pin?

Dann stellt '0' kein Problem dar, 0 allerdings schon.

Ich sachs nochmal: Bringe bitte Struktur in die Daten.
Bis jetzt ist noch keine drin.
Und wenn dann ein System drin ist, kannst du dir solche Fragen selber beantworten.

Nö 0 stellt so wie es jetzt ist kein problem da !!
Egal ob an erster oder letzter stelle. Er macht alles richtig.
Aber was meinst du mit struktur ?
Nur die bereiche umschreiben um die es bei meinem Problem geht also,
Schreiben und lesen im eeprom ?
Oder meinst du den ganzen code ?

Aber was meinst du mit struktur ?

struct Datensatz
{
 // hier könntest du auflisten, was
 // alles im EEPROM gespeichert werden soll
};

Hmmm das wäre nur der pin_1.

struct Datensatz
{
uint16_t pin_1
};

ich würde dennoch den Weg zu einem unsigned integer gehen.

pin darf auch mit 0 beginnen, dafür brauchte ich eine lokale hilfsvariable pinlength als Stellenzähler. Wird nicht dramatisch sein.

deine pinnummer habe ich umbenannt, weil ich mit etwas wie

“Personal Identifcation Number nummer”

nicht leben kann.

der anmelde_pin ist pin_anmeldung geworden damits zu den anderen passt.

Logisch hast imho noch den Fehler dass du schon beim ersten PIN speicherst. aus meiner Sicht sollst du erst speichern, wenn der zweite PIN übereinstimmt. Das spart dir dann auch das löschen, wenn der zweite PIN falsch ist.

evtl. musst du nun mit einen anderen Sketch zunächst dein eeprom an den stellen wieder löschen (0xff) oder du akzeptierst jetzt einmal einen falschen PIN.

grundsätzlich hat Combie mit allen seinen Anmerkungen wohl recht. Aber ich bau das jetzt nicht um, also gibts nun die EEPROM Adresse als Konstante und wird auch verwendet (weil das hast zum Teil mit Magic-Numbers gemacht). Die Codeduplikate lass ich auch. Kurzum dein Code war grauslich und ist es immer noch.

Egal: ich kanns mangels keypad nicht prüfen, vieleicht funktionierts.

sketch_dec17a.zip (5.29 KB)

Total-Newby:
Hmmm das wäre nur der pin_1.

struct Datensatz

{
uint16_t pin_1
};

Ah, ja....

Das kann aber nicht sein!

Ich sehe beim überfliegen mindestens 3 Dinge, welche du speicherst.

int eeprom_addresse = 0;              // Startadresse zum schreiben im eeprom
int eeprom_groesse = 17;              // Grösse des verwendeten speichers 16 stellen und die 17 für das Terminierungszeichen
.....
int pin_eeprom_addresse = 20;         // Startadresse zum schreiben des Pin im eeprom
int pin_eeprom_groesse = 24;          // Pinnummer belegt 4 stellen im eeprom + Terminierungszeichen
....
auswahl = EEPROM.read(18);               // Merker aus eeprom lesen ob sms(1) oder telefonanruf(2) ausgewählt wurde
....

Das solltest du also noch mal überdenken!

Dann definierst du zwar Adressen, nutzt sie aber nirgendwo/selten.
Im Code arbeitest du mit Zahlen, nicht mit den Konstanten.

Und hier ist noch ein semantischer Bug: pin_eeprom_groesse
Die gösse der Pin im EEPROM soll doch wohl 4 sein, und nicht 24, oder?

Und hier "uint16_t pin_1" ist auch eine Diskrepanz.
Du sagst uint16_t (das sind 2 Byte), meinst aber 4 Byte denn 24-20=4

Du siehst, dein Code ist verwirrend (für mich)

Ich als Mensch, kann das evt. so gar noch richtig interpretieren.
Aber der Kompiler ist da gnadenlos.
Der Übersetzt das, wenn er kann.
Auch wenn da Mist bei raus kommt, das merkt er nicht.
Denn er denkt nicht.