Pour jouer des mélodies avec un piezo buzzer, je devais stocker sur un Arduino Nano une douzaine de tableaux de char représentant les notes à émettre, les rythmes, etc. Seulement voilà, j’ai rencontré cet obstacle de mémoire insuffisante, que j’ai pu résoudre en utilisant le modificateur de variable PROGMEM fourni avec la librairie pgmspace.
Types de Mémoire d’un ATmega328P
Un Arduino est en fait une plateforme qui permet de facilement connecter des extensions aux pins d’un micro-controler. Un peu comme les prises de courant dans votre maison, reliées au disjoncteur.
Ce tableau de contrôle, dans le cas d’un Arduino nano, c’est le micro-contrôleur ATmega328P. A noter: la différence entre ATmega328P et ATmega328 est ce petit « P » qui signifie « Pico-power ». En d’autres termes, cette version va coûter un peu plus cher mais consommera moins de courant. Pratique.
Le micro-controler ATmega328P possède une mémoire pour stocker les instructions, mais pas que. Voici ses différentes mémoires du nano :
- Mémoires non volatiles (conservées en cas d’arrêt de l’alimentation)
- Mémoire Flash: Aussi appelée mémoire programme, c’est là où est stocké le programme (le code)
- EEPROM: Stockage d’information long-terme
- Mémoire volatile (vidée en cas d’arrêt de l’alimentation)
- SRAM (Static Random Access Memory): Mémoire où les variables sont créées et manipulée lorsque le programme est lancé
Capacité de mémoire
Un arduino nano aura une capacité de mémoire non volatile relativement faible, mais sa mémoire volatile est plus sympa !
- Flash: 32 kBytes
- EEPROM: 1024 bytes
- SRAM: 2048 bytes
Mémoire insufisante: PROGMEM et pgmspace.h
Lorsque j’ai joué avec des mélodies RTTTL, j’ai du stocker des tableaux de char énormes déclaré à même le code du programme. L’Arduino les stock dans la mémoire Flash, réservée pour les variable. Voici le message d’erreur que j’obtenais :
Le croquis utilise 13576 octets (44%) de l’espace de stockage de programmes. Le maximum est de 30720 octets.
Les variables globales utilisent 6776 octets (330%) de mémoire dynamique, ce qui laisse -4728 octets pour les variables locales. Le maximum est de 2048 octets.
Mémore insuffisante.
Plus haut nous avons remarqué que si la mémoire SRAM où sont stockées les variables du programme est petite (2048bytes), la mémoire flash, elle, est assez énorme en comparaison (32kBytes). 16x plus grande. Alors utilisons-là grâce au modificateur de variable PROGMEM. Il va aller forcer les variables à rester dans la mémoire programme (la mémoire Flash) au lieu de la mémoire SRAM.
Pour l’utiliser, vous aurez besoin d’importer la bibliothèque pgmspace.h. Elle est inclue dans les dernières version des IDE, mais si vous avez un doute importez-la:
#include <avr/pgmspace.h>
Puis, pour utiliser PROGMEM, il faut respecter cette syntaxe: const dataType variableName[] PROGMEM = {data0, data1, data3…};
Par exemple:
const char songStarwars[] PROGMEM = "starwars:d=4,o=5,b=180:8f,8f,8f,2a#.,2f.6,8d#6,8d6,8c6,2a#.6,f.6,8d#6,8d6,8c6,2a#.6,f.6,8d#6,8d6,8d#6,2c6,p,8f,8f,8f,2a#.,2f.6,8d#6,8d6,8c6,2a#.6,f.6,8d#6,8d6,8c6,2a#.6,f.6,8d#6,8d6,8d#6,2c6";
Vous aurez alors stocké ce tableau dans la mémoire Flash au moment du boot de l’arduino au lieu de la mémoire :
Le croquis utilise 13574 octets (44%) de l’espace de stockage de programmes. Le maximum est de 30720 octets.
Les variables globales utilisent 672 octets (32%) de mémoire dynamique, ce qui laisse 1376 octets pour les variables locales. Le maximum est de 2048 octets.
Aller plus loin
Adafruit à réaliser un article complet si vous souhaitez aller plus en détail sur les types d’architectures et l’usage de la mémoire: https://learn.adafruit.com/memories-of-an-arduino