Besoin de stocker durablement des valeurs en mémoire ? Alors rien de tel que l’EEPROM pour cela ! Mais nul besoin d’acheter d’eeprom externe à l’Arduino, car la plupart du temps, les Arduino sont équipés de mémoire eeprom en interne (quasiment tous les « modèles de base », en fait).
Ici, je vous propose de découvrir comment lire et écrire à l’intérieur de cette eeprom interne aux arduino, afin de sauvegarder vos données. Comme toujours, j’essayerai de vous mettre un maximum d’exemples et de commentaires, afin de vous compreniez bien comment se servir des eeprom en pratique !
Du reste, n’hésitez pas à poser vos questions en fin d’article. J’y répondrai dès que je pourrais, mais bien entendu, dans la limite du temps dont je dispose, et dans les limites de mes connaissances ! Ceci étant dit, commençons par une courte intro pour vous présenter les principales caractéristiques des eeprom arduino. C’est parti !
Intro : les caractéristiques de l’EEPROM interne aux microcontrôleurs ATmega
Avant de commencer, sachez que la mémoire EEPROM n’est qu’une des 3 mémoires généralement disponibles dans les microcontrôleurs ATmega (avec la mémoire Flash, et la mémoire SRAM). Et il ne faut surtout pas confondre la mémoire eeprom avec les deux autres, car chacune a un rôle bien spécifique. En effet :
- La mémoire EEPROM sert au stockage de données particulières, selon « vos désirs », car vous avez l’entière maîtrise de cet espace mémoire, qui vous « appartient »
- La mémoire FLASH, quant à elle, sert au stockage du programme arduino en lui-même (le code assembleur, si vous préférez)
- La mémoire SRAM, à l’image de la RAM de nos ordis, sert au stockage de variables temporaires, issue de l’exécution du programme contenu dans l’arduino
Au niveau des propriétés de cette mémoire EEPROM, on peut dire que :
- Elle permet de sauvegarder des données, du fait qu’elle ne perd pas ses valeurs après coupure d’alimentation (contrairement à la RAM, qui elle perd tout son contenu à chaque coupure de courant).
- Elle est totalement « personnalisable » et disponible pour soi. On ne la partage pas, avec qui que ce soit, contrairement aux mémoires flash ou ram, qui elles peuvent avoir des parties réservées à autre chose.
- Elle a une durée de vie d’environ 100.000 cycles en écriture (source Atmel ATmega328P). Au-delà, des dégradations/altérations peuvent apparaître au niveau des données. À noter toutefois que ce nombre de cycles d’écritures/effacements est toujours 10 fois meilleur que celui de la mémoire Flash, qui est donné pour 10.000 cycles seulement !
- Elle est plutôt lente, au niveau rapidité de fonctionnement, comparée aux deux autres types de mémoire (flash et ram).
Pour résumer, voici un tableau résumant ses différents avantages et inconvénients :
Avantages de l’EEPROM arduino |
---|
– Elle est totalement libre d’utilisation pour nous |
– Elle nous permet de sauvegarder des données « durablement » (du fait qu’elle n’est pas « effacée » lors de coupure de courant, comme c’est le cas avec la RAM) |
Inconvénients de l’EEPROM arduino |
---|
– Elle est lente, comparée à la mémoire flash ou sram |
– Elle a une durée de vie limitée (100.000 cycles d’écritures environ ; source : Atmel ATmega328P) |
Maintenant que nous avons vu ses propriétés, voyons voir quelle taille elle fait ! Et là en fait, tout est fonction du type de carte Arduino que vous utilisez (et plus précisément, de quel microcontrôleur figure sur cette carte arduino). Voici un autre tableau, vous détaillant tout cela :
Pour ma part, utilisant un Arduino Uno doté d’un ATmega328P, j’ai donc accès à 1 Ko de mémoire EEPROM (soit 1024 octets). Mais attention à ne pas vous méprendre, quant à cette taille. Car suivant le type de variable que vous voudrez stocker dedans, cette mémoire pourrait être remplie bien plus vite que vous ne le pensez. En effet :
- 1024 octets d’EEPROM = 1024 valeurs de 1 octet (de type byte / char / uint8_t / int8_t / boolean, par exemple)
- 1024 octets d’EEPROM = 512 valeurs de 2 octets (de type int / word / short / uint16_t / int16_t, par exemple)
- 1024 octets d’EEPROM = 256 valeurs de 4 octets (de type long / float / uint32_t / int32_t, par exemple)
- Ou… un mix de tout ça (de 1 à plusieurs octets), bien entendu, car vous êtes libre de stocker différents types de variables, comme ça vous chante (car au final, en arrière-plan, cela revient simplement à remplir des octets !)
Faites donc très attention à ne pas croire que 1024 octets d’EEPROM soit égal à 1024 variables stockables ! Parallèlement, comme c’est vous qui affectez chaque case mémoire à ce qui vous intéresse, n’oubliez jamais l’adresse à laquelle vous stockez chacune de vos données. Sinon, vous risquez d’avoir du mal à les retrouver, par la suite 😉
Le saviez-vous ? chaque « case mémoire » des eeprom de nos Arduino a une durée de vie d’environ 100 000 cycles d’écriture/effacement. Du coup, si vous créez un programme qui mémorise une valeur en EEPROM toutes les secondes, toujours à la même adresse, alors la case mémoire visée sera « morte » en moins de 2 jours ! En effet, 100.000 / (24×3600) = 1,15 jours (sachant qu’il y a 24 heures de 3600 secondes chacune, dans une journée). Bien sûr, votre eeprom ne sera pas « morte » en soi, mais son bon fonctionnement ne sera plus garantie à l’avenir. Du coup, veillez à ne pas trop abuser de la mémoire EEPROM, sinon celle-ci va vite défaillir !
La librairie EEPROM.h (bibliothèque arduino)
Afin de pouvoir lire et écrire dans l’eeprom interne aux arduino, nous allons nous servir de la librairie EEPROM.h, disponible dans l’IDE Arduino. Et pour faire appel à cette bibliothèque, rien de plus simple ! Car il suffit simplement d’écrire la ligne suivante, pour faire appel à elle :
#include <EEPROM.h>
Une fois fait, vous pourrez interagir avec la mémoire EEPROM de votre carte Arduino. Pour cela, vous disposez de tout un tas de fonctions, détaillées sur le site arduino.cc (consultable ici : https://www.arduino.cc/en/Reference/EEPROM, en anglais).
Au niveau des fonctions les plus couramment utilisées, on retrouve :
- La fonction « read » : pour lire 1 octet stocké dans l’eeprom, à une adresse donnée
- La fonction « write » : pour écrire 1 octet stocké dans l’eeprom, à une adresse donnée
- La fonction « update » : pour mettre à jour 1 octet présent dans l’eeprom (l’enregistrement de cette valeur ne se fera que si la valeur précédente est différente ; ceci permet d’éviter de consommer des « cycles d’écritures » inutilement, afin de préserver au maximum la durée de vie de l’EEPROM)
- La fonction « get » : pour lire tout type de variable primitive (byte, int, float, …) ou structure (de type « struct », donc), à partir d’une adresse donnée
- La fonction « put » : pour écrire une variable primitive (comme vu juste avant), ou de type struct, là encore à partir d’une adresse bien précise
À noter que cette bibliothèque Arduino n’a pas besoin d’être instanciée. Du coup, une fois que vous l’aurez appelé avec un « #include <EEPROM.h> », vous pourrez directement faire appel à ses fonctions : EEPROM.read, EEPROM.write, EEPROM.update, EEPROM.get, ou encore EEPROM.put, pour lire ou écrire en mémoire, tel que vu précédemment.
Par contre, gardez toujours en tête que vous devrez spécifier par vous-même l’adresse à laquelle vous voudrez lire ou écrire (allant de 0 à 1023, par exemple, pour un Arduino Uno). Du coup, si vous souhaitez par exemple enregistrer 3 valeurs en EEPROM, vous devrez choisir 3 adresses en mémoire, et les noter. Sinon, vous risquez fort de ne plus retrouver vos données, si jamais vous oubliez l’adresse de chacune d’elle 😉
Le saviez-vous ? Par défaut, toutes les cases mémoires EEPROM qui n’ont pas encore été utilisées ont la valeur 255. Elles ne sont donc pas initialement à 0, contrairement à ce qu’on aurait pu croire !
Voilà pour les généralités ! À présent, nous allons voir chacune de ces fonctions une par une, histoire de bien comprendre comment s’en servir. Alors en avant !
Comment lire une valeur en eeprom (avec read ou get) ?
Lire des valeurs dans la mémoire eeprom d’un Arduino n’est vraiment pas difficile en soi. Pour ce faire, la librairie EEPROM.h offre 3 possibilités :
- En utilisant l’instruction EEPROM.read
- En utilisant l’instruction EEPROM.get
- Ou en utilisant l’instruction EEPROM[] comme un tableau
En fait, ces trois instructions sont quasiment identiques. Mais une est plus « poussée » que les deux autres. Pour être plus précis :
- La commande EEPROM.read permet de lire 1 octet en mémoire (et pas plus)
- La commande EEPROM[] permet de faire exactement la même chose (tout en étant écrit plus « simplement »)
- La commande EEPROM.get, quant à elle, permet de lire tout type de variable primitive du langage arduino, s’étalant sur 1, 2, 3, 4, ou encore plus d’octets
Voici un tableau qui résume tout ça, visuellement :
Au niveau de la syntaxe d’appel dans un code arduino, voici comment utiliser EEPROM.read :
// Exemple pour lire la valeur contenue à l’adresse 14 de l’EEPROM de son Arduino
// avec la fonction EEPROM.read
#include <EEPROM.h>
int adresse = 14;
byte valeur;
void setup() {
Serial.begin(9600) ;
valeur = EEPROM.read(adresse); // Retourne la valeur contenue dans l'eeprom, à l’adresse "14"
Serial.print("Valeur à l’adresse ");
Serial.print(adresse);
Serial.print(" = ");
Serial.println(valeur);
}
void loop() {
}
C’est à peu près aussi simple, si vous souhaitez utiliser la librairie EEPROM comme un tableau :
// Exemple pour lire la valeur contenue à l’adresse 14 de l’EEPROM de son Arduino
// avec la fonction EEPROM[]
#include <EEPROM.h>
int adresse = 14;
byte valeur;
void setup() {
Serial.begin(9600);
valeur = EEPROM[adresse]; // Retourne la valeur contenue à l’adresse "14" de l’eeprom
Serial.print("Valeur à l’adresse ");
Serial.print(adresse);
Serial.print(" = ");
Serial.println(valeur);
}
void loop() {
}
Et enfin, la fonction EEPROM.get, quant à elle, permet d’aller bien plus loin :
// Exemple utilisant la fonction EEPROM.get pour
// - lire la valeur « INT » (2 octets) contenue à l’adresse 17 de l’EEPROM de son Arduino
// - lire la valeur « FLOAT » (4 octets) contenue à l’adresse 19 de l’EEPROM de son Arduino
#include <EEPROM.h>
int adresse1 = 17;
int valeur1;
int adresse2 = 19;
float valeur2;
void setup() {
Serial.begin(9600) ;
EEPROM.get(adresse1, valeur1); // Retourne la valeur INT contenue à l’adresse « 17 » de l’eeprom
EEPROM.get(adresse2, valeur2); // Retourne la valeur FLOAT contenue à l’adresse « 19 » de l’eeprom
Serial.print("Valeur à l’adresse "); Serial.print(adresse1); Serial.print(" = "); Serial.println(valeur1);
Serial.print("Valeur à l’adresse "); Serial.print(adresse2); Serial.print(" = "); Serial.println(valeur2);
}
void loop() {
}
Mais cette fonction « EEPROM.get » permet d’aller bien au-delà encore, en acceptant une structure complète de données. Voici un exemple, permettant de lire un « profil de personne » préalablement enregistré en mémoire eeprom :
// Exemple utilisant la fonction EEPROM.get pour lire un « profil de personne » en mémoire,
// stocké à partir de l’adresse 120, et contenant :
// - un champ pour un numéro identifiant (INT)
// - un champ pour le nom (CHAR, 20 caractères)
// - un champ pour l’âge (BYTE)
// - un champ pour mettre sa taille, exprimée en mètre (FLOAT) ; par exemple « 1,75 m »
#include <EEPROM.h>
int adresse = 120;
struct ProfilType {
int numero;
char nom[20];
byte age;
float taille;
};
void setup() {
Serial.begin(9600) ;
ProfilType monProfil;
EEPROM.get(adresse, monProfil);
Serial.print("Numero = "); Serial.println(monProfil.numero);
Serial.print("Nom = "); Serial.println(monProfil.nom);
Serial.print("Age = "); Serial.println(monProfil.age);
Serial.print("Taille = "); Serial.println(monProfil.taille);
}
void loop() {
}
Comme vous pouvez le voir, les possibilités sont vraiment bien plus étendues, avec la fonction GET. Par contre, pour rappel, n’abusez pas de la mémoire EEPROM à tout va, car celle-ci n’est « garantie » que pour une durée de vie d’environ 100.000 écritures par cellule, à l’intérieur. Au-delà, des dysfonctionnements vont potentiellement apparaître, et vos données risquent d’être corrompues. Donc n’abusez pas des bonnes choses 😉
Comment écrire une valeur en eeprom (avec write, update, ou put) ?
Maintenant que nous avons vu la partie lecture, vous allez voir que c’est la même chose en écriture, à peu de choses près. En fait :
- « write » remplace « read »
- « put » remplace « get »
- Et une instruction particulière, nommée « update » fera son apparition !
Plus précisément, voici chacune des fonctions permettant d’écrire en mémoire eeprom :
- La commande EEPROM.write permet d’écrire 1 octet en mémoire eeprom (et pas plus)
- La commande EEPROM[] permet également d’écrire un octet en mémoire (et pas plus)
- La commande EEPROM.put, quant à elle, permet d’écrire tout type de variable primitive du langage Arduino, pouvant s’étaler sur 1, 2, 3, 4, … ou bien plus d’octets encore !
- Et la commande EEPROM.update, qui, à peu de choses près, fait exactement la même chose que la fonction EEPROM.write (à ceci près qu’elle ne force pas la réécriture, si la valeur à enregistrer est identique à la valeur déjà présente en mémoire). Avec cette instruction, on évite de « consommer » des cycles d’écriture pour rien, si jamais les valeurs sont identiques (avant/après). Du coup, cela permet d’éviter de raccourcir la durée de vie de l’eeprom inutilement.
Voici d’ailleurs un tableau qui résume un peu tout ça, de manière synthétique :
Au niveau du code arduino, à présent, voici comment on peut utiliser la fonction EEPROM.write :
// Exemple pour écrire la valeur 125 à l’adresse 14 de l’EEPROM de son Arduino
// avec la fonction EEPROM.write
#include <EEPROM.h>
int adresse = 14;
byte valeur = 125;
void setup() {
EEPROM.write(adresse, valeur);
}
void loop() {
}
Sachez qu’on peut également simplifier l’écriture de ce programme, en remplaçant la ligne « EEPROM.write(adresse, valeur); » par la commande : « EEPROM[adresse] = valeur; ». À vous de voir ce qui vous plait le plus 😉
À présent, si on souhaite écrire plus d’un seul octet à la fois, la fonction EEPROM.put est idéale pour ça. Voici d’ailleurs un exemple, montrant comment vous servir de cette fonction :
// Exemple utilisant la fonction EEPROM.put pour
// - écrire la valeur « INT = 19500 » (2 octets) à l’adresse 17 de l’EEPROM de son Arduino
// - écrire la valeur « FLOAT = 85.68 » (4 octets) à l’adresse 19 de l’EEPROM de son Arduino
#include <EEPROM.h>
int adresse1 = 17;
int valeur1 = 19500;
int adresse2 = 19;
float valeur2 = 85.68;
void setup() {
EEPROM.put(adresse1, valeur1);
EEPROM.put(adresse2, valeur2);
}
void loop() {
}
Enfin, sachez qu’on peut également écrire tout un ensemble de données à la fois, en utilisant une structure de type « struct ». Ainsi, vous irez bien plus vite ! Voici un exemple permettant de faire cela :
// Exemple utilisant la fonction EEPROM.put pour stocker un « profil de personne » en mémoire,
// à partir de l’adresse 120, et qui contiendra :
// - un numéro identifiant (INT), égal à 1
// - un champ pour le nom (CHAR, 20 caractères), égal à "ABCD"
// - un champ pour l’âge (BYTE), égal à 42
// - un champ pour la taille, exprimée en mètre (FLOAT), égal à 1.75 m
#include <EEPROM.h>
int adresse = 120;
struct ProfilType {
int numero ;
char nom[20];
byte age;
float taille;
};
void setup() {
Serial.begin(9600) ;
ProfilType monProfil = {
1,
"ABCD",
42,
1.75f
};
EEPROM.put(adresse, monProfil);
Serial.println("Données bien enregistrées en mémoire EEPROM !");
}
void loop() {
}
Voilà ! Je pense que nous avons fait le tour complet de ce qui est faisable ici, pour écrire des valeurs dans la mémoire eeprom de votre Arduino. Il ne reste donc plus qu’à vous faire plaisir, en vous exerçant, puis en intégrant tout cela à vos futurs projets arduino 😉
Exemple d’affichage complet des cases mémoire EEPROM d’un Arduino Uno
J’en profite ici pour vous partager un petit programme que j’ai écrit. Celui-ci permet d’afficher l’intégralité de la mémoire EEPROM d’un Arduino Uno (mapping), sous forme de tableau, et dans le moniteur série de l’interface IDE Arduino. Bien entendu, ce programme n’a pas d’utilité particulière, si ce n’est didactique, ou pour bien visualiser l’intégralité de sa mémoire EEPROM (pour du débogage, par exemple).
Histoire d’être plus explicite, voici ce que ce programme affiche à l’écran, dans le cas de mon Arduino Uno :
Pour arriver à cela, voici les lignes de codes que j’ai écrit :
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_)
| [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___
| ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \
| | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___|
| |
\_|
Fichier: LectureCompleteMemoireEepromATmega328P.ino
Description: Affiche l'intégralité de la mémoire EEPROM d'un microcontrôleur ATmega328P sur le moniteur série
Auteur: Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le 28.05.2021
*/
#include <EEPROM.h>
void afficheNombreDecimalAvecEspaces(int valeur, byte nbreDeChiffres) {
switch(nbreDeChiffres) {
case 2:
if(valeur<10) Serial.print(" ");
break;
case 3:
if(valeur<10) Serial.print(" ");
if(valeur<100) Serial.print(" ");
break;
case 4:
if(valeur<10) Serial.print(" ");
if(valeur<100) Serial.print(" ");
if(valeur<1000) Serial.print(" ");
break;
default:
break;
}
Serial.print(valeur, DEC);
}
void setup() {
Serial.begin(9600);
Serial.println("=======================================================================");
Serial.println(" TABLEAU affichant les valeurs contenues dans la mémoire EEPROM ");
Serial.println(" d'un microcontrôleur ATmega328 (Arduino Uno, Nano, Pro mini) ");
Serial.println("=======================================================================");
Serial.println("");
Serial.println("Nota : toutes les valeurs sont affichées en décimal (0..255)");
Serial.println("");
byte lignes, colonnes;
// Affichage de l'entête (numéros de colonnes, de 0 à 15)
Serial.print(" \t");
for(colonnes = 0; colonnes < 16 ; colonnes++) {
afficheNombreDecimalAvecEspaces(colonnes, 3);
Serial.print(" ");
}
Serial.println("");
// Affichage du tableau en lui-même (avec adresse de la 1ère case mémoire, à chaque retour à la ligne)
for(lignes = 0; lignes < 64 ; lignes++) {
afficheNombreDecimalAvecEspaces(lignes*16, 4);
Serial.print("\t");
for(colonnes = 0; colonnes < 16 ; colonnes++) {
afficheNombreDecimalAvecEspaces(EEPROM.read(colonnes+lignes*16), 3);
Serial.print(" ");
}
Serial.println("");
}
// Affichage en dessous du tableau
Serial.println("");
Serial.print("Total = "); Serial.print(lignes*16); Serial.println(" cases mémoire lues");
}
void loop() {
}
Une fois uploadé, vous devriez obtenir un « beau » tableau s’affichant sur le moniteur série de votre IDE Arduino, vous montrant l’intégralité de la mémoire de votre microcontrôleur, comme visible ci-dessous :
=======================================================================
TABLEAU affichant les valeurs contenues dans la mémoire EEPROM
d'un microcontrôleur ATmega328 (Arduino Uno, Nano, Pro mini)
=======================================================================
Nota : toutes les valeurs sont affichées en décimal (0..255)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 125 255
16 255 44 76 41 92 171 66 255 255 255 255 255 255 255 255 255
32 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
48 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
64 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
80 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
96 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
112 255 255 255 255 255 255 255 255 1 0 65 66 67 68 0 0
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0
144 0 224 63 255 255 255 255 255 255 255 255 255 255 255 255 255
160 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
176 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
192 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
208 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
224 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
240 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
256 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
272 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
288 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
304 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
320 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
336 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
352 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
368 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
384 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
400 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
416 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
432 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
448 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
464 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
480 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
496 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
512 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
528 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
544 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
560 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
576 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
592 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
608 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
624 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
640 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
656 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
672 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
688 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
704 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
720 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
736 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
752 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
768 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
784 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
800 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
816 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
832 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
848 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
864 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
880 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
896 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
912 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
928 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
944 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
960 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
976 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
992 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
1008 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
Total = 1024 cases mémoire lues
À noter que j’ai écrit ce programme pour mon Arduino Uno (doté d’un microcontrôleur ATmega328P), possédant 1024 octets de mémoire EEPROM. Libre à vous d’adapter ce code de programmation à votre arduino, si ce dernier possède un nombre différent de cases mémoire (ici, j’avais 1 Ko à lire, d’où les 64 lignes à 16 colonnes, qui font bien 1024 « cases mémoire »).
Outre la fonction « afficheNombreDecimalAvecEspaces » qui fait essentiellement de la mise en forme, afin d’avoir un bel affichage au niveau des colonages, il n’y a rien de compliqué ici ! En fait, ce programme est ni plus ni moins qu’un exemple d’application de la partie « LECTURE en eeprom » vue plus haut 😉
Eeprom arduino : conclusion !
Voilà ! Vous en savez à présent suffisamment pour faire vos premiers pas avec la mémoire EEPROM de votre Arduino ! Il ne reste donc plus qu’à vous exercer, pour intégrer cette solution de stockage à vos futurs programmes ! Mais encore une fois, n’abusez pas trop des écritures en mémoire eeprom, car celles-ci ont une durée de vie limitée (comptez environ 100.000 cycles d’écritures « sûrs » par case mémoire, avant que l’eeprom ne commence à défaillir).
Du reste, comme toujours, n’hésitez pas à laisser vos commentaires sous cet article, ainsi que vos éventuelles questions. J’y répondrais dès que je le pourrais, et bien entendu, dans les limites de mes connaissances, et du temps dont je dispose. Dans tous les cas, à bientôt !
Jérôme.
À découvrir aussi : introduction aux timer arduino, avec exemples de code
(*) Mis à jour le 21/12/2021
Bonjour,
Permettez-moi de corriger une erreur sur la longévité des EEPROM. Les EEPROMs sont les mémoires non-volatiles les plus endurantes avec au minimum 1 million de cycles écriture/effacement et ensuite une bonne rétention. Les mémoires Flash sont au contraire 10 fois moins endurantes avec 100 000 cycles maximum et ensuite des risques sur la rétention des données.
Bonjour Filipe !
Oui, une erreur s’était effectivement glissée au niveau de mon comparatif « durée de vie mémoire EEPROM/mémoire FLASH », merci ! Car en effet, la mémoire flash est bien 10 fois moins endurante que la mémoire Eeprom.
Par contre, concernant le nombre d’écritures/effacements que l’on peut faire avec, tes chiffres ne correspondent pas à ce qui est publié par le fabricant Atmel, pour son microcontrôleur ATmega328P (équipant les Arduino Uno, Nano, …). En effet, comme indiqué en toute première page du datasheet de ce µC (accessible ici : datasheet ATmega328P), il est clairement spécifié ceci : « Write/erase cycles : 10,000 flash / 100,000 EEPROM ». Ce qui veut dire qu’on est limité ici à 10.000 écriture/effacement sur la mémoire flash (et non 100.000), et limité à 100.000 écritures/effacements sur la mémoire EEprom (et non 1.000.000 de cycles).
Voilà !
Jérôme.
Ce document est vachement bien foutu. Je cherche à stocker des données d’un instrument de mesure dans l’EEPROM. Ce document va me faire gagner quelques heures de découverte et de sueur. Merci.
Héhé, au plaisir !
Intéressant et très bien expliqué
Bonjour Jérôme !
Tout d’abord merci beaucoup pour ces explications qu’on ne retrouve nul part ailleurs !
J’ai toutefois un soucis (car nul en codage). Je dois, pour un projet d’architecture, installer mon arduino dans une pièce pour mesurer la température et l’humidité au fil de la journée (pour voir l’évolution des données avec le passage des étudiants, des ordinateurs qui chauffent, etc) dans le cadre d’une réhabilitation thermique du bâtiment.
J’ai donc pour l’instant un programme qui fonctionne et qui permet d’écrire sur le moniteur série les données de mes capteurs. Pour une question pratique, je dois écrire ces données sur la mémoire arduino pour pouvoir laisser mon dispositif dans la salle jour et nuit, et récupérer l’ensemble des données 1 ou 2 semaines après.
– Est-ce que la mémoire peut encaisser 2 semaines de données (prise d’information toutes les 30 minutes, soit 336 nombres) ?
– Si oui, comment intégrer mon programme au tient pour qu’il écrive dans la mémoire eeprom ? Je ne m’y retrouve pas malgré tes superbes explications.
– Et comment y avoir accès par la suite ?
Merci beaucoup d’avance, tu serais un sauveur !
Bonne journée à toi.
Salut Romain !
Alors, pour répondre à tes questions :
Maintenant, j’ai l’impression que ton problème n’est pas vraiment l’écriture du code en soi, mais plutôt de savoir comment organiser toute cette logique d’écriture et de relecture au besoin. Sans compter que tu dois te poser plusieurs questions au passage, du type : quand la mémoire sera-t-elle remise à zéro, comment indiquer à l’arduino lors de sa mise sous tension si c’est de l’enregistrement de données qu’on souhaite qu’il fasse ou de la relecture de ce qu’il y a en mémoire EERPOM, etc …
Pour répondre à ces questions, imagine toi d’abord comment toi, utilisateur, tu visualiserais l’ensemble. Y aura-t-il des boutons à appuyer pour lancer un enregistrement, pour accéder aux données enregistrées en mémoire EEPROM, pour effacer tout le contenu de cette mémoire ? Comment vois-tu tout cela ? Et une fois que tu auras visualisé cela, tu pourras concevoir un schéma électrique, puis enfin, coder le programme arduino qui répondra à tes besoins. Mais surtout : ne commence pas par écrire du code Arduino si tu ne sais pas déjà comment l’ensemble devra être articulé, et fonctionner !
Voilà … je pense que tu as là déjà matière à démarrer, donc à toi de jouer 😉
Bon courage.
Jérôme.
Bonjour Jérôme,
Merci pour ce tuto vraiment complet et très clair.
Est ce tu aurais à tout hasard, vu que tu semble bien maitriser le sujet, la même chose pour une Eeprom externe I2C genre 24LC16 …
Merci d’avance.
Alain
Salut Alain !
Non, malheureusement pas encore. Mais je me note à faire un sujet là dessus, dès que j’arriverai à me dégager plus de temps (ce n’est donc pas pour tout de suite, désolé …).
Par contre, garde bien à l’esprit que je ne suis pas un expert en EEPROM, mais seulement quelqu’un qui est passionné par l’électronique, et qui aime partager.
Sur ce, à bientôt !
Jérôme.
Ok,
C’est tout à ton honneur !
Alain
Bonjour, j’ai besoin de mémoriser au fil de l’eau des données sur la mémoire eeprom, mais j’ai 2 problèmes :
1°) Comment connaitre la dernière adresse utilisée (pour permettre l’utilisation de l’octet suivant disponible) si entre temps il y a eu un reset de l’arduino (peut-être enregistrer la dernière adresse utilisée, sur les 2 premiers octets de l’eeprom, mais dans ce cas, ces 2 premiers octets seront très sollicités). Ou existe-il une fonction qui permet de trouver la dernière adresse utilisée (bien sur hors programme au cause du cas reset) ?
2°) Comment fait on la différence entre la valeur 255 écrit en mémoire et la valeur par défaut ?
Salut !
Si tu veux uniquement travailler avec une mémoire EEPROM, et mémoriser l’emplacement de la dernière case mémoire modifiée, tu n’auras effectivement pas d’autre choix que de sauvegarder à un endroit précis de la mémoire (par exemple au début, comme tu proposes) l’adresse de cette dernière case modifiée. Sinon, comme tu l’as parfaitement bien compris, la moindre coupure de courant ou RESET te fera perdre l’adresse de cette dernière case mémoire EEPROM modifiée.
Par ailleurs, comme tu l’as également bien compris, il faudra faire attention au nombre de fois où tu modifieras les cases mémoires réservées au stockage de l’adresse de la dernière case EEPROM utilisée (car leur « durée de vie » est limitée). Maintenant, reste à savoir si celles-ci seront modifiées vraiment souvent, ou pas !
Du reste, à ma connaissance :
Sinon, si tu le souhaites, tu peux contourner le problème en stockant tes valeurs sur une carte SD, plutôt qu’en EEPROM. Pour te mettre sur la voie, tu peux reprendre mon tuto sur les cartes SD et Arduino. Mais reste à toi de compléter cela, pour arriver à tes fins 😉
Voilà ! Bon courage à toi.
Jérôme.
Très bien. Merci pour toutes ces précisions très claires.
Dans mon cas, je vais scanner la mémoire pour retrouver la première valeur 255 et faire en sorte que de ne jamais enregistrer cette valeur.
Merci encore pour la qualité de la réponse
De rien !
Afin de filtrer au maximum les messages de type "spam" ou "inappropriés", chaque commentaire est soumis à modération, et validé manuellement. Du coup, il se peut que certains commentaires ne soient pas publiés, ou sinon, avec un peu de retard. Par ailleurs, j'ai malheureusement plus de messages à traiter que de temps pour y répondre ; c'est pourquoi je ne pourrais pas répondre à tout le monde. Désolé …