Hallo,
ich habe ein Problem mit laden von Werten aus dem Controller EEprom. Es funktioniert erst mit dem 2. Aufruf der Funktion. Der erste Aufruf liefert Datenmüll aus dem EEprom. Ich weiß nicht warum. Kann mir bitte jemand helfen?
Das ist Terminal gesteuert.
Eigentlich sollen nach Reset 3 Werte aus dem EEprom in den RAM geladen/übernommen werden. dataEEprom/dataRAM.
Das macht die Funktion loadValuesFromEEpromInRAM() die man auch mit dem Befehl 'load' aufrufen kann.
Alle aktuellen Werte im EEprom und RAM kann man sich mit dem Befehl 'read' anzeigen lassen.
Mit dem Befehl 'save' kann einen der 3 Werte einzeln ins RAM übernehmen und mit "y/Y" Bestätigung wird das ins EEprom gespeichert. Das funktioniert soweit.
Bsp.
save 1 111
save 2 222
save 3 333
Mein Problem ist das das laden der Werte nach Reset nicht wie gewünscht funktioniert. Warum nur?
Es ist auch egal ob die EEprom Startadresse auf 0 oder bspw. auf 20 steht.
Im EEprom stehen 111, 222 und 333.
LOAD nach Reset
uC Reset ### ### ###
EEPROM.length: 4096
aktuell im EEprom > A:3724541952 B:1291845632 C:4278190081
aktuell im RAM > A:3724541952 B:1291845632 C:4278190081
Werte vom EEprom in den RAM geladen.
Eingelesen: load
Länge: 4
Debug: rxCommand: 'load' countCharacter: 4
aktuell im EEprom > A:111 B:222 C:333
aktuell im RAM > A:111 B:222 C:333
Werte vom EEprom in den RAM geladen.
READ nach Reset
uC Reset ### ### ###
EEPROM.length: 4096
aktuell im EEprom > A:3724541952 B:1291845632 C:4278190081
aktuell im RAM > A:3724541952 B:1291845632 C:4278190081
Werte vom EEprom in den RAM geladen.
Eingelesen: read
Länge: 4
Debug: rxCommand: 'read' countCharacter: 4
aktuell im EEprom > A:111 B:222 C:333
aktuell im RAM > A:3724541952 B:1291845632 C:4278190081
Alles mit der Standard Arduino IDE 1.8.16 und original Arduino Mega2560.
Ideen?
/*
Arduino IDE 1.8.16
Arduino Mega 2560
13.11.2021
*/
#include <Streaming.h>
#include <EEPROM.h>
constexpr bool DEBUG {false};
constexpr uint8_t BUFFER_SIZE_COMMAND {5};
constexpr uint8_t BUFFER_SIZE_VALUE {20};
constexpr uint8_t BUFFER_SIZE {BUFFER_SIZE_COMMAND + BUFFER_SIZE_VALUE};
struct ReceiveData
{
char buffer [BUFFER_SIZE + 3]; // + zwei Leerzeichen + Null-Terminator
char command [BUFFER_SIZE_COMMAND + 1]; // + Null-Terminator
uint8_t valueFirst;
uint32_t valueSecond;
};
ReceiveData rx;
struct sensorDaten
{
const int16_t startAddr {20};
uint32_t sensorA {0};
uint32_t sensorB {0};
uint32_t sensorC {0};
};
sensorDaten dataEEprom;
sensorDaten dataRAM;
// --------------------------------------------------------
void setup (void)
{
Serial.begin(9600);
Serial.println(F("\nuC Reset ### ### ###"));
pinMode(LED_BUILTIN, OUTPUT);
Serial.print(F("EEPROM.length: "));
Serial.println(EEPROM.length() );
loadValuesFromEEpromInRAM(Serial);
Serial.println();
}
void loop (void)
{
if (readSerial(Serial, rx.buffer, sizeof(rx.buffer)))
{
findCommand(Serial, rx.buffer, sizeof(rx.buffer));
}
heartbeat(500);
}
// ****** Funktionen ****************************** //
// Sucht die n'te nummerische Zeichkette (num) in der übergegeben Zeichenkette (ptrString) und liest ab da
// solange wie es Digits sind bzw. bis die maximal übergebene Zeichenanzahl (maxDigits) erreicht ist.
// Die gefunden nummerischen Zeichen werden in einen Integer gewandelt und zurückgegeben.
uint32_t findValueFromString (char *ptrString, byte num, const uint8_t maxDigits)
{
/*
input: pointer to a char array
return: an integer number from the string (positive numbers only!)
num=1, returns 1st number from the string
num=2, returns 2nd number from the string, and so on
*/
uint8_t countDigits {0};
char *ptrEnd {nullptr};
char numberChain [BUFFER_SIZE_VALUE + 1];
while (num > 0)
{
num--;
// skip non-digits
while ( (!isdigit(*ptrString)) && (*ptrString != 0) )
{
if (DEBUG) {
Serial << F("Debug0: ") << F("ptrString: zeigt auf addr: ") << ((uint16_t) ptrString)
<< F(" Inhalt: ") << ptrString << endl;
}
ptrString++;
}
if (DEBUG) {
Serial << F("Debug1: ") << F("ptrString: zeigt auf addr: ") << ((uint16_t) ptrString)
<< F(" Inhalt: ") << ptrString << endl;
}
ptrEnd = ptrString;
countDigits = 0;
// find digits
while ( (isdigit(*ptrEnd)) && (*ptrEnd != 0) && (countDigits < maxDigits) )
{
numberChain [countDigits] = (*ptrEnd);
if (DEBUG) {
const uint8_t var = (*ptrEnd)-48;
Serial << F("Debug2: ") << F("countDigits: ") << countDigits << F(" var: ") << var << endl;
Serial << F("Debug3: ") << F("ptrEnd: zeigt auf addr: ") << ((uint16_t) ptrEnd)
<< F(" Inhalt: ") << ptrEnd << endl;
}
ptrEnd++;
countDigits++;
}
numberChain [countDigits] = '\0';
if (num > 0) ptrString = ptrEnd; // new search string is the string after that number
}
if (DEBUG) {
Serial << F("Debug4: ") << F("ptrEnd: zeigt auf addr: ") << ((uint16_t) ptrEnd)
<< F(" Inhalt: ") << ptrEnd << endl;
Serial << F("Debug5: ") << F("countDigits: ") << countDigits << endl;
Serial << F("Debug6: ") << F("numberChain: ") << numberChain << endl;
}
ptrEnd = numberChain;
return (strtoul(numberChain, &ptrEnd, 10));
}
// Sucht nach Buchstaben in der übergegeben Zeichenkette (ptrString) und liest ab da
// solange wie es Buchstaben sind bzw. bis die maximal übergebene Zeichenanzahl (maxChars) erreicht ist.
// Die gefundene Zeichenkette wird dem char buffer 'rx.command' übergeben.
// Zurückgegeben wird die Länge der gefundenen Zeichenkette.
uint8_t findCommandFromString (char *ptrString, const uint8_t maxChar)
{
uint8_t index {0};
// find alphas
while ( (isalpha(*ptrString)) && (*ptrString != 0) && (index < maxChar) )
{
rx.command[index] = (*ptrString);
if (DEBUG) {
Serial << F("Debug7: ") << F("ptrString: zeigt auf addr: ") << ((uint16_t) ptrString)
<< F(" Inhalt: ") << ptrString << endl;
}
index++;
ptrString++;
}
if (DEBUG) {
Serial << F("Debug8: ") << F("ptrString: zeigt auf addr: ") << ((uint16_t) ptrString)
<< F(" Inhalt: ") << ptrString << endl;
}
rx.command[index] = '\0';
return index;
}
void findCommand (Stream &out, char *buffer, const uint8_t LENGTH)
{
out << F("Eingelesen: ") << buffer << endl;
out << F("Länge: ") << strlen(buffer) << endl;
const uint8_t countCharacter = findCommandFromString (buffer, BUFFER_SIZE_COMMAND);
out << F("Debug: ") << F("rxCommand: '") << rx.command << F("' countCharacter: ") << countCharacter << endl;
// ****** LOAD & 4 ************
if ( (countCharacter == 4) && (strstr(buffer, "load") == buffer) )
{
loadValuesFromEEpromInRAM (out);
}
// ****** READ EEPROM/RAM & 4 ************
else if ( (countCharacter == 4) && (strstr(buffer, "read") == buffer) )
{
readValuesFromEEprom (out);
readValuesFromRAM (out);
}
// ****** SAVE & 4 ************
else if ( (countCharacter == 4) && (strstr(buffer, "save") == buffer) )
{
rx.valueFirst = findValueFromString (buffer, 1, BUFFER_SIZE_VALUE);
rx.valueSecond = findValueFromString (buffer, 2, BUFFER_SIZE_VALUE);
out << F("save erkannt &") << F(" rx.valueFirst: ") << rx.valueFirst
<< F(" rx.valueSecond: ") << rx.valueSecond << endl;
if ( (rx.valueFirst > 0) && (rx.valueFirst < 4) )
{ // Übernahme der Benutzereingabe in den RAM
switch (rx.valueFirst)
{
case 1: dataRAM.sensorA = rx.valueSecond; break;
case 2: dataRAM.sensorB = rx.valueSecond; break;
case 3: dataRAM.sensorC = rx.valueSecond; break;
default: break;
}
readValuesFromEEprom (out);
readValuesFromRAM (out);
out.println(F("save RAM to EEprom? [Y/N]"));
// warten auf Benutzereingabe
while ( !readSerial(out, buffer, LENGTH) )
{ ; }
const uint8_t c = findCommandFromString (buffer, BUFFER_SIZE_COMMAND);
if ( (c == 1) && ( (strstr(buffer, "y")) || (strstr(buffer, "Y")) == buffer) )
{ // Wert vom RAM in den EEprom speichern
switch (rx.valueFirst)
{
case 1: dataEEprom.sensorA = dataRAM.sensorA; break;
case 2: dataEEprom.sensorB = dataRAM.sensorB; break;
case 3: dataEEprom.sensorC = dataRAM.sensorC; break;
default: break;
}
EEPROM.put(dataEEprom.startAddr, dataEEprom);
out.println(F("Wurde im EEprom gespeichert."));
readValuesFromEEprom (out);
readValuesFromRAM (out);
}
else {
out.println(F("Es wurde nichts im EEprom geändert."));
}
}
else {
out.println(F("Erster Wert ist ungültig."));
}
}
else
{
out.println(F("Befehl unbekannt."));
}
out.println();
}
void readValuesFromRAM (Stream &out)
{
out << F("aktuell im RAM >")
<< F(" A:") << dataRAM.sensorA
<< F(" B:") << dataRAM.sensorB
<< F(" C:") << dataRAM.sensorC << endl;
}
void readValuesFromEEprom (Stream &out)
{
EEPROM.get(dataEEprom.startAddr, dataEEprom);
out << F("aktuell im EEprom >")
<< F(" A:") << dataEEprom.sensorA
<< F(" B:") << dataEEprom.sensorB
<< F(" C:") << dataEEprom.sensorC << endl;
}
void loadValuesFromEEpromInRAM (Stream &out)
{
readValuesFromEEprom(out);
dataRAM.sensorA = dataEEprom.sensorA;
dataRAM.sensorB = dataEEprom.sensorB;
dataRAM.sensorC = dataEEprom.sensorC;
readValuesFromRAM(out);
out.println(F("Werte vom EEprom in den RAM geladen."));
}
bool readSerial (Stream &stream, char *buffer, const uint8_t LENGTH)
{
static byte index {0};
bool status {false};
while (stream.available())
{
char c = stream.read();
if (c == '\n') // wenn LF eingelesen
{
buffer[index] = '\0'; // Terminierung
index = 0;
status = true; // Character fertig eingelesen
}
else if ( (c >= 32) && (index < LENGTH) ) // wenn noch Platz im Buffer ist
{
buffer[index++] = c; // Zeichen speichern und Index inkrementieren
}
}
return status;
}
void heartbeat (const unsigned long interval)
{
static unsigned long lastMillis {0};
static bool state {false};
if (millis() - lastMillis >= interval)
{
lastMillis += interval;
state = !state;
digitalWrite(LED_BUILTIN, state);
}
}