Enregistrer et récupérer 2 données différentes en Eeprom

Bonjour, J'ai trouvé une multitude de post décrivant comment sauvegarder une donnée en Eeprom, mon soucis est d'en sauvegarder 2 différentes.
En l'occurence, dans le programme test ci dessous, Compteur et valeur.
Si je créer une seconde ligne EEPROM.put (adEeprom+1, valeur); et idem en lecture, le programme se bloque à la mise en service. De même si je crée (adEeprom1, valeur) . en affectant adEeprom1 à l'adresse 1.
Tel qu'il est édité, je récupère bien le compteur, je tourne en rond pour faire de même avec la valeur.

type#include <EEPROM.h>                          // bibliothèque EEprom
#include <simpleBouton.h>                    // bibliothèque de gestion des entrées

simpleBouton SW1 = 4;
simpleBouton SW2 = 5;
simpleBouton SW3 = 6;
simpleBouton SW4 = 7;
const unsigned adEeprom = 0;                 // mémoire adresse EEprom compteur
int compteur = 0;
int valeur = 0;

void powerLoss()                            // fonction appelée si coupure courant
{
  EEPROM.put (adEeprom, compteur);
}
void setup ()
{ Serial.begin(9600);
  EEPROM.get(adEeprom, compteur);            // relecture EEprom
  pinMode (SW1, INPUT);
  pinMode (SW2, INPUT);
  pinMode (SW3, INPUT);
  pinMode (SW4, INPUT);
}


void loop()
{ attachInterrupt(digitalPinToInterrupt(3), powerLoss, FALLING);     // exécution enregistrement EEprom


  SW1.actualiser();
  SW2.actualiser();
  SW3.actualiser();
  SW4.actualiser();

  if (SW1.vientDEtreEnfonce())
  { compteur++;
    Serial.println(compteur);
  }

  if (SW2.vientDEtreEnfonce())
  { compteur--;
    Serial.println(compteur);
  }

  if (SW3.vientDEtreEnfonce())
  { valeur++;
    Serial.println(valeur);
  }

  if (SW4.vientDEtreEnfonce())
  { valeur--;
    Serial.println(valeur);
  }
}
 or paste code here

Tu mets des int en mémoire. Ils occupent 2 deux octets chacun. Ici, tu n'as que la moitié de ta variable.

Tu ferais mieux d'utiliser les méthode put() et get() de la librairie qui savent lire et écrire n'importe quel type de donnée. Ceci dit il faut quand même que tu gères correctement l'adresse à laquelle tu places tes données. Si ce sont des int il faut faire avancer l'adresse de 2 en 2.

Bonjour vangel
Le moyen le plus simple de sauver plusieurs variables, de type différent, est de les mettre dans une structure, structure que tu sauves avec un EEPROM.put et que tu relis avec un EEPROM.get.
Ainsi plus de soucis d'adresse si ce n'est celle de départ.

Voici ton programme adapté:

#include <EEPROM.h>                          // bibliothèque EEprom
//#include <simpleBouton.h>                    // bibliothèque de gestion des entrées

//simpleBouton SW1 = 4;
//simpleBouton SW2 = 5;
//simpleBouton SW3 = 6;
//simpleBouton SW4 = 7;
const unsigned adEeprom = 0;                 // mémoire adresse EEprom compteur

struct donneesDef // Définition de la structure
{
	int compteur = 0;
	int valeur = 0;	
};
donneesDef donnees;  // Création des données

void powerLoss()                            // fonction appelée si coupure courant
{
	EEPROM.put (adEeprom, donnees);  // Sauvegarde de la structure
}
void setup ()
{ 
	Serial.begin(9600);
	
	EEPROM.get (adEeprom, donnees);  // Restitution de la structure

	Serial.println("Compteur " + String(donnees.compteur));
	Serial.println("Veleur " + String(donnees.valeur));

	donnees.compteur = 145;
	donnees.valeur = 53;

	//pinMode (SW1, INPUT);
	//pinMode (SW2, INPUT);
	//pinMode (SW3, INPUT);
	//pinMode (SW4, INPUT);
	powerLoss();
}


void loop()
{ 
	attachInterrupt(digitalPinToInterrupt(3), powerLoss, FALLING);     // exécution enregistrement EEprom


	//SW1.actualiser();
	//SW2.actualiser();
	//SW3.actualiser();
	//SW4.actualiser();

	//if (SW1.vientDEtreEnfonce())
	//{ compteur++;
		//Serial.println(compteur);
	//}
//
	//if (SW2.vientDEtreEnfonce())
	//{ compteur--;
		//Serial.println(compteur);
	//}
//
	//if (SW3.vientDEtreEnfonce())
	//{ valeur++;
		//Serial.println(valeur);
	//}
//
	//if (SW4.vientDEtreEnfonce())
	//{ valeur--;
		//Serial.println(valeur);
	//}
}

Cordialement
jpbbricole

Comme nous ne connaissons pas la cible et même si l'on connait la taille d'un int, il est préférable d'incrémenter/décrémenter les adresses au moyen d'un sizeof(int)

De plus, cela permet une portabilité du code entre un UNO (int sur 2 octets) et un ESP32 (int sur 4 octets) par exemple

A suivre...

1 Like

Merci Claudius pour cette piste, le code repris ainsi suivrait-il ton idée?

#include <EEPROM.h>                          // bibliothèque EEprom
#include <simpleBouton.h>                    // bibliothèque de gestion des entrées

simpleBouton SW1 = 4;              
simpleBouton SW2 = 5;             
simpleBouton SW3 = 6;
simpleBouton SW4 = 7;
const unsigned adEeprom = 0;                 // mémoire adresse EEprom compteur
int compteur = 0;
int valeur = 0;

void powerLoss()                            // fonction appelée si coupure courant
{
  EEPROM.put (adEeprom,compteur);
  EEPROM.put (sizeof(compteur),valeur);}        
void setup ()
{ Serial.begin(9600);
  EEPROM.get(adEeprom,compteur);                    // relecture donnée compteur
  EEPROM.get(sizeof(compteur),valeur);              // relecture donnée valeur
    
  pinMode (SW1,INPUT);
  pinMode (SW2,INPUT);
  pinMode (SW3,INPUT);
  pinMode (SW4,INPUT); }


void loop()
{   attachInterrupt(digitalPinToInterrupt(3), powerLoss, FALLING);     // exécution enregistrement EEprom

  
    SW1.actualiser();
    SW2.actualiser();
    SW3.actualiser();
    SW4.actualiser(); 
    
  if (SW1.vientDEtreEnfonce()) 
   {compteur++; 
   Serial.println(compteur);}  

   if (SW2.vientDEtreEnfonce()) 
   {compteur--;  
   Serial.println(compteur);}
   
   if (SW3.vientDEtreEnfonce()) 
   {valeur++;  
    Serial.println(valeur);}
    
   if (SW4.vientDEtreEnfonce()) 
   {valeur--;  
    Serial.println(valeur);}}

Bonjour JPbbricole, Merci pour cette réponse plus complète que je n'osait espérer.
D'autant que si je comprends bien, cette structure permet d'y insérer davantage de données. Dans quelle limite d'ailleurs?
Cordialement.
Vangel

Bonsoir vangel

Oui, tu peux mélanger des int, long, float, char...
A ne pas utiliser que pour sauver des données en EEPROM, mais également pour gérer les variables d'un programme, par exemple, pour traiter un servo, créer une structure servo par ex, contenant toutes ses variables nécessaires comme angleDebut, angleFin et on écrira ensuite servo.angleDebut = 12 servo.angleFin = 90.
Avec l'autocomplétion, ça rend l'écriture plus aisée, en autres avantages.

Aucune idée :woozy_face:

Les structure, à ne surtout pas éviter :wink:

Bonne soirée
jpbbricole

Le seul limite est la mémoire disponible.
Il est aussi possible d'insérer une autre structure.
Autant pour deux variables l'utilité est relativement limité, mais sur un nombre conséquent de variable, c'est très intéressant.

Oui, c'est l'idée, par contre du coup ta variable adEeprom, ne sert plus à rien.

adEeprom = 0;
EEPROM.get(adEeprom, compteur);
adEeprom += sizeof(compteur);
EEPROM.get(adEeprom, valeur);

Bien sûre si tu n'a que deux variables, c'est comme la structure, l'utilisation d'une variable avec l'adresse est peu utile, mais si au cours de ton développement, tu as besoin d'une troisième et d'une quatrième variable, cela devient très utile.

Même si on n'en a que deux, l'intérêt est de grouper ce qui va ensemble d'un point de vue "conceptuel". Si vous voulez décrire un servo, comme le dit @jpbbricole, vous allez pouvoir grouper le N° de pin qui pilote le servo, le Servo lui même, l'angle min et max, la vitesse de déplacement si on la pilote, ... Si vous voulez décrire une personne, vous allez mettre le nom, le prénom, la date de naissance, l'adresse, ...

Un autre avantage des structures est que l'on peut intégrer des fonctions travaillant sur la structure et un constructeur pour initialiser la structure. (on se rapproche alors très fortement de la notion de classe).

Quand on veut écrire une structure en EEPROM cependant, Il faut bien comprendre que certains types ne sont pas compatibles. Par exemple si vous mettez une String dans une structure, ça ne va pas fonctionner car le type String contient un pointeur sur des données (le texte) qui sont ailleurs en mémoire. Si on archive la structure contenant la String, on va archiver la valeur du pointeur mais pas le texte.

Oui, c'est exactement le cas que j'évoque finalement, dans le cas que tu décris, on a plus que deux variables.
Je ne vois toujours aucun intérêt de regrouper deux variables qui se batte en duel dans une structure, un simple nommage commun suffit.
Le seul intérêt serait de ne pas se soucier de décaler l'adresse dans l'EEPROM pour la seconde variable, mais encore une fois, l'utilité est très relative.

Tu bien fait de la rappeler car c'est un gros "inconvénient" de la structure qui peut engendrer des bug assez traite.

Si vous voulez un tableau de positions par exemple latitude et longitude, c’est plus parlant de faire

struct Position {
  double latitude;
  double longitude;
};

Position waypoints[20];

Que

double waypoints[20][2];

A mon avis (et en plus avec la possibilité d’embarquer des fonctions).

Mais je suppose que vous voulez dire que si le code ne nécessite qu’une seule latitude et longitude alors ce n’est pas la peine ? Oui ça se discute, tout dépend du besoin dans le code. On peut facilement copier une structure dans une autre, passer ou retourner une structure par une fonction, impossible de retourner 2 variables d’un coup sans les mettre en référence ou pointeur dans la liste des paramètres par exemple ou comme dans le cas présent c’est plus simple de mettre en EEPROM en un seul appel toute la structure.

(Un exemple si vous voulez une fonction qui retourne le point au milieu de deux positions latitude et longitude, la structure rendra la fonction plus lisible.)

Bonjour,

Très intéressant la solution d'utiliser "plusieurs variables élémentaires" vs "une structure", structure que j'utilise dans la pratique dans le but de préserver la durée de vie l'EEPROM pour écrire dans une EEPROM mais malheureusement, nous n'avons pas de nouvelles de vangel et notamment si cela à répondu à son problème; à savoir:

... le programme se bloque à la mise en service ...

A suivre...

Oui, c'est exactement ça, l'utilité est relativement limité :slight_smile:
Tu auras remarqué que je ne dis pas qu'il ne faut pas l'utilisé, mais bien que son utilité dans le cas présenté est relativement limité.

Oui, la structure à une pléthore de cas ou elle peut être utile.
Mais encore une fois, dans le cas et le code de @vangel on est loin de tous ça et même pour la sauvegarde l'utilité est plus que discutable.

OK

oui on peut faire sans même pour la sauvegarde. L'intérêt de la structure est quand même que les débutants ne se plantent pas sur les adresses mémoire puisqu'il n'y en a qu'une à gérer :slight_smile:

Oui, c'est clair que pour les débutants c'est un tracas en moins, même si sizeof permet de ne pas trop se poser de questions.

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