Skip to Content

Contrôler les animations Parola sur un afficheur LED MAX7219

Contrôler les animations Parola sur un afficheur LED MAX7219

Dans ce tutoriel, vous allez apprendre à contrôler les animations Parola sur un écran à matrice LED MAX7219. Nous allons enchaîner des animations, utiliser des boutons pour changer d’animation et des potentiomètres pour ajuster la luminosité et la vitesse des animations.

La bibliothèque MD_Parola est une bibliothèque populaire qui facilite la programmation d’animations sur un écran, comme un texte défilant. Alors que la mise en place d’une animation unique est simple, il peut être plus difficile d’enchaîner ou de contrôler plusieurs animations. De plus, il est souvent utile de lire des données de capteurs sans interrompre l’animation. Ce tutoriel va vous montrer comment faire.

Pièces nécessaires

J’ai utilisé un Arduino Uno pour ce projet, mais n’importe quelle autre carte Arduino, ou une carte ESP8266/ESP32, fonctionnera tout aussi bien. Ici, nous utilisons un écran à matrice LED MAX7219 composé de 4 modules. Mais le code et le câblage pour des écrans avec plus ou moins de modules sont essentiellement les mêmes.

Écran à matrice LED MAX7219 

Arduino

Arduino Uno

Dupont wire set

Jeu de fils Dupont

Half_breadboard56a

Breadboard

USB Data Sync cable Arduino

Câble USB pour Arduino UNO

Bouton-poussoir

Potentiomètre 10KΩ

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Connexion de l’écran LED MAX7219 avec Arduino

Dans ce tutoriel, nous allons utiliser un écran à matrice LED MAX7219 pour afficher des animations. Le contrôleur d’affichage MAX7219 communique avec l’Arduino via SPI (Serial Peripheral Interface). Donc, la première chose à faire est de connecter l’écran à l’Arduino en utilisant l’interface SPI.

Câblage

Le schéma suivant vous montre le câblage nécessaire entre l’écran MAX7219 et un Arduino Uno. Assurez-vous de vous connecter au côté entrée (DIN) et non à la sortie (DOUT) de l’écran.

Connecting MAX7219 Display to Arduino UNO
Connexion de l’écran MAX7219 à l’Arduino UNO

Commencez par connecter les broches de l’interface SPI : la broche 11 de l’Arduino est reliée à la broche DIN de l’écran. Ensuite, connectez la broche 3 à CS et la broche 13 à CLK. Enfin, connectez le 5V à VCC et GND à GND. Le tableau suivant récapitule les connexions :

Écran Arduino
VCC 5 V
GND GND
DIN 11 (MOSI)
CS 3 (SS)
CLK 13 (SCK)

Les broches choisies ci-dessus sont pour le SPI matériel, qui est plus rapide que le SPI logiciel mais nécessite d’utiliser des broches spécifiques qui varient selon la carte. Pour plus de détails, consultez la MAX7219 LED dot matrix display Arduino tutorial .

Ensuite, écrivons et lançons un code de test pour vérifier que les connexions sont correctes.

Installer les bibliothèques MD_Parola et MD_MAX72XX

Tout d’abord, nous devons installer la MD_MAX72XX et la MD_Parola bibliothèque. Vous pouvez installer ces bibliothèques via le gestionnaire de bibliothèques de l’ Arduino IDE . Allez dans Tools > Manage Libraries pour ouvrir le gestionnaire de bibliothèques. Cherchez « MD_MAX72XX » et les bibliothèques concernées apparaîtront. Dans la capture d’écran ci-dessous, vous pouvez voir que j’ai déjà installé les deux bibliothèques (en jaune) :

Install MD_MAX72XX and MD_Parola library
Installer MD_MAX72XX et MD_Parola bibliothèque

La bibliothèque MD_MAX72XX est essentiellement le pilote logiciel pour l’écran LED MAX7219. Et la bibliothèque MD_Parola l’utilise pour créer des animations comme le texte défilant ou des effets de sprite. Si vous voulez en savoir plus sur les animations disponibles, jetez un œil à la MAX7219 LED dot matrix display Arduino tutorial .

Code de test

Le code suivant est un exemple minimal pour tester le câblage et le fonctionnement de l’écran. Il affiche simplement le texte défilant « Test » sur l’écran.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3  

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  disp.displayText("Test", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

void loop() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

Le code commence par inclure les bibliothèques nécessaires. La SPI bibliothèque est disponible par défaut, et vous avez installé la MD_Parola et la MD_MAX72xx bibliothèque précédemment.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

Ensuite, nous devons définir quelques constantes et créer l’objet display ( disp ). Il faut notamment définir le type d’écran, le nombre de modules de l’écran et quelle broche de l’Arduino est connectée au signal Chip Select ( CS ).

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3  

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

Si vous avez un écran avec plus ou moins de modules, vous devrez régler MAX_DEVICES en conséquence. Notez aussi que nous utilisons ici le SPI matériel. Pour le SPI logiciel, il faut définir les broches utilisées. Consultez la MAX7219 LED dot matrix display Arduino tutorial pour plus de détails.

Dans la fonction setup , le code prépare l’écran, règle la luminosité et efface l’affichage. Enfin, on définit une animation qui fait défiler le texte  » Test  » de la gauche vers la droite avec une vitesse de 100, c’est-à-dire un délai de 100 ms entre chaque étape d’animation. Plus la valeur est basse, plus c’est rapide.

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  disp.displayText("Test", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

La boucle principale loop exécute continuellement l’animation en appelant displayAnimate() . Si cette fonction retourne true, l’animation est terminée et l’affichage se réinitialise pour un nouveau cycle. Cela signifie que le texte recommence à défiler.

void loop() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

Si vous téléversez et exécutez ce code, vous devriez voir le texte « Test » défiler de gauche à droite sur votre écran MAX7219 :

Scrolling Test Output on MAX7219 LED Display
Sortie du test de défilement sur l’écran LED MAX7219

Si cela fonctionne, félicitations ! Nous sommes prêts pour plus d’animations.

Enchaîner les animations

Une question fréquente est comment créer une chaîne ou une séquence d’animations qui s’exécutent les unes après les autres. Par exemple, disons que nous voulons faire défiler le texte « Left » vers la gauche puis « Right » vers la droite, et répéter le cycle.

Chaining of two animations
Enchaînement de deux animations

Cependant, nous ne pouvons pas interrompre la boucle d’animation ou enchaîner facilement deux boucles l’une après l’autre. Il faut donc changer d’animation à l’intérieur de la boucle.

void loop() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

Le code suivant vous montre comment y parvenir :

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3  

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void switchAnimation(int animationId) {
  switch(animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, 100, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;      
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  switchAnimation(0);
}

void loop() {
  static int animationId = 0;
  if (disp.displayAnimate()) {
    disp.displayReset();
    switchAnimation(++animationId % 2);
  }
}

Regardons ce code de plus près. Les instructions d’inclusion, la définition des constantes et la création de l’écran MD_Parola sont identiques à avant.

Fonction switchAnimation

Ce qui est nouveau, c’est la fonction switchAnimation() . Elle prend l’ id d’une animation et définit soit l’animation de défilement à gauche, soit celle à droite. Notez que switchAnimation() n’exécute pas l’animation. Elle indique simplement à l’écran quelle animation exécuter. L’exécution réelle de l’animation est faite par displayAnimate() dans la boucle principale.

void switchAnimation(int animationId) {
  switch(animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, 100, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;      
  }
}

Fonction setup

La fonction setup reste quasiment inchangée. Comme avant, elle prépare l’écran, règle la luminosité et efface l’affichage. Mais à la fin, on appelle switchAnimation(0), ce qui définit l’animation avec id=0. Dans ce cas, il s’agit du défilement du texte « Left ».

Fonction loop

Dans la fonction loop, on définit la variable animationId pour suivre l’animation en cours. Elle est static , ce qui veut dire que sa valeur est conservée entre les boucles.

void loop() {
  static int animationId = 0;
  if (disp.displayAnimate()) {
    disp.displayReset();
    switchAnimation(++animationId % 2);
  }
}

Dans la boucle, l’appel à displayAnimate() exécute l’animation en cours. Quand une animation est terminée (texte complètement défilé), cette fonction retourne true et on entre dans le corps du if . Là, on effectue une réinitialisation puis on passe à l’animation suivante.

L’expression ++animationId % 2 incrémente l’id de l’animation jusqu’à atteindre 2, puis le remet à 0. Si vous avez plus de 2 animations à enchaîner, il faut remplacer le 2 par le nombre d’animations que vous avez. Ces animations doivent aussi être définies dans la fonction switchAnimation() .

Voici un exemple de code pour une séquence de trois animations :

...

void switchAnimation(int animationId) {
  switch(animationId) {
    case 0:
      disp.displayText(...);
      break;
    case 1:
      disp.displayText(...);
      break;    
    case2:
      disp.displayText(...);
      break;     
  }
}

void setup() {
...
}

void loop() {
  static int animationId = 0;
  if (disp.displayAnimate()) {
    disp.displayReset();
    switchAnimation(++animationId % 3);
  }
}

Si vous téléversez et exécutez ce code, vous devriez voir l’animation suivante :

Chained "Left" and "Right" animation
Animations « Left » et « Right » enchaînées

Dans la section suivante, je vous montre comment changer d’animation en fonction d’entrées externes, comme des boutons-poussoirs.

Changer d’animation

Souvent, on souhaite changer d’animation en fonction d’une entrée externe. Cela peut être un bouton-poussoir, une télécommande, un détecteur de mouvement ou des données de capteur comme la température. Dans l’exemple suivant, nous allons utiliser deux boutons-poussoirs pour activer soit l’animation « Left », soit l’animation « Right ».

Switching two animations
Changement entre deux animations

Commençons par ajouter les deux boutons-poussoirs à notre circuit.

Câblage

Ajouter les deux boutons-poussoirs est simple. Il suffit de connecter une broche de chaque bouton à la masse (GND) et l’autre broche aux broches 7 et 8 de l’Arduino, comme indiqué ci-dessous :

Wiring for Control Buttons
Câblage pour les boutons de contrôle

Faites attention en connectant le bouton à bien utiliser les broches qui sont effectivement commutées. Notez que nous n’avons pas besoin de résistances de pull-up, car nous allons utiliser les pull-ups internes de l’Arduino.

Code pour changer d’animation

Le code pour passer d’une animation à l’autre est une simple extension du code pour les animations enchaînées.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3

#define BTN1_PIN 6
#define BTN2_PIN 7

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void switchAnimation(int animationId) {
  switch (animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, 100, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;
  }
}

void setAnimation(int btn_pin, int animationId) {
  if (!digitalRead(btn_pin)) {
    disp.displayReset();
    disp.displayClear();
    switchAnimation(animationId);
    delay(200);
  }
}

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  setAnimation(0);

  pinMode(BTN1_PIN, INPUT_PULLUP);
  pinMode(BTN2_PIN, INPUT_PULLUP);
}

void loop() {
  setAnimation(BTN1_PIN, 0);
  setAnimation(BTN2_PIN, 1);
  animate();
}

La partie qui inclut les bibliothèques nécessaires, définit les constantes et crée l’objet d’affichage MD_Parola reste en grande partie inchangée. La seule différence est que nous définissons les broches auxquelles les deux boutons sont connectés.

#define BTN1_PIN 6
#define BTN2_PIN 7

La fonction switchAnimation() est aussi la même qu’avant. Mais nous avons maintenant une nouvelle fonction setAnimation() :

void setAnimation(int btn_pin, int animationId) {
  if (!digitalRead(btn_pin)) {
    disp.displayReset();
    disp.displayClear();
    switchAnimation(animationId);
    delay(200);
  }
}

Elle prend une broche de bouton et un id d’animation, et vérifie si le bouton à la broche spécifiée est pressé en appelant !digitalRead(btn_pin) . Notez que la logique est inversée, car nous mettons la broche GPIO à la masse quand le bouton est pressé.

Si le bouton est pressé, on réinitialise et efface l’affichage, puis on passe à l’animation assignée à ce bouton. Le délai de 200 ms sert à l’anti-rebond du bouton. Ce délai ne pose pas de problème ici, car on vient de changer d’animation et on ne retarde donc pas une animation en cours.

Ensuite, on déplace le code qui exécute une animation de la boucle principale vers une nouvelle fonction animate() . Cela rend la fonction loop beaucoup plus lisible.

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

La fonction setup() est quasiment la même, mais on définit le mode des deux broches auxquelles les boutons sont connectés. Notez que l’on règle INPUT_PULLUP pour utiliser le pull-up resistors interne.

void setup() {
  ...

  pinMode(BTN1_PIN, INPUT_PULLUP);
  pinMode(BTN2_PIN, INPUT_PULLUP);
}

La fonction loop est maintenant très simple. On assigne juste l’id d’une animation aux boutons via setAnimation() puis on appelle animate() pour exécuter l’animation active. Notez que cela se lit comme une petite histoire ou une recette. C’est ce qu’on veut pour notre code.

void loop() {
  setAnimation(BTN1_PIN, 0);
  setAnimation(BTN2_PIN, 1);
  animate();
}

Téléversez le code et essayez ! Les courtes vidéos ci-dessous montrent les deux animations que vous devriez voir en appuyant sur le bouton gauche (BTN1) ou droit (BTN2).

Animation for left button
Animation pour le bouton gauche
Animation for right button
Animation pour le bouton droit

Dans la section suivante, nous allons modifier la fonction des deux boutons.

Basculer ou suspendre les animations

Au lieu d’utiliser un bouton séparé pour chaque animation, nous allons utiliser un bouton (BTN1) pour basculer entre les animations et l’autre bouton (BTN2) pour mettre en pause l’animation en cours. Le code suivant vous montre comment faire.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3

#define BTN1_PIN 6
#define BTN2_PIN 7

int animationId = 0;

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void switchAnimation() {
  switch (animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, 100, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;
  }
}

void toggleAnimation() {
  if (!digitalRead(BTN1_PIN)) {    
    disp.displayReset();
    disp.displayClear();
    animationId = (animationId + 1) % 2;
    switchAnimation();
    delay(200);
  }
}

void pauseAnimation() {
  static bool isPaused = false;
  if (!digitalRead(BTN2_PIN)) {
    isPaused = !isPaused;
    disp.displaySuspend(isPaused);
    delay(200);
  }
}

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  switchAnimation();

  pinMode(BTN1_PIN, INPUT_PULLUP);
  pinMode(BTN2_PIN, INPUT_PULLUP);
}

void loop() {
  toggleAnimation();
  pauseAnimation();
  animate();
}

Il y a quelques changements par rapport au code précédent. D’abord, la fonction switchAnimation() ne prend plus d’ animationId en argument, mais utilise une variable globale pour suivre l’animation en cours.

Ensuite, nous avons deux nouvelles fonctions : toggleAnimation() et pauseAnimation() . Regardons de plus près toggleAnimation() d’abord.

void toggleAnimation() {
  if (!digitalRead(BTN1_PIN)) {    
    disp.displayReset();
    disp.displayClear();
    animationId = (animationId + 1) % 2;
    switchAnimation();
    delay(200);
  }
}

Cette fonction vérifie si BTN1 a été pressé. Si c’est le cas, elle réinitialise et efface l’affichage, met à jour le animationId pour passer à l’animation suivante et appelle switchAnimation() pour définir l’animation correspondante. À la fin, on retrouve le délai habituel pour l’anti-rebond.

La fonction pauseAnimation() vérifie si BTN2 a été pressé et, si c’est le cas, bascule le drapeau isPaused . Selon la valeur de ce drapeau, l’animation de l’affichage est alors suspendue ou non.

void pauseAnimation() {
  static bool isPaused = false;
  if (!digitalRead(BTN2_PIN)) {
    isPaused = !isPaused;
    disp.displaySuspend(isPaused);
    delay(200);
  }
}

La fonction setup est essentiellement inchangée et la fonction loop se lit à nouveau très bien, comme une petite histoire :

void loop() {
  toggleAnimation();
  pauseAnimation();
  animate();
}

À chaque itération, on gère la bascule ou la suspension de l’animation. Comme vous pouvez le voir, il est facile de changer la fonction des boutons et de garder le code bien organisé.

Dans les deux prochaines sections, nous allons encore plus loin en ajoutant un potentiomètre pour ajuster la luminosité ou la vitesse d’une animation en cours.

Changer la luminosité de l’animation

Dans cette partie, nous allons voir comment ajuster la luminosité du texte affiché pendant que l’animation tourne.

Câblage

Commençons par ajouter un potentiomètre à notre circuit. Nous allons l’utiliser pour ajuster la luminosité de l’écran de façon analogique. J’ai utilisé un potentiomètre de 10kΩ, mais n’importe quelle valeur entre 1kΩ et 100kΩ fonctionnera aussi.

Wiring for Potentiometer
Câblage pour le potentiomètre

Connectez la broche centrale du potentiomètre (POT) à l’entrée analogique A0 de l’Arduino. Ensuite, connectez le 5V et le GND aux deux autres broches du potentiomètre. L’ordre n’a pas vraiment d’importance, mais il déterminera si la luminosité augmente en tournant le potentiomètre à gauche ou à droite. Inversez simplement les connexions 5V et GND sur le potentiomètre si vous préférez une direction spécifique, par exemple tourner à droite pour augmenter la luminosité.

Code pour changer la luminosité

Voici le code utilisé précédemment, avec la fonctionnalité supplémentaire pour ajuster la luminosité de l’écran en fonction de la position du potentiomètre.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3

#define BTN1_PIN 6
#define BTN2_PIN 7

int animationId = 0;

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void switchAnimation() {
  switch (animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, 100, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, 100, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;
  }
}

void toggleAnimation() {
  if (!digitalRead(BTN1_PIN)) {    
    disp.displayReset();
    disp.displayClear();
    animationId = (animationId + 1) % 2;
    switchAnimation();
    delay(200);
  }
}

void pauseAnimation() {
  static bool isPaused = false;
  if (!digitalRead(BTN2_PIN)) {
    isPaused = !isPaused;
    disp.displaySuspend(isPaused);
    delay(200);
  }
}

void adjustBrightness() {
  int val = analogRead(A0);
  int intensity = map(val, 0, 1023, 0, 15);
  disp.setIntensity(intensity);
}

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  switchAnimation();

  pinMode(BTN1_PIN, INPUT_PULLUP);
  pinMode(BTN2_PIN, INPUT_PULLUP);
}

void loop() {
  toggleAnimation();
  pauseAnimation();
  adjustBrightness();
  animate();
}

Voyons les changements dans le code. Nous avons juste besoin d’une nouvelle fonction qui lit la valeur du potentiomètre via analogRead(), la convertit en une valeur d’intensité entre 0 et 15, puis règle l’intensité/luminosité de l’écran en conséquence.

void adjustIntensity() {
  int val = analogRead(A0);
  int intensity = map(val, 0, 1023, 0, 15);
  disp.setIntensity(intensity);
}

Il suffit ensuite d’appeler adjustBrightness() dans la boucle principale pour ajuster la luminosité de l’écran pendant que l’animation tourne. Et c’est tout. Maintenant, on peut basculer et mettre en pause les animations, et changer la luminosité.

Dans la section suivante, nous allons faire quelque chose de très similaire, mais au lieu d’ajuster la luminosité de l’écran, nous allons ajuster la vitesse de l’animation.

Changer la vitesse de l’animation

Voici le code complet pour régler la vitesse de l’animation en fonction de la position du potentiomètre.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3

#define BTN1_PIN 6
#define BTN2_PIN 7

int animationId = 0;

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void switchAnimation() {
  int speed = disp.getSpeed();
  switch (animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, speed, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, speed, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;
  }
}

void toggleAnimation() {
  if (!digitalRead(BTN1_PIN)) {
    disp.displayReset();
    disp.displayClear();
    animationId = (animationId + 1) % 2;
    switchAnimation();
    delay(200);
  }
}

void pauseAnimation() {
  static bool isPaused = false;
  if (!digitalRead(BTN2_PIN)) {
    isPaused = !isPaused;
    disp.displaySuspend(isPaused);
    delay(200);
  }
}

void adjustSpeed() {
  int val = analogRead(A0);
  int speed = map(val, 0, 1023, 10, 1000);
  disp.setSpeed(speed);
}

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  switchAnimation();

  pinMode(BTN1_PIN, INPUT_PULLUP);
  pinMode(BTN2_PIN, INPUT_PULLUP);
}

void loop() {
  toggleAnimation();
  pauseAnimation();
  adjustSpeed();
  animate();
}

Ce code est un peu plus complexe, car il faut ajouter une nouvelle fonction et modifier la fonction switchAnimation() . Dans la fonction switchAnimation() , on récupère maintenant la vitesse actuelle de l’écran et on l’utilise lorsqu’on passe à une autre animation :

void switchAnimation() {
  int speed = disp.getSpeed();
  switch (animationId) {
    case 0:
      disp.displayText("Left", PA_CENTER, speed, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      break;
    case 1:
      disp.displayText("Right", PA_CENTER, speed, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
      break;
  }
}

Et nous avons la nouvelle fonction adjustSpeed() , qui ressemble beaucoup à la fonction précédente adjustBrightness() . La fonction adjustSpeed() lit la valeur du potentiomètre via analogRead(), la convertit en une valeur de vitesse entre 10 et 1000, puis règle la vitesse de l’animation en conséquence.

void adjustSpeed() {
  int val = analogRead(A0);
  int speed = map(val, 0, 1023, 10, 1000);
  disp.setSpeed(speed);
}

Changer le contenu de l’animation

Pour finir, je veux vous montrer une méthode simple pour mettre à jour le contenu d’une animation. Vous en aurez besoin si vous souhaitez afficher des données de capteur, par exemple une température ou l’heure.

Au lieu d’utiliser un capteur spécifique, dans l’exemple ci-dessous, nous réutilisons le potentiomètre pour simuler des lectures de capteur. Mais vous pouvez facilement remplacer le potentiomètre par n’importe quel autre capteur.

#include "MD_Parola.h"
#include "MD_MAX72xx.h"
#include "SPI.h"

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 3

MD_Parola disp = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void updateAnimation() {
  static char buffer[32] = "";
  int value = analogRead(A0);
  sprintf(buffer, "value=%d", value);
  disp.displayText(buffer, PA_CENTER, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
    updateAnimation();
  }
}

void setup() {
  disp.begin();
  disp.setIntensity(0);
  disp.displayClear();
  updateAnimation();
}

void loop() {
  animate();
}

La fonctionnalité principale pour la mise à jour de l’animation se trouve dans la fonction updateAnimation() . Elle lit la valeur actuelle du capteur, dans cet exemple la valeur du potentiomètre, la formate et l’écrit dans une chaîne buffer via sprintf , puis met à jour le texte affiché via displayText() . Si vous téléversez et exécutez le code, vous devriez voir l’animation suivante :

Animation update from potentiometer reading
Mise à jour de l’animation à partir de la lecture du potentiomètre

Notez que la taille du tampon de chaîne est fixée à 32 caractères. Si vous voulez afficher des textes plus longs, il faudra augmenter la taille du tampon.

La fonction updateAnimation() peut facilement être modifiée pour afficher d’autres données. Supposons que vous connectiez un capteur de température DHT11 à la place du potentiomètre. Il suffirait de modifier la fonction comme suit :

float t = dht.readTemperature();
void updateAnimation() {
  static char buffer[32] = "";
  float temp = dht.readTemperature();
  sprintf(text, "Temp=%.2f", temp);
  disp.displayText(buffer, PA_CENTER, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

Cela suppose bien sûr que vous avez connecté le capteur DHT11 et configuré sa fonction dans le code. Consultez le tutoriel sur How to use DHT11 and DHT22 Sensors with Arduino pour plus d’informations.

Notez que la mise à jour du contenu se fait au début d’une nouvelle animation, mais pas pendant l’exécution d’une animation. Par exemple, si on utilise l’animation de texte défilant, le texte ne sera pas mis à jour pendant le défilement. Il sera mis à jour au début d’un nouveau cycle. Vous pouvez le voir dans la fonction animate() , où l’on appelle updateAnimation() lorsque l’animation en cours est terminée.

void animate() {
  if (disp.displayAnimate()) {
    disp.displayReset();
    updateAnimation();
  }
}

Et voilà ! Plusieurs exemples, j’espère utiles, pour contrôler différentes fonctionnalités d’une animation à l’aide d’entrées numériques ou analogiques, sans interrompre l’animation. Si vous avez des questions, n’hésitez pas à laisser un commentaire.

Conclusions

La bibliothèque Parola est excellente pour les animations, mais il peut être un peu difficile de comprendre comment contrôler, modifier ou mettre à jour les animations sans les interrompre. J’espère que ce tutoriel vous a donné toutes les informations nécessaires pour y parvenir dans vos projets.

Nous avons utilisé des boutons et un potentiomètre comme entrées pour contrôler les animations. Mais il est facile d’utiliser d’autres entrées numériques ou analogiques à la place. Par exemple, vous pourriez contrôler les animations via une télécommande IR, ou utiliser une photorésistance pour ajuster la luminosité de l’écran en fonction de la lumière ambiante, et afficher des données météo à jour depuis Internet.

De plus, la bibliothèque Parola permet de diviser un écran en plusieurs zones pouvant exécuter différentes animations, par exemple une zone pour une horloge et une autre pour la météo. Si vous voulez en savoir plus, consultez le tutoriel Coordinate Parola Zone Animations on MAX7219 Display .

Enfin, même si nous avons utilisé un Arduino dans ce tutoriel, n’importe quel autre microcontrôleur courant comme l’ESP32 ou l’ESP8266 fonctionnera aussi.

Et maintenant, amusez-vous à animer vos projets ; )