concat 2 chars to uint8_t

Hallo,
wieder mal ein Problem, um Strings zu vermeiden.
Ich lese auf einem ESP32 aus dem Eeprom 2 byte. Dort sind Zahlen als Text gespeichert. Das ist zwar Speicherverschwendung, geht aber momentan (noch) nicht anders.
Diese sollen zu einer Zahl verknüpft werden.
Wie komme ich zum Ziel?

uint8_t EepromReadInt8(uint16_t StartAddress, uint8_t defaultValue = 0) {
  char lowByte = (char)EEPROM.read(StartAddress);
  char highByte = (char)EEPROM.read(StartAddress + 1);

  Serial.print("lowByte: ");
  Serial.println(lowByte); // = 2
  Serial.print("highByte: ");
  Serial.println(highByte); // = 5

  uint8_t result = 0;
  .
  .

  return result; // soll in diesem Fall 25 zurück geben
}

Mache einen C-string draus (ungetestet):

char arr[3];
arr[0] = highChar;
arr[1] = lowChar;
arr[2] = '\0';
int i = atoi(arr);

Gruß Tommy

auch wenn die Bezeichnung lowByte / highByte etwas verwirrend ist:

uint8_t EepromReadInt8(uint16_t StartAddress, uint8_t defaultValue = 0) {
  char lowByte = (char)EEPROM.read(StartAddress);
  char highByte = (char)EEPROM.read(StartAddress + 1);

  Serial.print("lowByte: ");
  Serial.println(lowByte); // = '2'
  Serial.print("highByte: ");
  Serial.println(highByte); // = '5'

  

  uint8_t zehner = lowByte - '0'; // BinärWerte
  uint8_t einer   = highByte - '0';
  uint8_t result = zehner*10 + einer;
  
  return result;
}

Wie üblich: Ungetesteter Code ohne Fehlerbehandlung, kann noch weiter vereinfacht werden :slight_smile:

@Tommy56
funktioniert, THX

@michael_x
probiere ich gleich noch aus

Hab jetzt Variante 2 so zusammengefasst:

return ((uint8_t)((char)EEPROM.read(StartAddress) - '0') * 10 + (uint8_t)((char)EEPROM.read(StartAddress + 1) - '0'));

funktioniert, kommt 25 raus.
Ist das C-technisch in Ordnung?

Ist das C-technisch in Ordnung?

ja klar.
Ergibt natürlich Mist, wenn im EEPROM nicht das Erwartete ('0' ... '9') steht,
aber das ist ja hier nicht die Frage

@TO: Schau Dir doch mal die EEPROM-Lib an, besonders die Methoden get und put. Damit kannst Du Zahlen problemlos speichern und lesen.

Gruß Tommy

@Tommy56
Ich baue nach und nach Alles auf Preferences um. Da werden die Daten auch dauerhaft gespeichert.

Wenn ich das richtig verstanden habe, emuliert der ESP32 das EEPROM. Funktioniert...
Du kannst dir aber auch mal die Preferences ansehen.

Kurz zusammenkopiert:

#include <Preferences.h>

Preferences* MyPreferences1;                        
MySettings::MyPreferences1 = new Preferences();
MyPreferences1->begin("Settings", false);

Conf_Light_UP = MyPreferences1->getBool("Light_UP", Conf_Light_UP);
Conf_Light_UP_FLASHES = MyPreferences1->getUInt("Light_UP_FL", Conf_Light_UP_FLASHES);
MyPreferences1->getBytes("AP_SSID", (char*) Conf_AP_SSID, sizeof(Conf_AP_SSID) );

Edit: Da warst du schneller :slight_smile:

Der Ansatz mit weniger Strings ist schon mal sau geil

Der Sketch verwendet 955002 Bytes (72%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
Globale Variablen verwenden 42640 Bytes (13%) des dynamischen Speichers, 285040 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes.

Vorher waren es 971966 Bytes verwendeter Programmspeicherplatz.
Der Platz für lokale Variablen hat sich auch um ein paar 100 Bytes vergrößert.

Mal abwarten, wann der wdt meckert und einen Reboot auslöst, weil kein genügend großer Block mehr im RAM verfügbar ist. Das passierte bisher so alle 3-4 Tage.

freddy64:
weil kein genügend großer Block mehr im RAM verfügbar ist. Das passierte bisher so alle 3-4 Tage.

Verwendest du String Objekte (Arduino String) ?

Hi

Wenn man den 'Block' einfach da lässt, wo Er - zumindest zum Anfang - Seinen Platz gefunden hat und nur leert?
Dann muß auch kein neuer Platz gesucht werden, wo das Trumm an String hin muß (oder Array oder was weiß ich denn).
Also static oder global wäre mein Vorgehen.

MfG

@freddy64: Grundsätzlich kommt man ohne die Klasse String aus.

Wenn es dann doch sein muss, solltest Du Dir mal die Methode String.reserve(länge) anschauen.
Mit der kannst Du im Setup den Speicher für die maximallänge reservieren, da wird weniger fragmentiert.

Gruß Tommy

Der Asynchrone Webserver arbeitet viel mit Strings.
Jetzt habe ich aber gesehen, dass die Klasse AsyncWebServerRequest 2 Funktionen hat:

  const String& arg(const String& name) const; // get request argument value by name
  const String& arg(const __FlashStringHelper * data) const; // get request argument value by F(name)

Also alle requests von request->arg("value") in request->arg(F("value")) geändert.
Evtl hilft das schon etwas weiter.

Die Strings der AsyncWebServerResponses verändern ständig ihre Größe, da viele AJAX-Anfragen rein kommen und die Antworten des Servers dann immer unterschiedlich ausfallen (Sensorwerte, Relay-Zustände, Uhrzeit....).

Mal abwarten, wie sich die Sache jetzt verhält.
ESP.getFreeHeap() zeigt immer über 228000 bytes an. Trotzdem startet der ESP aus bisher noch unbekannten Gründen alle paar Tage neu. Das ist zwar nicht so tragisch, da die Konfiguration im Eeprom gespeichert ist und der Server sofort nach dem Neustart alle vorherigen Zustände wieder herstellt.

Das nenne mal eine Anleitung für die Verwendung von char[] und char* an Stelle dieser speicherfressenden Strings.