Sauvegarder du texte en EEPROM

Bonjour à tous,

Je cherche à sauvegarder en EEPROM le nom d'un moteur en texte.
Je voudrais aussi pouvoir le modifier grace à une console série.
J'ai donc créé une structure dans laquelle j'ai quelques variables y compris celle pour le nom de mon moteur.
Mais lorsque je le liste après la sauvegarde (commande SW), ça me retourne n'importe quoi.
Par contre, le changement du nom (commande E TOTO) semble fonctionner.

Debug_StringToEeprom.ino (2.2 KB)

Pourriez vous m'indiquer la bonne solution ?
Merci par avance,

Super réveillon à vous tous,

Voici mon code qui fonctionne sur Uno ou autre.

Postez votre code ici entre balises de code on ne peut pas simplement lire le code sinon depuis un smartphone . (Je n’ai donc pas pu voir votre code).


Pour sauver du texte en eeprom faites une structure avec ce que vous voulez sauvegarder dedans et n’utilisez pas la classe String mais une cString de taille fixe (un tableau de char). Vous pourrez alors utiliser put et get sur la structure.

Bonne année 2025 !

Bonjour,

Je vous souhaites une très belle année 2025 ainsi qu'une bonne santé :slight_smile:
Voici mon code.

#include <EEPROM.h>

#include <SerialCommand.h>	//https://github.com/kroimon/Arduino-SerialCommand/tree/master
SerialCommand sCmd;

const byte tailleMax = 10+1; // 10 caractères max
struct MaStructure {
  uint8_t ENGINE_CH;
  uint8_t ENGINE_MODE;
  char ENGINE_SOUND[tailleMax];
  bool SMOKE_ONOFF;
  uint8_t SMOKETIMEOFF;
};

MaStructure ms;

#define PRINT_BUF_SIZE   100
static char PrintBuf[PRINT_BUF_SIZE + 1];
#define PRINTF(fmt, ...)    do{if(Serial){snprintf_P(PrintBuf, PRINT_BUF_SIZE, PSTR(fmt) ,##__VA_ARGS__);Serial.print(PrintBuf);}}while(0)

void setup()
{
  Serial.begin(115200);
  
  sCmd.addCommand("SW", writeSettings);
  sCmd.addCommand("S?", readAllEEprom);
  sCmd.addCommand("E", writeEngineName);
  sCmd.addCommand("R",resetEEPROM);

  sCmd.setDefaultHandler(unrecognized);

  EEPROM.get(0,ms);

}

void loop()
{
  sCmd.readSerial();     // We don't do much, just process serial commands
}

void writeEngineName()
{
  char *arg;
  arg = sCmd.next();    // Get the next argument from the SerialCommand object buffer
  strncpy(ms.ENGINE_SOUND, arg, tailleMax);
  Serial.print("Engine = ");Serial.println(ms.ENGINE_SOUND);
  EEPROM.put(0,ms);
}

void readAllEEprom()
{
  EEPROM.get(0,ms);// Read all EEPROM settings in one time

  Serial.print("Engine Name: ");Serial.print((char *)ms.ENGINE_SOUND);
  Serial.println(ms.ENGINE_MODE==1?" (Ship)":" (Plane)");
  PRINTF("EngineCh:    %d\r\n",ms.ENGINE_CH);
  Serial.print(ms.SMOKE_ONOFF?"Engine Smoke:On":"Engine Smoke:Off");
  PRINTF(" (Stop after: %ds)\r\n",ms.SMOKETIMEOFF);

}

void writeSettings()
{
  SettingsWriteDefault();
}

void SettingsWriteDefault()
{
  ms.ENGINE_CH  = 2;
  ms.ENGINE_MODE = 0;
  ms.SMOKE_ONOFF = false;
  ms.SMOKETIMEOFF = 3;
  strncpy(ms.ENGINE_SOUND, "VAPEUR", tailleMax);
  Serial.println("Saved !");
}

void resetEEPROM()
{
  for (int i = 0 ; i < EEPROM.length() ; i++) 
  {
    EEPROM.write(i, 0);
  }
  Serial.println("EEprom clear !")
}

// This gets set as the default handler, and gets called when no other command matches.
 void unrecognized(const char *command) {
   Serial.println("Unreconnized command !");
 }

Dans cette fonction

vous avez oublier d'appeler EEPROM.put(0,ms); :wink:


il manque un ; après cette commande


il y a quelques autres warning à corriger - voici un code qui doit être plus fonctionnel

#include <EEPROM.h>

#include "SerialCommand.h"  //https://github.com/kroimon/Arduino-SerialCommand/tree/master
SerialCommand sCmd;

const byte tailleMax = 10 + 1; // 10 caractères max
struct MaStructure {
  uint8_t ENGINE_CH;
  uint8_t ENGINE_MODE;
  char ENGINE_SOUND[tailleMax];
  bool SMOKE_ONOFF;
  uint8_t SMOKETIMEOFF;
};

MaStructure ms;

#define PRINT_BUF_SIZE   100
static char PrintBuf[PRINT_BUF_SIZE + 1];
#define PRINTF(fmt, ...)    do{if(Serial){snprintf_P(PrintBuf, PRINT_BUF_SIZE, PSTR(fmt) ,##__VA_ARGS__);Serial.print(PrintBuf);}}while(0)

void setup()
{
  Serial.begin(115200);
  sCmd.addCommand("SW", writeSettings);
  sCmd.addCommand("S?", readAllEEprom);
  sCmd.addCommand("E", writeEngineName);
  sCmd.addCommand("R", resetEEPROM);
  sCmd.setDefaultHandler(unrecognized);
  EEPROM.get(0, ms);
  Serial.println("Ready");
}

void loop()
{
  sCmd.readSerial();     // We don't do much, just process serial commands
}

void writeEngineName()
{
  char *arg;
  arg = sCmd.next();    // Get the next argument from the SerialCommand object buffer
  strncpy(ms.ENGINE_SOUND, arg, tailleMax);
  Serial.print("Engine = "); Serial.println(ms.ENGINE_SOUND);
  EEPROM.put(0, ms);
}

void readAllEEprom()
{
  EEPROM.get(0, ms); // Read all EEPROM settings in one time

  Serial.print("Engine Name: "); Serial.print((char *)ms.ENGINE_SOUND);
  Serial.println(ms.ENGINE_MODE == 1 ? " (Ship)" : " (Plane)");
  PRINTF("EngineCh:    %d\r\n", ms.ENGINE_CH);
  Serial.print(ms.SMOKE_ONOFF ? "Engine Smoke:On" : "Engine Smoke:Off");
  PRINTF(" (Stop after: %ds)\r\n", ms.SMOKETIMEOFF);

}

void writeSettings()
{
  SettingsWriteDefault();
}

void SettingsWriteDefault()
{
  ms.ENGINE_CH  = 2;
  ms.ENGINE_MODE = 0;
  ms.SMOKE_ONOFF = false;
  ms.SMOKETIMEOFF = 3;
  strncpy(ms.ENGINE_SOUND, "VAPEUR", tailleMax);
  EEPROM.put(0, ms);
  Serial.println("Saved !");
}

void resetEEPROM()
{
  for (size_t i = 0 ; i < EEPROM.length() ; i++)
  {
    EEPROM.write(i, 0);
  }
  Serial.println("EEprom clear !");
}

// This gets set as the default handler, and gets called when no other command matches.
void unrecognized(const char *command) {
  Serial.print("Unreconnized command: ");
  Serial.println(command);
}

Je n'ai pas modifié mais notez qu'à la fin de votre setup vous faites

Généralement on insère aussi en EEPROM un mot magique qui dit si la mémoire a déjà été initialisée. Si c'est le cas on fait le get, sinon on charge les valeurs par défaut dans la structure et on fait un write puis on écrit le mot magique afin que les données soit initialisées correctement la première fois. ça évite de lire n'importe quoi depuis l'EEPROM. par exemple il se pourrait que vous chargiez dans votre chaîne ENGINE_SOUND des données sans le caractère nul de fin et ensuite quand vous essayez de l'imprimer ça fera n'importe quoi et ira lire d'autres données en mémoire.


sinon si vous utilisez le mot magique, au lieu de mettre 0 pour l'adresse mémoire EEPROM, créez des constante par exemple

const uint16_t adresseMotMagique = 0;
const uint16_t adresseParametres = adresseMotMagique + sizeof motMagique;
const uint32_t motMagique = 0xDEADBEEF;

et utilisez cela.

  EEPROM.put(adresseMotMagique, motMagique);
  EEPROM.put(adresseParametres, ms);

(ou une autre façon est de mettre le mot magique dans la structure comme premier élément. Si quand vous lisez la structure vous ne trouvez pas le mot magique, ça veut dire que les autres éléments ne sont pas corrects)

1 Like

D'autant que l'EEPROM est initialisée par défaut à 0xFF donc il n'y aura pas de terminateur de chaine.

Merci pour votre aide :slight_smile:
En recopiant mon code, j'avais omit la variable du mot magique car la sauvegarde ne se faisant pas (oubli du EEPROM.put(0,ms) , du coup, je l'avais viré.
Et oui, je test cette variable dans le setup.

Je test ça et vous tiens au courant :slight_smile:

Toul fonctionne merci et encore bonne année :slight_smile:

parfait

amusez vous bien

Bonjour JML,

Une petite question, comment puis-je savoir quelle est la dernière adresse utilisée en EEPROM par ma structure ?

Bonjour

Vous prenez l’adresse du début de sauvegarde et ajoutez sizeof(la structure) et vous avez l’adresse du premier octet libre après la structure (donc enlever 1 pour avoir l’adresse du dernier octet)

l’opérateur sizeof donne le nombre d’octets utilisé par une variables ou un type

Merci beaucoup :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.