EEPROM speichert Daten "falsch" ab

Hallo zusammen,
ich bastel an einer LED-Beleuchtung für ein Brotbackhaus, welche über eine App auf meinem Android-Smartphone gesteuert werden soll.

Die Datenübertragung zwischen Smartphone und Arduino klappt jetzt schon ganz gut (jedenfalls solange der Arduino am PC angesteckt ist), aber der Empfangene Wert wird meiner Meinung nach falsch im EEPROM abgespeichert.

Es soll 3 Lichtbänder geben. Dementsprechend gibt es 3 Buttons in der App, mit denen sich Farben auswählen und per Bluetooth an den Arduino senden lassen.

Das Gesendete sieht wie folgt aus: [Kennzeichen]+[Farbwert]
z. B.: uff21ad4c

Es gibt je nach Button die Kennzeichen "v" für "LED-Band Vorne", "o" für "LED-Band Oben" und "u" für "LED-Band Unten"

Hier der Code für den Arduino Nano(DFRobot mit integriertem Bluetooth LE):

/****************************************************
  Ansteuerung von 3 separaten RGB-LED-Bändern
  über 16-Kanal PWM-Board mit Mosfet-Modulen.
  Datenempfang von Smartphone-App über Bluetooth LE.
 ****************************************************/

#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_PWMServoDriver.h>

// PWM über I2C-Bus an Adresse 40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(&Wire, 0x40);

// Umrechnungstabelle für RGB-Farbwerte von 8Bit auf 12Bit mit Gamma-Korrektur
const int PROGMEM Farbwert[] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,
  2,  2,  2,  3,  3,  4,  4,  5,  5,  6,  7,  8,  8,  9, 10, 11,
  12, 13, 15, 16, 17, 18, 20, 21, 23, 25, 26, 28, 30, 32, 34, 36,
  38, 40, 43, 45, 48, 50, 53, 56, 59, 62, 65, 68, 71, 75, 78, 82,
  85, 89, 93, 97, 101, 105, 110, 114, 119, 123, 128, 133, 138, 143, 149, 154,
  159, 165, 171, 177, 183, 189, 195, 202, 208, 215, 222, 229, 236, 243, 250, 258,
  266, 273, 281, 290, 298, 306, 315, 324, 332, 341, 351, 360, 369, 379, 389, 399,
  409, 419, 430, 440, 451, 462, 473, 485, 496, 508, 520, 532, 544, 556, 569, 582,
  594, 608, 621, 634, 648, 662, 676, 690, 704, 719, 734, 749, 764, 779, 795, 811,
  827, 843, 859, 876, 893, 910, 927, 944, 962, 980, 998, 1016, 1034, 1053, 1072, 1091,
  1110, 1130, 1150, 1170, 1190, 1210, 1231, 1252, 1273, 1294, 1316, 1338, 1360, 1382, 1404, 1427,
  1450, 1473, 1497, 1520, 1544, 1568, 1593, 1617, 1642, 1667, 1693, 1718, 1744, 1770, 1797, 1823,
  1850, 1877, 1905, 1932, 1960, 1988, 2017, 2045, 2074, 2103, 2133, 2162, 2192, 2223, 2253, 2284,
  2315, 2346, 2378, 2410, 2442, 2474, 2507, 2540, 2573, 2606, 2640, 2674, 2708, 2743, 2778, 2813,
  2849, 2884, 2920, 2957, 2993, 3030, 3067, 3105, 3143, 3181, 3219, 3258, 3297, 3336, 3376, 3416,
  3456, 3496, 3537, 3578, 3619, 3661, 3703, 3745, 3788, 3831, 3874, 3918, 3962, 4006, 4050, 4095
};

// Pinbelegung für PWM-Board
const uint8_t ledPinVorneG = 0, ledPinVorneR = 1, ledPinVorneB = 2;   // Pins für LED-Band "Vorne"
const uint8_t ledPinObenG = 3, ledPinObenR = 4, ledPinObenB = 5;      // Pins für LED-Band "Oben"
const uint8_t ledPinUntenG = 6, ledPinUntenR = 7, ledPinUntenB = 8;   // Pins für LED-Band "Unten"

// Variablen und Startwerte
int AdrStatusVorne = 0, AdrStatusOben = 16, AdrStatusUnten = 32;      // Speicher-Adressen der LED-Stati
int AdrFarbeVorne = 48, AdrFarbeOben = 64, AdrFarbeUnten = 80;        // Speicher-Adressen der LED-Farben
int AdrHellVorne = 96, AdrHellOben = 112, AdrHellUnten = 128;         // Speicher-Adressen der LED-Helligkeiten
bool StatusVorne, StatusOben, StatusUnten;                            // Status "EIN"/"AUS"
String FarbeVorne, FarbeOben, FarbeUnten;                             // Farbwerte der LED-Bänder
int HelligkeitVorne, HelligkeitOben, HelligkeitUnten;                 // Helligkeitswerte der LED-Bänder
String SerialEingabe;                                                 // Eingelesener String


void setup() {

  Serial.begin(115200);
Serial.println("Backhaus Beleuchtung");
Serial.println(" |-> Serial Setup done!");

Serial.println(" |-> I2C Setup");
  // I2C-Frequenz (400000 = schneller Modus)
  Wire.setClock(400000);
Serial.println(" |-> I2C Setup done!");

Serial.println(" |-> PWM Setup");
  pwm.begin();
  pwm.setPWMFreq(1600);  // PWM-Frequenz (Max. 1600)
Serial.println(" |-> PWM Setup done!");

Serial.println(" |-> Licht aus");
  // LEDs zu Beginn AUS
  pwm.setPWM(ledPinVorneG, 0, 4096);
  pwm.setPWM(ledPinVorneR, 0, 4096);
  pwm.setPWM(ledPinVorneB, 0, 4096);
  pwm.setPWM( ledPinObenG, 0, 4096);
  pwm.setPWM( ledPinObenR, 0, 4096);
  pwm.setPWM( ledPinObenB, 0, 4096);
  pwm.setPWM(ledPinUntenG, 0, 4096);
  pwm.setPWM(ledPinUntenR, 0, 4096);
  pwm.setPWM(ledPinUntenB, 0, 4096);
  pwm.setPWM( 9, 0, 4096);
  pwm.setPWM(10, 0, 4096);
  pwm.setPWM(11, 0, 4096);
  pwm.setPWM(12, 0, 4096);
  pwm.setPWM(13, 0, 4096);
  pwm.setPWM(14, 0, 4096);
  pwm.setPWM(15, 0, 4096);
Serial.println(" '-> DONE!");
}


void loop() {
  // Bei jedem Zyklus Farben updaten
Serial.println();
Serial.println("Farbwerte auslesen!");
Serial.println("  Adresse - Farbwert - Größe");
  
  // gespeicherte Werte "Vorne" auslesen
  EEPROM.get(AdrStatusVorne, StatusVorne);
  EEPROM.get(AdrFarbeVorne, FarbeVorne);
Serial.print ("Vorne: "); Serial.print(AdrFarbeVorne); Serial.print (" - "); Serial.print(FarbeVorne); Serial.print (" - "); Serial.println (sizeof(FarbeVorne));
  EEPROM.get(AdrHellVorne, HelligkeitVorne);
  
  // gespeicherte Werte "Oben" auslesen
  EEPROM.get(AdrStatusOben, StatusOben);
  EEPROM.get(AdrFarbeOben, FarbeOben);
Serial.print ("Oben:  "); Serial.print(AdrFarbeOben); Serial.print (" - "); Serial.print(FarbeOben); Serial.print (" - "); Serial.println (sizeof(FarbeOben));
  EEPROM.get(AdrHellOben, HelligkeitOben);
  
  // gespeicherte Werte "Unten" auslesen
  EEPROM.get(AdrStatusUnten, StatusUnten);
  EEPROM.get(AdrFarbeUnten, FarbeUnten);
Serial.print ("Unten: "); Serial.print(AdrFarbeUnten); Serial.print (" - "); Serial.print(FarbeUnten); Serial.print (" - "); Serial.println (sizeof(FarbeUnten));
  EEPROM.get(AdrHellUnten, HelligkeitUnten);
  
  
  // Wenn keine Verbindung besteht: nichts machen
  while (Serial.available() == 0) {
  }

Serial.println();
  // Wenn eine Verbindung besteht: Seriell als String einlesen
  while (Serial.available() != 0) {
    SerialEingabe = Serial.readStringUntil('\r');
Serial.print ("Empfangen: "); Serial.println(SerialEingabe);
  }
  // Daten für "Vorne"?
  if (SerialEingabe.startsWith("v")) {
    FarbeVorne = SerialEingabe.substring(1);
Serial.print ("Farbwert "); Serial.print(FarbeVorne); Serial.print(" in Adresse "); Serial.print(AdrFarbeVorne); Serial.println (" speichern");
    // speichern
    EEPROM.put(AdrFarbeVorne, FarbeVorne);
  }
  // Daten für "Oben"?
  else if (SerialEingabe.startsWith("o")) {
    FarbeOben = SerialEingabe.substring(1);
Serial.print ("Farbwert "); Serial.print(FarbeOben); Serial.print(" in Adresse "); Serial.print(AdrFarbeOben); Serial.println (" speichern");
    // speichern
    EEPROM.put(AdrFarbeOben, FarbeOben);
  }
  // Daten für "Unten"?
  else if (SerialEingabe.startsWith("u")) {
    FarbeUnten = SerialEingabe.substring(1);
Serial.print ("Farbwert "); Serial.print(FarbeUnten); Serial.print(" in Adresse "); Serial.print(AdrFarbeUnten); Serial.println (" speichern");
    // speichern
    EEPROM.put(AdrFarbeUnten, FarbeUnten);
  }
  // undefinierte Daten
  else {
Serial.println("ungültige Daten");
Serial.println(sizeof(SerialEingabe));
  }
}

Nach dem Setup liest er also erstmal die gespeicherten Werte aus und gibt die Adresse, den Wert und die Größe der Variable zurück:

Backhaus Beleuchtung
 |-> Serial Setup done!
 |-> I2C Setup
 |-> I2C Setup done!
 |-> PWM Setup
 |-> PWM Setup done!
 |-> Licht aus
 '-> DONE!

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247897 - 6
Oben:  64 - ff2123ad - 6
Unten: 80 - ff2123ad - 6

Wähle ich jetzt am Smartphone für z.B. Vorne eine andere Farbe aus, bekomme ich folgendes zurück:

Empfangen: v88247897
Farbwert 88247897 in Adresse 48 speichern

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247897 - 6
Oben:  64 - ff2123ad - 6
Unten: 80 - ff2123ad - 6

Klappt einwandfrei!

Mache ich das gleiche für Oben ODER Unten, sieht die Konsole so aus:

Empfangen: od2865949
Farbwert d2865949 in Adresse 64 speichern

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247897 - 6
Oben:  64 - d2865949 - 6
Unten: 80 - d2865949 - 6
Empfangen: uff21ad4c
Farbwert ff21ad4c in Adresse 80 speichern

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247897 - 6
Oben:  64 - ff21ad4c - 6
Unten: 80 - ff21ad4c - 6

Der übertragene Wert wird also entweder in 2 Speicherbereichen gespeichert, oder doppelt aus dem gleichen ausgelesen.

Meine Vermutung liegt bei den Speicheradressen.
Habe ich bei der Speicher-Adressierung etwas übersehen?

Wenn Du deine quote (=Zitat)-Tags durch code ersetzt, wird alles besser lesbar.
Das kannst Du auch nachträglich ändern.

Gruß Tommy

Erledigt

Das habe ich von Anfang an schon so gewollt, nur habe ich den Button dafür übersehen :o :confused:

also wenn ich den Serial-Monitor nur auf CR stelle, dann klappt es eigentlich

arbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247897 - 6
Oben:  64 - 88247897 - 6
Unten: 80 - 88247891 - 6

Empfangen: v88247810
Farbwert 88247810 in Adresse 48 speichern

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247810 - 6
Oben:  64 - 88247897 - 6
Unten: 80 - 88247891 - 6

Empfangen: o88247866
Farbwert 88247866 in Adresse 64 speichern

Farbwerte auslesen!
  Adresse - Farbwert - Größe
Vorne: 48 - 88247810 - 6
Oben:  64 - 88247866 - 6
Unten: 80 - 88247891 - 6

was ich gemacht habe,
Einmal das ganze eeprom gelöscht,
die pwm. auskommentiert, da ich das nicht habe
die Adressen auch auf const 8byte gesetzt:

const uint8_t AdrStatusVorne = 0, AdrStatusOben = 16, AdrStatusUnten = 32;      // Speicher-Adressen der LED-Stati
const uint8_t AdrFarbeVorne = 48, AdrFarbeOben = 64, AdrFarbeUnten = 80;        // Speicher-Adressen der LED-Farben
const uint8_t AdrHellVorne = 96, AdrHellOben = 112, AdrHellUnten = 128;         // Speicher-Adressen der LED-Helligkeiten

P.S.: ... bau das um und verabschiede dich von Strings. Wenn das RGB Farben sind, dann nimm die 3 Werte in 3 Byte.
Auch die Code-Duplikate für vorne unten oben lassen sich verbessern.

Hey noiasca, erstmal vielen Dank!

noiasca:
was ich gemacht habe,
Einmal das ganze eeprom gelöscht,
die pwm. auskommentiert, da ich das nicht habe
die Adressen auch auf const 8byte gesetzt:

Den EEPROM einmal komplett auf NULL setzen hat das Problem gelöst :slight_smile:
Und die Adressen als Const uint8_t speichern macht auch Sinn. Hätte ich auch selber merken können..

noiasca:
also wenn ich den Serial-Monitor nur auf CR stelle, dann klappt es eigentlich

Ein guter Hinweis - zumindest kommt mir das bei mir komisch vor.
Wenn der Arduino über einem USB-Hub am PC hängt und ich per Smartphone Daten sende, dann klappt das (jetzt) wunderbar.
Stecke ich den Arudino an einem separaten USB-Hub an, der nicht am PC angeschlossen ist, dann empfängt er vom Smartphone augenscheinlich irgendwelchen Müll.
In der App wird das in Form von Rauten mit Fragezeichen, arabischen Zeichen, Strichen und weiteren bunt zusammengemischten Zeichen angezeigt. Der "String" ist dann ca. 100 Zeichen lang.
-> Der EEPROM muss noch einmal auf NULL gesetzt werden, damit wieder alles richtig abgespeichert wird

Kann das damit zusammen hängen, oder steckt der Teufel in einem anderen Detail?

noiasca:
P.S.: ... bau das um und verabschiede dich von Strings. Wenn das RGB Farben sind, dann nimm die 3 Werte in 3 Byte.
Auch die Code-Duplikate für vorne unten oben lassen sich verbessern.

Das wird wohl der nächste Schritt werden, weil ich die Werte zum ansteuern der Mosfets sowieso als einzelne RGB-Werte brauche.
Bisher habe ich das als String gemacht, weil es so recht einfach ist das ganze Paket vom Handy zum Arduino zu schicken.
Im String sind:

  1. welches LED-Band
  2. Intensität/Helligkeit
  3. Rot-Anteil
  4. Grün-Anteil
  5. Blau-Anteil
    (6.) es soll noch ein Bit für "Ein" oder "Aus" dazu kommen

ich betone es noch mal: nutze ein char-array statt dem String Objekt am Uno.

Zum Einlesen der Seriellen: gib dir mal den Thread Serial Input Basics Serial Input Basics - updated - Introductory Tutorials - Arduino Forum

Die Werte würde ich mit Trennzeichen getrennt eingeben lassen und dann mittels strtok zerteilen und in die einzelnen Variablen übernehmen.

Okay, vielen Dank für den Tipp!
Ich werd's mir mal anschauen