ESP8266 EEPROM

Tach zusammen,

ich möchte 4 zweistellige Werte im EEPROM meines Wemos D1 mini Pro speichern.
Das Tutorial hab ich dazu gefunden: www.kriwanek.de

Allerdings bekomme ich ‘cfgStart’ was not declared in this scope beim kompilieren.
Wenn ich das selbst deklariere, kommt das gleiche mit ‘cfg’ dann ‘cfg.letter1’.
Das müsste ja in der library deklariert sein oder. Und die scheint schon gefunden zu werden da in der IDE vorhanden.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <EEPROM.h>
#include "myTypes.h"

int LED = D6;
char* letter1 = "";
String t_state;

const char* ssid = "***";
const char* password = "***";

ESP8266WebServer server(80);

void handleLED() {  
 if(t_state == "11") {digitalWrite(LED,HIGH);}
}

void setup(void){
  Serial.begin(115200);  
  WiFi.begin(ssid, password);

  pinMode(LED,OUTPUT);

  server.begin();

  loadConfig();
}


void loop(void){
  configData_t cfg;
}

void loadConfig() {
  EEPROM.begin(4095);
  EEPROM.get( cfgStart, cfg );
  EEPROM.end();
  t_state = cfg.letter1;
  handleLED();

}

Warum nimmst Du nicht die Beispiele zur EEPROM-Lib?

put und get sind Deine Freunde.

Gruß Tommy

Allerdings bekomme ich 'cfgStart' was not declared in this scope beim kompilieren.

Glaube der Meldung!
Lasse da keine Irritationen/Zweifel aufkommen.

Das müsste ja in der library deklariert sein oder.

Das hast du dir nur ausgedacht!

Beachte die Sichtbarkeitsbereiche/Geltungsbereiche von Variablen.
Gerade hier die von lokalen Variablen.

put und get sind Deine Freunde.

Macht ihm doch.

combie:
Macht ihm doch.

Sorry, hatte ich übersehen.

Gruß Tommy

Tommy56:
Warum nimmst Du nicht die Beispiele zur EEPROM-Lib?
put und get sind Deine Freunde.

Wenn ich die beiden hintereinander hochlade, wird auch nicht das ausgebegeben was es sollte.
https://www.arduino.cc/en/Reference/EEPROMPut
https://www.arduino.cc/en/Reference/EEPROMGet

combie:
Glaube der Meldung!

Dann ist die verlinkte Anleitung falsch/unvollständig?
Die Andere auch schon als "sehr gut" verlinkt haben, man also annehmen könnte dass sie schon mal bei irgendjemand funktioniert hatte.
Wenn ich jetzt das an den Anfang der Datei schreib geht es auch nicht.
#define cfgStart 0
#define cfg
#define cfg.letter1

#define cfg.letter1

Was willst du mit einem Brief?

"myTypes.h"

Was willst du damit?

ich möchte 4 zweistellige Werte im EEPROM meines Wemos D1 mini Pro speichern.

Das ist ein Ansatzpunkt!

Stopfe die 4 Werte in ein Array oder Struktur, und dann lese und schreibe nach belieben.


Dann ist die verlinkte Anleitung falsch/unvollständig?
Die Andere auch schon als "sehr gut" verlinkt haben, man also annehmen könnte dass sie schon mal bei irgendjemand funktioniert hatte.

Dazu kann ich nichts sagen.
Außerdem ist der Link zum Code dort defekt.

Auch halte ich wenig von halbgaren Tutorials.
Die verwirren eher mehr, als informativ zu sein!

Sprachdoku lesen und verstehen.
Librarydoku lesen und verstehen.
Dann erledigen sich die meisten Probleme fast von selber.

Okay dass kann gut sein dass unter deren Link dann die noch fehlenden Sachen gestanden hätten.
myTypes.h und Brief sind einfach Strukturset und Strukturname.

Nicht einmal das geht. Muss wohl etwas anderes kaputt sein…

#include <EEPROM.h>
int addr = 10;
void setup()
{
  EEPROM.begin(4095);  
  EEPROM.write(addr, 'G');
  EEPROM.commit();
}
void loop(){
}
#include <EEPROM.h>
int addr = 10; 
void setup()
{
  EEPROM.begin(4095);
  Serial.begin(9600);
  Serial.println(""); 
  Serial.print(char(EEPROM.read(addr)));
}
 void loop(){
}

Hi

Vll. bin ich ja zu einfach gestrickt - aber jeden 2-stelligen (0...99) Wert kann ich als Byte (0...255), oder als BCD (0x00,01,...,09,10,11,...,99 passt auch in ein Byte) speichern.

Wo tauchen Da Probleme auf?

MfG

postmaster-ino:
Wo tauchen Da Probleme auf?

Mir würden jetzt tatsächlich auch 4 einzelne Zahlen reichen.
Dazu die zwei maximal simplen Schnipsel in meinem letzten Post, um es mit einer Zahl auf einen fest Speicherplatz zu versuchen.
Es wird statt dem "G" nichts im Monitor ausgegeben außer die üblichen Fragezeichen die generell vom ESP kommen. Lass ich es durch Loop ausgeben, gibt es nur viele leere Zeilen.
Ob das Schreiben oder das Lesen nicht geht, kann ich natürlich schlecht sagen.

Tipp:
Wenn die Baudrate nicht stimmt, hagelt es Schrottzeichen.


Ich kann nur raten, da mit “Struktur” ran zu gehen.
Gilt auch für andere ähnliche Speicher. Wie z.B. RAM, AVR-EEPROM, FRAM usw.

Hier mal ein Beispiel für den ESP mit kleinem Menue.
(auf die Schnelle aus meiner Wühlkiste zusammengeklaubt)

#include <EEPROM.h>

using Container = byte[4];



struct EpData // eine Datensammlung im EEPROM
{
  int kram;
  Container container;
  bool flagge;
  // usw
};



Container satzA {7,42,23,1}; // beispieldaten
Container satzB {5,6,8,9};  // beispieldaten



void setup(void)
{
  EEPROM.begin(4096);
  Serial.begin(9600);

  delay(3000);

  Serial.println();
  Serial.println();
  Serial.println(" Menue");
  Serial.println(" a) schreibt satzA");
  Serial.println(" b) schreibt satzB");
  Serial.println(" p) ließt EEPROM und zeigt den Inhalt");
  
  Serial.println();
  Serial.println();

}


void loop(void)
{
  switch(Serial.read())
  {
    case 'a':  EEPROM.put(offsetof(EpData,container),satzA);
               EEPROM.commit();
               Serial.println(" SatzA geschrieben");
               break;
               
    case 'b':  EEPROM.put(offsetof(EpData,container),satzB);
               EEPROM.commit();
               Serial.println(" SatzB geschrieben");
               break;
               
    case 'p':   Serial.println(" Satz lesen ");
                Container gelesenerSatz;
                EEPROM.get(offsetof(EpData,container),gelesenerSatz );
                for(byte g:gelesenerSatz)
                {
                  Serial.print(g); 
                  Serial.print(',');
                }
                Serial.println();
                break;
  }
}

combie:
Hier mal ein Beispiel für den ESP mit kleinem Menue.

Oh okay das funktioniert :slight_smile: danke.

Hab jetzt schon ne Weile probiert aber bekomm es nicht so recht an meine Bedürfnisse angepasst. Weil Dinge vorkommen mit denen ich wenig anfangen kann.
Eventuell möchte ich das Array entfernen damit es, zwar länger aber dafür verständlicher ist.
Vor dem Speichern und nach dem Laden müssen die Werte in 4 einzelnen Variablen sein. Ah und es sollen immer alle 4 Werte zusammen gespeichert und geladen werden.
Meine Werte ins Array rein bekomm ich schon mal nicht, weil kein normales aus einem Wort ist. Verschiedenste Schreibweißen schon versucht.

char* letter1 = "1";
char* letter2 = "2";
char* letter3 = "3";
char* letter4 = "4";

Container satzA {7,42,23,1}; // beispieldaten
Container satzB {5,6,8,9};  // beispieldaten

Container satzA[0] = letter1;
Container satzA[1] = letter2;
Container satzA[2] = letter3;
Container satzA[3] = letter4;

Raus müssten sie dann auch wieder in einzelne Variablen, ich kann und will nicht alles was ich damit dann mache, in die for Schleife schreiben.

Dann solltest Du dringend anfangen, die Grundlagen zu lernen. Dann verstehst Du auch die Hilfestellungen.

Gruß Tommy

Ungefähr so hatte ich es vor über 1,5 Jahren mal mit dem UNO gemacht und es klappte alles.
Ich hab gerade keinen freien Arduino mehr, aber vermute dass es am ESP liegt.
Es werden nur 0er statt der 5en ausgegeben.

#include <EEPROM.h>
int value;
int wert = 5;

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

void loop() {
delay(1000);
EEPROM.write(2, wert);

delay(1000);
  
value = EEPROM.read(2);
Serial.print("");
Serial.println(value);
}

Wie kann ich dir helfen?

Vorsichtshalber wiederhole ich meinen Rat:

Ich kann nur raten, da mit "Struktur" ran zu gehen.
Gilt auch für andere ähnliche Speicher. Wie z.B. RAM, AVR-EEPROM, FRAM usw.

Aus meiner Sicht das einzig wahre.

combie:
Wie kann ich dir helfen?

Am besten und einfachsten natürlich sagen was an meinem Code falsch ist. Oder eben dass es richtig aussieht, schon gehen müsste und irgendwie sehr mysteriös ist.

Genau so hätte ich das eigentlich ganz gern, doch auch amit ist die Ausgabe leer.
Und wenn ich in der letzten Zeile alle 4 Werte ausgeben will, kommt unteranderem
invalid operands of types ‘const char*’ and ‘const char [2]’ to binary ‘operator+’

#include <EEPROM.h>
int letter1 = 5;
int letter2 = 6;
int letter3 = 7;
int letter4 = 8;

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

void loop() {
delay(2000);
speichern();
}

void speichern() {
EEPROM.write(1, letter1);
EEPROM.write(2, letter1);
EEPROM.write(3, letter1);
EEPROM.write(4, letter1);
delay(50);
laden();
}

void laden() {  
letter1 = EEPROM.read(1);
letter2 = EEPROM.read(2);
letter3 = EEPROM.read(3);
letter4 = EEPROM.read(4);
Serial.println("");
Serial.println(letter1 + "-" + letter2);
}

Und wenn ich in der letzten Zeile alle 4 Werte ausgeben will, kommt unteranderem
invalid operands of types ‘const char*’ and ‘const char [2]’ to binary ‘operator+’

Tja…
Stringverkettung geht anders.

Ich könnte dir Streaming empfehlen…

#include <Streaming.h> // findest du sicherlich

int letter1 = 5;
int letter2 = 6;
int letter3 = 7;
int letter4 = 8;


void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;

  Serial << endl
         << letter1 <<  "-"  <<  letter2 << endl;
}

void loop() 
{

}

Gut zu wissen.

Ich hab es in deinem Beispiel jetzt geschafft meine einzelnen Variablen rein und auch wieder einzeln raus zu bekommen. :slight_smile: Damit klappt jetzt alles was ich wollte, thank youuu.

#include <EEPROM.h>

using Container = byte[4];

struct EpData
{
  Container container;
};

int letter1 = 66;
int letter2 = 77;
int letter3 = 88;
int letter4 = 99;
Container satzA {letter1,letter2,letter3,letter4};

void setup(void)
{
  EEPROM.begin(4096);
  Serial.begin(9600);

  delay(3000);

  Serial.println();
  Serial.println();
  Serial.println(" Menue");
  Serial.println(" a) schreibt satzA");
  Serial.println(" p) ließt EEPROM und zeigt den Inhalt");
  Serial.println();
}

void loop(void)
{
  switch(Serial.read())
  {
    case 'a':  EEPROM.put(offsetof(EpData,container),satzA);
               EEPROM.commit();
               Serial.println(" SatzA geschrieben");
               break;
              
    case 'p':   Serial.println(" Satz lesen ");
                Container gelesenerSatz;
                EEPROM.get(offsetof(EpData,container),gelesenerSatz );
                int counter = 1;
                for(byte g:gelesenerSatz)
                {
                 if (counter == 1) {letter1 = g;}
                 if (counter == 2) {letter2 = g;}
                 if (counter == 3) {letter3 = g;}
                 if (counter == 4) {letter4 = g;}
                 counter++;
                }
                  Serial.print(letter1);
                  Serial.print(',');
                  Serial.print(letter2);
                  Serial.print(',');
                  Serial.print(letter3);
                  Serial.print(',');
                  Serial.print(letter4);               
                break;
  }
}

Hier Re: uint16_t in den EEPROM scheiben heule ich mich gerade aus...

Einerseits, schön dass es jetzt klappt.
Andererseits, hast du da jetzt überflüssige Umwege eingebaut.

Mir liegt die Ansage auf der Zunge:

int counter = 1;
                for(byte g:gelesenerSatz)
                {
//.........
                 counter++;
                }

Wenn man eine Zählvariable benötigt, verwendet man zählende Schleifen und nicht den range based loop.

using Container = byte[4];

struct EpData
{
  Container container;
};

int letter1 = 66;
int letter2 = 77;
int letter3 = 88;
int letter4 = 99;
Container satzA {letter1,letter2,letter3,letter4};

Wenn man schon Strukturen benutzt, dann sollte man das auch tun.
So ist es nur ein komischer Umweg.

Hier ist es das beharren auf einzelne Variablen, was mir u.A. quer geht.
Z.B. das durchzählen der Variablen.

Aber selbst damit...
Und der händischen Null als Adresse ...

struct Container
{
  int letter1;
  int letter2;
  int letter3;
  int letter4;
};

Container datenImSpeicher {1,2,4,5};


// später dann
EEPROM.put(0,datenImSpeicher);
// oder
EEPROM.get(0,datenImSpeicher);


Serial.print(datenImSpeicher.letter1);

Sieht es noch schlichter aus.

Da dort schon eine Schleife ist, wusste ich nicht wohin mit meiner Schleife die hochzählt. Ist in dem Fall aber so voll okay für mich. Ich hab schon mit funktionsfähig hart zu kämpfen, da muss kurz & schön echt hintanstehen.

Jetzt würde ich gerne meine beim Start aus dem eeprom geladenen Werte in Javascript Varibalen bekommen. Um auch auf dem Webserver darzustellen was der ESP damit bereits über die Pins treibt.
Hier ist ein sehr schönes Beispiel das auch gut funktioniert.
In dem this.responseText in Zeile 39 der index.h ist dann das was ich in Zeile 30 der .ino in der String adcValue eingetragen hab.

Soo, jetzt hab ich aber 4 Werte und nicht nur einen.
Ich hab schon versucht verschiedene Stellen wo adcValue, handleADC, readADC vorkommt zu kopieren und eine Zahl dranzuhängen.
Eventuell ist responseText ein Array in den alle Werte können..
Ich weiß es nicht, find es auch nach mehreren Tagen nicht alleine raus und kann nicht einschätzen wie viel und was noch fehlt.
Zur Not versuch ich auch vier getData() Funktionen aber hm..

Du musst die 4 Werte in einen zusammenpacken und auf der anderen Seite nach der Übertragung wieder zerlegen. Evtl. könnte Dir auch JSON dabei helfen.

Gruß Tommy