Affichage XL pour Matrice LED 72xx

Dans cet article , je vais expliquer comment mettre en place un affichage sur une Double hauteur de matrice LED. Chaque Matrice étant un carré composé de 8×8 Led , doubler la zone d’affichage donnera une grande matrice , composé de 4 matrices , soit un affichage de 16×16 .

Chaque caractère aura donc une hauteur max pouvant aller jusqu’a 16 LED.

Pour cela , il va falloir :

Disposition des matrices

Singe vs Double taille

Pour obtenir un double affichage en hauteur , il va falloir multiplier par 4 le nombre de matrice. Deux pour la hauteur et deux pour la largeur. Ce qui nous permet de passe d’un affichage de 8×8 à un affichage de 16×16.
Pour l’affichage d’une police de caractère en double taille , j’utilise le système des Zones , fournis avec la bibliothèque MD_Parola . Chaque Zone représentera une moitié d’affichage , la Zone Inférieur la moitié inférieur du caractère et la Zone Supérieur la moitié supérieur du caractère.
Selon les types de matrices utilisés , il faudra connecter la zone supérieur de deux façons différentes :

Matrice type FC16 ou ICStation : ( Mode ZigZag )

Connexion Zone Inferieur avec Zone Supérieur
pour type ICS ou FC16

Dans ce mode , chaque début de Zone , commence à droite .

ou pour les Matrices de type Parola ou Génerique . ( Mode S )

Parola ou generic

Dans ce mode , les debuts de Zones sont alternés , une fois a droite , une fois a gauche , etc ….

Branchement

Un affichage sur double hauteur implique , d’utiliser beaucoup plus de matrices. Afin d’avoir un affichage “correct” , il faut utiliser 4 Modules de 4 matrices au minimum ( soit une surface totale de 16×64 ).

Pin à relier ( schema avec Wemos D1R1 )
pour Wemos mini D8 à la place de D10

Attention aux PIN , en fonction de votre module ESP. Vérifier , selon votre module ou se situe les PIN ( SS , MOSI et SCK).
Le branchement sera toujours le suivant :
ESP ——–> Matrice LED
SCK ——–> Clock
MOSI ——–> DIN
SS ——–> CS

Définir une police en double taille

Pour cela , il faut utiliser des tableaux de définitions pour chaque caractère . Par exemple , pour l’affichage des caractéres sur le Notifheure , j’utilise le tableau fournis dans le fichier Parola_font_data.h .
Ce qui donne , par exemple pour les chiffres :

  5, 62, 81, 73, 69, 62,		// 48 - '0'
  3, 66, 127, 64,		        // 49 - '1'
  5, 114, 73, 73, 73, 70,		// 50 - '2'
  5, 33, 65, 73, 77, 51,		// 51 - '3'
  5, 24, 20, 18, 127, 16,		// 52 - '4'
  5, 39, 69, 69, 69, 57,		// 53 - '5'
  5, 60, 74, 73, 73, 49,		// 54 - '6'
  5, 65, 33, 17, 9, 7,		        // 55 - '7'
  5, 54, 73, 73, 73, 54,		// 56 - '8'
  5, 70, 73, 73, 41, 30,		// 57 - '9'

Ce tableau se lit de la manière suivante :
Pour le code Ascii 48 ( qui représente le chiffre 0 ) , je vais l’afficher sur 5 colones . Les 5 autres chiffres ( 62,81,73,69,62 ) sont les “poids” binaire qui permet de cibler les leds à allumer sur la colonne 1, 2 , 3 , 4 et 5 .
La led la plus haute à le poids 1 , puis 2 , 4 , 8 , 16 , 32 , 64 et 128. Avec la valeur 62 , sur la première colonne , j’aurais donc les led 2,3,4,5 et 6 allumés.
Pour créer ses propres polices de caractères , il existe des simulateur comme celui ci. ( il peut être téléchargé en local sur le github )

Exemple : tableau des codes ascii étendus

Pour afficher un caractère en double taille , il faut donc deux définitions de police de caractére , une qui sera affiché sur la zone inférieur et l’autre moitié qui sera affiché sur la zone supérieur.
Pour cela , il est possible d’utiliser deux tableau de définition ou un tableau.
Utiliser deux tableau permettra de définir , un plus grand nombre de caractère , mais prendra plus de place en mémoire.
Un tableau , permettra de réduire l’encombrement mémoire , mais devra être divisé par deux . De 0 à 127 la moitié inférieur et de 128 à 255 la moitié supérieur . Il contiendra , moins de caractères.

Dans cet article , je vais me baser sur la police bigfont , fournis avec la bibliothèque Parola . Ce tableau contient les deux définitions ( inférieur et supérieur ) .

Dans les illustrations ci dessous , les définitions des caractères répartis sur les 255 codes Ascii , de 0 à 127 la moitié basse et de 128 à 255 la moitié haute . Ainsi que le visuel de ce que l’on obtient une fois les deux définitions réunis.

Par exemple , pour le caractère “A” , il est définis par le code Ascii 65 et 193 ( 65 + 128 ).

Maintenant , que l’on a toutes les clés pour modifier ou jouer avec les polices de caractères à afficher , comment les afficher et synchroniser le tout.

Programmation

la théorie …

Pour que le caractère supérieur et inférieur soit afficher automatiquement sur les deux zones , il va falloir envoyer le bon code au bon nomment sur chaque Zone. Chaque caractère est donc égale au code ASCII de la lettre ( A=65 ) et de la moitié supérieur ( décalé de 128 ).

Pour cela j’utilise la fonction suivante :

// chaine decalage
void createHString(char *pH, char *pL)
{
  for (; *pL != '\0'; pL++)  *pH++ = *pL | 0x80;   // decalage caractére en positionnant le 8eme bit ( 128) à 1
    *pH = '\0'; // termine la chaine
}

Cette fonction , fabrique pour chaque caractère de la chaine inférieur un caractère décalé de 128 ( ou en hexa 0x80 ) pour la chaine supérieur . Par exemple pL contiendra le code ascii 65 ( A inferieur ) et pH contiendra le code ascii 193 ( A supérieur ) . Il suffit, ensuite d’envoyer sur chaque Zone les deux chaines de caractères et synchroniser le tout par la commande : P.synchZoneStart();

Pour gérer , les différents types de matrices ( Parola , generic , ICS , FC16 … ) , le test If invertUpperZone va tester le type définis et en fonction de ce dernier inversera le sens de l’écriture sur la zone supérieur ( pour les montages de type S ).

  // Selon type module inversion ou non de la zone supérieur 
  if (invertUpperZone)
  {
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
  }

…La pratique : Afficher un simple Texte

Pour commencer , on va afficher un texte , en utilisant la police livré avec la bibliothèque MD_Parola ( bigfont ) , et un effet de scrollig vertical, pour un peu d’animation.

// Tuto affichage double taille
// Byfeel 2019
// ****************************
// Exemple affichage texte sur 4 module de 4 Matrices Led 72xx
//
// Selon Module , il faudra brancher les matrices de deux façon differentes
// * Modules ( type FC16 ou ICSstation ) - Type ZigZag
//  n n-1 n-2 ... n/2+1   <- Matrice haute
//  n/2 ... 3  2  1  0    <- Matrice basse
//
// * Modules (Parola ou Generic )  - type S
//  n/2+1 ... n-2 n-1 n   -> Matrice haute
//  n/2 ... 3  2  1  0    <- Matrice basse

// Bibliotheque à inclure
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"

//****************************************************
// En fonction de vos matrices , si probléme         *
// d'affichage ( inversé , effet miroir , etc .....) *
// ***************************************************
// matrix   - decocher selon config matrix    ********
//#define HARDWARE_TYPE MD_MAX72XX::FC16_HW        //***
//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW    //***
#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW //***
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW   //***
// ***************************************************
// Taille des deux zones
#define MAX_ZONES 2
#define ZONE_SIZE 8
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
// Définition de la zone inferieur et de la zone superieur
#define ZONE_UPPER  1
#define ZONE_LOWER  0
// gestion des effets
#define PAUSE_TIME 5000
#define SCROLL_SPEED 60
// Branchement des matrices
#define CLK_PIN   14  // SCK (D5 wemos D1 ou mini )
#define DATA_PIN  13  // MOSI ( D7 wemos D1 ou mini )
#define CS_PIN    15  // SS ( GPIO 15 sur D1  ou D8 sur Mini )

//variable pour inversion zone superieur selon module
bool invertUpperZone = false;  // Type ICS ou FC16

// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// définition des chaines de stockage pour les zones inf et sup
char *msgH; 
char msgL[15]; // un buffer de 15 caractères au max

// Message a afficher
String Msg="Byfeel";

// chaine decalage
void createHString(char *pH, char *pL)
{
  for (; *pL != '\0'; pL++)  *pH++ = *pL | 0x80;   // decalage caractére en positionnant le 8 bit ( 128) à 1
    *pH = '\0'; // termine la chaine
}

void setup() {
// transfére de la chaine String dans la chaine inférieur  
  Msg.toCharArray( msgL,15);
  uint8_t max = 0;
  // Selon modele des matrices - inversion de l'affichage ( true si Generic ou Parola )
  invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
 
//calcul taille champs à afficher et allocation mémoire
    if (strlen(msgL) > max) max = strlen(msgL);
     msgH = (char *)malloc(sizeof(char)*(max + 2));

  // initialisation des Zones
  P.begin(MAX_ZONES);

  // Création des deux Zones pour les deux moitiés d'affichage
  P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
  P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
  // police de caractére à afficher
  P.setFont(BigFont);
  
  // Selon type module inversion ou non de la zone supérieur 
  if (invertUpperZone)
  {
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
  }
}

void loop() {
  P.displayAnimate();
// l'animation commence
  if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
  {
     createHString(msgH, msgL);  // fabrique la chaine Supérieur
     P.displayClear();
     
    P.displayZoneText(ZONE_LOWER, msgL, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_SCROLL_UP, PA_SCROLL_UP);
    P.displayZoneText(ZONE_UPPER, msgH, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_SCROLL_DOWN, PA_SCROLL_DOWN);

  P.synchZoneStart();
  }

}

Et le fichier de définition des polices de caractères

// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H

MD_MAX72XX::fontType_t BigFont[] PROGMEM = {
    0,		// 0
    0,		// 1
    0,		// 2
    0,		// 3
    0,		// 4
    0,		// 5
    0,		// 6
    0,		// 7
    0,		// 8
    0,		// 9
    0,		// 10
    0,		// 11
    0,		// 12
    0,		// 13
    0,		// 14
    0,		// 15
    0,		// 16
    0,		// 17
    0,		// 18
    0,		// 19
    0,		// 20
    0,		// 21
    0,		// 22
    0,		// 23
    0,		// 24
    0,		// 25
    0,		// 26
    0,		// 27
    0,		// 28
    0,		// 29
    0,		// 30
    0,		// 31
    4, 0, 0, 0, 0,		// 32 - 'Space lower'
    2, 51, 51,		// 33 - '! lower'
    6, 0, 0, 0, 0, 0, 0,		// 34 - '" lower'
    10, 3, 3, 63, 63, 3, 3, 63, 63, 3, 3,		// 35 - '# lower'
    10, 24, 56, 48, 48, 127, 127, 48, 57, 31, 15,		// 36 - '$ lower'
    8, 48, 60, 15, 3, 24, 36, 36, 24,		// 37 - '% lower'
    10, 15, 31, 57, 48, 48, 59, 31, 14, 63, 51,		// 38 - '& lower'
    2, 0, 0,		// 39 - ' lower'
    5, 3, 15, 28, 56, 48,		// 40 - '( lower'
    5, 48, 56, 28, 15, 3,		// 41 - ') lower'
    10, 6, 7, 7, 1, 31, 31, 1, 3, 7, 6,		// 42 - '* lower'
    10, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0,		// 43 - '+ lower'
    2, 176, 112,		// 44 - ', lower'
    9, 0, 0, 0, 0, 0, 0, 0, 0, 0,		// 45 - '- lower'
    2, 48, 48,		// 46 - '. lower'
    8, 48, 60, 15, 3, 0, 0, 0, 0,		// 47 - '/ lower'
    10, 15, 31, 57, 48, 48, 48, 48, 56, 31, 15,		// 48 - '0 lower'
    5, 0, 48, 63, 63, 48,		// 49 - '1 lower'
    10, 63, 63, 49, 48, 48, 48, 48, 48, 48, 48,		// 50 - '2 lower'
    10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15,		// 51 - '3 lower'
    10, 3, 3, 3, 3, 3, 3, 3, 63, 63, 3,		// 52 - '4 lower'
    10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15,		// 53 - '5 lower'
    10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15,		// 54 - '6 lower'
    10, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0,		// 55 - '7 lower'
    10, 15, 31, 57, 48, 48, 48, 48, 57, 31, 15,		// 56 - '8 lower'
    10, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63,		// 57 - '9 lower'
    2, 24, 24,		// 58 - ': lower'
    2, 88, 56,		// 59 - '; lower'
    8, 0, 1, 3, 7, 14, 28, 56, 48,		// 60 - '< lower'
    9, 6, 6, 6, 6, 6, 6, 6, 6, 6,		// 61 - '= lower'
    8, 48, 56, 28, 14, 7, 3, 1, 0,		// 62 - '> lower'
    10, 0, 0, 0, 0, 55, 55, 1, 0, 0, 0,		// 63 - '? lower'
    10, 15, 31, 56, 51, 54, 54, 51, 54, 55, 19,		// 64 - '@ lower'
    10, 63, 63, 1, 1, 1, 1, 1, 1, 63, 63,		// 65 - 'A lower'
    10, 63, 63, 48, 48, 48, 48, 48, 57, 31, 15,		// 66 - 'B lower'
    10, 15, 31, 56, 48, 48, 48, 48, 56, 28, 12,		// 67 - 'C lower'
    10, 63, 63, 48, 48, 48, 48, 48, 56, 31, 15,		// 68 - 'D lower'
    9, 63, 63, 48, 48, 48, 48, 48, 48, 48,		// 69 - 'E lower'
    9, 63, 63, 0, 0, 0, 0, 0, 0, 0,		// 70 - 'F lower'
    10, 15, 31, 56, 48, 48, 48, 49, 57, 31, 15,		// 71 - 'G lower'
    10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63,		// 72 - 'H lower'
    4, 48, 63, 63, 48,		// 73 - 'I lower'
    8, 12, 28, 56, 48, 48, 56, 31, 15,		// 74 - 'J lower'
    9, 63, 63, 1, 3, 7, 14, 28, 56, 48,		// 75 - 'K lower'
    9, 63, 63, 48, 48, 48, 48, 48, 48, 48,		// 76 - 'L lower'
    10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63,		// 77 - 'M lower'
    10, 63, 63, 0, 0, 0, 0, 1, 3, 63, 63,		// 78 - 'N lower'
    10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15,		// 79 - 'O lower'
    10, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0,		// 80 - 'P lower'
    10, 15, 31, 56, 48, 48, 54, 62, 28, 63, 55,		// 81 - 'Q lower'
    10, 63, 63, 0, 1, 3, 7, 14, 28, 56, 48,		// 82 - 'R lower'
    10, 24, 56, 48, 48, 48, 48, 48, 57, 31, 15,		// 83 - 'S lower'
    8, 0, 0, 0, 63, 63, 0, 0, 0,		// 84 - 'T lower'
    10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15,		// 85 - 'U lower'
    10, 3, 7, 14, 28, 56, 56, 28, 14, 7, 3,		// 86 - 'V lower'
    10, 15, 31, 56, 60, 31, 31, 60, 56, 31, 15,		// 87 - 'W lower'
    10, 60, 62, 7, 3, 1, 1, 3, 7, 62, 60,		// 88 - 'X lower'
    10, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0,		// 89 - 'Y lower'
    10, 60, 62, 55, 51, 49, 48, 48, 48, 48, 48,		// 90 - 'Z lower'
    4, 63, 63, 48, 48,		// 91 - '[ lower'
    8, 0, 0, 0, 0, 3, 15, 60, 48,		// 92 - '\ lower'
    4, 48, 48, 63, 63,		// 93 - '] lower'
    8, 0, 0, 0, 0, 0, 0, 0, 0,		// 94 - '^ lower'
    10, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,		// 95 - '_ lower'
    3, 0, 0, 0,		// 96 - '` lower'
    10, 12, 30, 51, 51, 51, 51, 51, 51, 63, 31,		// 97 - 'a lower'
    10, 63, 63, 28, 56, 48, 48, 48, 56, 31, 15,		// 98 - 'b lower'
    9, 15, 31, 56, 48, 48, 48, 56, 28, 12,		// 99 - 'c lower'
    10, 15, 31, 56, 48, 48, 48, 56, 28, 63, 63,		// 100 - 'd lower'
    9, 15, 31, 59, 51, 51, 51, 59, 27, 9,		// 101 - 'e lower'
    7, 0, 63, 63, 0, 0, 0, 0,		// 102 - 'f lower'
    9, 49, 115, 231, 198, 198, 198, 230, 127, 63,		// 103 - 'g lower'
    9, 63, 63, 0, 0, 0, 0, 0, 63, 63,		// 104 - 'h lower'
    2, 63, 63,		// 105 - 'i lower'
    8, 48, 112, 224, 192, 192, 224, 127, 63,		// 106 - 'j lower'
    8, 63, 63, 3, 7, 15, 28, 56, 48,		// 107 - 'k lower'
    4, 48, 63, 63, 48,		// 108 - 'l lower'
    10, 63, 63, 0, 0, 63, 63, 0, 0, 63, 63,		// 109 - 'm lower'
    9, 63, 63, 0, 0, 0, 0, 0, 63, 63,		// 110 - 'n lower'
    9, 15, 31, 56, 48, 48, 48, 56, 31, 15,		// 111 - 'o lower'
    9, 255, 255, 7, 14, 12, 12, 14, 7, 3,		// 112 - 'p lower'
    9, 3, 7, 14, 12, 12, 14, 7, 255, 255,		// 113 - 'q lower'
    9, 63, 63, 0, 0, 0, 0, 0, 0, 0,		// 114 - 'r lower'
    9, 24, 57, 51, 51, 51, 51, 51, 30, 12,		// 115 - 's lower'
    6, 0, 31, 63, 48, 56, 24,		// 116 - 't lower'
    9, 15, 31, 56, 48, 48, 56, 28, 63, 63,		// 117 - 'u lower'
    9, 7, 15, 28, 56, 48, 56, 28, 15, 7,		// 118 - 'v lower'
    10, 15, 31, 56, 56, 31, 31, 56, 56, 31, 15,		// 119 - 'w lower'
    10, 48, 56, 28, 15, 7, 7, 15, 28, 56, 48,		// 120 - 'x lower'
    9, 49, 115, 230, 198, 198, 198, 230, 127, 63,		// 121 - 'y lower'
    10, 48, 56, 60, 62, 55, 51, 49, 48, 48, 48,		// 122 - 'z lower'
    6, 0, 1, 15, 31, 56, 48,		// 123 - '{ lower'
    2, 255, 255,		// 124 - '| lower'
    6, 48, 56, 31, 15, 1, 0,		// 125 - '} lower'
    0,		// 126
    0,		// 127
    0,		// 128
    0,		// 129
    0,		// 130
    0,		// 131
    0,		// 132
    0,		// 133
    0,		// 134
    0,		// 135
    0,		// 136
    0,		// 137
    0,		// 138
    0,		// 139
    0,		// 140
    0,		// 141
    0,		// 142
    0,		// 143
    0,		// 144
    0,		// 145
    0,		// 146
    0,		// 147
    0,		// 148
    0,		// 149
    0,		// 150
    0,		// 151
    0,		// 152
    0,		// 153
    0,		// 154
    0,		// 155
    0,		// 156
    0,		// 157
    0,		// 158
    0,		// 159
    4, 0, 0, 0, 0,		// 160 - 'Space upper'
    2, 255, 255,		// 161 - '! upper'
    6, 15, 15, 0, 0, 15, 15,		// 162 - '" upper'
    10, 48, 48, 255, 255, 48, 48, 255, 255, 48, 48,		// 163 - '# upper'
    10, 56, 124, 238, 198, 255, 255, 198, 198, 142, 12,		// 164 - '$ upper'
    8, 6, 9, 9, 198, 240, 60, 15, 3,		// 165 - '% upper'
    10, 0, 128, 204, 254, 243, 243, 158, 12, 0, 0,		// 166 - '& upper'
    2, 15, 15,		// 167 - '' upper'
    5, 240, 252, 14, 7, 3,		// 168 - '( upper'
    5, 3, 7, 14, 252, 240,		// 169 - ') upper'
    10, 48, 112, 224, 192, 252, 252, 192, 224, 112, 48,		// 170 - '* upper'
    10, 192, 192, 192, 192, 252, 252, 192, 192, 192, 192,		// 171 - '+ upper'
    2, 0, 0,		// 172 - ', upper'
    9, 192, 192, 192, 192, 192, 192, 192, 192, 192,		// 173 - '- upper'
    2, 0, 0,		// 174 - '. upper'
    8, 0, 0, 0, 192, 240, 60, 15, 3,		// 175 - '/ upper'
    10, 252, 254, 135, 195, 99, 51, 27, 15, 254, 252,		// 176 - '0 upper'
    5, 4, 6, 255, 255, 0,		// 177 - '1 upper'
    10, 12, 142, 199, 195, 195, 195, 195, 231, 126, 60,		// 178 - '2 upper'
    10, 12, 14, 7, 3, 3, 195, 195, 199, 254, 60,		// 179 - '3 upper'
    10, 128, 192, 224, 112, 56, 28, 14, 255, 255, 0,		// 180 - '4 upper'
    10, 63, 63, 51, 51, 51, 51, 51, 115, 227, 195,		// 181 - '5 upper'
    10, 252, 254, 231, 99, 99, 99, 99, 231, 198, 132,		// 182 - '6 upper'
    10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15,		// 183 - '7 upper'
    10, 28, 190, 247, 227, 195, 195, 227, 247, 190, 28,		// 184 - '8 upper'
    10, 60, 126, 231, 195, 195, 195, 195, 231, 255, 254,		// 185 - '9 upper'
    2, 48, 48,		// 186 - ': upper'
    2, 48, 48,		// 187 - '; upper'
    8, 192, 224, 240, 56, 28, 14, 7, 3,		// 188 - '< upper'
    9, 96, 96, 96, 96, 96, 96, 96, 96, 96,		// 189 - '= upper'
    8, 3, 7, 14, 28, 56, 240, 224, 192,		// 190 - '> upper'
    10, 12, 14, 7, 3, 3, 131, 195, 231, 126, 60,		// 191 - '? upper'
    10, 252, 254, 7, 243, 27, 27, 243, 7, 254, 252,		// 192 - '@ upper'
    10, 248, 254, 134, 131, 131, 131, 131, 134, 254, 248,		// 193 - 'A upper'
    10, 255, 255, 195, 195, 195, 195, 195, 231, 254, 60,		// 194 - 'B upper'
    10, 252, 254, 7, 3, 3, 3, 3, 7, 14, 12,		// 195 - 'C upper'
    10, 255, 255, 3, 3, 3, 3, 3, 7, 254, 252,		// 196 - 'D upper'
    9, 255, 255, 195, 195, 195, 195, 195, 3, 3,		// 197 - 'E upper'
    9, 255, 255, 195, 195, 195, 195, 195, 3, 3,		// 198 - 'F upper'
    10, 252, 254, 7, 3, 3, 3, 131, 135, 142, 140,		// 199 - 'G upper'
    10, 255, 255, 192, 192, 192, 192, 192, 192, 255, 255,		// 200 - 'H upper'
    4, 3, 255, 255, 3,		// 201 - 'I upper'
    8, 3, 3, 3, 3, 3, 3, 255, 255,		// 202 - 'J upper'
    9, 255, 255, 224, 240, 56, 28, 14, 7, 3,		// 203 - 'K upper'
    9, 255, 255, 0, 0, 0, 0, 0, 0, 0,		// 204 - 'L upper'
    10, 255, 255, 14, 28, 120, 120, 28, 14, 255, 255,		// 205 - 'M upper'
    10, 255, 255, 28, 56, 112, 224, 192, 128, 255, 255,		// 206 - 'N upper'
    10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252,		// 207 - 'O upper'
    10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60,		// 208 - 'P upper'
    10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252,		// 209 - 'Q upper'
    10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60,		// 210 - 'R upper'
    10, 60, 126, 231, 195, 195, 195, 195, 195, 135, 6,		// 211 - 'S upper'
    8, 3, 3, 3, 255, 255, 3, 3, 3,		// 212 - 'T upper'
    10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255,		// 213 - 'U upper'
    10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255,		// 214 - 'V upper'
    10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255,		// 215 - 'W upper'
    10, 15, 31, 56, 240, 224, 224, 240, 56, 31, 15,		// 216 - 'X upper'
    10, 15, 31, 56, 112, 224, 224, 112, 56, 31, 15,		// 217 - 'Y upper'
    10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15,		// 218 - 'Z upper'
    4, 255, 255, 3, 3,		// 219 - '[ upper'
    8, 3, 15, 60, 240, 192, 0, 0, 0,		// 220 - '\ upper'
    4, 3, 3, 255, 255,		// 221 - '] upper'
    8, 24, 12, 6, 3, 3, 6, 12, 24,		// 222 - '^ upper'
    10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		// 223 - '_ upper'
    3, 3, 15, 12,		// 224 - '` upper'
    10, 0, 96, 112, 48, 48, 48, 48, 112, 224, 192,		// 225 - 'a upper'
    10, 255, 255, 224, 112, 48, 48, 48, 112, 224, 192,		// 226 - 'b upper'
    9, 192, 224, 112, 48, 48, 48, 112, 224, 192,		// 227 - 'c upper'
    10, 192, 224, 112, 48, 48, 48, 112, 224, 255, 255,		// 228 - 'd upper'
    9, 192, 224, 112, 48, 48, 48, 112, 224, 192,		// 229 - 'e upper'
    7, 192, 252, 254, 199, 199, 14, 12,		// 230 - 'f upper'
    9, 192, 224, 112, 48, 48, 48, 112, 224, 192,		// 231 - 'g upper'
    9, 255, 255, 224, 112, 48, 48, 112, 224, 192,		// 232 - 'h upper'
    2, 246, 246,		// 233 - 'i upper'
    8, 0, 0, 0, 0, 0, 0, 246, 246,		// 234 - 'j upper'
    8, 254, 254, 0, 128, 192, 224, 112, 48,		// 235 - 'k upper'
    4, 3, 255, 255, 0,		// 236 - 'l upper'
    10, 240, 240, 48, 48, 240, 240, 48, 48, 240, 224,		// 237 - 'm upper'
    9, 240, 240, 224, 112, 48, 48, 112, 224, 192,		// 238 - 'n upper'
    9, 192, 224, 112, 48, 48, 48, 112, 224, 192,		// 239 - 'o upper'
    9, 240, 240, 96, 112, 48, 48, 112, 224, 192,		// 240 - 'p upper'
    9, 192, 224, 112, 48, 48, 112, 96, 240, 240,		// 241 - 'q upper'
    9, 240, 240, 224, 112, 48, 48, 112, 224, 192,		// 242 - 'r upper'
    9, 192, 224, 48, 48, 48, 48, 112, 96, 0,		// 243 - 's upper'
    6, 96, 252, 252, 96, 96, 0,		// 244 - 't upper'
    9, 240, 240, 0, 0, 0, 0, 0, 240, 240,		// 245 - 'u upper'
    9, 240, 240, 0, 0, 0, 0, 0, 240, 240,		// 246 - 'v upper'
    10, 240, 240, 0, 0, 0, 0, 0, 0, 240, 240,		// 247 - 'w upper'
    10, 48, 112, 224, 192, 128, 128, 192, 224, 112, 48,		// 248 - 'x upper'
    9, 240, 240, 0, 0, 0, 0, 0, 240, 240,		// 249 - 'y upper'
    10, 48, 48, 48, 48, 48, 176, 240, 240, 112, 48,		// 250 - 'z upper'
    6, 192, 224, 252, 62, 7, 3,		// 251 - '{ upper'
    2, 255, 255,		// 252 - '| upper'
    6, 3, 7, 62, 252, 224, 192,		// 253 - '} upper'
    0,		// 254
    0,		// 255
  };

#endif

les deux fichier , doivent êtres présent dans le même dossier.

Exemple structure dossier
le résultat

… Afficher l’heure

Afin de récupérer l’heure et de l’afficher , il va falloir :

  • Se connecter au réseau WIFI
  • Récupérer l’heure via NTP
  • Formater l’heure pour affichage ( adapter une police type Clock )

Il suffit de rajouter les lignes suivantes :

Pour la partie Wifi et NTP , inclure les bibliothèques suivantes . ( la bibliotheque NTP peut etre récupéré à l’adresse suivante sur le github de fabrice weinberg).

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

Puis configurer le WIFI et le service NTP

const char *ssid     = "SSID";
const char *password = "password";

WiFiUDP ntpUDP;

// serveur NTP , Decalage heure ici 7200 secondes pour les deux heures ETE ou 3600 pour hiver , et synchro toutes les 60 secondes ( temps en millisecondes )
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000);

Enfin dans la boucle Setup() , on active le Wifi et le service NTP

setup() {  
WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    //Serial.print ( "." );
  }

  timeClient.begin();
//......
// code ...
//.....
}

Pour le formatage de l’heure , j’utilise la fonction getDisplayClock , qui met en forme les heures et les minutes ,séparé par les deux points : qui clignote toutes les secondes .

Pour l’affichage , je supprime les effets précedents , et je demande un affichage sans effet et une pause à Zero ( define PAUSE_TIME 0 )

     if (millis() - lastTime >= 1000)
    {
      lastTime = millis();
      getDisplayClock(msgL, flasher);
      createHString(msgH, msgL);  // fabrique la chaine Supérieur
      flasher = !flasher; // inverse affichage des deux points
    }
// affichage sans effet
    P.displayZoneText(ZONE_LOWER, msgL, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
    P.displayZoneText(ZONE_UPPER, msgH, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);

  P.synchZoneStart();

Pour avoir un affichage de l’heure qui ne bouge pas, il faut utiliser une police de caractére ou tous les chiffres ont la même largeur ( ce qui n’est pas le cas avec la police bigfont ). J’utilise ici , la police numeric7SegDouble qui est affecté aux zones par la commande P.setFont(numeric7SegDouble);

// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H

MD_MAX72XX::fontType_t numeric7SegDouble[] PROGMEM = {
    0,		// 0
    0,		// 1
    0,		// 2
    0,		// 3
    0,		// 4
    0,		// 5
    0,		// 6
    0,		// 7
    0,		// 8
    0,		// 9
    0,		// 10
    0,		// 11
    0,		// 12
    0,		// 13
    0,		// 14
    0,		// 15
    0,		// 16
    0,		// 17
    0,		// 18
    0,		// 19
    0,		// 20
    0,		// 21
    0,		// 22
    0,		// 23
    0,		// 24
    0,		// 25
    0,		// 26
    0,		// 27
    0,		// 28
    0,		// 29
    0,		// 30
    0,		// 31
    2, 0, 0,		// 32 - 'Space'
    0,		// 33 - '!'
    0,		// 34 - '"'
    0,		// 35 - '#'
    0,		// 36 - '$'
    0,		// 37 - '%'
    0,		// 38 - '&'
    0,		// 39 - '''
    0,		// 40 - '('
    0,		// 41 - ')'
    0,		// 42 - '*'
    0,		// 43 - '+'
    0,		// 44 - ','
    0,		// 45 - '-'
    2, 48, 48,		// 46 - '.'
    0,		// 47 - '/'
    10, 62, 127, 192, 192, 192, 192, 192, 192, 127, 62,		// 48 - '0'
    10, 0, 0, 0, 0, 0, 0, 0, 0, 127, 62,		// 49 - '1'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 64, 0,		// 50 - '2'
    10, 0, 65, 193, 193, 193, 193, 193, 193, 127, 62,		// 51 - '3'
    10, 0, 0, 1, 1, 1, 1, 1, 1, 127, 62,		// 52 - '4'
    10, 0, 64, 193, 193, 193, 193, 193, 193, 127, 62,		// 53 - '5'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 54 - '6'
    10, 0, 0, 0, 0, 0, 0, 0, 0, 127, 62,		// 55 - '7'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 56 - '8'
    10, 0, 64, 193, 193, 193, 193, 193, 193, 127, 62,		// 57 - '9'
    2, 6, 6,		// 58 - ':'
    0,		// 59 - ';'
    0,		// 60 - '<'
    0,		// 61 - '='
    0,		// 62 - '>'
    0,		// 63 - '?'
    0,		// 64 - '@'
    10, 62, 127, 1, 1, 1, 1, 1, 1, 127, 62,		// 65 - 'A'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 66 - 'B'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0,		// 67 - 'C'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 68 - 'D'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0,		// 69 - 'E'
    10, 62, 127, 1, 1, 1, 1, 1, 1, 1, 0,		// 70 - 'F'
    0,		// 71 - 'G'
    0,		// 72 - 'H'
    0,		// 73 - 'I'
    0,		// 74 - 'J'
    0,		// 75 - 'K'
    0,		// 76 - 'L'
    0,		// 77 - 'M'
    0,		// 78 - 'N'
    0,		// 79 - 'O'
    0,		// 80 - 'P'
    0,		// 81 - 'Q'
    0,		// 82 - 'R'
    0,		// 83 - 'S'
    0,		// 84 - 'T'
    0,		// 85 - 'U'
    0,		// 86 - 'V'
    0,		// 87 - 'W'
    0,		// 88 - 'X'
    0,		// 89 - 'Y'
    0,		// 90 - 'Z'
    0,		// 91 - '['
    0,		// 92 - '\'
    0,		// 93 - ']'
    0,		// 94 - '^'
    0,		// 95 - '_'
    0,		// 96 - '`'
    10, 62, 127, 1, 1, 1, 1, 1, 1, 127, 62,		// 97 - 'a'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 98 - 'b'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0,		// 99 - 'c'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62,		// 100 - 'd'
    10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0,		// 101 - 'e'
    10, 62, 127, 1, 1, 1, 1, 1, 1, 1, 0,		// 102 - 'f'
    0,		// 103 - 'g'
    0,		// 104 - 'h'
    0,		// 105 - 'i'
    0,		// 106 - 'j'
    0,		// 107 - 'k'
    0,		// 108 - 'l'
    0,		// 109 - 'm'
    0,		// 110 - 'n'
    0,		// 111 - 'o'
    0,		// 112 - 'p'
    0,		// 113 - 'q'
    0,		// 114 - 'r'
    0,		// 115 - 's'
    0,		// 116 - 't'
    0,		// 117 - 'u'
    0,		// 118 - 'v'
    0,		// 119 - 'w'
    0,		// 120 - 'x'
    0,		// 121 - 'y'
    0,		// 122 - 'z'
    0,		// 123 - '{'
    2, 255, 255,		// 124 - '|'
    0,		// 125
    0,		// 126
    0,		// 127
    0,		// 128
    0,		// 129
    0,		// 130
    0,		// 131
    0,		// 132
    0,		// 133
    0,		// 134
    0,		// 135
    0,		// 136
    0,		// 137
    0,		// 138
    0,		// 139
    0,		// 140
    0,		// 141
    0,		// 142
    0,		// 143
    0,		// 144
    0,		// 145
    0,		// 146
    0,		// 147
    0,		// 148
    0,		// 149
    0,		// 150
    0,		// 151
    0,		// 152
    0,		// 153
    0,		// 154
    0,		// 155
    0,		// 156
    0,		// 157
    0,		// 158
    0,		// 159
    2, 0, 0,		// 160
    0,		// 161
    0,		// 162
    0,		// 163
    0,		// 164
    0,		// 165
    0,		// 166
    0,		// 167
    0,		// 168
    0,		// 169
    0,		// 170
    0,		// 171
    0,		// 172
    0,		// 173
    2, 0, 0,		// 174
    0,		// 175
    10, 124, 254, 3, 3, 3, 3, 3, 3, 254, 124,		// 176
    10, 0, 0, 0, 0, 0, 0, 0, 0, 254, 124,		// 177
    10, 0, 2, 131, 131, 131, 131, 131, 131, 254, 124,		// 178
    10, 0, 130, 131, 131, 131, 131, 131, 131, 254, 124,		// 179
    10, 124, 254, 128, 128, 128, 128, 128, 128, 254, 124,		// 180
    10, 124, 254, 131, 131, 131, 131, 131, 131, 2, 0,		// 181
    10, 124, 254, 131, 131, 131, 131, 131, 131, 2, 0,		// 182
    10, 0, 2, 3, 3, 3, 3, 3, 3, 254, 124,		// 183
    10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124,		// 184
    10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124,		// 185
    2, 96, 96,		// 186
    0,		// 187
    0,		// 188
    0,		// 189
    0,		// 190
    0,		// 191
    0,		// 192
    10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124,		// 193
    10, 124, 254, 128, 128, 128, 128, 128, 128, 0, 0,		// 194
    10, 0, 0, 128, 128, 128, 128, 128, 128, 0, 0,		// 195
    10, 0, 0, 128, 128, 128, 128, 128, 128, 254, 124,		// 196
    10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0,		// 197
    10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0,		// 198
    0,		// 199
    0,		// 200
    0,		// 201
    0,		// 202
    0,		// 203
    0,		// 204
    0,		// 205
    0,		// 206
    0,		// 207
    0,		// 208
    0,		// 209
    0,		// 210
    0,		// 211
    0,		// 212
    0,		// 213
    0,		// 214
    0,		// 215
    0,		// 216
    0,		// 217
    0,		// 218
    0,		// 219
    0,		// 220
    0,		// 221
    0,		// 222
    0,		// 223
    0,		// 224
    10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124,		// 225
    10, 124, 254, 128, 128, 128, 128, 128, 128, 0, 0,		// 226
    10, 0, 0, 128, 128, 128, 128, 128, 128, 0, 0,		// 227
    10, 0, 0, 128, 128, 128, 128, 128, 128, 254, 124,		// 228
    10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0,		// 229
    10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0,		// 230
    0,		// 231
    0,		// 232
    0,		// 233
    0,		// 234
    0,		// 235
    0,		// 236
    0,		// 237
    0,		// 238
    0,		// 239
    0,		// 240
    0,		// 241
    0,		// 242
    0,		// 243
    0,		// 244
    0,		// 245
    0,		// 246
    0,		// 247
    0,		// 248
    0,		// 249
    0,		// 250
    0,		// 251
    2, 255, 255,		// 252
    0,		// 253
    0,		// 254
    0,		// 255
  };

#endif
Aperçu police horloge

j’obtiens , alors l’affichage suivant.

Affichage Horloge format XL

Ci dessous le code complet

// Tuto affichage double taille Horloge
// Byfeel 2019
// ****************************
// Exemple affichage  horloge synchronisé via NTP
//  sur 4 module de 4 Matrices Led 72xx
//
// Selon Module , il faudra brancher les matrices de deux façon differentes
// * Modules ( type FC16 ou ICSstation ) - Type ZigZag
//  n n-1 n-2 ... n/2+1   <- Matrice haute
//  n/2 ... 3  2  1  0    <- Matrice basse
//
// * Modules (Parola ou Generic )  - type S
//  n/2+1 ... n-2 n-1 n   -> Matrice haute
//  n/2 ... 3  2  1  0    <- Matrice basse

// Bibliotheque à inclure
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Clock.h"
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
//****************************************************
// En fonction de vos matrices , si probléme         *
// d'affichage ( inversé , effet miroir , etc .....) *
// ***************************************************
// matrix   - decocher selon config matrix    ********
//#define HARDWARE_TYPE MD_MAX72XX::FC16_HW        //***
//#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW    //***
#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW //***
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW   //***
// ***************************************************
// Taille des deux zones
#define MAX_ZONES 2
#define ZONE_SIZE 8
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
// Définition de la zone inferieur et de la zone superieur
#define ZONE_UPPER  1
#define ZONE_LOWER  0
// gestion des effets
#define PAUSE_TIME 0
#define SCROLL_SPEED 60
// Branchement des matrices
#define CLK_PIN   14  // SCK (D5 wemos D1 ou mini )
#define DATA_PIN  13  // MOSI ( D7 wemos D1 ou mini )
#define CS_PIN    15  // SS ( GPIO 15 sur D1  ou D8 sur Mini )

const char *ssid     = "Votre SSID";
const char *password = "Votre password";

WiFiUDP ntpUDP;

// By default 'pool.ntp.org' is used with 60 seconds update interval and
// no offset
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000);

//variable pour inversion zone superieur selon module
bool invertUpperZone = false;  // Type ICS ou FC16

// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// définition des chaines de stockage pour les zones inf et sup
char *msgH; 
char msgL[15]; // un buffer de 15 caractères au max

// Message a afficher
String Msg="00:00";

// chaine decalage
void createHString(char *pH, char *pL)
{
  for (; *pL != '\0'; pL++)  *pH++ = *pL | 0x80;   // decalage caractére en positionnant le 8 bit ( 128) à 1
    *pH = '\0'; // termine la chaine
}

void getDisplayClock(char *psz, bool f = true)
// Code pour affichage time
{
  sprintf(psz, "%02d%c%02d", timeClient.getHours(), (f ? ':' : ' '), timeClient.getMinutes());

}

void setup() {
    WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    //Serial.print ( "." );
  }

  timeClient.begin();
  
// transfére de la chaine String dans la chaine inférieur  
  Msg.toCharArray( msgL,15);
  uint8_t max = 0;
  // Selon modele des matrices - inversion de l'affichage ( true si Generic ou Parola )
  invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
 
//calcul taille champs à afficher et allocation mémoire
    if (strlen(msgL) > max) max = strlen(msgL);
     msgH = (char *)malloc(sizeof(char)*(max + 2));

  // initialisation des Zones
  P.begin(MAX_ZONES);

  // Création des deux Zones pour les deux moitiés d'affichage
  P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
  P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
  // police de caractére à afficher
  P.setFont(numeric7SegDouble);
  
  // Selon type module inversion ou non de la zone supérieur 
  if (invertUpperZone)
  {
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
    P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
  }
}

void loop() {
  timeClient.update();
   static uint32_t  lastTime = 0; // millis() memory
  static bool flasher = false;  // seconds passing flasher
  
  P.displayAnimate();
// l'animation commence
  if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
  {
     if (millis() - lastTime >= 1000)
    {
      lastTime = millis();
      getDisplayClock(msgL, flasher);
       createHString(msgH, msgL);  // fabrique la chaine Supérieur
      flasher = !flasher;
    }
    
     //P.displayClear();
     
    P.displayZoneText(ZONE_LOWER, msgL, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
    P.displayZoneText(ZONE_UPPER, msgH, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);

  P.synchZoneStart();
  }

}

A vous de jouer , pour vous créer une horloge ou un bandeau de notification de taille XL !
Et pourquoi pas un Notifheure de taille XL ?

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

16 commentaires sur “Affichage XL pour Matrice LED 72xx”

%d blogueurs aiment cette page :