Écran TFT ST7735 et encodeur rotatif avec Arduino
J’ai découvert assez récemment l’écran TFT couleur ST7735. Avec sa technologie TFT LCD qui lui permet d’afficher des nuances de couleur 16bits, sa diagonale de 4,5 cm et sa résolution de 128×160 j’ai rapidement été emballé.
La principale difficulté de cet écran est la nécessitée de s’interfacer en signaux logique 3,3V alors que la majorité des cartes Arduino est en logiques 5V. Nous verrons au chapitre suivant comment adresser ce point.
Concernant le type de carte Arduino, vous avez le choix entre 3 cartes pour ce tutoriel: Arduino Uno, Arduino Mega et Michelino. La carte Michelino offre l’avantage d’intégrer nativement l’écran TFT couleur ST7735 et l’encodeur rotatif. (Vous n’avez donc pas de fil qui se déconnecte ou d’encodeur instable sur la platine d’essai).
Si vous souhaitez que ce projet aborde également d’autre cartes (ESP32, ESP8285, ou autre), laissez moi un petit message dans les commentaires afin que j’enrichisse l’article.
Le matériel nécessaire
Pour ce projet, vous pouvez soit utiliser la carte Michelino intégrant nativement l’écran et l’encodeur rotatif:
soit effectuer le montage vous même à l’aide d’une carte Arduino Mega 2560 ou Arduino Uno et différents composants électroniques requis:
Câblage
L’écran TFT couleur ST7735 repose sur une liaison SPI (Serial Peripheral Interface). Les broches importantes pour le bus SPI sont les broches SCK, MISO et MOSI qui diffèrent selon les carte Arduino utilisées. Celles-ci sont résumées dans le tableau suivant:
SCK | MISO | MOSI | |
Arduino UNO | 13 | 12 | 11 |
Arduino Mega 2560 | 52 | 50 | 51 |
Michelino (ATmega128) | 9 | 11 | 10 |
Comme indiqué précédemment, il n’est pas possible de relier directement les broches de l’écran TFT ST7735 à la carte Arduino Uno ou Arduino Mega sous peine d’endommager l’écran car les tensions logiques sont différentes. Plusieurs solutions sont possibles pour convertir les signaux logiques 5V en signaux logiques 3,3V comme par exemple l’utilisation de transistors. Dans cet article, le choix a été fait d’ajouter des résistances d’1 kOhm pour abaisser la tension du signal. C’est une solution simple et robuste.
Câblage de l’écran TFT ST7735 et de l’encodeur avec la carte Michelino
L’encodeur rotatif et l’écran TFT ST7735 sont déjà présents sur la carte Michelino. Aucun câblage n’est nécessaire.
Câblage de l’écran TFT ST7735 et de l’encodeur avec la carte Arduino Uno
Le câblage de l’écran TFT Couleur ST7735 et de l’encodeur rotatif avec l’Arduino Uno est le suivant:
Pour l’alimentation de l’écran:
- Fil rouge, la broche VCC est à relier au +3,3v de l’Arduino Uno.
- Fil noir, la broche GND est à brancher à la masse de l’Arduino Uno.
- Fil violet, la broche BL (BackLight) est à relier à la sortie 7 de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm.
Pour le transfert des données depuis l’Arduino Uno vers l’écran :
- Fil vert, la broche SCL (Serial Clock Line) de l’écran à la sortie 13 (SCK de l’interface SPI) de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm. C’est pour le signal de synchronisation .
- Fil jaune, la broche SDA (Serial Data Line) à la sortie 11 (MOSI de l’interface SPI) de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm. C’est pour les données d’affichage.
- Fil blanc, la broche RES (Reset) à la sortie 10 de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm. C’est pour réinitialiser l’écran.
- Fil gris, la broche DC (Data/Command Select) à la sortie 9 de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm. C’est pour sélectionner l’utilisation en “Donnée” ou ”Commande” des signaux envoyés sur la broche SDA.
- Fil orange, la broche CS (Chip/Slave Select) à la sortie 8 de l’Arduino Uno par l’intermédiaire d’une résistance 1 kOhm. C’est pour la sélection du destinataire.
Pour la détection du mouvement de rotation de l’encodeur rotatif:
- Fil bleu, la broche du signal B de l’encodeur est branchée à l’entrée 6 de l’Arduino Uno.
- Fil noir, la broche commune C de la partie rotative de l’encodeur est reliée à la masse de l’Arduino Uno.
- Fil blanc, la broche du signal A de l’encodeur est branchée à l’entrée 5 de l’Arduino Uno.
Pour le bouton poussoir de l’encodeur rotatif:
- Fil noir, la broche E de l’encodeur est à la masse de l’Arduino Uno.
- Fil gris, la broche D de l’encodeur est reliée à l’entrée 4 de l’Arduino Uno.
Câblage de l’écran TFT ST7735 et de l’encodeur avec la carte Arduino Mega 2560
Le câblage de l’écran TFT Couleur ST7735 et de l’encodeur rotatif avec l’Arduino Mega est le suivant:
Pour l’alimentation de l’écran:
- Fil rouge, la broche VCC est à relier au +3,3v de l’Arduino Mega.
- Fil noir, la broche GND est à brancher à la masse de l’Arduino Mega.
- Fil violet, la broche BL (BackLight) est à relier à la sortie 7 de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm.
Pour le transfert des données depuis l’Arduino Uno vers l’écran :
- Fil vert, la broche SCL (Serial Clock Line) de l’écran à la sortie 52 (SCK de l’interface SPI) de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm. C’est pour le signal de synchronisation .
- Fil jaune, la broche SDA (Serial Data Line) à la sortie 51 (MOSI de l’interface SPI) de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm. C’est pour les données d’affichage.
- Fil blanc, la broche RES (Reset) à la sortie 10 de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm. C’est pour réinitialiser l’écran.
- Fil gris, la broche DC (Data/Command Select) à la sortie 9 de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm. C’est pour sélectionner l’utilisation en “Donnée” ou ”Commande” des signaux envoyés sur la broche SDA.
- Fil orange, la broche CS (Chip/Slave Select) à la sortie 8 de l’Arduino Mega par l’intermédiaire d’une résistance 1 kOhm. C’est pour la sélection du destinataire.
Pour la détection du mouvement de rotation de l’encodeur rotatif:
- Fil bleu, la broche du signal B de l’encodeur est branchée à l’entrée 6 de l’Arduino Mega.
- Fil noir, la broche commune C de la partie rotative de l’encodeur est relié à la masse de l’Arduino Uno.
- Fil blanc, la broche du signal A de l’encodeur est branchée à l’entrée 5 de l’Arduino Mega.
Pour le bouton poussoir de l’encodeur rotatif:
- Fil noir, la broche E de l’encodeur est à la masse de l’Arduino Mega.
- Fil gris, la broche D de l’encodeur est reliée à l’entrée 4 de l’Arduino Mega.
Les bibliothèques utilisées
Pour la gestion de l’écran, j’ai choisi la bibliothèque Arduino “lcdgfx” de “Alexey Dynda” qui permet entre autres fonctionnalités intéressante, d’afficher des images stockées en mémoire flash et de gérer des menus.
Il y a beaucoup de bibliothèques pour gérer les encodeurs rotatifs, celle que je préfère est celle d’ “AlexGyver” nommée “EncButton”. Elle est à la fois simple à utiliser et offre de bonnes performances.
Je vous invite à installer ces 2 bibliothèques.
Si vous souhaitez connaitre la procédure d’installation d’une bibliothèque sous Arduino, vous pouvez vous reporter au chapitre “Installation d’une bibliothèque pour l’écran OLED” de l’article “Température et humidité avec Arduino”.
Premier affichage et première saisie de valeur
A fin de de monter en connaissance sur ce montage, nous allons commencer par afficher le message “Coucou” à l’écran suivi d’une valeur numérique comprise entre 0 et 99 qui pourra être modifiée à l’aide de l’encodeur rotatif. Cela nous permettra de:
- vérifier le câblage du projet,
- vérifier l’environnement Arduino,
- mettre en place les bases des interfaces avec l’écran TFT couleur ST7735 et avec l’encodeur rotatif.
Affichage de “Coucou”
Comme d’habitude, nous démarrons l’écriture du logiciel par l’ossature de code Arduino suivante:
// Fonction de démarrage, s'exécute une seule fois: void setup() { } // Fonction principale du programme, s'exécute en boucle: void loop() { }
Nous ajoutons la déclaration de la bibliothèque de gestion de l’écran TFT ST7735:
/* Déclaration des bibliothèques utilisées */ #include <lcdgfx.h>
Puis, nous déclarons des alias pour les ports utilisés par l’écran TFT ST7735 dans notre projet. C’est à dire pour la carte Arduino Michelino :
// Ports d'E/S pour la carte Michelino //////////////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 40 #define PORT_ECRAN_CS 38 #define PORT_ECRAN_DC 39 #define PORT_ECRAN_MOSI_SDA 10 #define PORT_ECRAN_SCK_SCL 9 #define PORT_ECRAN_ECLAIRAGE 37
pour la carte Arduino Uno :
// Ports d'E/S pour la carte Mega Uno ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 11 #define PORT_ECRAN_SCK_SCL 13 #define PORT_ECRAN_ECLAIRAGE 7
et enfin pour la carte Mega 2560 :
// Ports d'E/S pour la carte Mega 2560 ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 51 #define PORT_ECRAN_SCK_SCL 52 #define PORT_ECRAN_ECLAIRAGE 7
La librairie lcdgfx met à disposition des classes d’objets différentes selon les caractéristiques de l’écran utilisé (protocole de communication, driver de l’écran, résolution, etc.). La classe correspondant à l’écran de cet article est la classe “DisplayST7735_128x160x16_SPI” dont les paramètres sont les suivant:
- “rstPin” -> La broche de réinitialisation de l’écran
- “busId” -> Ce paramètre n’est pas utile pour les cartes Arduino de notre projet, aussi nous le positionnons à la valeur “-1”.
- “dc” -> La broche DC de l’interface SPI avec l’écran.
- “frequency” -> La fréquence (exprimée en Hertz) à laquelle sera rafraichie l’écran. La valeur 0 permet de sélectionner la fréquence la plus élevée supportée par notre carte Arduino.
- “scl” -> La broche SCL de l’interface SPI avec l’écran.
- “sda” -> La broche SDA de l’interface SPI avec l’écran.
On en déduit la ligne de code suivante pour la création de l’objet “afficheur_g” qui va nous permettre de piloter l’écran:
// Déclaration globales DisplayST7735_128x160x16_SPI afficheur_g = DisplayST7735_128x160x16_SPI(PORT_ECRAN_RESET,{-1, PORT_ECRAN_CS, PORT_ECRAN_DC, 0, PORT_ECRAN_MOSI_SDA, PORT_ECRAN_SCK_SCL});
Au démarrage du programme il est nécessaire d’initialiser l’écran par la méthode “begin” de notre objet afficheur_g:
afficheur_g.begin(); // Initialisation de l'écran
La configuration par défaut de l’orientation de l’écran TFT couleur ST7735 est l’orientation verticale. Afin d’être conforme à l’orientation habituelle des écrans de notre quotidien, nous utilisons la méthode “getInterface().setRotation” qui prend la valeur de rotation comme paramètre:
- 0 -> normal
- 1 -> 90° ( dans le sens des aiguilles d’une montre)
- 2 -> 180°
- 3 -> 270°
La ligne suivant nous permet d’avoir un écran TFT ST7735 horizontal:
afficheur_g.getInterface().setRotation(1); // Rotation de l'écran de 90°
Il est temps maintenant de sélectionner la police de caractères que nous souhaitons utiliser. La bibliothèque “lcdgfx” offre la possibilité de définir et utiliser ses propres polices de caractères. Dans ce premier exemple nous utilisons la police ssd1306xled_font8x16 de Neven Boyanov déjà incluse dans la librairie:
afficheur_g.setFixedFont(ssd1306xled_font8x16); // Sélection de la police ssd1306xled 8x16
Le drivers de l’écran TFT couleur ST7735 mémorise la matrice d’affichage même après une coupure de son alimentation. En début de programme, il est donc important d’effacer l’écran par un appel à la méthode “clear”.
afficheur_g.clear(); // Effacement de l'écran
L’écran TFT ST7735 de ce tutoriel est un écran “couleur”, nous pouvons donc mettre de la couleur à notre texte.
Pour cela nous utilisons la fonction “RGB_COLOR16” pour calculer la couleur au format 16 bits à partir de l’intensité des 3 couleurs de bases (rouge, vert et bleu) passées en paramètres.
#define BLEU RGB_COLOR16(0, 0, 255)
Puis nous appelons la méthode “setColor” de notre objet afficheur_g avec pour paramètre la couleur au format 16 bits précédemment calculée.
afficheur_g.setColor(BLEU);
L’écriture d’un texte à une position précise de l’écran se fait par la méthode “printFixed” de notre objet afficheur_g avec en paramètres:
- la position X du texte,
- la position y du texte,
- l’adresse de la chaine de caractères à afficher,
- le style à utiliser: soit “STYLE_NORMAL” (normal) soit “STYLE_BOLD” (gras).
Pour calculer les position X et Y du texte, il est à rappeler qu’en position horizontale, l’écran TFT couleur ST7735 se compose de 128 lignes de 160 points. L’origine des coordonnées des points se situe sur le sommet gauche. Un texte de 9 caractères utilisant une police de 8 x 16 sera donc centré en l’affichant au coordonnées:
- x= (160-9×8)/2 = 44:
- y = (128 -16)/2 = 56
Ce qui nous donne la ligne de code suivante pour l’affichage du texte:
afficheur_g.printFixed (44, 56 , "Coucou", STYLE_NORMAL);
Affichage d’une valeur numérique dynamique
Nous commençons par déclarer notre variable en globale :
uint8_t valeur_g;
Puis lui assignons une valeur initiale au démarrage:
valeur_g = 50;
Cette valeur nécessite d’être convertie en chaine de caractères avant son affichage. Aussi nous déclarons un tableaux de caractère tampons.
char texte_valeur_l[3];
et utilisons la fonction snprintf pour la conversion.
snprintf(texte_valeur_l, sizeof(texte_valeur_l), "%2d", valeur_g);
Pour l’affichage en lui même, nous utilisons de nouveau la méthode “printFixed” de notre objet afficheur_g en décalant la position de 7 caractères (1 caractère d’espacement).
afficheur_g.printFixed (44+7*8, 56 , texte_valeur_l, STYLE_NORMAL);
L’affichage de la valeur numérique dynamique va s’effectuer dans la fonction “loop” de notre programme qui est appelée en permanence. Comme l’affichage sur l’écran TFT dure un temps non négligeable (temps de communication SPI + temps de traitement de l’écran TFT), nous n’afficherons cette valeur que lorsque celle-ci sera modifiée.
Pour détecter cette modification nous créons le booléen valeur_modifiee_g que nous positionnerons à “vrai” lorsqu’un affichage sera nécessaire.
valeur_modifiee_g = true;
et que nous testerons avant l’affichage de la valeur numérique.
if(valeur_modifiee_g) { snprintf(texte_valeur_l, sizeof(texte_valeur_l), "%2d", valeur_g); afficheur_g.printFixed (44+7*8, 56 , texte_valeur_l, STYLE_NORMAL); valeur_modifiee_g = false; }
Modification de la valeur à l’aide de l’encodeur rotatif
Nous complétons la déclaration des bibliothèque avec celle choisi pour l’encodeur rotatif.
#include <EncButton.h>
Dans un souci de clarté du code, nous définissons des alias pour les ports de l’encodeur rotatif.
Ces ports diffèrent entre la carte Michelino…
/* Encodeur */ #define PORT_BOUTON_SELECTION 43 #define PORT_ENCODEUR_ROTATIF_1 41 #define PORT_ENCODEUR_ROTATIF_2 42
.. et les cartes Uno et Mega 2560.
/* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6
La librairie EncButton propose plusieurs classes d’objet. Celle correspond antle mieux à notre utilisation est la classe “EncButton” dont les paramètres de template sont les suivants:
- “EB_MODE” -> Il est possible d’utiliser la librairie sous 2 modes: le mode “EB_TICK” ou le mode “EB_CALLBACK”. Nous choisissons le mode “EB_TICK” plus simple à manipuler.
- “S1” -> La broche A de l’encodeur rotatif
- “S2” -> La broche B de l’encodeur rotatif
- “KEY” -> La broche reliée au bouton poussoir de l’encodeur rotatif
En faisant le lien avec les ports utilisés pour notre projet, nous obtenons:
EncButton <EB_TICK, PORT_ENCODEUR_ROTATIF_1, PORT_ENCODEUR_ROTATIF_2, PORT_BOUTON_SELECTION> encodeur_g;
Dans le mode “EB_TICK” choisi pour la gestion de l’encodeur, le rafraichissement de l’objet encodeur_g s’effectue par la méthode “tick”:
encodeur_g.tick();
La classe “EncButton” offre les méthodes “left” et “right” pour déterminer si une rotation de l’encodeur a eu lieu et son sens. Nous allons utiliser ces deux méthode pour incrémenter ou décrémenter la valeur numérique affichée:
if(encodeur_g.left()&&(valeur_g<99)) { valeur_g++; valeur_modifiee_g = true; } else if (encodeur_g.right()&&(valeur_g>0)) { valeur_g--; valeur_modifiee_g = true; }
Voici le récapitulatif de notre programme à ce stade du tutoriel:
/* Déclaration des bibliothèques utilisées */ #include <lcdgfx.h> #include <EncButton.h> /* Déclaration des headers utilisées */ #include "image.h" #if defined(__AVR_ATmega128__) // Ports d'E/S pour la carte Michelino ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 40 #define PORT_ECRAN_CS 38 #define PORT_ECRAN_DC 39 #define PORT_ECRAN_MOSI_SDA 10 #define PORT_ECRAN_SCK_SCL 9 #define PORT_ECRAN_ECLAIRAGE 37 /* Encodeur */ #define PORT_BOUTON_SELECTION 43 #define PORT_ENCODEUR_ROTATIF_1 41 #define PORT_ENCODEUR_ROTATIF_2 42 #elif defined(ARDUINO_AVR_UNO) // Ports d'E/S pour la carte Mega Uno ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 11 #define PORT_ECRAN_SCK_SCL 13 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #elif defined(ARDUINO_AVR_MEGA2560) // Ports d'E/S pour la carte Mega 2560 ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 51 #define PORT_ECRAN_SCK_SCL 52 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #endif #define BLEU RGB_COLOR16(0, 0, 255) // Déclaration globales DisplayST7735_128x160x16_SPI afficheur_g = DisplayST7735_128x160x16_SPI(PORT_ECRAN_RESET,{-1, PORT_ECRAN_CS, PORT_ECRAN_DC, 0, PORT_ECRAN_MOSI_SDA, PORT_ECRAN_SCK_SCL}); EncButton <EB_TICK, PORT_ENCODEUR_ROTATIF_1, PORT_ENCODEUR_ROTATIF_2, PORT_BOUTON_SELECTION> encodeur_g; uint8_t valeur_g; bool valeur_modifiee_g; // Fonction de démarrage, s'exécute une seule fois: void setup() { afficheur_g.begin(); // Initialisation de l'écran afficheur_g.getInterface().setRotation(1); // Rotation de l'écran de 90° afficheur_g.setFixedFont(ssd1306xled_font8x16); // Sélection de la police ssd1306xled 8x16 afficheur_g.clear(); // Effacement de l'écran afficheur_g.setColor(BLEU); afficheur_g.printFixed (44, 56 , "Coucou", STYLE_NORMAL); valeur_g = 50; valeur_modifiee_g = true; encodeur_g.tick(); } // Fonction principale du programme, s'exécute en boucle: void loop() { char texte_valeur_l[3]; encodeur_g.tick(); if(encodeur_g.left()&&(valeur_g<99)) { valeur_g++; valeur_modifiee_g = true; } else if (encodeur_g.right()&&(valeur_g>0)) { valeur_g--; valeur_modifiee_g = true; } if(valeur_modifiee_g) { snprintf(texte_valeur_l, sizeof(texte_valeur_l), "%2d", valeur_g); afficheur_g.printFixed (44+7*8, 56 , texte_valeur_l, STYLE_NORMAL); valeur_modifiee_g = false; } }
Dans le code précédent, vous avez surement remarqué l’utilisation d’instructions de compilation conditionnelle #if, #elif et #endif afin d’avoir un code commun aux 3 cartes Arduino. Ces instructions testent la définition ou la non-définition de macros résultant du choix du type de carte dans la liste du gestionnaire de carte de l’Arduino IDE.
Afin de valider cette première étape, nous allons compiler ce programme puis le transférer dans la carte Arduino. Vous devez obtenir le résultat suivant pour l’Arduino Uno:
pour la carte Michelino: |
pour l’Arduino Mega: |
Avez-vous remarqué les parasites sur le bord inférieur et le coté droit de l’écran ? C’est un peu moche non ? Rassurez-vous, nous allons le corriger au prochain paragraphe. 🙂
Correction du décalage de l’écran TFT ST7735
Les parasites que vous pouvez-voir sur les bords de l’écran TFT couleur ST7735 sont dus à un décalage entre l’origine des coordonnées de l’écran TFT physique et l’origine des coordonnées renseignées par défaut en usine dans le driver ST7735.
Afin de caractériser ce problème et faciliter sa résolution, je vous propose de tracer un cadre rouge d’1 pixel d’épaisseur tout autour de l’écran.
Comme précédemment, la fonction “RGB_COLOR16” est utilisée pour calculer la couleur rouge au format 16 bits.
#define ROUGE RGB_COLOR16(255,0,0)
Et la méthode “setColor” de notre objet afficheur_g permet de la sélectionner.
afficheur_g.setColor(ROUGE);
Le dessin du rectangle se réalise à l’aide de la méthode “drawRect” de notre objet afficheur_g avec en paramètres les coordonnées X et Y de deux coins:
- le coin supérieur gauche ( 0, 0 dans notre cas )
- le coin inférieur droit ( 159, 127 dans notre cas )
afficheur_g.drawRect(0, 0, 159, 127); // Trace un cadre tout autour de l'écran
Maintenant que la bordure de l’écran est dessinée, nous allons utiliser la méthode “getInterface().setOffset” pour corriger les coordonnées d’origine par défaut du driver ST7735. Les valeurs de décalage de l’offset à renseigner en paramètre sont à déterminer de manière empirique par le moyen d’essais successif avec différentes valeurs jusqu’à temps que la bordure rouge apparaisse complétement à l’écran.
Pour ma part, les valeurs obtenues sont de 2 en abscisse et 1 en ordonnée:
afficheur_g.getInterface().setOffset(2,1); // Correction du décalage de l'origine des coordonnées
donc le code complet est le suivant:
/* Déclaration des bibliothèques utilisées */ #include <lcdgfx.h> #include <EncButton.h> /* Déclaration des headers utilisées */ #include "image.h" #if defined(__AVR_ATmega128__) // Ports d'E/S pour la carte Michelino ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 40 #define PORT_ECRAN_CS 38 #define PORT_ECRAN_DC 39 #define PORT_ECRAN_MOSI_SDA 10 #define PORT_ECRAN_SCK_SCL 9 #define PORT_ECRAN_ECLAIRAGE 37 /* Encodeur */ #define PORT_BOUTON_SELECTION 43 #define PORT_ENCODEUR_ROTATIF_1 41 #define PORT_ENCODEUR_ROTATIF_2 42 #elif defined(ARDUINO_AVR_UNO) // Ports d'E/S pour la carte Mega Uno ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 11 #define PORT_ECRAN_SCK_SCL 13 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #elif defined(ARDUINO_AVR_MEGA2560) // Ports d'E/S pour la carte Mega 2560 ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 51 #define PORT_ECRAN_SCK_SCL 52 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #endif #define BLEU RGB_COLOR16(0, 0, 255) #define ROUGE RGB_COLOR16(255,0,0) // Déclaration globales DisplayST7735_128x160x16_SPI afficheur_g = DisplayST7735_128x160x16_SPI(PORT_ECRAN_RESET,{-1, PORT_ECRAN_CS, PORT_ECRAN_DC, 0, PORT_ECRAN_MOSI_SDA, PORT_ECRAN_SCK_SCL}); EncButton <EB_TICK, PORT_ENCODEUR_ROTATIF_1, PORT_ENCODEUR_ROTATIF_2, PORT_BOUTON_SELECTION> encodeur_g; uint8_t valeur_g; bool valeur_modifiee_g; // Fonction de démarrage, s'exécute une seule fois: void setup() { afficheur_g.begin(); // Initialisation de l'écran afficheur_g.getInterface().setRotation(1); // Rotation de l'écran de 90° afficheur_g.getInterface().setOffset(2,1); // Correction du décalage de l'origine des coordonnées afficheur_g.setFixedFont(ssd1306xled_font8x16); // Sélection de la police ssd1306xled 8x16 afficheur_g.clear(); // Effacement de l'écran afficheur_g.setColor(ROUGE); afficheur_g.drawRect(0, 0, 159, 127); // Trace un cadre tout autour de l'écran afficheur_g.setColor(BLEU); afficheur_g.printFixed (44, 56 , "Coucou", STYLE_NORMAL); valeur_g = 50; valeur_modifiee_g = true; encodeur_g.tick(); } // Fonction principale du programme, s'exécute en boucle: void loop() { char texte_valeur_l[3]; encodeur_g.tick(); if(encodeur_g.left()&&(valeur_g<99)) { valeur_g++; valeur_modifiee_g = true; } else if (encodeur_g.right()&&(valeur_g>0)) { valeur_g--; valeur_modifiee_g = true; } if(valeur_modifiee_g) { snprintf(texte_valeur_l, sizeof(texte_valeur_l), "%2d", valeur_g); afficheur_g.printFixed (44+7*8, 56 , texte_valeur_l, STYLE_NORMAL); valeur_modifiee_g = false; } }
Voici ce que vous obtenez une fois déterminés les bons paramètres x et y de la méthode “getInterface().setOffset” :
Gestion de la vitesse de rotation de l’encodeur avec Arduino
Comme le décalage des coordonnées d’origine de l’écran est corrigé, nous choisissions une couleur blanche plus douce pour l’affichage de la bordure de l’écran.
Procédons maintenant à une dernière amélioration du programme. Dans le cas de saisie de valeurs numériques importantes, comme par exemple le passage de 0 à 100 ou même de 0 à 500, l’utilisation de l’encodeur rotatif peut-être fastidieuse pour l’utilisateur. Pour améliorer l’expérience utilisateur, la rendre plus satisfaisante, nous allons ajouter la gestion de la rotation rapide de l’encodeur.
La classe EncButton propose la méthode “fast” pour détecter une rotation rapide de l’encodeur. Lorsque notre programme va détecter une rotation rapide de l’encodeur, l’incrément ou le décrément de la valeur numérique ne va pas être de 1 mais de 10 unités !
Voici le programme complet auquel vous devez arriver:
/* Déclaration des bibliothèques utilisées */ #include <lcdgfx.h> #include <EncButton.h> #if defined(__AVR_ATmega128__) // Ports d'E/S pour la carte Michelino ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 40 #define PORT_ECRAN_CS 38 #define PORT_ECRAN_DC 39 #define PORT_ECRAN_MOSI_SDA 10 #define PORT_ECRAN_SCK_SCL 9 #define PORT_ECRAN_ECLAIRAGE 37 /* Encodeur */ #define PORT_BOUTON_SELECTION 43 #define PORT_ENCODEUR_ROTATIF_1 41 #define PORT_ENCODEUR_ROTATIF_2 42 #elif defined(ARDUINO_AVR_UNO) // Ports d'E/S pour la carte Mega Uno ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 11 #define PORT_ECRAN_SCK_SCL 13 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #elif defined(ARDUINO_AVR_MEGA2560) // Ports d'E/S pour la carte Mega 2560 ////////////////////////////////////// /* Ecran */ #define PORT_ECRAN_RESET 10 #define PORT_ECRAN_CS 8 #define PORT_ECRAN_DC 9 #define PORT_ECRAN_MOSI_SDA 51 #define PORT_ECRAN_SCK_SCL 52 #define PORT_ECRAN_ECLAIRAGE 7 /* Encodeur */ #define PORT_BOUTON_SELECTION 4 #define PORT_ENCODEUR_ROTATIF_1 5 #define PORT_ENCODEUR_ROTATIF_2 6 #endif // Definition des couleurs de base au format RGB #define BLANC RGB_COLOR16(255,255,255) #define ROUGE RGB_COLOR16(255,0,0) #define VERT RGB_COLOR16(0,255,0) #define BLEU RGB_COLOR16(0, 0, 255) #define JAUNE RGB_COLOR16(255,255,0) #define CYAN RGB_COLOR16(0,255,255) #define MAGENTA RGB_COLOR16(255,0,255) // Déclaration globales DisplayST7735_128x160x16_SPI afficheur_g = DisplayST7735_128x160x16_SPI(PORT_ECRAN_RESET,{-1, PORT_ECRAN_CS, PORT_ECRAN_DC, 0, PORT_ECRAN_MOSI_SDA, PORT_ECRAN_SCK_SCL}); EncButton <EB_TICK, PORT_ENCODEUR_ROTATIF_1, PORT_ENCODEUR_ROTATIF_2, PORT_BOUTON_SELECTION> encodeur_g; uint8_t valeur_g; bool valeur_modifiee_g; uint16_t tableau_couleur_g[] = {BLANC, ROUGE, VERT, BLEU, JAUNE, CYAN, MAGENTA}; uint8_t index_couleur_g; // Fonction de démarrage, s'exécute une seule fois: void setup() { afficheur_g.begin(); // Initialisation de l'écran afficheur_g.getInterface().setRotation(1); // Rotation de l'écran de 90° afficheur_g.getInterface().setOffset(2,1); // Correction du décalage de l'origine des coordonnées afficheur_g.setFixedFont(ssd1306xled_font8x16); // Sélection de la police ssd1306xled 8x16 afficheur_g.clear(); // Effacement de l'écran afficheur_g.setColor(BLANC); afficheur_g.drawRect(0, 0, 159, 127); // Trace un cadre tout autour de l'écran afficheur_g.setColor(BLEU); afficheur_g.printFixed (44, 56 , "Coucou", STYLE_NORMAL); valeur_g = 50; valeur_modifiee_g = true; index_couleur_g = 0; encodeur_g.tick(); } // Fonction principale du programme, s'exécute en boucle: void loop() { char texte_valeur_l[3]; encodeur_g.tick(); if (encodeur_g.release()) { index_couleur_g++; // On vérifie que l'index ne dépasse pas la taille du tableau if (index_couleur_g>=sizeof(tableau_couleur_g)/sizeof(tableau_couleur_g[0])) { // Sinon on le repasse à 0 index_couleur_g = 0; } valeur_modifiee_g = true; } else if(encodeur_g.left()) { if(encodeur_g.fast()&&(valeur_g<89)) { valeur_g+=10; valeur_modifiee_g = true; } else if(valeur_g<99) { valeur_g++; valeur_modifiee_g = true; } } else if (encodeur_g.right()) { if(encodeur_g.fast()&&(valeur_g>=10)) { valeur_g-=10; valeur_modifiee_g = true; } else if(valeur_g>0) { valeur_g--; valeur_modifiee_g = true; } } if(valeur_modifiee_g) { snprintf(texte_valeur_l, sizeof(texte_valeur_l), "%2d", valeur_g); afficheur_g.setColor(tableau_couleur_g[index_couleur_g]); afficheur_g.printFixed (44+7*8, 56 , texte_valeur_l, STYLE_NORMAL); valeur_modifiee_g = false; } }
Une fois compilé puis transféré dans l’Arduino, nous obtenons pour la carte Michelino:
pour l’Arduino Mega: |
pour l’Arduino Uno: |
Voilà, nous avons maintenant non seulement vérifié le câblage de notre projet mais également utilisé les fonctions Arduino de base permettant de gérer à la fois un écran TFT couleur ST7735 et un encodeur rotatif.
Je vous propose maintenant d’aborder l’affichage d’image avec cet écran (page 2).
Bonjour,
A la compilation j’ai cette erreur :
fatal error: image.h: No such file or directory
#include “image.h”
^~~~~~~~~
compilation terminated.
exit status 1
Que dois-je faire ?
Merci de votre réponse
Cordialement
Bonjour Pascal,
avez vous bien inclus le fichier “image.h” dans votre projet comme décrit ici https://tropratik.fr/ecran-tft-couleur-st7735-et-encodeur-rotatif-avec-arduino/2#Creation-2eme-fichier ?
Ah , non, j’ai sauter cette étape. Je vais le faire !
Désolé pour ma négligence.
Merci pour votre réponse et sa rapidité.
Bonne journée et encore bravo pour votre travail !