Écran TFT ST7735 et encodeur rotatif avec Arduino

  • Auteur/autrice de la publication :
  • Post category:Arduino
  • Post comments:0 commentaire

Afficher une image sur l’écran TFT ST7735 avec Arduino

L’écran TFT ST7735 avec ses dégradés de couleur et sa résolution de 128×160 se prête bien à l’affichage d’image.

Dans ce paragraphe, nous allons voir qu’il est possible de partir d’un fichier image de dimension 160×128 au format .bmp, .png ou autre, disponible sur son PC,  de le convertir en code C (Arduino) et de l’afficher sur un TFT ST7735 couleur. L’encodage des couleurs utilisé ici sera de 16 bits par pixel, ce qui signifie qu’une image englobant la totalité de l’écran (160×128) nécessite 40 Ko (40960 octets) de mémoire.

Pour le cas particulier de la carte Arduino Uno, celle-ci ne possède que 32ko de mémoire flash auxquels il faut retirer 5ko occupé par le bootloader (programme d’amorçage). Une image réduite sera donc utilisée pour l’Arduino Uno.

Code logiciel de départ

Dans ce paragraphe, nous partons du code logiciel suivant:

/* Déclaration des bibliothèques utilisées */
#include <lcdgfx.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

// 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});

// 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.clear();  // Effacement de l'écran
}

// Fonction principale du programme, s'exécute en boucle:
void loop()
{
}

Choix de l’image

Concernant, l’image le choix de l’image est libre du moment qu’elle respecte les mêmes dimensions et le format cité précédemment. Pour ma part, j’utilise l’image libre de droit suivante :

au format 160×128 pour l’Arduino Mega et la carte Michelino

Image de sorcière aux dimensions de l'écran TFT couleur ST7735

au format 110×110 pour l’Arduino Uno qui possède une mémoire flash réduite

Image de sorcière aux réduite pour permettre son stockage dans l'Arduino Uno

Téléchargement et exécution de l’utilitaire de conversion

Pour convertir cette image en code logiciel compréhensible par le compilateur Arduino, je vous invite à télécharger l’outil également disponible ici.

Une fois dézippé, vous avez juste à cliquer sur l’exécutable “lcd-image-converter.exe” pour lancer l’application. Sélectionnez ensuite « Open… » dans le menu « File » et choisissez l’image que vous souhaitez convertir. 

Charger une image dans LCD Image Converter

Paramètres de conversion

Avant de convertir l’image, il est nécessaire de définir les paramètres pour la conversion. Pour cela, aller dans le menu « Options… » et choisir « Conversion… ».

Accéder aux paramètres de conversion dans LCD Image Converter

Vous atterrissez alors sur l’onglet “Prepare” des options de conversion. Il est à vérifier que la valeur par défaut du menu déroulant situé au dessus est bien “Color R5G6B5”.  Pour le reste, les paramètres par défaut de l’onglet “Prepare” sont satisfaisants.

Onglet 'Prepare' des paramètres de conversion de LCD Image Converter

Les paramètres par défaut de l’onglet “Matrix” n’ont pas besoin d’être modifiés.

Onglet 'Matrix' des paramètres de conversion de LCD Image Converter

Les paramètres par défaut de l’onglet “Reordering” sont également satisfaisants.

Onglet 'Reordering' des paramètres de conversion de LCD Image Converter

Sous l’onglet “Image” la valeur par défaut pour le “Block size” est à remplacer par la “8 bit” car nous utiliserons des tableaux d’octets.

Onglet 'Image' des paramètres de conversion de LCD Image Converter

Les valeurs des 2 autres onglets “Font” et “Template” n’ont pas d’importance pour notre projet. La fenêtre des paramètres peut être fermée.

Conversion de l’image

Pour réaliser la conversion de l’image en code C, allez dans le menu « File » et choisir « Convert… ». Une fenêtre demandera ensuite de choisir un nom de fichier C. Je choisis “Sorciere.c” pour ma part.

Lancer la conversion avec LCD Image Converter

Création d’un 2ème fichier de code logicel dans le répertoire projet de l’Arduino IDE

Pour une meilleure lisibilité de notre programme, nous créons un fichier dédié “Image.h” à l’aide de notre éditeur de texte favori (Notepad++ pour ma part mais le Bloc-notes de Windows suffit pour ce que nous avons à écrire). 

Le contenu initial de ce fichier “Image.h” est le suivant:

/*
  Image.h - Definitions des images utilisées pour l'affichage graphique.
*/
#ifndef Image_h
#define Image_h

#endif

Quelques explication sur le code précédent:

Définir un “Image_h” à l’aide de la directive “#define” uniquement s’il n’a pas déjà été défini permet d’empêcher de créer une boucle d’inclusion du fichier header lors de la compilation du programme. Pour plus de détails je vous invite à vous reporter à l’article Wikipédia Include guard.

L’ajout de ce fichier d’en-tête à votre projet Arduino s’effectue de la façon suivante:

1) Enregistrez le fichier “Image.h” au même endroit que votre fichier croquis (fichier .ino).

2) Fermez l’IDE Arduino

3) Ré-ouvrez votre projet dans l’éditeur Arduino,  un deuxième onglet apparait nommé “Image.h”.

4) Indiquez au compilateur qu’une partie de vos déclarations se situe dans un fichier séparé, en ajoutant l’instruction “#include” au début de votre fichier principal (.ino):

/* Déclaration des headers utilisées */
#include "image.h"

Voici à quoi doit ressembler votre projet sous l’IDE Arduino une fois le fichier “Image.h” inclus:

Inclusion du fichier "Image.h" au projet Arduino
Inclusion du fichier “Image.h” au projet Arduino

Insertion dans le programme Arduino du code généré

Du fait de la taille important de l’image, nous allons demander au compilateur de la stocker dans la mémoire flash du microcontrôleur plutôt que la mémoire SRAM plus réduite (emplacement par défaut). Pour cela, nous utilisons l’instruction PROGMEM et baptisons le tableau de stockage de cet image “Sorciere” dans le fichier “Image_h” :

const uint8_t Sorciere[] PROGMEM =
{

};

Une fois ce tableau déclaré, nous le remplissons par un copié/collé de l’énumération de valeurs hexadécimales du fichier “Sorciere.c” généré (la suite de valeurs “0x??” séparées par des virgules) représentant l’encodage de l’image. 

const uint8_t Sorciere[] PROGMEM =
{
  0x30, 0xa1, 0x30, 0xa1, 0x30, 0xa1, 0x30, 0xa1, 0x30, 0xc1, 0x38, 0xc1,
    ...
    et ainsi de suite
    ...
  0x41, 0x08, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20
};

Il ne reste plus qu’à demander à Arduino d’afficher cette image par un appel à la méthode drawBitmap16 de notre objet afficheur_g avec en paramètres:

  • la position X de l’image (son bord gauche),
  • la position y de l’image (son bord supérieur),
  • la largeur de l’image en nombre de pixels,
  • la hauteur de l’image en nombre de pixels.
  • l’adresse du tableau d’octet des données de l’image

Ce qui donne pour les cartes Michelino et Mega 2560 :

afficheur_g.drawBitmap16(0, 0, 160, 128, Sorciere);

et pour la carte carte Uno :

afficheur_g.drawBitmap16(0, 0, 110, 110, Sorciere);

Erreur de compilation pour les cartes Mega 2560 et Michelino

Lorsque vous lancer la compilation Arduino pour les cartes Mega 2560 et Michelino, vous tombez sur l’erreur ci dessous. Cette erreur de compilation n’est pas présente pour la carte Uno :

Erreur de compilation "size of variable is too large"

Mais que se passe-t-il ?

Il se passe que nous venons de déclarer un tableau de 40 Ko (40960 octets) de mémoire pour les cartes Michelino / Mega 2560 et un tableau de taille inférieur à 24 Ko (24200 octets) pour la carte Arduino Uno. Or l’environnement de dévelopement Arduino utilise le compilateur AVR-GCC qui limite la taille des tableaux à 32 Ko !

La solution que je vous propose est de découper l’image en 2 parties égales:

const uint8_t Sorciere_01[] PROGMEM =
{
  // Première partie de l'image (ligne 1 à 64)
};

const uint8_t Sorciere_02[] PROGMEM =
{
  // Deuxième partie de l'image (ligne 65 à 128)
};

Et d’effectuer deux appels successifs à la méthode drawBitmap16 pour afficher la partie supérieur puis la partie inférieur de l’image:

afficheur_g.drawBitmap16(0, 0, 160, 64, Sorciere_01);
afficheur_g.drawBitmap16(0, 64, 160, 64, Sorciere_02);

Code source pour afficher l’image et résultat

Du fait de la taille conséquent du fichier “Image_h”, vous trouverez le code source des projet sous forme de zip ci-dessous:

Une fois le code logiciel compilé puis transféré dans l’Arduino, voici ce que nous obtenons pour l’Arduino Mega:

Affichage d'une image sur l'écran TFT couleur ST7735 avec Arduino Mega

pour la carte Michelino:

Affichage d'une image sur l'écran TFT couleur ST7735 avec Arduino Michelino

pour l’Arduino Uno:

Affichage d'une image sur l'écran TFT couleur ST7735 avec Arduino Uno

Nous sommes à la fin du tutoriel. J’espère que cet article vous a plu et que vous êtes maintenant familiarisé avec l’utilisation sous Arduino d’un écran TFT couleur ST7735 et d’un encodeur rotatif.

Laisser un commentaire