Les écrans TFT sont devenus incontournables dans les projets d’électronique DIY, dès lors qu’on souhaite faire des affichages couleurs un peu complexe (avec des images, formes géométriques, etc). Parmi eux, on en trouve de plus ou moins grande taille. Aujourd’hui, je vous propose de découvrir les écrans TFT à contrôleur ILI9341, ayant une taille généralement comprise entre 2,2 et 3,5 pouces (plus précisément, je vous propose de voir un modèle 2,8 pouces, avec partie tactile, pour interagir avec lui !).
Nous verrons ici comment écrire du texte dessus (de différentes tailles/couleurs), comme dessiner des formes simples (lignes, rectangles, cercles, triangle, …), comment afficher des images, et enfin, comment prendre le contrôle de l’écran couleur TFT via sa surface tactile ! Et ce, piloté aussi bien depuis un Arduino Uno (5V), qu’un ESP32 (3,3V). Ça vous dit ? Alors en avant !
Remarque : afin de ne pas surcharger cet article, je me suis limité ici aux écrans TFT à puce ILI9341. Bien sûr, il en existe bien d’autres, permettant d’avoir des tailles/formes bien différentes, à l’image des modèles à contrôleur ST7735 ou GC9A01, par exemple. Je vous les détaillerai à l’occasion, dans d’autres articles ! Du reste, comme toujours, si vous relevez des coquilles ou autre, n’hésitez pas à m’en faire part en zone commentaire ! Bonne lecture à vous 🙂
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Caractéristiques des écrans TFT (à puce ILI9341)
Si je devais résumer, je dirais que les écrans TFT (équipés du contrôleur ILI9341) sont des écrans couleurs (65 536 couleurs), possédant une résolution de 240×320 pixels, et dont la taille (en diagonale) fait généralement de 2,2 à 3,5 pouces. Leur pilotage se fait en 3,3V via le bus SPI (lignes MOSI, MISO, SCK, sur Arduino), et leur alimentation peut se faire en 3,3V et/ou 5V (selon le fabricant). Et pour que ceux que ça intéresse, voici plus de détails !
Dimensions et tailles (TFT display à puce ILI9341)
Les écrans TFT reposant sur le contrôleur ILI9341 se déclinent en plusieurs tailles, généralement comprises entre 2,2 pouces et 3,5 pouces en diagonale (ce qui donne du 5,6 cm à 8,9 cm de longueur, en diagonale).
Les tailles les plus courantes sont, en diagonale :
- 2,4 pouces (6,1 cm), qui est très populaire pour les projets Arduino et ESP32, surtout pour démarrer
- 2,8 pouces (7,1 cm), qui est le meilleur compromis entre taille, lisibilité, et prix, selon moi
- 3,2 pouces (8,1 cm), qui est idéal pour les projets nécessitant un affichage plus grand
Ces tailles sont mesurées en diagonale, pour rappel, c’est à dire du coin bas/gauche au coin haut/droit (ou dans l’autre sens, si vous préférez !).
Résolution de l’écran
La résolution standard des écrans ILI9341 est de 240×320 pixels. Cela correspond à :
- soit 240 px de large sur 320 px de haut, si on est en « mode portrait » (afficheur posé verticalement)
- soit 240 px de haut sur 320 px de large, si on est en « mode paysage » (afficheur posé horizontalement)
En clair : vous aurez toujours 240×320 px de résolution, mais selon comment vous tournez votre écran, la largeur peut être la hauteur, et vice-versa 😉
Au passage, certains modèles (plus rares) peuvent proposer des résolutions légèrement différentes à celles évoquées ici, mais globalement, 240×320 reste la norme !
Du reste, cette résolution de 240 x 320 pixels (avec 65K couleurs différentes par pixel) offre un bon équilibre entre quantité/qualité d’éléments affichables à l’écran, et simplicité de pilotage (même si l’on travaille avec des microcontrôleurs à l’espace mémoire limité, comme celui présent sur l’Arduino Uno, par exemple).
Nombre de couleurs possibles, par pixel
Le contrôleur ILI9341, équipant les écrans TFT dont je vous parle ici, supporte 65 536 couleurs. Cela correspond à 216 couleurs, ce qui veut dire que chaque couleur est codée sur 16 bits. En sachant que chacune de ces 65536 couleurs est en fait un mélange des 3 couleurs « fondamentales », que sont le rouge, le vert, et le bleu. Ainsi, on obtient des couleurs allant du noir au blanc, en utilisant des nuances de rouge, vert, et bleu pour se faire (RVB en français, ou RGB en anglais, pour Red/Green/Blue).
Ces 3 nuances (quantités) de rouge/vert/bleu sont codées sur 16 de la manière suivante :
- 5 bits pour le rouge
- 6 bits pour le vert
- et 5 bits pour le bleu
Ce codage de couleurs se fait donc sur 16 bits ; c’est ce qu’on appelle le format RGB565 (ou RVB 565, en français !).
Vous noterez au passage qu’il y a un bit « supplémentaire » pour le vert (6 au lieu de 5), par rapport au rouge et au bleu. Mais rassurez-vous, cela ne rendra pas l’image plus verdâtre pour autant ! En fait, ce bit supplémentaire provient simplement du fait que 16 divisé par 3 ne donnait pas un nombre entier (16/3 = 5,33333), et qu’il aurait été dommage que de n’utiliser que 15 des 16 bits pour avoir 5 bits pour chaque couleur ! Du coup, pour remplir les 16 bits définissant la couleur, le choix a été fait « d’augmenter la précision » d’une de ces 3 couleurs (sur 6 bits au lieu de 5, ce qui donne 26 soit 64 niveaux de dégradé plutôt que 25 soit 32 niveaux de couleur), afin de profiter pleinement de cet espace offert. Et le choix s’est porté sur le « vert », car l’œil humain est en fait plus sensible aux nuances de vert. Le fait d’avoir 1 bit supplémentaire sur le vert permet d’améliorer donc la perception des couleurs sur l’écran TFT, tout en profitant pleinement des 16 bits codant chaque couleur !
Mais pourquoi avoir opté pour 16 bits à la base, au fait ?
Comme vous le savez certainement, on a tendance à regrouper les bits par « lots de 8 » (ce qu’on appelle des octets), pour quantifier/codifier les choses. Historiquement, cela provient du fait que les premiers caractères (ASCII) étaient codés sur 8 bits, et qu’ainsi tout était codé en « lot de 8 bits », ce qu’on a appelé des octets ; et cette mesure « d’octets » est restée jusqu’à maintenant (pour des raisons de compatibilité), même si elle a moins de sens aujourd’hui, sauf à réduire la taille des gros nombres par 8 ! L’octet s’est donc établi comme une norme, par convention, à travers les années. Du coup, les architectures physiques et informatiques se sont donc reposées sur cette base (octet), et ensuite, sur des multiples de cette base (2 octets, 4 octets, 8 octets, par exemple, pour du 16, 32, 64 bits), et ce, au fur et à mesure des évolutions. Et comme vous vous en doutez, le codage des couleurs s’est lui aussi reposé sur ce découpage en octets, ce qui a donné, lorsque pleinement utilisés :
- 8 bits = 256 couleurs
- 16 bits = 65K couleurs (65 536 couleurs)
- 24 bits = 16M couleurs (16 777 216 couleurs)
- etc.
Dans le cas de nos écrans TFT couleur, 16 bits était très certainement le meilleur compromis, pour un affichage en 320 x 240 pixels, pilotable en SPI via de simples microcontrôleurs ! Voilà, pour le petit bout d’histoire 😉
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Alimentation 3,3V ou 5V des écrans TFT (ILI9341)
Les écrans TFT ILI9341 fonctionnent généralement avec une tension d’alimentation de 3,3V et/ou 5V, selon le modèle. Aussi, afin d’éviter tout dommage électrique, vous devrez IMPÉRATIVEMENT consulter la documentation fabricant ou la récupérer auprès de votre vendeur, pour savoir quelle tension appliquer, au niveau de l’alimentation de votre TFT display.
Dans mon cas, comme support à ce tuto, j’utilise un écran TFT configurable en 3V3 ou 5V au niveau de son alim, comme on en trouve maintenant très souvent en vente sur le net. Et pour indiquer à l’écran TFT si on compte lui envoyer du +3,3V ou du +5V en alim, un simple jumper (2 plots de cuivre rapprochés) au dos du module TFT permet de spécifier ce choix. Ce jumper est noté « J1 », la plupart du temps, au dos du PCB de ces écrans TFT. Pour info :
- si J1 est ouvert (par défaut, sans pont de soudure), alors l’alimentation de l’écran TFT devra se faire en +5V
- si J1 est fermé (via un pont de soudure), alors l’alimentation de l’écran TFT devra se faire en +3,3V
Pour ceux que ça intéresse : ce jumper « J1 » est en fait un simple shunt placé entrée l’entrée et la sortie d’un régulateur de tension embarqué sur le PCB au dos de l’écran TFT. Si le shunt est ouvert, alors le régulateur fonctionne ; si le shunt est fermé, alors le régulateur est court-circuité.
Histoire d’être plus parlant, voici une photo prise à l’arrière de cet écran TFT 3,3/5V (ici, on voit bien le texte « J1 », noté au dessus de 2 plots de cuivre étamés, sur lesquels on peut venir mettre un pont de soudure ou non) :

Mais ATTENTION à ne pas vous méprendre ici ! La notion de +5V ou +3,3V d’alim ne change rien au fait que « toutes » les autres pins d’un écran TFT doivent être pilotées en 3,3V uniquement. Sans quoi, vous risquez d’endommager votre écran, au moins à long terme, car ce n’est pas fait pour !
Du coup, si jamais vous utilisez un microcontrôleur fonctionnant en 5V (comme l’ATmega328P présent sur les cartes Arduino Uno), vous devrez impérativement abaisser ces tensions à 3,3V au niveau des lignes de commande, même si vous alimentez votre écran TFT en 5V. Et pour abaisser cette tension 5V en 3V3, rien de plus facile en utilisant :
- des ponts diviseurs de tension résistifs (abaissant ainsi le 5V en 3,3V)
- un convertisseur de niveaux logiques (pour le TXS0108E, 74HC4050, …)
- ou autre !
Nous verrons comment câbler tout cela dans cet article, ne vous inquiétez pas 😉
L’interface SPI (SDI/MOSI, SCLK/SCK, et SDO/MISO) et de commande (DC, CS, RST)
Les écrans TFT ILI9341 utilisent une interface série SPI (Serial Peripheral Interface) pour communiquer avec le microcontrôleur. Les principales broches utilisées sont :
- l’entrée CS (Chip Select), qui reçoit un signal d’activation (sélection) pour « encadrer » cette communication série (µC → écran TFT)
- l’entrée SCK (Serial Clock), qui reçoit l’horloge série (SPI) du microcontrôleur, pour synchroniser les données (µC → écran TFT)
- l’entrée SDI (Serial Data In) ou MOSI (Master Out Slave In), qui reçoit les données séries envoyées par le microcontrôleur (µC → écran TFT)
- la sortie SDO (Serial Data Out) ou MISO (Master In Slave Out), qui renvoie éventuellement des données au microcontrôleur ; celle-ci est optionnelle, et uniquement utilisée en pratique pour le tactile, ou la lecture de carte SD, si présent au dos du module TFT (µC ← écran TFT)
- l’entrée DC (Data/Command), qui reçoit un signal bas ou haut, selon si le microcontrôleur souhaite envoyer à l’écran des données d’affichage, ou des instructions de commande (µC → écran TFT)
- l’entrée RST (Reset), pour réinitialiser l’écran au besoin (µC → écran TFT)
Note importante : certains écrans utilisent une nomenclature légèrement différente, comme par exemple la mention « SDA » à la place de « SDI » ou « MOSI ». Ceci peut clairement créer la confusion, car le terme « SDA » est traditionnellement employé pour les communication I²C (qui ont des lignes SDA et SCL). Or, ici, il n’en n’est rien. C’est bien d’un bus SPI dont il s’agit, pour piloter l’écran TFT, et en aucun cas d’un bus i2c. Du coup, même si vous voyez une étiquette/notation « SDA » sur votre écran TFT, dites vous bien que cela correspond à une broche d’entrée de données séries, équivalente aux labels SDI ou MOSI, et non à une ligne I2C ! Du reste, au moindre doute, vérifiez toujours la documentation constructeur de votre module avant tout, pour éviter tout impair !
Fonctions supplémentaires
Enfin, les bornes de connexion d’un écran TFT peuvent comporter d’autres broches, correspondant à des « fonctions supplémentaires » (optionnelles, pour la plupart) :
- la fonction tactile : comme souvent, certains écrans ILI9341 intègrent une couche tactile résistive, pilotée par un contrôleur type XPT2046 ou autre, communiquant également en SPI ; il y a donc partage des lignes MOSI/SCK/MISO avec l’écran TFT en lui-même, mais des CS séparés permettent de distinguer l’un et l’autre
- la prise en charge de carte SD : certains modules incluent un lecteur de carte SD (visible au dos du module/PCB) ; cela peut être particulièrement utile pour stocker des images volumineuses, ou des polices de caractère personnalisées, relativement gourmandes en terme d’espace mémoire
- la fonction rétroéclairage : il s’agit généralement d’un système LED, contrôlable via une broche dédiée (souvent notée LED ou BL) ; dans le présent tuto, je l’ai simplement reliée au +3,3V (peut être différente d’un fabricant à l’autre, attention)
Voilà ! Je pense que nous avons fait le tour des principales caractéristiques des écrans TFT reposant sur contrôleur ILI 9341. À présent, voyons comme brancher cela sur un Arduino, puis sur un ESP32 !
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Branchement d’un écran TFT ILI9341 à un Arduino Uno (en SPI)
Raccorder un écran TFT à un Arduino Uno n’est aussi simple qu’on pourrait le croire, car comme vu précédemment, les signaux pilotant l’écran TFT doivent être de type 0-3,3V. Or, l’Arduino Uno repose sur un microcontrôleur ATmega328P, qui lui, fonctionne en 0-5V. Et ce, encore une fois, que vous alimentiez l’écran TFT en +5V ou en +3,3V (il ne faut pas confondre, pour rappel, la tension d’alimentation d’un écran TFT, et la tension des signaux permettant de le piloter).
Cela étant dit, il suffit juste d’abaisser les signaux 5V vers 3,3V au niveau des lignes de commande, pour que ça marche ! Et cela est faisable assez simplement, heureusement ! Parmi les différentes façons de faire cela, on retrouve le plus couramment :
- soit l’utilisation de ponts diviseurs de tension résistifs au niveau de chaque ligne de commande Arduino Uno → écran TFT
- soit l’utilisation d’un circuit intégré prévu/conçu pour faire de l’abaissement de tension (comme le TXS 0108E, ou un 74HC4050, par exemple)
Je vous présenterais ces 2 façons de câbler un TFT ILI9341 sur un Arduino Uno dans les exemples de code #1 et #2, un peu plus bas. Mais si vous voulez savoir à quoi ressemble un câblage basique, en voici un, mettant en œuvre des ponts diviseurs résistifs :

À noter que je n’ai pas câblé la partie tactile de l’écran ici (aussi appelée « touch »), pour ne pas alourdir le schéma. Mais je vous inquiétez pas, car je vous détaillerai tout cela dans l’exemple de code #3, un peu plus bas !
Sinon, pour être complet, voici les raccordements typiques entre un écran TFT et un Arduino Uno, avec les broches correspondantes :
| Broche TFT | Broche Arduino Uno | Remarque |
|---|---|---|
| VCC | 3,3V ou 5V | Selon le positionnement du jumper J1 (J1 ouvert = 5V ; J1 fermé = 3,3V) |
| GND | GND | Masse |
| CS | 10 | Chip Select (sélection de l’écran TFT, pour dire qu’on veut communiquer avec lui) |
| RST | 9 | Reset de l’écran (peut être raccordé au +3,3V si non utilisé) |
| DC | 8 | Data/Command (broche permettant d’indiquer à l’écran TFT si les données qui vont lui être transmises juste après seront des données, ou des instructions/commandes) |
| SDI/MOSI/SDA | 11 (*) | Ligne d’envoi de données SPI (Arduino → écran TFT) |
| SCK/SCLK | 13 (*) | Ligne d’horloge SPI (Arduino → écran TFT) |
| LED | 3,3V | À confirmer selon les fabricants (certains autorisent du 5V et/ou du PWM, par exemple, mais à vérifier) |
| SDO/MISO | 12 (*) | Optionnel : ligne de retour de données SPI (Arduino ← écran TFT) |
| T_CLK | idem SCK | Optionnel : horloge SPI pour la partie « touch » de l’écran TFT |
| T_CS | 7 | Optionnel : ligne de sélection « touch », pour communiquer avec lui |
| T_DIN | idem MOSI | Optionnel : ligne d’envoi de données SPI (Arduino → touch) |
| T_DO | idem MISO | Optionnel : ligne de retour de données SPI (Arduino ← touch) |
| T_IRQ | n.c. | Non connecté, généralement, à moins de vouloir utiliser les interruptions |
(*) La communication entre Arduino et écran TFT ILI9341 (et touch) se faisant en SPI, ce sont donc usuellement les lignes physiques MOSI (11), MISO (12), et SCK (13) de l’arduino qui sont utilisées (pour une communication SPI native/matérielle, aussi nommée « hardware SPI » en anglais). Cela étant dit, on peut utiliser d’autres broches que celles-ci, et faire de « l’émulation SPI » (communication faite manuellement/logiciellement). Mais attention, car dans ce cas la vitesse de transmission sera bien plus basse, ce qui rendra l’affichage d’infos sur l’écran TFT vraiment lent (d’autant plus si on rafraîchit celles-ci souvent). Le « software SPI » (émulation logicielle) est donc à éviter au possible, bien que techniquement réalisable ! En tout cas, c’est mon conseil 😉
Bien sûr, comme vous vous en doutez, tous les écrans TFT ne sont pas pareils (peut différer d’un fabricant à l’autre, j’entends). C’est pourquoi vous trouverez parfois des noms de broches différents (comme « SDA » à la place de « SDI », par exemple), et des formats PCB différents (certains pouvant par exemple s’emboîter directement sur l’Arduino Uno, ce qu’on appelle un « shield »). Dans tous les cas, vérifiez bien la documentation de votre écran TFT avant tout branchement, aussi bien au niveau de ses lignes d’alimentation (VCC/GND), que de ses lignes de communication SPI (SDI, SCK, etc) et de commande (CS, RST, DC), que de ses dimensions et de son footprint !
Raccordement d’un écran TFT ILI9341 à un ESP32-S3-DevKitC (avec tactile)
Ici, comme vous allez le voir, c’est beaucoup plus simple qu’avec un Arduino ! En fait, cela vient du fait qu’un ESP32-S3 fonctionne en 3,3V et qu’un écran TFT ILI9341 aussi, contrairement à l’Arduino Uno, où il fallait faire un abaissement de tension 5V → 3,3V, au niveau des lignes de commande/communication.
En effet, voici un exemple de raccordement d’écran TFT à contrôleur ILI9341, sur un ESP32 S3 (ici la version ESP32-S3-DevKitC) :

Au passage, sur ce schéma, vous avez à la fois le câblage de l’écran TFT en lui-même, et celui de la partie tactile (lignes notées T_xxx). Car au final, mise à part d’une ligne de commande supplémentaire pour cette partie « touch screen », les lignes de communication SPI sont partagées avec celles de l’écran TFT en lui-même.
Du reste, comme avec l’arduino, lorsqu’on veut profiter au maximum de la vitesse de communication SPI, il faut se brancher sur les entrées/sorties SPI matérielles prévues à cet effet (sinon, il s’agirait « d’émulation logicielle SPI », ce qui est bien plus lent).
Concernant l’ESP32 S3 DevKit C, voici où brancher les fils entre ESP32 et écran TFT :
| Broche TFT | Broche ESP32 | Remarque |
|---|---|---|
| VCC | 3,3V | Assurez-vous que le jumper J1, au dos du PCB, est bien « fermé » (avec un pont de soudure), si jamais votre écran dispose d’un tel dispositif, pour lui dire que ce n’est pas du +5V mais du +3,3V qui lui sera envoyé ! |
| GND | GND | Masse |
| CS | 10 ou 40, usuellement | Chip Select (broche de sélection écran TFT, permettant de dire quand on souhaite communiquer avec lui. Pour rappel, le bus SPI pouvant être partagé entre plusieurs périphériques, il faut cette ligne spéciale, dite de « sélection », permettant au microcontrôleur de dire qu’il s’adresse à lui) ; là, vous être « libres » de choisir le numéro de broche qui vous conviendra le mieux ! |
| RST | 9 ou 39, par exemple | Reset écran TFT (à raccorder au +3,3V, si non utilisé) ; choix libre de pin |
| DC | 8 ou 38, par exemple | Data/Command (broche permettant d’indiquer à l’écran TFT si les données qui vont lui être transmises en suivant seront des données, ou des commandes/instructions) ; choix libre au niveau de la broche de raccordement |
| SDI/MOSI/SDA | 11 (*) ou 35 (**) | Ligne d’envoi des données SPI (ESP32 → écran TFT) |
| SCK/SCLK | 12 (*) ou 36 (**) | Ligne d’horloge SPI (ESP32 → écran TFT) |
| LED | 3,3V | Pour alimenter le rétroéclairage (à alimenter en 3,3 volts généralement, mais à confirmer auprès du fabricant) |
| SDO/MISO | 13 (*) ou 37 (**) | Optionnel : ligne de retour de données SPI (ESP32 ← écran TFT) |
| T_CLK | idem SCK | Optionnel : horloge SPI pour la partie « touch » de l’écran TFT |
| T_CS | 41, par exemple | Optionnel : ligne de sélection « touch », pour communiquer avec lui ; choix de la pin que vous souhaitez |
| T_DIN | idem MOSI | Optionnel : ligne d’envoi de données SPI (ESP32 → touch) |
| T_DO | idem MISO | Optionnel : ligne de retour de données SPI (ESP32 ← touch) |
| T_IRQ | n.c. | Non connecté, sauf si gestion des interruptions souhaitées, au niveau du tactile |
(*) Pour utiliser le mode FSPI/VSPI, c’est à dire le port SPI2 de l’ESP32-S3
(**) Pour utiliser le mode HSPI, c’est à dire le port SPI3 de l’ESP32-S3
Encore une fois, la partie touch (« tactile »), lorsque branchée, partage souvent le même bus SPI que l’écran TFT ; les lignes MOSI, MISO, et SCK sont donc communes/câblées ensemble, mais leurs lignes CS sont distinctes (afin que le µC puisse dire à qui il s’adresse, lorsqu’il envoie des commandes/données).
Au passage, utiliser un ESP32-S3 plutôt qu’un Arduino Uno est vraiment un atout, car l’ESP32 offre :
- plus de mémoire disponibles, pour afficher des images/icônes ou autre
- des sorties en 0-3,3V natives, ne nécessitant donc pas de convertisseur de tension au niveau des lignes de communication SPI, ni au niveau des lignes de commande (RST/DC)
- une fréquence d’horloge plus élevée, offrant au final de meilleures performances
Voilà ! Maintenant que nous avons vu la partie matérielle, passons à la partie logicielle 🙂
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Librairies compatibles pour Arduino IDE (Adafruit et TFT_eSPI)
Comme vous êtes nombreux à utiliser l’IDE Arduino, je vous ai fait ce tuto avec. Bien sûr, si vous utilisez VS Code ou un autre environnement de développement, il faudra adapter quelque peu ce qui suit !
Ici, j’ai choisis de vous présenter deux des librairies les plus utilisées, pour piloter des écrans TFT à puce ILI9341. À savoir :
- la librairie « Adafruit_ILI9341 » de Adafruit, pour Arduino/ESP32
- la libraire « TFT_eSPI » de Bodmer, optimisée pour l’ESP32
Remarque 1 : ces deux librairies sont accessibles directement via le gestionnaire de librairie Arduino. Vous n’aurez donc rien à télécharger en dehors d’Arduino IDE ; tout se passe/s’installe « à l’intérieur » !
Remarque 2 : pour info, la librairie Adafruit seule ne gère que l’écran TFT, tandis que la librairie TFT_eSPI pour ESP32 gère l’écran TFT + la partie tactile. Du coup, si vous souhaitez utiliser la partie « touch » de votre écran TFT lorsque vous utilisez la librairie Adafruit, vous aurez besoin de télécharger une librairie complémentaire, pour gérer le tactile. Dans mon cas, comme le tactile était géré par une puce XPT2046 (visible au dos du PCB de l’écran TFT), alors j’ai utilisé la librairie XPT2046_Touchscreen de Paul Stoffregen, car c’est là aussi une des plus utilisées !
La librairie Adafruit_ILI9341 d’Adafruit, pour Arduino et ESP32
Pour utiliser la libraire « ILI9341 » de Adafruit, il faut bien évidemment l’installer avant ! Et cela se fait tout simplement, à partir d’Arduino IDE. En effet, pour ce faire, il suffit d’aller dans le menu Outils > Gérer les bibliothèques, de taper le terme « ili9341 » dans la zone de recherche, pour voir la librairie « Adafruit ILI9341 » apparaître. Ensuite, il suffit de cliquer sur « INSTALLER », tout simplement ! Au passage, il se peut qu’Arduino IDE vous demande si vous souhaitez installer des dépendances, comme visible ci-dessous ; si c’est le cas, je vous recommande de cliquer sur « TOUT INSTALLER » :

Pour rappel, la librairie Adafruit_ILI9341 est compatible avec l’Arduino Uno et l’ESP32 (même s’il existe une librairie plus optimisée pour l’ESP32, comme nous le verrons au chapitre suivant). Du reste, cette librairie Adafruit est vraiment très utilisée, et super bien documentée. C’est donc un choix idéal, si vous débutez en électronique, avec Arduino et les écrans TFT à puce ILI9341 !
Au niveau du code, il suffira d’appeler cette librairie pour pouvoir l’utiliser ensuite (nous verrons comment utiliser cette librairie en pratique, dans les exemples de code #1, #2, et #3, un peu plus bas, dans cet article).
Ah oui… et comme je vous avais précisé un peu plus haut, la librairie Adafruit ILI9341 ne gère que la partie « tactile TFT ». C’est pourquoi il faudra installer la librairie correspondante à votre écran TFT (enfin, il me semble qu’il y avait une librairie touchscreen dans le temps, mais qui est dépréciée depuis). Dans mon cas, la partie tactile étant gérée par une puce « XPT2046 » (gravé sur une des puces visibles, au dos du PCB de l’écran TFT en lui-même), j’ai donc opté pour l’installation de la librairie « XPT2046_Touchscreen ». Pour ce faire, il suffit de :
- cliquer sur Outils > Gérer les librairies (bibliothèques)
- taper « XPT2046_Touchscreen » dans le champ de recherche
- et cliquer sur « INSTALLER », comme visible sur l’image ci-dessous

Du reste, comme pour la librairie ILI9341 d’Adafruit, il faudra ensuite l’appeler et l’instancier, pour faire appel à cette librairie, et à ses fonctions (comme nous le verrons ensemble, dans l’exemple de code #3, un peu plus bas dans cet article).
La librairie TFT_eSPI, spécifiquement conçue pour les ESP32
Si vous utilisez un ESP32, rien de tel que la librairie TFT_eSPI pour piloter un écran TFT ! Car celle-ci est optimisée pour les ESP32, et gère nativement la partie tactile.
Pour l’installer sous Arduino IDE, rien de plus simple ! Car il vous suffira de :
- cliquer sur le menu Outils > Gérer les bibliothèques…
- taper « TFT_eSPI » dans le champ de recherche
- et de cliquer sur « INSTALLER »
En image, ça ressemble à ceci, de mon côté :

Par contre, autant l’installation de la librairie TFT_eSPI est facile, autant la configuration est un poil pénible ! Car ceci ne se passe pas au niveau du programme arduino, mais dans le répertoire même de la librairie TFT_eSPI, et plus exactement au niveau d’un fichier nommé « User_Setup.h », dans ce répertoire.
Mais encore faut-il savoir où se trouve le répertoire où est stockée la librairie TFT_eSPI, pour ensuite pouvoir accéder à son fichier de configuration « User_Setup.h ». Cela dit, rassurez-vous, car ce n’est pas si compliqué que cela. Car il suffit simplement d’aller dans les préférences d’Arduino IDE (Menu Fichier > Préférences). Une fenêtre s’ouvre alors devant vous, et apparaîtra sous vos yeux le chemin d’accès à toutes les librairies de votre IDE Arduino. Dans mon cas, le répertoire était « C:\Users\JEROME\Documents\Arduino », comme visible ci-dessous :

Bien entendu, ce nom de répertoire sera fort probablement différent chez vous (là, étant relié à mon profil windows, il se nomme en partie « JEROME »).
Du reste, ensuite, il suffira d’aller dans ce répertoire, puis d’entrer dans le sous-répertoire « librairies », pour retrouver toutes les librairies installées sur votre IDE Arduino. Enfin, il suffira d’entrer dans le répertoire « TFT_eSPI », pour trouver le fameux fichier de configuration « User_Setup.h » à l’intérieur.
L’illustration en image (rappel : les chemins d’accès seront certainement différents chez vous) :


À noter que le fichier « User_Setup.h » fournit de base n’est qu’un exemple/squelette de configuration. À chacun de le changer, pour l’adapter à ses besoins/projets. Nous verrons d’ailleurs par quoi remplacer son contenu (dont je vous conseille de faire une copie, pour garder l’original), dans les exemples de code #4 et #5.
Voilà ! Maintenant que nous avons fait le tour de tout ce qui est « théorique », passons à la pratique 🙂
Code exemple #1 : écriture de textes, avec rotation écran (Arduino + résistances + TFT ILI9341)
Pour commencer en douceur, je vous propose de voir ensemble un bout de code, permettant d’afficher du texte de différentes tailles, de différentes couleurs, et dans différents sens, sur un écran TFT ILI9341 ! Et tout ça, avec un Arduino Uno, tout simplement 😉
Au passage, comme évoqué dans la partie « branchement d’un écran TFT à un Arduino Uno », je vous avais expliqué qu’il fallait abaisser la tension des signaux de commande arduino, car un TFT display ne supporte que du 3,3V à ce niveau, tandis qu’un Uno travaille en 0-5V. Aussi, à l’occasion de ce premier exemple, nous verrons comment faire cela d’une première façon, avec des résistances branchées en ponts diviseurs de tension !
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Côté câblage, voici comment relier Arduino Uno, écran TFT, et ponts diviseurs résistifs, pour ce 1er exemple :

Au niveau des composants électroniques et autre, voici ce dont nous aurons besoin :
- 1 x Arduino Uno R3
- 1 x Écran TFT 2,8″ SPI 240×320 (ILI9341)
- 5 x Résistance axiale 1000 ohms 1/4 watt
- 5 x Résistance axiale 2000 ohms 1/4 watt
- 1 x Breadboard et fils duponts, pour câbler tout cela simplement
Voici d’ailleurs à quoi ce ressemble ce montage, une fois câblé sur breadboard :


Et le code pour afficher du texte de différentes couleurs, tailles, et orientations, sur l’écran TFT ILI9341 (écrit sous Arduino IDE) :
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_) | [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___ | ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \ | | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___| | |
\_|
Fichier : prg1-ArduinoUno-TFT_ILI9341-ecriture-texte-et-rotation.ino
Dépôt : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Description : Programme permettant d'afficher du texte et de faire des rotations d'écran,
à partir d'un Arduino Uno, sur un écran TFT de 2,8" à contrôleur ILI9341
Licence : BY-NC-ND 4.0 CC (https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr)
Remarques : Version avec ponts diviseurs de tension résistifs (1K/2K, pour passer du 5V au 3,3V environ)
Auteur : Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le : 27.08.2025
*/
// Inclusion des librairies dont nous aurons besoin ici
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// Définition des broches utilisées ici (hors pins SPI)
#define TFT_CS 10 // Pin D10 de l'Arduino -> broche CS de l'écran TFT
#define TFT_RST 9 // Pin D9 de l'Arduino -> broche RESET de l'écran TFT (aussi nommée RST, dans certains cas)
#define TFT_DC 8 // Pin D8 de l'Arduino -> broche DC de l'écran TFT
// Définition des couleurs utilisées ici
#define NOIR 0x0000
#define BLEU 0x001F
#define VERT 0x07E0
#define CYAN 0x07FF
#define ROUGE 0xF800
#define MAGENTA 0xF81F
#define ORANGE 0xFBA0
#define JAUNE 0xFFE0
#define BLANC 0xFFFF
// Initialisation de l’écran TFT (contrôleur ILI9341)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); // Le reste = SPI matériel (hardware spi), donc il ne faut pas le renseigner ;
// sinon on passerait en émulation logicielle (software spi)
// Tableau de couleurs possibles ici, à personnaliser/compléter selon ses envies (avec son index correspondant, pour les faire afficher l'une après l'autres)
uint16_t couleurs[] = {BLEU, VERT, CYAN, ROUGE, MAGENTA, ORANGE, JAUNE, BLANC};
uint8_t indexCouleur = 0;
uint8_t nombreDeCouleursPossibles;
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialisation de l’écran
tft.begin();
// Calcul du nombre de différentes couleurs à gérer
nombreDeCouleursPossibles = sizeof(couleurs) / sizeof(uint16_t); // Pour avoir le nombre d'éléments présents dans notre "tableau" de couleurs, il faut
// diviser la taille totale de ce tableau, par la taille de chaque élément de ce tableau
}
// =================
// Boucle principale
// =================
void loop() {
// Parcours des 4 orientations d'écran possible (rotation de 90° à chaque fois, donc)
for (int rotation = 0; rotation < 4; rotation++) {
// Nota : démarrage portrait, puis tourne de 90 en 90°, en sens horaire
// Fixation du sens de rotation souhaité
tft.setRotation(rotation);
// Effacement de l'écran
tft.fillScreen(NOIR);
// Affichage de texte en mode "normal" (écriture selon couleur choisie, sur fond noir, par exemple)
tft.setCursor(0, 30);
tft.setTextColor(couleurs[indexCouleur], NOIR); // Nota : on aurait pu simplement écrire "tft.setTextColor(couleurs[indexCouleur])", sans préciser la couleur du fond,
tft.setTextSize(1); // car celui-ci est déjà noir (cf. fonction setup plus haut) ; ainsi, on écrirait en "transparence", au niveau
tft.println("Texte normal (taille 1)"); // de l'arrière plan du texte (très utile, si vous souhaitez un jour écrire du texte sur une image, par exemple)
// Affichage de texte en mode inversé (écriture noire, sur fond de la couleur choisie)
tft.setCursor(0, 80);
tft.setTextSize(2);
tft.setTextColor(NOIR, couleurs[indexCouleur]); // Texte noir sur fond blanc
tft.println("Texte inverse");
tft.println("(taille 2)");
// Et... un affichage en taille 3, histoire de montrer ce que ça donne !
tft.setCursor(0, 150);
tft.setTextColor(couleurs[indexCouleur], NOIR);
tft.setTextSize(3);
tft.println("Taille 3 !");
// Attente d'une seconde, avant de reboucler
delay(1000);
// Et changement de couleur, pour le prochain tour !
indexCouleur++;
if(indexCouleur >= nombreDeCouleursPossibles) indexCouleur = 0;
}
}Je vous ai mis un maximum de commentaires dans ce code, afin que ce soit le plus clair possible ! Au passage, on y retrouve :
- le codage des couleurs sur 16 bits (entre 0x0000 et 0xFFFF, donc), qui correspond bien au format RGB565 (revoir paragraphe 1.3 tout en haut, pour plus d’explications)
- l’utilisation de fonction de la librairie Adafruit ILI9341, à savoir :
- setRotation(valeur), en sachant que cette « valeur » doit être un nombre compris entre 0 et 3 inclus (0=aucune rotation, 1=rotation de 90°, 2=rotation de 180°, et 3=rotation de 270°)
- fillScreen(couleur_RGB565), pour remplir l’écran d’une couleur donnée
- setCursor(position_sur_X, position_sur_Y), pour positionner le « curseur » (l’endroit à partir duquel on souhaite écrire du texte, par exemple) à des coordonnées précises (nota : les valeurs X et Y sont exprimées en nombre de pixel, en fonction de comment est tourné/configuré votre TFT display)
- setTextColor(couleur_RGB565), pour spécifier la couleur du texte qu’on souhaite écrire (sans argument supplémentaire, on écrira de cette couleur en « transparence » du fond ; c’est à dire par dessus le reste, mais sans effacer le fond sous le texte)
- setTextColor(couleur_texte_RGB565, couleur_fond_RGB565), idem, mais en spécifiant une couleur de fond, à mettre sous le texte qui sera écrit ensuite
- setTextSize(valeur), qui permet de définir la taille des caractères/textes à écrire ; la valeur 1 donne une taille par défaut (fonction de la police de caractère utilisée), et les valeurs suivantes (2, 3, 4, …) permettent d’avoir des caractères de plus en plus gros
En vidéo, voici ce que donne l’exécution de ce premier code arduino, une fois uploadé (désolé pour la piètre qualité !) :

Sympa, non ? Maintenant, voyons comment tracer des formes graphiques, pour ne pas se limiter à du texte seulement !
Code exemple #2 : générer des formes aléatoires colorées (Arduino + convertisseur 5V/3,3V + TFT)
Que diriez vous de tracer des lignes, rectangles, triangles, et cercles, de manière aléatoire et de différentes couleurs, un peu partout sur un écran TFT ? Eh bien c’est ce que je vous propose de voir ensemble, à présent !
Mais avant de parler du code arduino permettant de faire cela, voyons tout d’abord comment câbler l’Arduino Uno à notre écran TFT ILI9341 ; mais cette fois-ci, avec un convertisseur de niveau logiques 5V → 3,3V, et non de simples résistances ! Pour ce faire, nous utiliserons ici la puce TXS 0108E de Texas Instrument, monté sur PCB (avec broches au pas de 2,54mm, ce qui permet de le câbler sur breadboard).
Voici à quoi ressemble le câblage :

Et les éléments dont nous aurons besoins ici :
- 1 x carte Arduino Uno
- 1 x Écran TFT ILI9341 (2,8″ SPI)
- 1 x Convertisseur de tension TXS 0108E
- 1 x Résistance axiale 10K ohms 1/4 watt
- 1 x Ensemble breadboard + fils duponts, pour relier tout ça ensemble !
Une fois câblé sur breadboard, voici comment le tout se présente :


Maintenant que nous avons vu la partie physique, voyons la partie logicielle (écrite sous Arduino IDE, pour rappel) :
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_) | [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___ | ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \ | | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___| | |
\_|
Fichier : prg2-ArduinoUno-TFT_ILI9341-generation-formes-aleatoires.ino
Dépôt : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Description : Programme permettant de générer formes aléatoires colorées,
via un Arduino Uno, sur un écran TFT 2,8" SPI (contrôleur ILI9341)
Licence : BY-NC-ND 4.0 CC (https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr)
Remarques : Version avec convertisseur 5V / 3,3V (TXS0108E)
Auteur : Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le : 01.09.2025
*/
// Inclusion des librairies dont nous aurons besoin ici
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// Définition des broches utilisées ici (hors pins SPI)
#define TFT_CS 10 // Pin D10 de l'Arduino Uno -> broche CS de l'écran TFT
#define TFT_RST 9 // Pin D9 de l'Arduino Uno -> broche RST de l'écran TFT
#define TFT_DC 8 // Pin D8 de l'Arduino Uno -> broche DC de l'écran TFT
// Initialisation de l’écran TFT (contrôleur ILI9341)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); // Le reste = SPI matériel (hardware spi), donc il ne faut pas le renseigner ;
// sinon on passerait en émulation logicielle (software spi)
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialisation de l’écran
tft.begin();
tft.setRotation(0); // Mode "portrait" (affichage vertical, soit 240 pixels en largeur et 320px en hauteur)
tft.fillScreen(ILI9341_BLACK); // Fond en "noir"
// Initialisation du générateur aléatoire
randomSeed(analogRead(0)); // On lit l'entrée A0, qui n'est reliée à rien ; cela permet d'avoir un nombre de base aléatoire, du fait du bruit
}
// =================
// Boucle principale
// =================
void loop() {
// ------------------------------------------------------------------------------------------------
// Nota : à chaque passage dans cette boucle loop, une nouvelle forme sera dessinée sur l'écran TFT
// ------------------------------------------------------------------------------------------------
// Compteur de formes (en fait, toutes les X formes dessinées, on effacera l'écran pour faire de la place, et y voir plus clair !)
// Remarque : le mot "static" permet de mettre à 0 cette variable UNIQUEMENT lors du 1er appel de cette boucle loop
static uint16_t nbre_de_formes_dessinees = 0;
// -------------------------------------------------------------------------------
// Génération d'une forme à la forme, couleur, remplissage, et position aléatoires
// -------------------------------------------------------------------------------
uint8_t forme = random(6); // 0: pixel, 1: ligne, 2: rectangle, 3: cercle, 4: rectangle arrondi, 5: triangle
bool rempli = random(2); // TRUE: forme remplie, FALSE: contour uniquement
uint16_t couleur = random(0xFFFF); // Couleur aléatoire (sur 2 octets, soit 16 bits, pour coller au RGB565 → 5 bits de rouge, 6 de vert, et 5 de bleu)
uint16_t x = random(240); // Position X aléatoire (position sur la largeur)
uint16_t y = random(320); // Position Y aléatoire (position sur la hauteur)
// ---------------------
// Dessinage de la forme
// ---------------------
switch(forme) {
case 0: // Pixel (posX, posY, couleur)
tft.drawPixel(x, y, couleur); // Pixel coloré
break;
case 1: // Ligne (posX_depart, posY_depart, posX_arrivee, posY_arrivee, couleur)
tft.drawLine(x, y, x + random(50), y + random(50), couleur); // Ligne colorée
break;
case 2: // Rectangle (posX, posY, largeur, hauteur, couleur)
if (rempli) tft.fillRect(x, y, random(20, 60), random(20, 60), couleur); // Rectangle rempli
else tft.drawRect(x, y, random(20, 60), random(20, 60), couleur); // Contour rectangle uniquement
break;
case 3: // Cercle (posX, posY, rayon, couleur)
if (rempli) tft.fillCircle(x, y, random(10, 30), couleur); // Disque (cercle rempli)
else tft.drawCircle(x, y, random(10, 30), couleur); // Cercle (contour uniquement dessiné)
break;
case 4: // Rectangle arrondi (posX, posY, largeur, hauteur, rayon, couleur)
if (rempli) tft.fillRoundRect(x, y, random(20, 60), random(20, 60), random(2, 10), couleur); // Rectangle arrondi rempli
else tft.drawRoundRect(x, y, random(20, 60), random(20, 60), random(2, 10), couleur); // Contour rectangle arrondi uniquement
break;
case 5: // Triangle (posX0, posY0, posX1, posY1, posX2, posY2, couleur)
if (rempli) tft.fillTriangle(x, y, x + random(50), y + random(50), x + random(50), y - random(50), couleur); // Triangle rempli
else tft.drawTriangle(x, y, x + random(50), y + random(50), x + random(50), y - random(50), couleur); // Contour triangle uniquement
break;
default:
break;
}
// -------------------------------------------
// Mise à jour du compteur de formes dessinées
// -------------------------------------------
nbre_de_formes_dessinees++;
// ----------------------------------------------------------------------------------------------------------
// Effacement de l'écran toutes les "n" formes dessinées, histoire d'y voir plus clair, à intervalle régulier
// ----------------------------------------------------------------------------------------------------------
if (nbre_de_formes_dessinees >= 150) {
tft.fillScreen(ILI9341_BLACK); // Effacement de l’écran (remplissage en noir, si vous préférez)
nbre_de_formes_dessinees = 0;
}
// ----------------------------------------------------------------
// Petite pause avant de reboucler, pour dessiner la forme suivante
// ----------------------------------------------------------------
delay(100);
}Là encore, je vous ai mis tout un tas de commentaires au niveau du code, afin de faciliter au maximum la compréhension.
Au niveau de la librairie ILI9341 d’Adafruit, nous utilisons ici les fonctions :
- drawPixel pour dessiner un point sur l’écran
- drawLine pour tracer une lignes
- drawRect pour dessiner un rectangle
- drawCircle pour tracer un cercle
- drawRoundRect pour dessiner un rectangle à coins arrondis
- et drawTriangle pour tracer un triangle quelconque
À noter que l’écran est « nettoyé » à intervalle régulier (à chaque fois que l’on dépassera les 150 formes dessinées, comme vous avez pu le voir dans le code). Cela permet d’avoir un rafraîchissement périodique, et par conséquent, une animation perpétuelle 😉
En vidéo, voici ce que donne ce programme, une fois uploadé (encore une fois, désolé pour la qualité d’image) :

Mais plutôt que dessiner des formes automatiques, pourquoi ne pas essayer de dessiner à la main, à même l’écran TFT ? Ce serait plus sympa, non ? Eh bien c’est ce que nous allons faire, à présent !
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Code exemple #3 : dessiner à la main (idem + câblage partie tactile « touch »)
Pour tester la partie tactile (touch) des écrans TFT, je vous propose ici un exemple pratique, et vraiment sympa vous verrez ! Il s’agit en fait de transformer votre écran tactile TFT en « mini tablette de dessin », avec différentes couleurs et épaisseurs de traits possibles. Ça vous dit ? Alors en avant !
Mais tout d’abord, voyons la partie câblage Arduino Uno + écran TFT + touch (qui est ni plus ni moins que le schéma de l’exemple précédent, mais avec la partie tactile câblée en plus !) :

Cette fois-ci, au niveau des composants, nous aurons besoin de :
- 1 x carte Arduino Uno (R3)
- 1 x Écran TFT ILI9341 + touch (2,8″ SPI)
- 1 x Adaptateur de tension TXS0108E
- 1 x Résistance 10K ohms (axiale, 1/4 watt)
- 1 x Ensemble breadboard et fils duponts, pour raccorder tout ça ensemble !
Vous noterez que la partie « touch » (tactile) se branche sur le même bus SPI que la partie « TFT display » (l’écran d’affichage), via les lignes MOSI/SCK/MISO. Et pour que l’arduino puisse dire à qui il s’adresse lorsqu’il envoie des commandes/données, il existe 2 lignes de sélections distinctes : un /CS pour l’écran TFT, et un autre /CS pour la partie tactile ; ainsi, pas de risque de conflit, même si ces 2 éléments sont tous deux branchés sur le même bus SPI !
Au passage, voici à quoi ressemble ce montage, un fois câblé sur breadboard :


Cela étant vu, passons à la partie logicielle, c’est à dire au code arduino de cette « mini tablette à dessiner » TFT ILI9341 faite-maison !
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_) | [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___ | ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \ | | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___| | |
\_|
Fichier : prg3-ArduinoUno-TFT_ILI9341-dessiner-a-la-main.ino
Dépôt : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Description : Programme permettant de dessiner à la main, en choisissant l'épaisseur et la couleur de traçage
(projet mettant en oeuvre un Arduino Uno + écran TFT 2,8" SPI ILI9341)
Licence : BY-NC-ND 4.0 CC (https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr)
Remarques : Version utilisant un convertisseur 5V / 3,3V (TXS0108E)
Auteur : Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le : 01.09.2025
*/
// Inclusion des librairies dont nous aurons besoin ici
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>
// Définition des broches utilisées ici (hors pins SPI)
#define TFT_CS 10 // Pin D10 de l'Arduino -> broche CS de l'écran TFT
#define TFT_RST 9 // Pin D9 de l'Arduino -> broche RST de l'écran TFT
#define TFT_DC 8 // Pin D8 de l'Arduino -> broche DC de l'écran TFT
#define TOUCH_CS 7 // Pin D7 de l'Arduino -> broche CS de la partie tactile (touch) de l'écran TFT
// Initialisation de l’écran TFT (contrôleur ILI9341)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); // Le reste = SPI matériel (hardware spi), donc il ne faut pas le renseigner ;
// sinon on passerait en émulation logicielle (software spi)
// Initialisation de la partie tactile de l'écran
XPT2046_Touchscreen ts = XPT2046_Touchscreen(TOUCH_CS);
// Tableau de couleurs sélectionnables ici, pour dessiner
uint16_t couleursSelectionnables[] = {ILI9341_LIGHTGREY, ILI9341_YELLOW, ILI9341_GREEN, ILI9341_BLUE, ILI9341_MAGENTA, ILI9341_RED};
// Variables
uint8_t tailleCrayonDeDessinSelectionne;
uint8_t couleurDuCrayonSelectionnee;
uint16_t tactile_min_X;
uint16_t tactile_min_Y;
uint16_t tactile_max_X;
uint16_t tactile_max_Y;
uint16_t point_touche_x;
uint16_t point_touche_y;
uint16_t point_touche_z;
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialisation de l’écran
tft.begin();
tft.setRotation(0); // Mode portrait (vertical)
tft.fillScreen(ILI9341_BLACK); // Fond noir
// Initialisation du tactile
ts.begin();
ts.setRotation(0); // Synchronisation avec l’écran
// Initialisation des variables de démarrage
tailleCrayonDeDessinSelectionne = 1;
couleurDuCrayonSelectionnee = 0;
// Calibration de l'écran tactile (actions manuelles, demandées à l'utilisateur, à même l'écran TFT)
calibration_ecran_tactile();
// Affichage initial
affichage_barre_du_haut(); // Affiche les boutons de commande (différentes tailles et bouton "effacer")
affichage_barre_du_bas(); // Affiche les boutons de commande (différentes couleurs sélectionnables)
}
// =================
// Boucle principale
// =================
void loop() {
// Attend qu'un endroit soit touché
if (ts.touched()) {
// Récupération des "coordonnées" du point touché
TS_Point p = ts.getPoint();
point_touche_x = p.x;
point_touche_y = p.y;
// Rognage des points éventuellement "sortant"
if(point_touche_x < tactile_min_X) point_touche_x = tactile_min_X;
if(point_touche_x > tactile_max_X) point_touche_x = tactile_max_X;
if(point_touche_y < tactile_min_Y) point_touche_y = tactile_min_Y;
if(point_touche_y > tactile_max_Y) point_touche_y = tactile_max_Y;
// Adaptation des coordonnées (les positions sur l'écran tactile allant de 200 à 3700 environ, alors que nous, l'écran fait 240 x 320 px)
point_touche_x = map(point_touche_x, tactile_min_X, tactile_max_X, 0, 240);
point_touche_y = map(point_touche_y, tactile_min_Y, tactile_max_Y, 0, 320);
// Teste si l'un des boutons du haut ou du bas a été appuyé
teste_si_bouton_appuye_en_haut(point_touche_x, point_touche_y);
teste_si_bouton_appuye_en_bas(point_touche_x, point_touche_y);
// Dessine un cercle à l'endroit visé
if(point_touche_y > 40 && point_touche_y < 280) {
tft.fillCircle(point_touche_x, point_touche_y, tailleCrayonDeDessinSelectionne * 4, couleursSelectionnables[couleurDuCrayonSelectionnee]);
}
}
// Petit délai de rebouclage, histoire de réduire la charge CPU
delay(10);
}
// ====================================
// Fonction : calibration_ecran_tactile
// ====================================
void calibration_ecran_tactile() {
// --------------------------------------------------------------------------------
// Pointage du coin haut/gauche (pour récupérer le minX et minY de l'écran tactile)
// --------------------------------------------------------------------------------
// Dessin de la flèche montrant où appuyer sur l'écran, pour initialiser ce 1er point
tft.drawLine(1, 1, 11, 1, ILI9341_GREEN);
tft.drawLine(1, 1, 1, 11, ILI9341_GREEN);
tft.drawLine(1, 1, 21, 21, ILI9341_GREEN);
delay(300);
// Affichage du texte correspondant
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(2);
tft.setCursor(10, 40); tft.println("Appuyez ici !");
tft.setTextColor(ILI9341_LIGHTGREY);
tft.setTextSize(1);
tft.setCursor(10, 60); tft.println("(au bout de la fleche,");
tft.setCursor(10, 70); tft.println("avec un stylet)");
// Attend que ce coin haut/gauche soit touché
while (!ts.touched()) {}
// Récupération des infos du point touché
TS_Point premier_point = ts.getPoint();
// Enregistrement des données
tactile_min_X = premier_point.x;
tactile_min_Y = premier_point.y;
// Effacement de l'écran pour passer à la suite
tft.fillScreen(ILI9341_BLACK);
// ------------------------------------------------------------------------------
// Pointage du coin bas/droit (pour récupérer le maxX et maxY de l'écran tactile)
// ------------------------------------------------------------------------------
// Dessin de la flèche montrant où appuyer sur l'écran, pour initialiser ce 2ème point
tft.drawLine(239, 319, 239, 309, ILI9341_GREEN);
tft.drawLine(239, 319, 229, 319, ILI9341_GREEN);
tft.drawLine(239, 319, 219, 299, ILI9341_GREEN);
delay(300);
// Affichage du texte correspondant
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(2);
tft.setCursor(50, 220); tft.println("Et appuyez la !");
tft.setTextColor(ILI9341_LIGHTGREY);
tft.setTextSize(1);
tft.setCursor(50, 240); tft.println("(au bout de la fleche,");
tft.setCursor(50, 250); tft.println("avec un stylet)");
// Attend que ce coin bas/droit soit touché
while (!ts.touched()) {}
// Récupération des infos du point touché
TS_Point second_point = ts.getPoint();
// Enregistrement des données
tactile_max_X = second_point.x;
tactile_max_Y = second_point.y;
// Et nettoyage de l'écran, enfin, avant de passer à la suite !
tft.fillScreen(ILI9341_BLACK);
delay(300);
}
// ==================================
// Fonction : affichage_barre_du_haut
// ==================================
void affichage_barre_du_haut() {
// Fond de la barre du haut
tft.fillRect( 0, 0,240, 40, ILI9341_LIGHTGREY);
// Quatre options de la barre du haut
tft.drawRect( 0, 0, 60, 40, ILI9341_BLACK);
tft.drawRect( 60, 0, 60, 40, ILI9341_BLACK);
tft.drawRect(120, 0, 60, 40, ILI9341_BLACK);
tft.drawRect(180, 0, 63, 40, ILI9341_BLACK);
// Trois traits, pour les 3 premières options (choix grosseur de crayon, en fait)
tft.fillRect( 15, 19, 30, 2, ILI9341_BLACK);
tft.fillRect( 75, 18, 30, 4, ILI9341_BLACK);
tft.fillRect(134, 16, 30, 8, ILI9341_BLACK);
// Texte de la 4ème option
tft.setCursor(188, 16);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(1);
tft.print("EFFACER");
// Entourage de la taille choisie ("2 pixels" de large)
tft.drawRect(60*(tailleCrayonDeDessinSelectionne - 1), 0, 60, 40, ILI9341_WHITE);
tft.drawRect(60*(tailleCrayonDeDessinSelectionne - 1) + 1, 1, 58, 38, ILI9341_WHITE);
}
// =================================
// Fonction : affichage_barre_du_bas
// =================================
void affichage_barre_du_bas() {
// Affichage des 6 couleurs possibles en bas (blocs de 40x40 pixels, la hauteur max du TFT faisant 320px)
tft.fillRect( 0, 280, 40, 40, couleursSelectionnables[0]);
tft.fillRect( 40, 280, 40, 40, couleursSelectionnables[1]);
tft.fillRect( 80, 280, 40, 40, couleursSelectionnables[2]);
tft.fillRect(120, 280, 40, 40, couleursSelectionnables[3]);
tft.fillRect(160, 280, 40, 40, couleursSelectionnables[4]);
tft.fillRect(200, 280, 40, 40, couleursSelectionnables[5]);
// Entourage de la couleur choisie ("2 pixels" de large)
tft.drawRect(40*couleurDuCrayonSelectionnee, 280, 40, 40, ILI9341_WHITE);
tft.drawRect(40*couleurDuCrayonSelectionnee + 1, 281, 38, 38, ILI9341_WHITE);
}
// ==========================================
// Fonction : teste_si_bouton_appuye_en_haut
// ==========================================
void teste_si_bouton_appuye_en_haut(uint16_t x, uint16_t y) {
// On sort, si on n'a pas appuyé dans cette zone
if(y > 40) {
return;
}
// Test si 1er choix du haut touché
if(x >= 10 && x < 50 && y >= 0 && y < 40) {
tailleCrayonDeDessinSelectionne = 1;
}
// Test si 2ème choix du haut touché
if(x > 70 && x < 110 && y >= 0 && y < 40) {
tailleCrayonDeDessinSelectionne = 2;
}
// Test si 3ème choix du haut touché
if(x > 130 && x < 170 && y >= 0 && y < 40) {
tailleCrayonDeDessinSelectionne = 3;
}
// Test si 4ème choix du haut touché (bouton "effacer")
if(x >= 180 && x < 240 && y >= 0 && y < 40) {
tft.fillScreen(ILI9341_BLACK);
affichage_barre_du_bas();
}
// Rafraîchissement partie haute/basse
affichage_barre_du_haut();
}
// ========================================
// Fonction : teste_si_bouton_appuye_en_bas
// ========================================
void teste_si_bouton_appuye_en_bas(uint16_t x, uint16_t y) {
// Teste si on est bien dans la zone du bas
if(x >= 0 && x < 240 && y >= 280 && y < 320) {
// Récupère la couleur sélectionnée (chaque "couleur" faisant 40px de large)
couleurDuCrayonSelectionnee = x / 40;
// Rafraîchissement partie haute/basse
affichage_barre_du_bas();
}
}Ah oui… je ne l’ai pas précisé avant, mais pour utiliser un tactile présent sur un écran TFT, il faut le calibrer avant tout. C’est à dire qu’il faut toucher au moins 2 points précis sur l’écran (deux angles opposés, par exemple), pour établir une relation mathématique linéaire entre la valeur retournée par le tactile, et la position physique sur l’afficheur en lui-même (faisant ici 240 pixels x 320 pixels). Ainsi, par exemple, le point (0,0) de l’afficheur donnera certaines valeurs résistives pour le tactile, et de même pour la position (240, 320) ; et à partir de là, on pourra établir une fonction mathématique permettant d’estimer la position sur l’écran en fonction l’endroit touché, d’après la valeur résistive retournée par le touch. C’est un peu complexe à expliquer, mais en lisant posément le code, vous devriez comprendre comment tout cela se met en scène !
Cela mise à part, le reste du code est vraiment simple. Car au final, on ne fait qu’afficher :
- deux « zones fixes » à l’écran (boutons de sélection des différentes épaisseurs de trait + bouton « effacer écran » en haut, et boutons de sélection couleur en bas)
- et une « zone dynamique » au milieu (où quand l’utilisateur appuiera à un endroit donné, un petit cercle plein se dessinera à ce même endroit, simulant ainsi un dessin manuel)
Voici le résultat d’un petit dessin (texte) fait à la main, sur l’écran ! Avec une couleur différente pour chaque lettre, histoire que ce soit plus sympa 😉

Sympa, non ?
Quelques remarques, cependant :
- ici, j’ai dessiné avec un stylet (fourni avec l’écran TFT), plutôt qu’avec les doigts ; cela m’a permis d’être plus précis au niveau de l’écriture, en fait
- j’ai noté quelques erreurs de lecture au niveau du tactile, générant ainsi parfois quelques artefacts sur l’écran (en clair : cela fait apparaître des points parfois « éloignés » de là où on appuie, ce qui empêche de bien dessiner ou écrire là où on veut). Ces « données indésirables », difficiles à filtrer, semblent être inhérentes à l’utilisation de la librairie « XPT2046_Touchscreen », car je n’ai pas eu de soucis avec l’utilisation de la librairie TFT_eSPI + l’ESP32 dans l’exemple #5, avec le même écran tactile)
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Code exemple #4 : affichage séquentiel d’images (ESP32 + TFT ILI9341)
À présent, voyons comment afficher des images sur un écran TFT ILI9341 à partir d’un ESP32 (ce qui peut servir de fond, pour un affichage sympa !). Ici, j’ai basculé sur un ESP32 car nous aurons besoin de plus d’espace mémoire, tout simplement. Et d’ailleurs, ce sera plus sympa que toujours utiliser un Arduino Uno 😉
Tout d’abord, voici le câblage sur lequel reposera cet exemple ESP32 + TFT display ILI9341 :

Et voici les éléments nécessaires à la réalisation de ce montage :
- 1 x carte ESP32-S3-DevKitC (modèle N16R8, ici)
- 1 x Écran TFT ILI9341 320×240 (2,8″ SPI)
- 2 x Breadboard, pour mettre l’ESP32 à cheval dessus
- 1 x Lot de fils dupont, pour raccorder le tout !
Ah oui… je ne l’ai pas précisé, mais nous allons afficher ici séquentiellement 4 images sur l’écran TFT, correspondant aux 4 saisons (printemps, été, automne, hiver, donc !). Et pour bien vous montrer que les images seront dessous (en « fond d’écran »), on écrira le nom des saisons par dessus.
Au passage, voici les liens des 4 images que j’ai pris (source : Pixabay)
- Printemps : https://pixabay.com/fr/photos/pin-feuille-plantes-vert-7857969/
- Été : https://pixabay.com/fr/photos/plage-recours-jet%C3%A9e-promenade-666122/
- Automne : https://pixabay.com/fr/photos/automne-or-feuilles-autumn-gold-2654751/
- Hiver : https://pixabay.com/fr/photos/hiver-cong%C3%A8re-montagnes-loger-6052851/
J’ai ensuite redimensionné/rogné ces images, afin qu’elles fassent 320 x 240 pixels (format « paysage »), afin que ça prenne toute la largeur et hauteur du TFT display.
Une fois fait, je suis allé sur le site https://marlinfw.org/tools/rgb565/converter.html pour convertir ces images au format texte/RGB565, pour qu’elles puissent être intégrées dans notre code, et compatibles avec notre écran TFT.
Ici, j’ai en fait copié le code résultant de chaque image, et l’ai mis dans des fichiers avec l’extension « .h » ; ce qui m’a permis d’obtenir les fichiers 1_printemps.h, 2_ete.h, 3_automne.h, et 4_hiver.h, que j’ai ensuite copié/coller dans le répertoire contenant le fichier « .ino » de cet exemple, écrit sous Arduino IDE (oui… j’ai utilisé l’IDE Arduino pour programmer l’ESP32, mais si vous préférez VS Code ou autre, n’hésitez pas à changer !).
Remarque : retrouvez tous ces fichiers en téléchargement à la fin de cet article, dans la rubrique « 11. Liens et téléchargements »
Autre point avant de passer au programme : comme je vous avais expliqué au paragraphe 4.2 (y faire un saut au besoin), il va falloir repérer puis modifier le fichier « User_Setup.h » de la librairie TFT_eSPI, afin de définir les broches utilisées ici. Perso, j’ai vidé ce fichier, et voici les lignes que j’ai mis dedans :
// Contrôleur de l'écran TFT : ici, l'ILI9341
#define ILI9341_DRIVER
// Option 1, branchement SPI et autre : (à commenter, si option 2 choisie)
// --> FSPI/VSPI = SPI2 (MOSI: 11, SCK: 12, et MISO: 13)
#define USE_FSPI_PORT
#define TFT_DC 8 // Choisir pins au choix, entre 1 et 31 compris, par exemple
#define TFT_RST 9
#define TFT_CS 10
#define TFT_MOSI 11 // Fixe (hardware SPI2)
#define TFT_SCLK 12 // Fixe (hardware SPI2)
#define TFT_MISO 13 // Fixe (hardware SPI2)
// Option 2, branchement SPI et autre : (à commenter, si option 1 choisie)
// --> HSPI = SPI3 (MOSI: 35, SCK: 36, et MISO: 37)
// #define USE_HSPI_PORT // Cas où port HSPI utilisé
// #define TFT_MOSI 35 // Fixe (hardware SPI3)
// #define TFT_SCLK 36 // Fixe (hardware SPI3)
// #define TFT_MISO 37 // Fixe (hardware SPI3)
// #define TFT_DC 38 // Choisir pins au choix, entre 1 et 31 compris, par exemple
// #define TFT_RST 39
// #define TFT_CS 40
// Partie tactile (optionnel, si souhaité)
// #define TOUCH_CS 16
// Intégration des fonts souhaitées, et autre
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#define SMOOTH_FONT
// Définition des vitesses maxi de transmission
#define SPI_FREQUENCY 40000000 // Maximum pour l'ILI9341
// #define SPI_READ_FREQUENCY 6000000
// #define SPI_TOUCH_FREQUENCY 2500000
// Ajout, pour corriger problème d'affichage RGB (rouge/vert/bleu) des images
#define TFT_RGB_ORDER TFT_BGR // S'utilise de paire avec "tft.setSwapBytes(true);", dans le code/programmeAinsi, on définit quelles sont les connexions faites entre l’ESP32 et le TFT display ILI9341. Je ne vais pas rentrer plus dans les détails que ça, afin de ne pas vous perdre en cours de route ! Sachez simplement que j’ai commenté les lignes non utilisées ici (avec un « // » devant), notamment au niveau du port SPI matériel utilisé ici, à savoir le FSPI (MOSI=11, SCK=12, et MISO=13) et non le HSPI (MOSI=35, SCK=36, et MISO=37).
Du reste, voici le code arduino de cet exemple ESP32/TFT ILI9341 (utilisant la librairie TFT_eSPI, optimisée pour le pilotage d’écrans TFT depuis un ESP32) :
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_) | [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___ | ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \ | | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___| | |
\_|
Fichier : prg4-ESP32_S3_DevKitC-TFT_ILI9341-afficher-des-images.ino
Dépôt : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Description : Programme permettant d'afficher des images sur un écran TFT (contrôleur ILI9341),
en utilisant un ESP32-S3-DevKitC
Licence : BY-NC-ND 4.0 CC (https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr)
Remarques : - jumper J1 "soudé/fait", pour que l'écran TFT fonctionne entièrement en 3,3V
- les broches utilisées ici (ESP32 ↔ écran TFT) sont définies dans le fichier "User_Setup.h" (dans le répertoire TFT_eSPI)
Auteur : Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le : 10.09.2025
*/
// Inclusion des librairies dont nous aurons besoin ici
#include <TFT_eSPI.h>
// Inclusion des images
#include "1_printemps.h"
#include "2_ete.h"
#include "3_automne.h"
#include "4_hiver.h"
// Constantes
#define pause_entre_chaque_image 3000 // 3000 ms (soit 3 sec) de pause, entre chaque image affichée sur l'écran TFT
// Création d'une instance de l'objet TFT_eSPI
TFT_eSPI tft = TFT_eSPI();
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialiser l'écran
tft.init();
tft.setSwapBytes(true); // Corrige un "bug" de décalage de couleurs
// Définir l'orientation de l'écran (0 à 3 pour rotation)
tft.setRotation(1); // Ajustez selon l'orientation souhaitée (1 = paysage)
// Remplir l'écran avec une couleur de fond (noir)
tft.fillScreen(TFT_BLACK);
}
// =================
// Boucle principale
// =================
void loop() {
// Affichage de la 1ère image
afficher_image_avec_texte_accompagnant(printemps, "Printemps", TFT_WHITE);
delay(pause_entre_chaque_image);
// Affichage de la 2ème image
afficher_image_avec_texte_accompagnant(ete, "Ete", TFT_WHITE);
delay(pause_entre_chaque_image);
// Affichage de la 3ème image
afficher_image_avec_texte_accompagnant(automne, "Automne", TFT_WHITE);
delay(pause_entre_chaque_image);
// Affichage de la 4ème image
afficher_image_avec_texte_accompagnant(hiver, "Hiver", TFT_WHITE);
delay(pause_entre_chaque_image);
}
// =================================================
// Fonction : afficher image avec texte accompagnant
// =================================================
void afficher_image_avec_texte_accompagnant(const uint16_t *image, const char *texte_accompagnant, uint16_t couleur_du_texte) {
// Afficher l’image
tft.pushImage(0, 0, 320, 240, image); // posX, posY, largeur, hauteur, lien_image
// Afficher le texte accompagnant
tft.setTextColor(couleur_du_texte);
tft.setTextSize(2);
tft.setCursor(20, 20);
tft.print(texte_accompagnant);
// Traçage d'une ligne horizontale, sous le texte
tft.drawLine(20, 40, 300, 40, couleur_du_texte);
}
Une remarque, avant upload de ce programme dans un ESP32 : voici les réglages que j’ai fait de mon côté, dans le menu Outil de l’IDE Arduino (montrant notamment la partition mémoire, côté ESP32-S3) :

En synthèse, j’ai sélectionné ici :
- en « Carte », j’ai pris une « ESP32S3 Dev Module », car j’utilise un ESP32-S3-DevKitC-N16R8
- en « Flash Size », j’ai choisi « 16MB (128Mb) », car ma carte est une « N16R8 » (16M de flash / 8M de PSRAM)
- en « Partition Scheme », j’ai opté pour du « 16M Flash (3MB APP / 9.9MB FATFS) », histoire d’avoir suffisamment de place pour tout mettre (images et prog) dans la mémoire programme
Une fois le programme uploadé, voici ce qui s’affiche sur l’écran TFT (désolé pour la médiocre qualité d’image, une fois encore !) :

Remarque : les textes sont écrits en blanc sur fond transparent (laissant donc apparaître l’image sous chaque caractère), ce qui n’est pas toujours très lisible ici. Mais cela peut être adapté en fonction des images, au besoin !
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Code exemple #5 : piloter une LED RGB avec ses doigts (ESP32 + TFT + touch)
Dernier exemple pratique que nous allons voir ici : comment piloter une led RGB (rouge/vert/bleu), à partir d’un écran TFT tactile, et d’un ESP32 ? Ainsi, nous verrons comment intégrer la partie touch des écrans TFT au programme arduino pour ESP32, et par la même occasion, nous verrons comment piloter la LED rgb embarquée sur l’ESP32-S3-DevKitC !
Mais avant tout, jetons un coup d’œil à la partie câblage matériel :

Au niveau matériel, on retrouve :
- 1 x carte ESP32 S3 DevKitC (modèle N16R8 ici, pour la démo)
- 1 x Écran TFT tactile ILI9341 (320×240 SPI 2,8″)
- 2 x Breadboard pour mettre l’ESP32 à cheval dessus, ou tout autre support adapté
- 1 x Ensemble de fils dupont, pour câbler le tout !
Au passage, à peu de choses près, c’est le même schéma que l’exemple #4. En fait, les seules différences sont :
- l’ajout du câblage pour la partie « touch » (tactile TFT)
- le branchement « alternatif » au niveau du port SPI de l’ESP32, histoire que vous ayez un exemple de chaque branchement SPI matériel possible !
Aussi, comme dans l’exemple précédent, utilisant la librairie TFT_eSPI (optimisée pour l’ESP32), il faut retrouver puis configurer le fichier « User_Setup.h » de cette librairie (comme détaillé au paragraphe 4.2 de ce tuto). Pour ma part, j’ai viré tout ce qu’il y avait dans ce fichier, et y ait mis les lignes suivantes :
// Contrôleur de l'écran TFT : ici, l'ILI9341
#define ILI9341_DRIVER
// Option 1, branchement SPI et autre : (à commenter, si option 2 choisie)
// --> FSPI/VSPI = SPI2 (MOSI: 11, SCK: 12, et MISO: 13)
// #define USE_FSPI_PORT
// #define TFT_DC 8 // Choisir pins au choix, entre 1 et 31 compris, par exemple
// #define TFT_RST 9
// #define TFT_CS 10
// #define TFT_MOSI 11 // Fixe (hardware SPI2)
// #define TFT_SCLK 12 // Fixe (hardware SPI2)
// #define TFT_MISO 13 // Fixe (hardware SPI2)
// Option 2, branchement SPI et autre : (à commenter, si option 1 choisie)
// --> HSPI = SPI3 ( MOSI: 35, SCK: 36, et MISO: 37)
#define USE_HSPI_PORT // Cas où port HSPI utilisé
#define TFT_MOSI 35 // Fixe (hardware SPI3)
#define TFT_SCLK 36 // Fixe (hardware SPI3)
#define TFT_MISO 37 // Fixe (hardware SPI3)
#define TFT_DC 38 // Choisir pins au choix, entre 1 et 31 compris, par exemple
#define TFT_RST 39
#define TFT_CS 40
// Partie tactile (optionnel, si souhaité)
#define TOUCH_CS 41
// Intégration des fonts souhaitées, et autre
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#define SMOOTH_FONT
// Définition des vitesses maxi de transmission
#define SPI_FREQUENCY 40000000 // Maximum pour l'ILI9341
// #define SPI_READ_FREQUENCY 6000000
#define SPI_TOUCH_FREQUENCY 2500000
// Ajout, pour corriger problème d'affichage RGB (rouge/vert/bleu) des images
#define TFT_RGB_ORDER TFT_BGR // S'utilise de paire avec "tft.setSwapBytes(true);", dans le code/programmeLà encore, je ne vais pas entrer dans les détails, pour l’heure. Retenez simplement qu’on définit ici quelles sont les connexions faites entre l’ESP32 et l’écran TFT type ILI9341, en précisant qu’on va utiliser le port matériel SPI HSPI (MOSI=35, SCK=36, et MISO=37), et non le FSPI/VSPI (MOSI=11, SCK=12, et MISO=13).Comme vous pouvez le constater, cela se fait en commentant/décommentant les lignes qui nous intéressent, ici.
Cela étant vu, voyons à présent le programme qui va pouvoir mettre en scène tout cela (écrit sous Arduino IDE, pour que ce soit plus simple) :
/*
______ _ _///_ _ _ _
/ _ \ (_) | ___| | | | (_) | [_| |__ ___ ___ _ ___ _ __ | |__ | | ___ ___| |_ _ __ ___ _ __ _ ___ _ _ ___ | ___/ _ \| __|| __| |/ _ \| '_ \_____| __|| |/ _ \/ _| _| '__/ \| '_ \| |/ \| | | |/ _ \ | | | ( ) |__ ||__ | | ( ) | | | |____| |__ | | __/| (_| |_| | | (_) | | | | | (_) | |_| | __/
\__| \__,_|___||___|_|\___/|_| [_| \____/|_|\___|\____\__\_| \___/|_| |_|_|\__ |\__,_|\___| | |
\_|
Fichier : prg5-ESP32_S3_DevKitC-TFT_ILI9341-piloter-led-RGB-avec-tactile.ino
Dépôt : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Description : Programme permettant de piloter la NeoPixel (LED RGB) embarquée sur un ESP32-S3-DevKitC,
à partir d'un écran TFT (contrôleur ILI9341) tactile (contrôleur XPT2046)
Licence : BY-NC-ND 4.0 CC (https://creativecommons.org/licenses/by-nc-nd/4.0/deed.fr)
Remarques : - jumper J1 "soudé/fait", pour que l'écran TFT fonctionne entièrement en 3,3V
- les broches utilisées ici (ESP32 ↔ écran TFT) sont définies dans le fichier "User_Setup.h" (dans le répertoire TFT_eSPI)
Auteur : Jérôme TOMSKI (https://passionelectronique.fr/)
Créé le : 11.09.2025
*/
// Inclusion des librairies dont nous aurons besoin ici
#include <TFT_eSPI.h>
#include <Adafruit_NeoPixel.h>
// Constantes
#define BROCHE_NEOPIXEL 48 // Broche GPIO48 pour la WS2812 embarquée sur l'ESP32-S3-DevKitC
#define NBRE_NEOPIXELS 1 // Nombre de LEDs (1 pour une seule, car c'est le cas sur l'ESP32-S3-DevKitC)
// Instanciation de l'objet "TFT_eSPI" (écran TFT, à contrôleur ILI9341)
TFT_eSPI tft = TFT_eSPI();
// Instanciation de l'objet "Adafruit_NeoPixel" (NeoPixel présente sur l'ESP32-S3-DevKitC)
Adafruit_NeoPixel neopixels(NBRE_NEOPIXELS, BROCHE_NEOPIXEL, NEO_GRB + NEO_KHZ800);
// Variables
uint8_t valeur_couleur_rouge;
uint8_t valeur_couleur_verte;
uint8_t valeur_couleur_bleue;
uint16_t tactile_min_X;
uint16_t tactile_min_Y;
uint16_t tactile_max_X;
uint16_t tactile_max_Y;
// ========================
// Initialisation programme
// ========================
void setup() {
// Initialisation de l'écran TFT
tft.init();
tft.setRotation(0); // 0 = affichage mode "portrait"
// Calibration de la partie tactile de l'écran TFT
calibrer_partie_tactile_de_l_ecran_TFT();
// Efface tout ce qui est affiché sur l'écran TFT
tft.fillScreen(TFT_BLACK);
// Initialisation des variables
valeur_couleur_rouge = 255;
valeur_couleur_verte = 210;
valeur_couleur_bleue = 20;
// Initialisation de la NeoPixel présente sur l'ESP32-S3-DevKitC
neopixels.begin();
neopixels.setBrightness(10); // Réglage de la luminosité (0-255, réglée sur 10 pour éviter de trop tirer sur l'alimentation)
// Tests
afficher_elements_graphiques_statiques();
afficher_elements_graphiques_dynamiques();
piloter_ESP32_neopixel();
}
// =================
// Boucle principale
// =================
void loop() {
// Variables temporaires, qui contiendront les coordonnées du "point" touché, et dire si une couleur a été modifiée
uint16_t touche_x = 0, touche_y = 0;
bool couleur_modifiee = false;
// Teste sur une touche "valide" a été détectée sur l'écran
bool touche_detectee = tft.getTouch(&touche_x, &touche_y);
// Si une touche valide a été détectée, alors on la traite
if (touche_detectee) {
// On regarde si on a touché dans la zone de la barre rouge (élargissement 5 pixels en dessus et en dessous)
if(touche_y > 75 && touche_y < 105) {
valeur_couleur_rouge = map(touche_x, 0, 239, 0, 255);
couleur_modifiee = true;
}
// On regarde si on a touché dans la zone de la barre verte (élargissement 5 pixels en dessus et en dessous)
if(touche_y > 145 && touche_y < 175) {
valeur_couleur_verte = map(touche_x, 0, 239, 0, 255);
couleur_modifiee = true;
}
// On regarde si on a touché dans la zone de la barre bleue (élargissement 5 pixels en dessus et en dessous)
if(touche_y > 205 && touche_y < 235) {
valeur_couleur_bleue = map(touche_x, 0, 239, 0, 255);
couleur_modifiee = true;
}
// Si une couleur a été modifiée, alors on met à jour les éléments graphiques dynamiques à l'écran, et la neopixel de l'ESP32
if(couleur_modifiee) {
afficher_elements_graphiques_dynamiques();
piloter_ESP32_neopixel();
}
}
}
// =================================================
// Fonction : afficher éléments graphiques statiques
// =================================================
void afficher_elements_graphiques_statiques() {
// Définition de la couleur des textes
tft.setTextColor(TFT_WHITE);
// -------------------
// Titre et sous-titre
// -------------------
// Affichage du titre, en haut
tft.setTextSize(2);
tft.setCursor(0, 0);
tft.print("Pilotage LED RGB");
// Affichage du sous-titre
tft.setTextSize(1);
tft.setCursor(0, 20);
tft.print("ESP32-S3-DevKitC");
// Soulignage du sous-titre
tft.drawLine(0, 35, 239, 35, TFT_WHITE);
// -------------------
// Barre pour le rouge
// -------------------
// Texte pour le rouge
tft.setTextSize(2);
tft.setCursor(0, 60);
tft.print("Rouge");
// Barre pour le rouge
tft.drawRect(0, 80, 240, 20, TFT_LIGHTGREY);
// ------------------
// Barre pour le vert
// ------------------
// Texte pour le vert
tft.setTextSize(2);
tft.setCursor(0, 130);
tft.print("Vert");
// Barre pour le vert
tft.drawRect(0, 150, 240, 20, TFT_LIGHTGREY);
// ------------------
// Barre pour le bleu
// ------------------
// Texte pour le bleu
tft.setTextSize(2);
tft.setCursor(0, 190);
tft.print("Bleu");
// Barre pour le bleu
tft.drawRect(0, 210, 240, 20, TFT_LIGHTGREY);
// ------------
// Partie basse
// ------------
// Texte "Résultat"
tft.setTextSize(2);
tft.setCursor(0, 284);
tft.print("Resultat >>");
// Cadre pour le résultat
tft.drawRect(150, 260, 90, 60, TFT_LIGHTGREY);
}
// =================================================================================================
// Fonction : conversion de composantes rouge/vert/bleu 8 bits en valeur résultante 16 bits (RGB565)
// =================================================================================================
uint16_t convertir_RGB_8bits_vers_RGB565(uint8_t rouge, uint8_t vert, uint8_t bleu) {
// Réduire les valeurs 8 bits à 5/6/5 bits, pour coller au "standard" RGB 565
uint16_t r = (rouge >> 3); // 8 bits -> 5 bits (0-31)
uint16_t g = (vert >> 2); // 8 bits -> 6 bits (0-63)
uint16_t b = (bleu >> 3); // 8 bits -> 5 bits (0-31)
// Combiner en une valeur 16 bits (RGB565)
return (r << 11) | (g << 5) | b;
}
// ==================================================
// Fonction : afficher éléments graphiques dynamiques
// ==================================================
void afficher_elements_graphiques_dynamiques() {
// Contrainte des différentes valeurs
uint8_t largeur_barre_rouge = map(valeur_couleur_rouge, 0, 255, 1, 238);
uint8_t largeur_barre_verte = map(valeur_couleur_verte, 0, 255, 1, 238);
uint8_t largeur_barre_bleue = map(valeur_couleur_bleue, 0, 255, 1, 238);
// Remplissage des barres de couleur
tft.fillRect(1, 81, largeur_barre_rouge, 18, TFT_RED);
tft.fillRect(1, 151, largeur_barre_verte, 18, TFT_GREEN);
tft.fillRect(1, 211, largeur_barre_bleue, 18, TFT_BLUE);
// Remplissage des parties non remplies, au niveau des barres de couleur
tft.fillRect(largeur_barre_rouge + 1, 81, 238 - largeur_barre_rouge, 18, TFT_BLACK);
tft.fillRect(largeur_barre_verte + 1, 151, 238 - largeur_barre_verte, 18, TFT_BLACK);
tft.fillRect(largeur_barre_bleue + 1, 211, 238 - largeur_barre_bleue, 18, TFT_BLACK);
// Détermination de la couleur résultante (et passage au format 16 bits / RGB565)
uint16_t couleur_resultante = convertir_RGB_8bits_vers_RGB565(valeur_couleur_rouge, valeur_couleur_verte, valeur_couleur_bleue);
// Remplissage de la couleur résultante
tft.fillRect(151, 261, 88, 58, couleur_resultante);
}
// ===================================================
// Fonction : piloter la NeoPixel présente sur l'ESP32
// ===================================================
void piloter_ESP32_neopixel() {
// Définition des composants R(ouge), G(reen), B(lue), pour la neopixel embarquée sur l'ESP32-S3-DevKitC
neopixels.setPixelColor(0, neopixels.Color(valeur_couleur_rouge, valeur_couleur_verte, valeur_couleur_bleue));
// Mise à jour de la NeoPixel
neopixels.show();
}
// ====================================================
// Fonction : calibrer la partie tactile de l'écran TFT
// ====================================================
void calibrer_partie_tactile_de_l_ecran_TFT()
{
// Variable temporaire
uint16_t donnees_de_calibration[5];
// Début de calibration
tft.fillScreen(TFT_BLACK);
tft.setTextSize(2);
tft.setTextColor(TFT_LIGHTGREY, TFT_BLACK);
tft.setCursor(10, 40);
tft.println("Touchez les coins,");
tft.setCursor(30, 65);
tft.println("comme indique !");
tft.calibrateTouch(donnees_de_calibration, TFT_WHITE, TFT_BLACK, 15);
// Calibration terminée
tft.fillScreen(TFT_BLACK);
tft.setCursor(40, 60);
tft.println("Calibration");
tft.setCursor(40, 85);
tft.println("terminee !");
tft.setCursor(40, 160);
tft.println("Demarrage...");
// Petite pause, avant de passer à la suite
delay(2000);
}Au passage, nous utilisons ici la librairie « Adafruit_NeoPixel » pour piloter la LED rgb présente sur l’ESP32-S3 ; il faudra donc préalablement l’installer via le menu Outils > Gérer les bibliothèques, si jamais vous ne vous en êtes jamais servis auparavant.
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
Du reste, le programme est assez simple. Il permet en fait d’afficher trois barres sur l’écran TFT (une rouge, une verte, et une bleue), et à l’aide de votre doigt ou stylet, vous pourrez faire varier chacune de ces trois barres, du mini au maxi. Ainsi, vous obtiendrez une couleur résultante de la composition de ces 3 couleurs de base, et le résultat sera visible au coin bas/droit de l’écran, ainsi que sur la LED RGB présente sur la carte ESP32-S3-DevKitC.
Pour que ce soit plus parlant, voici une petite animation vidéo, vous montrant tout cela :

Sur cette vidéo, la LED multicolore (RGB) est visible en haut/à gauche sur l’ESP32 (au dessus de la led rouge « power »). Vous noterez que sa couleur n’est pas aussi fidèle que sur l’écran TFT ILI9341, tout du moins d’aussi près, et dans ces conditions (sans compter que ma vidéo est de piètre qualité, hein !). Cela étant dit, en réalité, le rendu réel est bien meilleur que sur cet enregistrement 😉
Comparatif : écran TFT vs écran OLED (ILI9341 vs SSD1306/1309)
Pour finir, voici un résumé simplifié des avantages et inconvénients d’un écran TFT, par rapport à un écran OLED (puisqu’on emploie ces deux types d’écrans très souvent, dans nos montages électroniques, dès lors qu’on a besoin d’un affichage quel que peu complexe ou personnalisé).
Et pour que ce comparatif soit plus parlant vis à vis de cet article, je vous ai fait ici la comparaison entre les écrans TFT à puce ILI9341 (que je vous présente ici) et les écrans OLED à puce SSD1306 ou SSD1309 (que l’on retrouve couramment dans nos petits montages électroniques) :
| Critère | TFT (ILI9341) | OLED (SSD1306/SSD1309) |
|---|---|---|
| Nombre de couleurs | Multicolore (262 144 couleurs) | Monochrome (blanc, bleu, jaune, vert), et parfois bicolore (jaune/bleu) |
| Taille d’écran | Plutôt grande (de 2,2 à 3,5 pouces) | Plutôt petite (de 0,96 à 2,42 pouces) |
| Visibilité | Assez bonne, avec un angle de vue d’environ 120 à 160° ; par contre, la visibilité en extérieur peut vite se dégrader, dès lors qu’il fait un peu « trop jour » ! | Excellente (contraste infini, noirs parfaits), avec un angle de vue supérieur à 170° |
| Coût | Modéré (5 à 17 € environ, suivant la taille et si l’option touch est choisie ou non) | Faible (2 à 9 € environ ; c’est ce qu’il y a de plus économique pour nous, du moins pour les affichages « simples » !) |
| Résolution | 240 x 320 pixels (76 800 pixels) | 128 x 64 pixels (8192 pixels), généralement (car suivant le format, on peut trouver des résolutions plus ou moins variées) |
| Consommation | 50-100 mA environ (rétroéclairage constant) | 10-30 mA environ |
| Pilotage | SPI (4 fils) | I²C (2 fils) et SPI (4 fils) ; généralement, on préfère utiliser l’i2c, car plus économe en fils de pilotage |
| Temps de réponse | Plutôt « lent » (20 à 50 ms, mais cela reste acceptable pour les interfaces graphiques qui ne « bougent » pas sans arrêt !) | Très rapide (<10 µs, idéal pour animations/textes) |
| Durée de vie | > 50 000 h | 20 000 à 40 000 h (dégradation organique) |
| Applications typiques | GUIs riches, graphiques, projets avec couleurs (ESP32, Raspberry Pi, …) | Affichage texte/icônes, capteurs, appareils nomades (Arduino, IoT basique, …) |
Du reste, je vous renvoie vers l’article que j’avais fait sur les écrans OLED 0,96″ I2C/SPI à contrôleur SSD1306, pour compléter/approfondir au besoin !
Liens et téléchargements
Pour ceux que ça intéresse, tous les programmes / exemples de code sont disponibles sur GitHub, à l’adresse suivante : https://github.com/PassionElectronique/Programmes-tests-pour-ecrans-TFT-ILI9341
Et plus précisément, pour chaque programme :
- exemple #1 : écrire du texte en couleur sur un TFT display, et faire des rotation écran
- exemple #2 : tracer des formes aléatoires sur un écran TFT (lignes, cercles, rectangles, triangles, …)
- exemple #3 : dessiner à la main sur un écran tactile TFT (contrôleur ILI9341)
- exemple #4 : afficher des images, de manière séquentielle
- exemple #5 : piloter une LED RGB à partir d’un TFT touch display (ILI9341/XPT2046)
Écran TFT arduino/ESP32 (ILI9341) : conclusion !
Voilà ! Je pense que nous avons fait le tour de tout ce qu’il était bon de savoir pour bien démarrer avec les écrans TFT à contrôleur ILI9341, et ce, que vous soyez sur Arduino ou ESP32 ! J’espère que tout cela pourra vous aider dans vos créations / projets d’électronique, et ainsi agrémenter de milles couleurs vos réalisations 😉
Du reste, histoire de compléter cet article, je vous partagerai bientôt des exemples d’usages concrets de ce genre d’afficheur, dans la rubrique « Réalisations Passion Électronique ». Pour l’heure, je ne vous avais partagé que des montages mettant en œuvre des écrans OLED, mais bientôt, j’en rajouterai avec des écrans TFT. Comme ça, vous aurez des exemples plus parlants que ce tuto !
À très bientôt,
Jérôme.
| Module | Description | Lien |
|---|---|---|
![]() | Écran TFT tactile ILI9341 (afficheur 2,8" couleur SPI) |
À découvrir aussi : les écrans rétros monochromes type Nokia 5110 (puce PCD8544)
(*) Mis à jour le 28/10/2025




J’ai passé des jours à galérer avec ces écrans.
Un tout grand merci pour cette synthèse complète et exhaustive.
De rien, avec plaisir !
Salut Jérome
Merci pour cet article très bien documenté comme tous tes articles d’ailleurs. C’est une vraie mine d’or. C’est carrément un livre que tu nous a écrit sur le sujet.
Super. Merci.
Magnifique article, très détaillé et professionnel.
Merci d’y avoir consacré un temps sûrement très important.
Encore bravo et merci.
Pierre
Très bonne documentation sur cet écran
Encore Merci JEROME
Merci pour cet article comme tous tes articles d’ailleurs. C’est un travail remarquable. Merci de partager ta Passion.
Merci à vous d’avoir décortiqué cette présentation en autant de phase très bien expliquée.
Cela aidera sûrement beaucoup de personnes qui débute avec les écrans TFT.
Toujours d’excellent articles utiles.
RBerTux.
Merci à tous, pour tous vos messages chaleureux !
Je viens de le parcourir en travers et en effet il y a un travail colossal derrière tout ça. Je me suis empressé de le sauvegarder pour y revenir plus tard avec le matériel en main.
Bravo et merci
Grand merci pour ce tuto très détaillé et pour le temps passé … le tout en francais,
Bonne continuation, Régis.
Merci pour ce tuto vraiment bien expliqué et détaillé.
Néophyte, je reviens régulièrement sur votre site pour scroller les nouveautés et aller chercher des infos. J’ai quand même une question sur l’utilisation du TSX0108 pour l’adaptation bidirectionnelle des fronts du bus SPI : ne serait-il pas mieux d’utiliser d’autres buffer car il semblerait que son driver et ses commutations ne soient pas vraiment adaptés au SPI (plus pour les I2C) … Juste pour que je me couche moins bête 🙂
Salut Jean-François !
Non, c’est même exactement le contraire, en pratique : le TXS 0108E est « meilleur » en SPI qu’en I2C, si je puis dire ! Pour comprendre pourquoi, il faut bien comprendre le datasheet du TXS0108E de Texas Instruments, où l’on peut lire, dès le haut de la 1ère page :
Maximum data rates:– 110Mbps (push pull)
– 1.2Mbps (open drain)
Plus précisément :
Dans notre cas, on emploie le TSX 0108E lorsqu’on utilise un Arduino Uno, pour faire l’abaissement 5V → 3,3V. Or, classiquement, la fréquence d’horloge SPI du microcontrôleur de l’Arduino Uno (un ATmega328P) est de 4 MHz (plus ou moins, selon comment est configuré le prescaler au niveau des registres SPCR/SPSR, en sachant que l’ATmega328P est usuellement cadencé à 16 MHz). Du coup, avec nos 110 Mbps de « capacité de transmission » sur le TXS0108E, on est tranquille 😉
Voilà ! En espérant avoir pu t’éclairer !
@+
Jérôme.