Stockage d'une structure dans l'EEPROM

Bonjour,
Je suis en train d’apprendre à utiliser l’EEPROM d’un Arduino Nano pour un petit projet dont le but est de stocker une donnée quotidiennement sur 2 années glissantes mais je rencontre de petites difficultés : Les résultats obtenus ne sont pas ceux attendu.
Je souhaite stocker une structure constituée de 2 tableaux de taille 365 contenant des entiers et une variable entière :

struct MaStructure
{
  int TabYear[365];
  int TabPreviousYear[365];
  int NumJour;
};

Dans le setup je rempli mes tableaux et ma variable :

for (int i=0;i<365;i++)
  {
    ms.TabYear[i]=i;
    ms.TabPreviousYear[i]=i;
  }
ms.NumJour=5;

Et je stocke la structure dans l’EEPROM :

EEPROM.put(0,ms);

Dans la loop je récupère le contenu de ma structure

MaStructure ms_lue;

  EEPROM.get(0,ms_lue);

Puis j’affiche le résultat :
  Serial.print("jour : ");
  Serial.println(ms_lue.NumJour);
  Serial.println("************************");
  delay(2000);
  
  for (int i=0;i<50;i++)
  {
    Serial.print("Tab1 : valeur ");
    Serial.print(i);
    Serial.print("-> ");
    Serial.println(ms_lue.TabYear[i]);
    delay(1000);
  }
  for (int i=0;i<50;i++)
  {
    Serial.print("Tab2 : valeur ");
    Serial.print(i);
    Serial.print("-> ");
    Serial.println(ms_lue.TabPreviousYear[i]);
    delay(1000);
  }
  
  Serial.println("************************");
  delay(2000);

Et là j’ai des aberrations :

  • Ma variable NumJour me renvoi bien 5. Ca c’estOK
  • Mon 2eme tableau me renvoie les bonnes valeur : par ex ms.TabPreviousYear[5]=5 ; ms.TabPreviousYear[100]=100 ….. La aussi pas de soucis
  • Mais je rencontre des problèmes sur le premier tableau : il y a comme un décallage
    o ms_lue.TabYear[0]=217
    o ms_lue.TabYear[1]=218
    o …..
    o ms_lue.TabYear[149]=0
    o ms_lue.TabYear[150]=1
    o .....

J'ai essayé d'initialiser l'EEPROM avant de stocker ma structure mais ça ne change rien
Qu'est ce que j'ai raté ?
Merci pour votre aide.

Voici le programme au complet :

#include<EEPROM.h>

struct MaStructure
{
  int TabYear[365];
  int TabPreviousYear[365];
  int NumJour;
};

void setup() {
  Serial.begin(9600);

  // Initialisation de l'EEPROM
  for (unsigned int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  MaStructure ms;
  
  for (int i=0;i<365;i++)
  {
    ms.TabYear[i]=i;
    ms.TabPreviousYear[i]=i;
    ms.NumJour=5;
  }
  
  EEPROM.put(0,ms);
  
  delay(3000);

}

void loop()
{
  MaStructure ms_lue;

  EEPROM.get(0,ms_lue);
 
  Serial.print("jour : ");
  Serial.println(ms_lue.NumJour);
  Serial.println("************************");
  delay(2000);
  
  for (int i=0;i<50;i++)
  {
    Serial.print("Tab1 : valeur ");
    Serial.print(i);
    Serial.print("-> ");
    Serial.println(ms_lue.TabYear[i]);
    delay(1000);
  }
  for (int i=0;i<50;i++)
  {
    Serial.print("Tab2 : valeur ");
    Serial.print(i);
    Serial.print("-> ");
    Serial.println(ms_lue.TabPreviousYear[i]);
    delay(1000);
  }
  
  Serial.println("************************");
  delay(2000);
}

Dans ta structure tu stockes

  • un tableau de 365 entier soit 730 octets
  • un second tableau de 365 entier soit 730 octets
  • un entier soit 2 octets
    Soit un ensemble de 1462 octets.
    L'EEPROM intégrée dans un ATmega328 a une capacité de 1024 octets.
    Donc il y a une erreur de casting.
    Il faudrait réduire la quantité de données à stocker ou travailler avec une EEPROM externe.

Si tu changeais ta structure en un tableau de structures ?

struct MaStructure
{
 int Year;
 int PreviousYear;
 int NumJour;
};
MaStructure MaStructure[365];

Tu stockes ensuite comme ceci :

MaStructure[i].Year

Ensuite

EEPROM.put(0,MaStructure);

et pour lire l'indice k, tu vas à l'adresse qui va bien : k*sizeof MaStructure

EDIT : la remarque de fdufnews est pertinente ! Il faut peut-être stocker des bytes au lieu de int, ou passer sur un ESP8266/ESP32 pour plus de mémoire

Je suis en train d'apprendre à utiliser l'EEPROM d'un Arduino Nano pour un petit projet dont le but est de stocker une donnée quotidiennement sur 2 années glissantes mais je rencontre de petites difficultés : Les résultats obtenus ne sont pas ceux attendu.

une carte SD serait peut-être plus appropriée s'il y a trop de données

Merci pour vos réponses rapides.

Je ne sais pas pourquoi, je m'étais mis en tête que j'avais 2048 octets dispo
Forcément, ça dépend, ça dépasse :confused:

Je préférerais éviter d'utiliser un lecteur de carte SD.
j'essaye de faire un projet minimaliste.
Cette partie est vraiment la cerise sur le gâteau.
Effectivement les ESP ouvrent plus de possibilités.
Je les ai découvert récemment et suis déjà converti mais il faut bien que j'utilise la dizaine de nano que j'ai en stock :slight_smile:
Une bonne alternative serait bien une EEPROM externe

Dans un premier temps je ne vais stocker qu'un seul tableau en mémoire. Le second ne me servira que dans 1 an après tout !
D'ici là j'aurai eut le temps de m'équiper et de faire évoluer le projet

Encore merci !!

Suivant le type de données à stocker tu peux compresser les informations pour qu'elles occupent moins de place en mémoire.
Par exemple, si les valeurs d'un jour à l'autre sont assez proches, tu pourrais ne stocker que la différence avec le jour précédent si tu es certain que celle-ci peut tenir sur un octet. Ainsi, pour simplifier le dépouillement des données, tu pourrais tout les 10 ou 20 jours sauver une valeur complète et les autres jours seulement la différence.

Il y a aussi une lacune dans ton système. Il y a des années avec 366 jours.

clarifiez ce que vous capturez. est-ce que ça a besoin d'être sur un int?

watxm:
Je les ai découvert récemment et suis déjà converti mais il faut bien que j'utilise la dizaine de nano que j'ai en stock :slight_smile:

Fais toi un collier...

fdufnews:
Suivant le type de données à stocker tu peux compresser les informations pour qu'elles occupent moins de place en mémoire.
Par exemple, si les valeurs d'un jour à l'autre sont assez proches, tu pourrais ne stocker que la différence avec le jour précédent si tu es certain que celle-ci peut tenir sur un octet. Ainsi, pour simplifier le dépouillement des données, tu pourrais tout les 10 ou 20 jours sauver une valeur complète et les autres jours seulement la différence.

Interessant.
En fait mon projet consiste à relevé la capacité journalière d'une citerne à eau de pluie (capacité max 10600 L).
Mais ce volume est calculé à partir d'une distance (utilisation de capteurs ultrason).
Au lieu de stocker le résultat je pourrai peut être stocker la mesure initiale et refaire le calcul lors de l'exploitation et si ça ne suffit pas, effectivement n'enregistrer que la différence qui sera effectivement faible d'un jour à l'autre

fdufnews:
Il y a aussi une lacune dans ton système. Il y a des années avec 366 jours.

Oui je sais mais je vais faire avec. De plus j'ai 4 ans pour voir venir :slight_smile:

J-M-L:
clarifiez ce que vous capturez. est-ce que ça a besoin d'être sur un int?

Comme dis au-dessus j’étais parti pour stocker des entiers de 0 à 10600
Je vais essayer avec des décimales de 0.0 à 180.0
Mais si on peut faire mieux en convertissant, je suis preneur.
Comment peut-on convertir ces données en bytes par exemple ?
Et cela fera t il gagner de la place ?

Merci

qu'est-ce que retourne le capteur ? une distance en cm ? si elle fait moins de 255 vous stocker cela sur un seul octet. comme vous le dites vous pouvez toujours refaire les calculs pour afficher l'info

Oui une distance en cm mais au dixième. Donc utilisation d'un float ce qui n'arrange pas le stockage :confused:

watxm:
Oui une distance en cm mais au dixième.

Avec un capteur ultrason, je pense que le dixième est dans le bruit de mesure. Est-ce vraiment pertinent?

Je suppose qu’en fonction de cela vous estimez un volume et donc cette distance influence un truc au cube (puissance 3). Quelle est la précision sur la mesure de la cuve (qui ne doit pas être un cube parfait) ? Est-ce critique pour l’historique ?

J-M-L:
Je suppose qu’en fonction de cela vous estimez un volume et donc cette distance influence un truc au cube (puissance 3).

S'il mesure un niveau dans une cuve (supposée indéformable), le volume est plutôt linéaire (ou presque) en fonction du niveau.
Mais la question sur la précision réalistement recherchée reste pertinente.

bonjour
10600L / 256 =~42L ; à savoir si une précision de 42L est suffisante ?

fdufnews:
Avec un capteur ultrason, je pense que le dixième est dans le bruit de mesure. Est-ce vraiment pertinent?

Quand je parle du dixième, je parle d'un chiffre après la virgule et non d'une tolérance de
0.1. J'estime à 0.5 cm mon besoin de précision.
Quant au bruit, j'ai 2 capteurs. Chacun fait 100 relevés que je moyennise.
Enfin, je calibre chaque capteur par un coef correcteur que j'évalue tous les 5 cm (la cuve était vide la semaine dernière, j'en profite pour mesurer physiquement chaque jour et appliquer la correction)

J-M-L:
Je suppose qu’en fonction de cela vous estimez un volume et donc cette distance influence un truc au cube (puissance 3). Quelle est la précision sur la mesure de la cuve (qui ne doit pas être un cube parfait) ? Est-ce critique pour l’historique ?

Il faut que je regarde l'incidence , mais utiliser la racine cubique peut être aussi une approche. Merci pour le tuyau