Nano - EEPROM Daten auslesen

Hallo ,

ich beschäftige mich derzeit mit speichern und lesen von EEPROM Daten. Und jetzt bin ich auf ein Problem oder besser auf ein Verständnisproblem gestoßen.
Wenn ich die Daten auslese und jede Adresse einzeln anspreche , dann kann ich die 6 Zahlen auslesen. Wenn ich aber die Daten per FOR Schleife auslese , ließt er zwar scheinbar alle Adressen . Wobei die Adresse 2 dann den Inhalt von Adresse 6 hat und Adresse 0 ist korrekt. Der Rest ist mit 0 geladen. Die Variable “Daten” ist eine Array mit 6 angegeben. Vielleicht hat einer eine Erklärung warum das so ist. Der Zweck ist eigentlich nur , das ich mir die Zeilen sparren will und das Programm übersichtlicher wird. Ich bin ein Anfänger was das Thema betrifft.

Danke
Andi

Die Monitorausgabe schaut dann so aus (untereinander, würde aber jetzt zu lange sein) :
111,0,100,2,0,4,0,6,0,8,0,10 ← für FOR Schleife (Wert, Adresse)
red,111,green,112,blue,113,red2,100,green2,110,blue2,120 ← für einzel Zeilen (Bezeichnung,Wert)

for (int readData=0;readData<12;readData=readData+2){
  EEPROM.get(readData,Daten);
    Serial.println(Daten[readData]);
  Serial.println(readData);
}

// Group 1
  EEPROM.get(0, r);
  Serial.println("red :"); 
  Serial.println(r); 
  Serial.println("green :"); 
  EEPROM.get(2, g);
  Serial.println(g); 
  Serial.println("blue :"); 
  EEPROM.get(4, b);
  Serial.println(b); 
// Group 2
  EEPROM.get(6, r2);
  Serial.println("red2 :"); 
  Serial.println(r2); 
  Serial.println("green2 :"); 
  EEPROM.get(8, g2);
  Serial.println(g2); 
  Serial.println("blue2 :"); 
  EEPROM.get(10, b2);
  Serial.println(b2);

Traurig...
Ich leide mit dir...
Aber helfen kann ich dir (so) nicht.
Der Code ist untestbar.

Kann dir aber sagen, dass das bei mir nicht passiert.
Aber ich lese/schreibe meist ganze Strukturen

Die Adressberechnungen überlasse ich komplett dem Kompiler.
Der macht weniger Fehler beim Adressberechnen, als ich.
Und du hast damit ja scheinbar auch so deine Probleme.

Moin Andi,
denk mal vorsichtig darüber nach, woher und wohin mit EEPROM.get(readData, Daten) welche Menge an Bytes in der for-Schleife bei jedem Durchlauf transportiert werden.

Mir scheint, dass Du den kompletten Array (Bytes? ints? ganz was anderes?) erst von Adresse 0, dann von Adresse 2 usw. füllst.

Gruß Walter

ArdiAM:
... Ich bin ein Anfänger was das Thema betrifft. ...

... und Dein Code macht einen, äh, unaufgeräumten Eindruck.

Poste am besten mal den vollständigen Sketch. Evtl. lässt der Dein Anfängersein noch genauer durchblicken :slight_smile:

Gruß

Gregor

PS: Gewöhne Dir am besten sofort an, Deinen Code auch optisch zu strukturieren. Das entlastet beim Nachdenken und ist bei der Fehlersuche Gold wert.

[Tutorial] Umgang mit dem AVR EEPROM

wno158:
Moin Andi,
denk mal vorsichtig darüber nach, woher und wohin mit EEPROM.get(readData, Daten) welche Menge an Bytes in der for-Schleife bei jedem Durchlauf transportiert werden.

Mir scheint, dass Du den kompletten Array (Bytes? ints? ganz was anderes?) erst von Adresse 0, dann von Adresse 2 usw. füllst.

Gruß Walter

Da liegt ja mein Problem, von der Logik ist meines achtens alles richtig. Die Variable "Daten" ist eine "INT" und mit 6 Felder (INT Daten[6]). Bei einem Durchlauf der FOR Schleife wird 0, 2,4,6,8,10 durch "readData+2" veranlasst das er nur diese ausließt. Ist ja das selbe wenn ich EEPROM.get(0,Daten) usw. schreiben würde. Wenn ich die 6 Zeilen untereinander schreiben würde (mach ich auch) dann ließt er die 0,2,4,6,8,10 aus, diese sind auch tatsächlich so gepeichert. Im Prinzip ist es ja egal wie ich es schreibe , ich frage mich nur warum?

Bitte den gesamten Sketch, das Model des EEPROMS und den link zur benutzten Bibliothek.
Grüße Uwe

du schreibst ja selber
Die Variable "Daten" ist eine Array mit 6 angegeben.

schau dir deinen Code an

EEPROM.get(readData,Daten);

mach da draus mal ein

EEPROM.get(readData,Daten[readData]);

ein Tipp: verwende bessere Variablennamen (dein readData ist eigentlich eine Adresse im EEPROM oder?)
noch ein Tipp ... Drück mal STRG-T in der IDE.
noch ein dritter Tipp ... schau dir mal die Variablen-Typen an ... brauchst du in der For wirklich ints oder würde uint8_t auch reichen?

ArdiAM:
ich frage mich nur warum?

Weil Du Dir den Unterschied zwischen

EEPROM.get(readData, Daten)

und

EEPROM.get(readData, &Daten[readData/2])

noch erarbeiten musst.

Ich habe jetzt angenommen, dass Du die Standard-Bliothek für das on-chip EEPROM verwendest und nicht ausprobiert, ob noiascas Lösung ohne Adressoperator funktioniert - mache bisher immer Umwege um die C++-Anteile im Arduino.

. Die Variable "Daten" ist eine "INT" und mit 6 Felder (INT Daten[6]).

Das Array Daten hat also nur 6 Felder!

Aber du, nutzt den Index " 0, 2,4,6,8,10 " ?
Und wunderst dich, dass was schief läuft.....

Wie schon gesagt, auch wenn es dich nicht interessiert:
Deine Berechnungen der Adressen/Indices sind falsch.

ich frage mich nur warum?

Ja genau!
Warum rechnest du an der Stelle falsch?
Warum?

Ich habe dir versucht zu zeigen, wie es (fast) ohne rechnen geht.


Weiterhin lieferst du keinen testbaren Code.
Das ist schade...
Denn so bleibt auch geheim, was du überhaupt erreichen willst....


Ich habe jetzt angenommen, dass Du die Standard-Bliothek für das on-chip EEPROM verwendest und nicht ausprobiert, ob noiascas Lösung ohne Adressoperator funktioniert - mache bisher immer Umwege um die C++-Anteile im Arduino.

Hach....
Dabei ist die EEPROM Lib doch eins der ausgefeiltesten Stücke C++ Code in der Arduino Umgebung.
Da lohnt es sich wirklich, mal rein zu schauen.

combie:
Das Array Daten hat also nur 6 Felder!

Aber du, nutzt den Index " 0, 2,4,6,8,10 " ?
Und wunderst dich, dass was schief läuft.....

Wie schon gesagt, auch wenn es dich nicht interessiert:
Deine Berechnungen der Adressen/Indices sind falsch.
Ja genau!
Warum rechnest du an der Stelle falsch?
Warum?

Ich habe dir versucht zu zeigen, wie es (fast) ohne rechnen geht.


Weiterhin lieferst du keinen testbaren Code.
Das ist schade...
Denn so bleibt auch geheim, was du überhaupt erreichen willst....

---------Hach....
Dabei ist die EEPROM Lib doch eins der ausgefeiltesten Stücke C++ Code in der Arduino Umgebung.
Da lohnt es sich wirklich, mal rein zu schauen.

Erst mal besten Dank für die Hilfe. Wie schon geschrieben, das ist ein Test um zu sehen wie was funktioniert. Der Rest vom Programm ist einfach nur eine RGB LED ansteuern (sonst sieht man ja nichts).

Jetzt glaube ich wo der Fehler liegt. Ich kann es gerade nicht testen , aber werde ich noch machen. Vor EEPROM.get(readData,Daten) gehört ein Zähler rein. Daten ist eine Array also sollte ich auch beim durchlaufen der FOR Schleife der Array auch einen Bereich angeben. Vor dem EEPROM.get einfach Zähler=Zähler+1 ( Zähler++ ). Und dann müsste das so aussehen EPROM.get(readData,Daten[Zähler]). So müsste von 0 ab jede 2te Adresse in einen Bereich geschrieben werden.
Bestimmt gibt es eine bessere und schönere Lösung, aber ich muss so schreiben das ich es verstehe, verbessern kann man einen Stil immer.

Bestimmt gibt es eine bessere und schönere Lösung, aber ich muss so schreiben das ich es verstehe, verbessern kann man einen Stil immer.

Kann ich verstehen...

Hier allerdings hast du dich für den kompliziertesten und fehlerträchtigsten Weg entschieden.
z.B. möchtest du jetzt noch einen weiteren (vermutlich völlig überflüssigen) Zähler einführen.
Ob das dem Verständnis und einer (sauberen) Stil Bildung entgegen kommt?
Ich wage es zu bezweifeln.

Denn das "Prinzip der geringsten Verwunderung" verhindert oftmals eine Veränderung einer einmal gefundenen Lösung.

Vielleicht hättst du ja die Chance, den einfacheren (wollte fast sagen: wahren) Weg zu verstehen.
Aber solange du ihn ablehnst, wird das wohl nichts.


Erst mal besten Dank für die Hilfe. Wie schon geschrieben, das ist ein Test um zu sehen wie was funktioniert. Der Rest vom Programm ist einfach nur eine RGB LED ansteuern (sonst sieht man ja nichts).

Natürlich darfst du das geheim halten.
Nur kann ich dir dann nicht zeigen, wie es schöner, verständlicher und einfacher geht.
Verschließe dich, wenn das dein Wille ist, genieße dein Himmelreich.
Ich bin dir nicht böse darum.

combie:
Kann ich verstehen...

Hier allerdings hast du dich für den kompliziertesten und fehlerträchtigsten Weg entschieden.
z.B. möchtest du jetzt noch einen weiteren (vermutlich völlig überflüssigen) Zähler einführen.
Ob das dem Verständnis und einer (sauberen) Stil Bildung entgegen kommt?
Ich wage es zu bezweifeln.

Denn das "Prinzip der geringsten Verwunderung" verhindert oftmals eine Veränderung einer einmal gefundenen Lösung.

Vielleicht hättst du ja die Chance, den einfacheren (wollte fast sagen: wahren) Weg zu verstehen.
Aber solange du ihn ablehnst, wird das wohl nichts.


Natürlich darfst du das geheim halten.
Nur kann ich dir dann nicht zeigen, wie es schöner, verständlicher und einfacher geht.
Verschließe dich, wenn das dein Wille ist, genieße dein Himmelreich.
Ich bin dir nicht böse darum.

Ich verschließe mich nicht neuem, aber wenn ich es so hin bekomme wie ich es geschrieben habe dann verstehe ich den Hintergrund. Sauber schreiben soll auch gelernt sein. Warum nicht den Rest vom Programm, zum einen habe ich es gerade nicht zur Hand und zum anderem, wenn der Teil den ich jetzt schon gezeigt habe auf "kein schöner Programmierstil" stößt dann will ich erst gar nicht den Rest wissen :slight_smile: Da stehen Speziallisten und Anfänger gegenüber :slight_smile: Wobei man ja von ihnen lernt. Aber ein Programmierstil lässt sich schwer ändern, bzw. die Denkweise. Ob jetzt das Projekt einfach ist (zum lernen) , ja da gebe ich Dir recht. Hätte mit was einfachen anfangen können. Aber wie es so ist, wenn man was lernen will muss man eine Idee haben und dann auf das sich stürzen, mir ist einfach nur die Idee gekommen. Werte in EEPROM zu speichern für eine RGB LED und weil das so gut geklappt hat, einfach erweitern. Also zwei Werte speichern und theoretisch dann per Signal die LED auf den Farbwert umschalten. Daher auch die 6 Stellen, könnte man auf keine Ahnung wie viel erweitern (will ich aber nicht). Und wenn die Teilstücke dann funktionieren, das ganze etwas sauberer schreiben (was ich sauber nennen). Da bin ich dann auf das Problem gekommen, wenn es wahrscheinlich auch nur der Fehler war. Die Werte werden über die Serielle Schnittstelle übergeben und gespeichert. Eingegeben wird der RGB Wert und dann welche Gruppe. Mit der Gruppe unterscheide ich nur welche Farbwert wann kommen soll. Ein Beispiel "130,0,0,1" , bedeutet dann R=130 , G=0 , B=0 und 1= Gruppe 1 (Speicherstelle 0,2,4). Würde dann Gruppe 2 angewählt sein, dann wäre es die Speicherstelle 6,8,10. Die Gruppe wird nicht im EEPROM hinterlegt, nicht das jetzt eine Verwirrung aufkommt. Bei jedem Neustart wird erst das EEPROM ausgelesen und dann die LED angesteuert. Werden neue Werte eingeben , wird das EEPROM wieder beschrieben. Gerne zeige ich das komplette Programm, aber da wird der ein oder andere die Augen verdrehen und den Kopf schütteln :slight_smile: Aber erst wenn ich meine Idee getestet habe.

Jetzt habe ich das Programm etwas aufgeräumt und ich denke es schaut recht sauber aus. Die Funktion ist einfach erklärt. Mit dem Serieller Monitor kann man die Werte für die RGB LED eingeben. Also für den ersten RGB Wert wäre zum Beispiel “200,0,0,1” (rot). Wenn man dann “0,200,0,2” eingibt , dann wäre es grün für den zweiten RGB Wert. Gibt man den Wert “0,0,0,0” ein, wird der Script EEPROM Löschen ausgeführt. Was noch nicht im Programm ist, das die Werte je nach Eingang aktiviert werden. Den Seriellen Ausgabe kann man natürlich entfernen (ist nur zur Überprüfung).

#include <EEPROM.h>

int group; // Gruppenzuordnung
int Zaehler = 0; // Counter Daten
int Farbe[6]; // Farben für RGB LEDs

// analoge Ausgänge Gruppe 1
const int redPin = A0;
const int greenPin = A1;
const int bluePin = A2;

void setup() {
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// Serielle Schnittstelle
Serial.begin(9600);
 // warte bis Schnittstelle aufgebaut ist
 while (!Serial) {
    }
// lese Daten von EEPROM
for (int readData=0;readData<12;readData=readData+2){
  EEPROM.get(readData,Farbe[Zaehler]);
  Serial.print(Farbe[Zaehler]);
  Serial.print(",");
  Zaehler=Zaehler+1;
}
Serial.println("Ende");
}

void loop() {

// analoge Ausgänge A0,A1,A2 beschalten
      analogWrite(redPin, Farbe[1]);
      analogWrite(greenPin, Farbe[2]);
      analogWrite(bluePin, Farbe[3]);   
// Eingabe der seriellen Schnittstelle erfolgt  
  while (Serial.available() > 0) {
    Farbe[1] = Serial.parseInt();
    Farbe[2] = Serial.parseInt() ;
    Farbe[3] = Serial.parseInt();
    group = Serial.parseInt();
// Überprüfe Eingabe von 0 bis 255
   if (Serial.read() == '\n') {
// Abfrage auf Clear
if (group==0) {
  for (int i = 0 ; i < EEPROM.length() ; i++) {
  EEPROM.write(i, 000);
  }
}
      Farbe[1] = constrain(Farbe[1], 0, 255);
      Farbe[2] = constrain(Farbe[2], 0, 255);
      Farbe[3] = constrain(Farbe[3], 0, 255);
  }
if (group==1) {
        EEPROM.update(0, Farbe[1]);
        EEPROM.update(2, Farbe[2]);
        EEPROM.update(4, Farbe[3]);
}

if (group==2) {
        EEPROM.update(6, Farbe[1]);
        EEPROM.update(8, Farbe[2]);
        EEPROM.update(10, Farbe[3]);
}
  }
}

, aber da wird der ein oder andere die Augen verdrehen und den Kopf schütteln :slight_smile:

OK, einverstanden.

z.B.:

A0 bis A2 sind keine analogen/pwm Output.
Der Umstand könnte dir noch Probleme beim Dimmern bereiten.

Für die Farben, würde ich dir eine Struktur vorschlagen.

struct Farbe 
{
  uint8_t r;
  uint8_t g;
  uint8_t b;
};

combie:
OK, einverstanden.

z.B.:

A0 bis A2 sind keine analogen/pwm Output.
Der Umstand könnte dir noch Probleme beim Dimmern bereiten.

Für die Farben, würde ich dir eine Struktur vorschlagen.

struct Farbe 

{
 uint8_t r;
 uint8_t g;
 uint8_t b;
};

Hallo,

die Ports habe ich geändert und ich habe noch festgestellt das "int Zaehler=0" eigentlich "int Zaehler=1" sein soll. Sonst haut das mit dem Auslesen nicht hin. Aber weil ich gerade so in Fahrt war dachte ich mir nehme die anderen PWM's für eine andere LED her. Das wäre beim NANO dann PIN 3,5,6. Jetzt ist aber am Pin 6 noch was intern belegt , soweit ich das raus lesen konnte, zu mindestens gibt er was raus was ich nicht beschalte. Die Pins werden unter anderem mit dem Timer0 beschalten (genutzt). Diese braucht man auch für den PWM Ausgang (hoffe das ich da jetzt nicht was durcheinander bringe). Kurz gefragt, kann man den Pin 6 auch nur als PWM nutzen ? Der Befehl wird wahrscheinlich nicht richtig dazu passen "noTone(6)" aber dann flackert die LED nicht mehr so. Die anderen PWM Pins 9,10,11 habe ich schon mit einer anderen LED belegt. Abgesehen das die anderen PWM Pins (3,5,6) also der 6er scheinbar auch einen andere Frequenz haben, hoffe nicht das dass was ausmacht.

Danke

Dein Text ist fast nicht zu lesen, den solltest du aus dem Quote entfernen.
Sieh dir mal das Pinout vom Nano an, da ist der Pin D6 auch als PWM-Pin gekennzeichnet, sollte also funktionieren.

Oh, das war keine Absicht (Text). Ja, die Ports sind als PWM gekennzeichnet. Aber trotzdem bekomme ich von Pin 6 was raus, ich beschalte ihn nicht, da ich den Wert für blau (in dem Fall) auf null gestellt habe. Die anderen zwei Pins 3,5 funktionieren auch bestens (rot und grün). Wenn ich den Monitor aktivere , mit Serial.print dann zählt da ein Timer runter. Daher gehen ich davon aus das irgendwie der Pin intern dafür belegt ist und es bestimmt eine Möglichkeit gibt (oder auch nicht) diesen nur als PWM zu nutzen. Leider habe ich keine weiteren PWM's mehr frei.

das "int Zaehler=0" eigentlich "int Zaehler=1" sein soll.

Arrays fangen grundsätzlich (in C++) mit 0 an!
Mit deiner 1 biste also irgendwie schief gewickelt.

Wiederholung:
Übelasse dem Compiler die Fehlerträchtige Index und Adressberechnung!

Zuwenig PWM Pins?
Dann, ein Tipp: PCA9685