Comment stocker de manière permanente des données sur votre Arduino

bannière

Apprenez à utiliser l’EEPROM interne de votre Arduino et comment ajouter de la mémoire supplémentaire pour stocker des données de manière permanente.

  • MATÉRIAUX
  • PROJET

MATÉRIEL

  • arduino
  • 24LC16B

Certaines cartes Arduino vous permettent de stocker en permanence des données dans une EEPROM sans avoir à garder la carte branchée. Cet article vous apprendra comment écrire dans l’EEPROM intégrée (si votre Arduino en possède une) et vous présentera une méthode alternative qui vous permettra pour utiliser la mémoire externe. 

Vous pouvez utiliser ce guide pour n’importe quel microcontrôleur prenant en charge la communication via le bus I2C.

Cartes Arduino prises en charge

Le tableau suivant répertorie la quantité de données que chaque MCU peut stocker :

Tableau - Combien de données les cartes Arduino peuvent stocker

Interfacer l’EEPROM intégrée

EEPROM signifie Mémoire morte programmable effaçable électroniquement. Bien que vous puissiez écraser les données sur la puce, vous ne pouvez le faire qu’un nombre limité de fois avant qu’elle ne commence à mal fonctionner. Cependant, vous pouvez le lire autant de fois que vous le souhaitez.

La méthode Write()

L’exemple suivant illustre comment stocker un octet.

#include <EEPROM.h>

void setup()
{
    int word_address = 0;
 
    EEPROM.write(word_address, 0x7F);
}

void loop()
{ }

Utilisez la méthode write() avec une adresse de mot et la valeur que vous souhaitez stocker. L’adresse doit être une valeur comprise entre zéro et EEPROM.length()-1 et elle indique au MCU où stocker la valeur.

La méthode read()

L’exemple suivant lit un octet de l’EEPROM :

#include <EEPROM.h>

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

    int word_address = 0;
    byte value;
 
    value = EEPROM.read(word_address);
 
    Serial.println(value, HEX);
}

void loop()
{ }

La méthode read() prendra également une adresse comme paramètre et renverra la valeur sous forme d’octet.

Effacer la mémoire

Pour effacer la mémoire, stockez un zéro à chaque position de l’EEPROM :

void erase(void)
{
    for (int i = 0 ; i < EEPROM.length() ; i++)
        EEPROM.write(i, 0);
}

Un exemple de « Hello World »

Le code suivant effacera l’EEPROM puis stockera « Hello World ! » dedans avant d’écrire la chaîne sur la console :

#include <EEPROM.h>

void erase(void)
{
  for (int i = 0 ; i < EEPROM.length() ; i++)
	EEPROM.write(i, 0);
}

void printMessage(byte* first, size_t len)
{
  for (int i = 0; i < len; i++)
  {
	Serial.print((char)first[i]);
  }
}

void writeMsg(byte* first, size_t len)
{
  for(int i = 0; i < len; i++)
  {
	EEPROM.write(i, first[i]);
  }
}

void readMsg(size_t len)
{
  byte res;
 
  Serial.print("Message: ");
  for(int i = 0; i < len; i++)
  {
	res = EEPROM.read(i);
	Serial.print((char)res);
  }
  Serial.println("");
}

void setup()
{
  char* string = "Hello World!";
 
  Serial.begin(9600);
 
  Serial.print("Serial connection opened!\n");
  Serial.print("EEPROM length: ");
  Serial.println(EEPROM.length());
 
  Serial.print("Attempting to erase EEPROM... ");
  erase();
  Serial.print("Done!\n");
 
  Serial.print("Message: ");
  printMessage(string, 12);
  Serial.print("\n");
 
  Serial.print("Attempting to write to EEPROM...\n");
  writeMsg(string, 12);
  Serial.print("Done!\n");
  Serial.print("Attempting to read from EEPROM...\n");
  readMsg(12);
  Serial.print("Done!\n");
}

void loop()
{ }

Utilisation d’une EEPROM externe

Si vous n’utilisez pas d’Arduino ou si vous souhaitez disposer d’un espace de stockage supplémentaire, vous pouvez utiliser un circuit intégré EEPROM externe pour stocker les octets. Dans cet exemple, nous utiliserons le 4LC16B  (PDF), qui est une EEPROM I2C de 16 Ko.

Le circuit est simple et il vous suffit d’ajouter une résistance de rappel de 100 K et de connecter le circuit intégré à l’Arduino (ou à tout autre MCU que vous souhaitez utiliser) :

Ajout d'un CI EEPROM externe pour stocker des octets

Schéma de circuit pour ajouter l’EEPROM externe 4LC16B à un Arduino.

La septième broche de ce circuit intégré est un indicateur de protection en écriture. Connectez cette broche à GND si vous souhaitez écrire dans la mémoire. S’il est élevé, la puce ne sauvegardera aucune donnée. La lecture est possible quel que soit l’état du pin.

Communiquer avec la mémoire externe

La configuration de la communication entre l’Arduino et la mémoire externe est l’endroit où les choses deviennent plus compliquées par rapport à la mémoire intégrée. 

La fiche technique du CI 4LC16B décrit précisément comment communiquer avec lui pour stocker des données. J’ai écrit ce sketch pour vous permettre d’interfacer un mot (ou un octet) sur l’EEPROM externe. Je l’ai testé avec la variante 16 Ko mais il devrait fonctionner avec toutes les autres tailles (de ce fabricant) à condition que la communication fonctionne de la même manière :

#include <Wire.h>

static const byte DEVICE_BASE_ADDRESS = 0x50;

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

byte readByteFromEEPROM(byte block, byte word_offset)
{
   Wire.beginTransmission(block);
   Wire.write(int(word_offset));
   Wire.endTransmission(true);
  
   Wire.requestFrom(int(block), 1);
  
   if (Wire.available())
   	return Wire.read();
}

void readBlockFromEEPROM(byte block, byte outArray[256])
{
  for(int i = 0; i < 256; i++)
  {
	outArray[i] = readByteFromEEPROM(block, i);
  }
}

void readPageFromEEPROM(byte block, byte word_offset, byte outArray[16])
{
  for(int i = 0; i < 16; i++)
  {
	outArray[i] = readByteFromEEPROM(block, word_offset + i);
  }
}

void writeByteToEEPROM(byte block, byte word_offset, byte data)
{
  writePageToEEPROM(block, word_offset, &data, 1);
}

/**
 * block:
 * 0x50 = first block = DEVICE_BASE_ADDRESS
 * 0x51 = second block
 * ...
 * 0x57 = eight block
 */

void writePageToEEPROM(byte block, byte word_offset, byte *data, size_t len)
{
  Wire.beginTransmission(block);
  Wire.write(word_offset);
 
  for(int i = 0; i < len; i++)
  {
	Wire.write(data[i]);
  }
 
  Wire.endTransmission(true);
  delay(10);
}

La mémoire est organisée en huit blocs de 256 octets et chaque bloc peut être directement adressé. Le DEVICE_BASE_ADDRESS (0x50) représente le premier et 0x57 représente le dernier bloc.

Différentes puces ont également des adresses de base différentes. Référez-vous à la fiche technique de votre EEPROM et mettez à jour le code si nécessaire.

Un autre exemple de « Hello World »

Ce programme stockera « Hello World » dans la première page du premier bloc sur l’EEPROM externe, puis lira l’intégralité du premier bloc et l’imprimera sur la console :

void printBlock(byte blockContent[256])
{
  for(int i = 0; i < 16; i++)
  {
	Serial.print("Page ");
	
	if(i+1 < 10)
  	    Serial.print("0");
  	
	Serial.print(i+1);
	Serial.print(": ");
	
	for(int u = 0; u < 16; u++)
	{
   	    Serial.print((char)blockContent[i*16+u]);
   	
   	    if(u==7)
      	        Serial.print(" ");
	}
	
           Serial.println("");
  }
}

void loop()
{
  byte result[256];
  writePageToEEPROM(DEVICE_BASE_ADDRESS, 0, "Hello World!", 12); 
  readBlockFromEEPROM(DEVICE_BASE_ADDRESS, result);
  printBlock(result);
  delay(20000);
  exit(0);
}

L’exécution de cet exemple vous donnera le résultat suivant (ou quelque chose de similaire selon le contenu de votre EEPROM) :

exécuter hello world sur votre EEPROM externe

Comprendre l’EEPROM est important pour les débutants

Ce projet super simple est parfait pour les débutants qui souhaitent en savoir plus sur la mémoire et les communications I2C (et pour tous ceux qui souhaitent améliorer leurs prouesses en matière de création) car il vous permet de stocker en permanence des informations sur votre Arduino (ou autre MCU) même sans alimentation. 

Savoir comment stocker les informations rend vos projets mobiles et vous donne également la certitude que les parties les plus importantes de votre projet sont stockées, que votre carte soit branchée au secteur ou non.

A lire également

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *