Exemple : afficher une valeur sur la matrice LED
Le programme de base pour l'écran du ModuleAir : toutes les 2 secondes, une valeur de CO2 tirée au hasard, et un carré vert, orange ou rouge selon le niveau. Aucun capteur ni Wi-Fi : il suffit de la carte et de l'écran.
Code de l'exemple du guide IUT-AMU-08 « Afficher du texte et des couleurs sur la matrice LED », v1.1 du 2026-10-01. Les explications sont dans le PDF.
Mise en route
- Téléchargez le projet (bouton vert), décompressez-le. Dans VS Code, onglet PlatformIO, Open Project, choisissez le dossier décompressé.
Ou créez un projet PlatformIO (carte Espressif ESP32 Dev Module, framework Arduino) et remplacez ses fichiers par ceux ci-dessous, avec le bouton Copier. - Vérifiez que la carte est enfichée sur l'entrée (IN) du panneau et que le panneau est alimenté en 5 V.
- Téléversez (Upload), puis ouvrez le moniteur série (Monitor, 115200 bauds).
Couleurs fausses (rouge affiché en bleu…) ? Dans setupDisplay(), remplacez RRBBGG par RRGGBB : l'ordre des couleurs dépend du modèle de panneau (P2.5 ou P3). La carte redémarre quand l'écran est très lumineux ? Baissez setBrightness().
Le projet
Télécharger le projet IUT-AMU-08-exemple-v1.1.zip[env:moduleair]
platform = espressif32 @ 7.1.3
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
2dom/PxMatrix LED MATRIX library @ 1.8.2
adafruit/Adafruit GFX Library @ 1.11.11
// Exemple : toutes les 2 s, une valeur de CO2 et un carré coloré selon le niveau.
#include <Arduino.h>
#include <PxMatrix.h>
// Broches de la carte ModuleAir vers le connecteur HUB75 de l'écran
#define P_LAT 25
#define P_A 17
#define P_B 33
#define P_C 4
#define P_D 12
#define P_E 15
#define P_OE 16
PxMATRIX display(64, 32, P_LAT, P_OE, P_A, P_B, P_C, P_D, P_E);
// L'écran n'allume que 2 lignes sur 32 à la fois : il faut le redessiner sans
// arrêt, toutes les 4 ms. Un timer réveille une tâche qui s'en charge, en
// parallèle du reste du programme. Ce bloc se recopie tel quel.
hw_timer_t* timer = NULL;
SemaphoreHandle_t refreshSem;
void IRAM_ATTR onTimer() {
BaseType_t woken = pdFALSE;
xSemaphoreGiveFromISR(refreshSem, &woken);
if (woken) portYIELD_FROM_ISR();
}
void refreshTask(void* param) {
for (;;) {
if (xSemaphoreTake(refreshSem, portMAX_DELAY)) {
display.display(30); // durée d'allumage de chaque ligne, en µs
}
}
}
void setupDisplay() {
display.begin(16); // balayage 1/16
display.setDriverChip(SHIFT);
display.setColorOrder(RRBBGG); // couleurs inversées ? essayez RRGGBB
display.setBrightness(255); // luminosité : 0 à 255, ici le maximum
display.clearDisplay();
refreshSem = xSemaphoreCreateBinary();
xTaskCreatePinnedToCore(refreshTask, "refresh", 2048, NULL,
configMAX_PRIORITIES - 1, NULL, 0); // priorité max, cœur 0
timer = timerBegin(0, 80, true); // 80 MHz / 80 : un tic par µs
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 4000, true); // toutes les 4000 µs, en boucle
timerAlarmEnable(timer);
}
void setup() {
setupDisplay();
}
void loop() {
// Fausse mesure, tirée au hasard : à remplacer par la lecture du MH-Z19.
int co2 = random(400, 2001); // entre 400 et 2000 ppm
// Couleur selon le niveau de CO2
uint16_t color;
if (co2 < 800) {
color = display.color565(0, 255, 0); // vert : air correct
} else if (co2 < 1500) {
color = display.color565(255, 120, 0); // orange : aérer
} else {
color = display.color565(255, 0, 0); // rouge : aérer vite
}
display.clearDisplay(); // on efface, puis on redessine tout
// Un petit texte en haut à gauche (x = 1, y = 0)
display.setTextSize(1); // caractères de 6 x 8 pixels
display.setTextColor(display.color565(0, 255, 255));
display.setCursor(1, 0);
display.print("CO2 (ppm)");
// La valeur en grand, dans la couleur du niveau
display.setTextSize(2); // caractères de 12 x 16 pixels
display.setTextColor(color);
display.setCursor(1, 12);
display.print(co2);
// Un carré de 10 x 10 pixels de la même couleur, à droite
display.fillRect(52, 14, 10, 10, color);
delay(2000); // l'image reste affichée pendant l'attente, grâce au timer
}