Shield TFT LCD 3,5 pouces : un écran 480 × 320 sur un bus 8 bits rapide

La plupart des petits écrans utilisés en électronique amateur communiquent en SPI : une ligne d’horloge, une ligne de données, et chaque octet passe au compte-gouttes, un bit à la fois. Le shield rouge de 3,5 pouces de cet article fonctionne autrement. Retournez-le : au lieu de MOSI et SCK, vous trouverez huit lignes de données, LCD_D0 à LCD_D7, si bien que chaque coup d’horloge transporte un octet entier. Ajoutez 480 × 320 pixels, un film tactile résistif et un emplacement microSD, et vous obtenez l’un des plus grands écrans qui s’enfichent directement sur un Arduino Uno, sans un seul fil.

Il mérite qu’on s’y attarde, même si vous n’avez jamais possédé d’Uno. Nous l’avons relié à un ESP32-S3 doté d’un périphérique 8080 matériel, nous avons cadencé le bus à 20 MHz et lu depuis une carte microSD une vidéo plein écran en 480 × 320 à 25 images par seconde ; vous pouvez la voir dans la partie consacrée à la vitesse. Au programme : ce qu’il y a sur la carte, comment fonctionne son bus et comment le programmer, d’où vient la vitesse et où elle se perd, et ce qu’on peut construire avec, d’une station météo à un cadre photo ou un panneau mural.

La face arrière du shield TFT LCD de 3,5 pouces, avec ses éléments légendés. À gauche, les lignes de commande LCD_RST, LCD_CS, LCD_RS, LCD_WR et LCD_RD, puis les broches d'alimentation GND, GND, 5V et 3V3. À droite, les lignes de données LCD_D2 à LCD_D7, puis LCD_D0, LCD_D1 et les lignes microSD SD_CS, SD_DI, SD_DO et SD_SCK. Entre les deux, deux puces tampons de bus, un régulateur 3,3 V, un emplacement microSD et les cases imprimées ILI9486 et ILI9488.
La face arrière du shield, là où se trouve tout le marquage : lignes de commande et alimentation à gauche, les huit lignes de données et les lignes microSD à droite. Cliquez pour la version en taille réelle.

De quelle carte il est question exactement

Les boutiques le vendent sous le nom « 3.5 inch TFT LCD Shield for Arduino UNO/Mega », et plusieurs usines fabriquent des cartes qui se ressemblent mais diffèrent par leurs composants. Celle de cet article a un circuit imprimé rouge, la sérigraphie 3.5″ TFT LCD Shield et un code de date 2026-01-27. Son détail le plus révélateur se trouve dans un coin : deux cases imprimées, ILI9488 et ILI9486, dont aucune n’est cochée. Le contrôleur lui-même est monté en chip-on-glass et caché sous la dalle : la carte ne dit donc pas lequel des deux elle porte.

Notre exemplaire affiche une image correcte et stable avec la séquence d’initialisation de l’ILI9488 : il s’agit donc très probablement d’un ILI9488. C’est une hypothèse de travail plutôt qu’une identification : les deux contrôleurs partagent les commandes de base, et la mauvaise séquence donne souvent une image, elle aussi, simplement avec un contraste médiocre ou du scintillement. Une autre carte de la même boutique peut porter l’autre puce. La face avant accueille un film tactile résistif 4 fils, avec une nappe à quatre contacts le long du bord supérieur, et le verre est marqué H1454 7-3. Nulle part sur la carte on ne trouve de puce de contrôleur tactile.

Caractéristiques techniques

ÉlémentCe que c’estEn pratique
DalleTFT 3,5 pouces, 320 × 480 en natif, 480 × 320 en paysage153 600 pixels : de quoi afficher un graphique légendé, une photo ou une image vidéo
ContrôleurILI9486 ou ILI9488, en chip-on-glass ; le nôtre se comporte comme un ILI9488Les deux demandent des séquences d’init différentes ; la mauvaise affiche quand même une image, mais moins bonne
InterfaceBus parallèle de type Intel 8080 : huit lignes de données plus CS, RS, WR, RD et RST13 broches côté hôte ; un octet par impulsion d’écriture
CouleurRGB666, 262K couleurs, 3 octets par pixel : vérifié. RGB565, 65K couleurs, 2 octets : devrait fonctionnerDeux octets par pixel réduiraient le trafic d’un tiers
Horloge d’écriture20 MHz vérifiés avec des fils Dupont ; la fiche technique de l’ILI9488 autorise jusqu’à 25 MHzUne image complète en 23 ms à trois octets par pixel
TactileFilm résistif 4 fils, sans puce de contrôleurL’hôte le mesure avec son propre ADC, via des broches partagées avec l’écran
StockageLecteur microSD en SPI, broches D10–D13 de l’UnoPhotos, polices et vidéos sur la carte elle-même
Tension5 V sur la broche 5V ; régulateur AMS1117 3,3 V sur la carteUne seule alimentation pour la dalle, la logique et le rétro-éclairage
Niveaux logiquesHôte en logique 3,3 V : vérifié ; le shield a été conçu pour la logique 5 V d’un UnoFonctionne avec un ESP32, un RP2040 ou un STM32 aussi bien qu’avec les cartes AVR
Rétro-éclairageToujours allumé ; aucune broche de commandePas de réglage de luminosité par logiciel ; pour économiser l’énergie, coupez le 5 V
FormatShield Arduino Uno R3, 28 brochesS’enfiche sur un Uno ou un Mega ; tout autre hôte demande des fils Dupont

D’abord, un peu d’arithmétique. Une image compte 480 × 320 = 153 600 pixels : 460 800 octets à trois octets par pixel, 307 200 à deux. Le bus 8 bits transfère un octet par impulsion d’écriture : à 20 MHz, il transporte donc 20 millions d’octets par seconde, et une image complète prend 23 ms, ou 15,4 ms à deux octets par pixel. Le SPI, lui, transfère un bit par coup d’horloge. À 20 MHz, la limite que fixe la fiche technique de l’ILI9488 pour son interface SPI, la même image prend 184 ms, et même avec un SPI surcadencé à 40 MHz, il lui faut 92 ms.

Les broches : câbler d’après le marquage

Le shield reprend la disposition de l’Arduino Uno, mais le marquage compte davantage que les numéros de l’Uno. L’octet de données est scindé d’une manière qui en surprend plus d’un : LCD_D2 à LCD_D7 se trouvent sur les broches D2 à D7 de l’Uno, tandis que LCD_D0 et LCD_D1 ont été déplacées sur D8 et D9, afin que D0 et D1 restent libres pour le port série de l’Uno.

Broche UnoMarquageRôle
A0LCD_RDImpulsion de lecture, active à l’état bas ; à maintenir à l’état haut
A1LCD_WRImpulsion d’écriture, active à l’état bas ; la dalle capture les données sur son front montant
A2LCD_RSSélection de registre : 0 pour une commande, 1 pour des données ; D/C dans d’autres bibliothèques
A3LCD_CSSélection de la puce, active à l’état bas
A4LCD_RSTReset, actif à l’état bas
D2–D7LCD_D2–D7Bits de données 2 à 7
D8, D9LCD_D0, LCD_D1Bits de données 0 et 1
D10SD_CSSélection de la microSD
D11SD_DIEntrée de données de la microSD, MOSI
D12SD_DOSortie de données de la microSD, MISO
D13SD_SCKHorloge de la microSD
5V, GND5V, GNDAlimentent toute la carte
3.3V3V3On ne sait pas où elle est reliée ; ne pas s’en servir pour alimenter

Deux détails piègent bien des gens. Le marquage n’est imprimé qu’au dos, si bien qu’écran face à vous, les rangées de gauche et de droite changent de côté : câblez strictement d’après le marquage, jamais d’après la position. Et sur un Uno, le shield prend presque tout. Il reste D0 et D1, qui forment le port série, la broche A5, dépourvue de marquage, et les broches SPI partagées avec la carte mémoire. L’I²C disparaît, car A4, le SDA de l’Uno, sert de LCD_RST. Une station météo avec quelques capteurs réclame donc un Mega ou, mieux, une carte 32 bits reliée par des fils Dupont.

Comment dialogue le bus 8 bits

Le bus est de type Intel 8080, ce que la fiche technique de l’ILI9488 appelle DBI Type B. Il n’a pas d’horloge au sens du SPI : l’hôte place un octet sur D0–D7 et envoie une impulsion sur WR, et la dalle prend l’octet sur le front montant. RS indique la nature de l’octet : 0 pour une commande, 1 pour un paramètre ou des données de pixels. CS encadre la transaction, RST réinitialise le contrôleur, et RD est l’impulsion de lecture.

SignalAu reposRôle
CSHautBas tant que l’hôte dialogue avec la dalle
RSPeu importe0 pour un octet de commande, 1 pour un paramètre ou des données de pixels
WRHautUne brève impulsion basse par octet ; la dalle capture D0–D7 sur le front montant
RDHautNe doit jamais flotter ; maintenu haut sauf pendant une lecture
RSTHautUn niveau bas remet le contrôleur à zéro
D0–D7—Pilotées par l’hôte ; la dalle ne les pilote que lorsque RD est bas
Chronogramme d'une écriture sur le bus 8 bits. CS passe à l'état bas et y reste. Avec RS à l'état bas, l'octet 0x2C apparaît sur D0–D7 et une impulsion WR l'envoie. RS passe ensuite à l'état haut, et les octets R, G, B, R, G, B suivent, chacun avec son impulsion WR. Un repère vert marque chaque front montant de WR, la durée d'un octet est indiquée, 50 ns à 20 MHz, et RD reste à l'état haut du début à la fin.
Une transaction d’écriture : un octet de commande avec RS à l’état bas, puis des données de pixels avec RS à l’état haut. Chaque front montant de WR transfère un octet.

Voilà tout le protocole. Une commande part avec RS à l’état bas, et ses paramètres suivent avec RS à l’état haut. Les pixels ne diffèrent en rien des paramètres : après la commande RAMWR, 0x2C, chaque octet envoyé avec RS à l’état haut atterrit dans la mémoire de la dalle, et le flux peut durer aussi longtemps que l’hôte le souhaite.

Dessiner : une fenêtre et un flux

Le contrôleur garde toute l’image dans sa propre mémoire et rafraîchit lui-même la dalle à partir de celle-ci : l’hôte n’envoie donc que ce qui change. Pour dessiner, l’hôte ouvre une fenêtre : CASET, 0x2A, fixe la première et la dernière colonne, PASET, 0x2B, la première et la dernière ligne. Après RAMWR, les pixels remplissent cette fenêtre de gauche à droite et de haut en bas, sans aucune coordonnée intermédiaire. Deux fonctions de bus, l’une pour un octet de commande, l’autre pour des octets de données, suffisent à tout portage :

static void set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
    uint8_t ca[4] = { (uint8_t)(x0 >> 8), (uint8_t)x0,
                      (uint8_t)(x1 >> 8), (uint8_t)x1 };
    uint8_t pa[4] = { (uint8_t)(y0 >> 8), (uint8_t)y0,
                      (uint8_t)(y1 >> 8), (uint8_t)y1 };
    lcd_write_cmd(0x2A); lcd_write_data(ca, 4);   // CASET: columns
    lcd_write_cmd(0x2B); lcd_write_data(pa, 4);   // PASET: rows
}

// A solid rectangle in RGB666: 3 bytes per pixel, one window
static void fill_rect(uint16_t x, uint16_t y, uint16_t w, uint16_t h,
                      uint8_t r, uint8_t g, uint8_t b) {
    const uint8_t px[3] = { r, g, b };
    set_window(x, y, x + w - 1, y + h - 1);
    lcd_write_cmd(0x2C);                           // RAMWR
    for (uint32_t i = 0; i < (uint32_t)w * h; i++) {
        lcd_write_data(px, 3);
    }
}

C’est avec la fenêtre que la vitesse se gagne ou se perd. Envoyez autant de pixels que possible dans une même fenêtre : une fenêtre par pixel coûte onze octets de commandes et de coordonnées pour trois octets de couleur.

Formats de pixel et orientation

Deux registres déterminent l’aspect de l’image. COLMOD, 0x3A, fixe le format de pixel. 0x66, c’est le RGB666 : trois octets par pixel, avec la couleur dans les six bits de poids fort de chaque octet, et c’est ce qui tourne sur notre carte. 0x55, c’est le RGB565, deux octets par pixel : les deux fiches techniques le prévoient pour le bus parallèle et les bibliothèques populaires l’y utilisent, mais nous ne l’avons pas encore testé sur cet exemplaire. Si le nombre d’octets envoyés par pixel ne correspond pas à COLMOD, les aplats sortent sous forme de fines rayures de mauvaises couleurs qui ne couvrent qu’une partie de la fenêtre.

MADCTL, 0x36, fixe l’orientation et l’ordre des couleurs. Sur cette carte, la valeur 0x28 donne une image paysage de 480 × 320 correcte et sans effet miroir, et c’est grâce au bit BGR qu’elle contient que les couleurs partent dans l’ordre R, G, B tout simple. Un rouge et un bleu intervertis se corrigent avec ce bit, un effet miroir avec les bits MX et MY, et des axes permutés avec MV, jamais dans le code de l’application.

MADCTLImageSur cette carte
0x48Portrait, 320 × 480Valeur standard, non testée
0x28Paysage, 480 × 320Vérifiée
0x88Portrait, retournéNon testée
0xE8Paysage, retournéNon testée

ILI9486 ou ILI9488 ?

En théorie, le contrôleur décline son identité : la commande 0xD3 renvoie un octet factice, suivi de 0x00, 0x94 et 0x86 ou 0x88. En pratique, beaucoup de shields de cette famille sont en écriture seule. Leurs tampons de bus sont câblés dans un seul sens, des broches vers la dalle, si bien que rien de ce que dit la dalle n’atteint jamais l’hôte. La bibliothèque populaire MCUFRIEND_kbv relit alors son propre octet de commande et annonce l’ID 0xD3D3 ; son sketch de test signale ce cas comme un shield en écriture seule.

Sur une telle carte, le contrôleur s’identifie à l’œil. Initialisez-le avec la séquence de l’ILI9488 et dessinez des aplats, des dégradés de gris et de couleur et une grille d’un pixel, puis recommencez avec la séquence de l’ILI9486, et gardez celle qui donne des dégradés lisses, un bon contraste et aucun scintillement. Nous n’avons pas essayé de lire l’ID sur la nôtre. Avec la séquence de l’ILI9488, son image est correcte : c’est donc elle qui figure ci-dessous.

La séquence d’initialisation de l’ILI9488 qui fonctionne sur cette carte
RST: high 50 ms, low 50 ms, high 150 ms             ; hardware reset
0x01                                                ; SWRESET, wait 120 ms
0x28                                                ; DISPOFF
0xE0: 00 03 09 08 16 0A 3F 78 4C 09 0A 08 16 1A 0F  ; positive gamma
0xE1: 00 16 19 03 0F 05 32 45 46 04 0E 0D 35 37 0F  ; negative gamma
0xC0: 17 15                                         ; power control 1
0xC1: 41                                            ; power control 2
0xC5: 00 12 80                                      ; VCOM control
0x36: 48                                            ; MADCTL: portrait, BGR
0x3A: 66                                            ; COLMOD: RGB666
0xB0: 00                                            ; interface mode
0xB1: A0                                            ; frame rate
0xB4: 02                                            ; inversion control
0xB6: 02 02 3B                                      ; display function
0xB7: C6                                            ; entry mode
0xF7: A9 51 2C 82                                   ; adjust control 3
0x11                                                ; SLPOUT, wait 120 ms
0x29                                                ; DISPON, wait 25 ms
0x36: 28                                            ; MADCTL: landscape

Chaque ligne est une commande suivie de ses octets de paramètres. Avec COLMOD à 0x55 au lieu de 0x66, la dalle attendrait du RGB565, que nous n’avons pas encore testé. Les valeurs des registres correspondent au pilote ILI9488 de TFT_eSPI, à ceci près que la bibliothèque choisit 0x55 pour les bus parallèles. La variante pour l’ILI9486 se trouve dans le guide de programmation, à la fin de l’article.

D’où vient la vitesse

Le SPI transfère un bit par coup d’horloge. Le bus 8 bits, un octet. À horloge égale, cela fait huit fois plus de données, et c’est toute la raison pour laquelle cette interface d’un autre âge est toujours là : elle demande treize broches au lieu de quatre ou cinq, mais elle remplit un grand écran en une fraction du temps.

En haut : deux chronogrammes partagent huit coups d'horloge ; en SPI, ils transportent les huit bits d'un seul octet, sur le bus 8 bits, huit octets entiers. En bas : un diagramme en barres du temps que passe sur le bus une image complète de 480 par 320 : 184 ms en SPI à 20 MHz, 92 ms en SPI à 40 MHz, 23 ms sur le bus 8 bits à 20 MHz avec trois octets par pixel et 15,4 ms avec deux. Une ligne verticale marque 40 ms.
À horloge égale, le bus 8 bits transfère huit fois plus de données. Les barres sont calculées ; sur les quatre, seule la configuration à 23 ms a tourné sur notre carte.

Sur cette famille de contrôleurs en particulier, le SPI part en outre avec un handicap. En SPI, l’ILI9486 n’accepte la pleine couleur que sous forme 18 bits, et bien que la fiche technique de l’ILI9488 mentionne la couleur 16 bits pour son mode SPI 4 fils, en pratique ces puces sont pilotées à trois octets par pixel, et c’est exactement ce que font les bibliothèques populaires. La même fiche technique plafonne à 20 MHz l’horloge d’écriture SPI de l’ILI9488. Son bus parallèle a droit à un cycle d’écriture de 40 ns, soit 25 MHz : nos 20 MHz restent donc dans la spécification. L’ILI9486 est plus lent : sa fiche technique exige au moins 66 ns par écriture, soit environ 15 MHz. Si votre carte s’avère porter cette puce, commencez en dessous de cette valeur.

Mais le bus n’est jamais plus rapide que l’hôte qui le pilote. Basculer treize broches une à une avec digitalWrite() fait de l’interface la plus rapide de la carte l’une des plus lentes. Écrire des registres de port entiers vaut beaucoup mieux, et un périphérique matériel avec DMA, c’est l’idéal : le LCD_CAM d’un ESP32-S3, le PIO d’un RP2040 ou le FSMC d’un STM32 envoient les octets tout seuls pendant que le processeur prépare les suivants.

Notre test : vidéo à 25 i/s depuis une carte microSD

L’hôte était l’ESP32-S3-CAM N16R8 de notre article précédent, reliée au shield par des fils Dupont. Sur cette carte, les 13 lignes du bus ont pris des GPIO qu’utilise normalement la caméra, si bien que la caméra est restée sur la touche pendant ce test. Le bus passait par le pilote esp_lcd i80 d’ESP-IDF, sur le périphérique LCD_CAM du S3, avec une horloge d’écriture de 20 MHz, la séquence de l’ILI9488, le RGB666 et l’orientation paysage. Deux tampons DMA de 30 720 octets, de quoi loger 10 240 pixels chacun, travaillent à tour de rôle : pendant que l’un part vers la dalle, l’autre se remplit.

Le lecteur vidéo répartit le travail entre les deux cœurs. L’un lit les fichiers MJPEG sur la microSD de la carte hôte ; l’autre décode chaque image avec la bibliothèque JPEGDEC et pousse les blocs décodés directement dans les tampons DMA, en convertissant le RGB565 en RGB666 au passage. Résultat : une vidéo plein écran en 480 × 320, stable, à 25 images par seconde. Sur les 40 ms dont dispose chaque image, le bus en consomme 23. En SPI surcadencé à 40 MHz, la même image demanderait 92 ms rien que sur le bus : les 25 i/s seraient donc hors d’atteinte avant même qu’un seul pixel soit décodé.

Notre test en vidéo. L’ESP32-S3-CAM N16R8, sur la plaque d’essai en bas, pilote le shield par une nappe de fils Dupont et lit des clips MJPEG en 480 × 320 depuis sa carte microSD, à 25 i/s. Le petit écran à droite appartient à une autre carte. 33 secondes, sans son.

La configuration du bus tient en deux structures. Voici comment notre pilote s’y prend. RD n’en fait pas partie du tout : esp_lcd n’a pas de chemin de lecture, et un GPIO ordinaire se contente donc de maintenir RD à l’état haut.

esp_lcd_i80_bus_config_t bus_config = {};
bus_config.dc_gpio_num = PIN_LCD_RS;
bus_config.wr_gpio_num = PIN_LCD_WR;
bus_config.clk_src = LCD_CLK_SRC_PLL160M;
bus_config.data_gpio_nums[0] = PIN_LCD_D0;     // likewise [1] to [7]
bus_config.bus_width = 8;
// One DMA chunk: 32 lines of 320 pixels in RGB666
bus_config.max_transfer_bytes = 320 * 32 * 3;
esp_lcd_new_i80_bus(&bus_config, &i80_bus);

esp_lcd_panel_io_i80_config_t io_config = {};
io_config.cs_gpio_num = PIN_LCD_CS;
io_config.pclk_hz = 20 * 1000 * 1000;          // 20 MHz write clock
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 8;
io_config.lcd_param_bits = 8;
io_config.dc_levels.dc_cmd_level = 0;          // RS low: command
io_config.dc_levels.dc_data_level = 1;         // RS high: data
esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle);

Ensuite, esp_lcd_panel_io_tx_param() envoie les commandes avec leurs paramètres, et esp_lcd_panel_io_tx_color() met les données de pixels en file d’attente pour le DMA et rend la main aussitôt. C’est aussi là que se cache le piège : il ne faut pas remplir de nouveau un tampon avant la fin de son transfert, sinon des blocs de l’image sortent corrompus.

Il reste deux limites. Avec les réglages habituels, le contrôleur rafraîchit la dalle depuis sa mémoire environ 60 fois par seconde, et le shield ne sort pas le signal de tearing effect qui permettrait à l’hôte de caler ses écritures sur ce rafraîchissement : un mouvement rapide peut donc laisser apparaître une ligne de déchirure. Et un tampon d’image complet, 460 800 octets en RGB666, ne tient que dans une PSRAM externe : c’est pourquoi notre pilote envoie plutôt de petits morceaux depuis la mémoire interne.

Quel hôte, quelle bibliothèque

Le shield a été conçu pour l’Uno, mais l’Uno est l’hôte le plus lent qu’il puisse avoir. Le tableau résume les solutions habituelles ; le guide de programmation en fin d’article donne les contraintes de broches de chacune.

HôteSolutionÀ surveiller
Arduino UnoS’enfiche tel quel. MCUFRIEND_kbv avec Adafruit_GFX, plus Adafruit TouchScreen pour le film2 Ko de SRAM : pas de tampon d’image, les images sont lues en flux depuis la carte. L’octet de données est réparti sur deux ports, ce qui coûte du temps
Arduino MegaS’enfiche tel quel. MCUFRIEND_kbvLes broches de l’Uno tombent sur des ports dispersés du Mega, ce qui est plus lent que sur l’Uno ; mémoire et broches à revendre
ESP32esp_lcd i80 via l’I2S, LovyanGFX, TFT_eSPIGPIO34–39 ne servent qu’en entrée. Les cartes au format Uno comme la Wemos D1 R32 y placent LCD_RS, LCD_CS et LCD_RST : ces trois lignes sont à recâbler
ESP32-S3esp_lcd i80 sur LCD_CAM avec DMA, comme dans notre test ; LovyanGFX et Arduino_GFX utilisent aussi LCD_CAMN’importe quel GPIO peut porter n’importe quel signal. TFT_eSPI fonctionne aussi, mais sur le S3, il bascule les registres GPIO sans DMA
RP2040TFT_eSPI avec PIO et DMAD0–D7 doivent être sur des GPIO qui se suivent
STM32FSMC ou FMC en mode 8080 si le boîtier le permet ; sinon, écritures de portLes broches FSMC sont fixes pour chaque boîtier

Quel que soit l’hôte, prévoyez les broches en pensant au tactile : le film partage des lignes avec l’écran, et ses extrémités analogiques demandent des broches compatibles ADC. Nous y revenons plus bas.

Sur un Uno, le plus rapide pour démarrer est MCUFRIEND_kbv. Nous n’avons pas exécuté nous-mêmes ce sketch sur un Uno : c’est la méthode standard de la bibliothèque, avec un ajout pour les cartes en écriture seule.

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>

MCUFRIEND_kbv tft;

void setup() {
  Serial.begin(9600);
  uint16_t id = tft.readID();
  Serial.print(F("ID = 0x"));
  Serial.println(id, HEX);
  // A write-only shield reads back 0xD3D3: name the controller yourself
  if (id == 0xD3D3) id = 0x9488;
  tft.begin(id);
  tft.setRotation(1);              // landscape, 480 × 320
  tft.fillScreen(0x0000);          // black
  tft.setTextColor(0x07E0);        // green
  tft.setTextSize(3);
  tft.setCursor(24, 24);
  tft.print(F("Hello, 480 x 320"));
}

void loop() {}

Le tactile sans contrôleur tactile

Le film tactile est du type résistif 4 fils classique : deux couches résistives qui se touchent là où l’on appuie. Il n’y a ni XPT2046 ni puce similaire pour le lire. À la place, ses quatre électrodes sont reliées à des lignes que l’écran utilise déjà, et l’hôte les mesure avec son propre ADC. Il applique une tension aux bornes d’une couche et lit, par l’autre couche, la tension au point de contact, puis inverse les rôles pour l’autre axe.

Les lignes qui portent les électrodes varient d’une carte à l’autre, et sur la nôtre, nous ne les avons pas encore repérées. Sur les shields de cette famille, les extrémités analogiques se trouvent généralement sur LCD_WR, LCD_RS ou LCD_CS, et les extrémités numériques sur des lignes de données comme LCD_D6 et LCD_D7. Un multimètre les trouve en une minute : carte hors tension, deux paires entre les lignes de commande et les lignes de données présentent quelques centaines d’ohms, environ 300 pour une couche et 500 pour l’autre.

Lire le tactile revient alors à emprunter ces broches à l’écran. Attendez que le bus soit au repos, gardez inactive la ligne de commande qui n’est pas une électrode pour que la dalle ignore le bruit, prenez plusieurs échantillons, et rendez à chaque broche son rôle d’affichage avant le transfert suivant. Sautez cette dernière étape, et vous obtiendrez des pixels aléatoires et un écran figé. Avec un périphérique matériel comme LCD_CAM, c’est plus difficile encore, car il faut détacher les broches du périphérique puis les y rattacher : décidez donc comment vous lirez le tactile avant de figer le brochage. Le film préfère aussi les grandes cibles : des boutons de la taille du bout du doigt lui conviennent bien mieux qu’une interface façon smartphone.

microSD, alimentation et rétro-éclairage

L’emplacement microSD a ses propres lignes SPI, SD_CS, SD_DI, SD_DO et SD_SCK, sur les broches D10 à D13 de l’Uno, électriquement séparées du bus de l’écran. Sur tout autre hôte, il peut aller sur n’importe quelles broches compatibles SPI. Nous ne l’avons pas testé sur cet exemplaire : pour la vidéo ci-dessus, l’ESP32-S3 lisait la carte de son propre emplacement. Si vous ne l’utilisez pas, laissez ses lignes non connectées ou maintenez SD_CS à l’état haut.

L’alimentation arrive en 5 V sur la broche 5V. Le régulateur de la carte fournit le 3,3 V de la dalle et des tampons de bus, et un hôte en 3,3 V pilote directement la logique. Ne touchez pas à la broche 3V3 : on ne sait pas où elle est reliée, et elle ne remplace pas l’alimentation 5 V. Le rétro-éclairage n’a pas de broche de commande et reste allumé tant que la carte est alimentée : on ne peut donc ni le tamiser ni l’éteindre par logiciel ; DISPOFF et SLPIN effacent l’image, pas la lumière. Nous n’avons pas mesuré le courant. À titre indicatif, la spécification de la dalle d’un shield Uno de 3,5 pouces similaire donne 90 mA en valeur typique pour son rétro-éclairage à six LED : une alimentation USB trop faible ou le petit régulateur d’une carte de développement méritent donc une vérification à l’ampèremètre.

Que construire avec ce shield

Le 480 × 320 est une taille confortable : assez grande pour un graphique aux légendes lisibles, une photo ou une rangée de boutons de la taille du bout du doigt, assez petite pour se remplir vite. C’est pourquoi cette catégorie d’écrans revient sans cesse dans les projets, aussi bien sur ce shield précis que sur ses cousins.

Quatre interfaces dessinées en 480 par 320. Un écran météo sombre avec 18 degrés, partiellement nuageux, humidité 64 pour cent, pression 1014 hPa, vent 3 m/s et un graphique de température sur 24 heures. L'image d'un lac de montagne avec des points de diaporama. Un panneau tactile clair avec six grands boutons pour les lumières, le chauffage, un ventilateur, une imprimante 3D, la porte d'entrée et une scène du soir. Un écran d'oscilloscope avec une grille, une sinusoïde et un signal carré.
Quatre tâches que l’écran remplit bien, dessinées à sa vraie définition de 480 × 320.

1. Une station météo

Le montage le plus populaire de tous. Dans le projet Instructables Second Multi-functional Weather Station, un Arduino Mega porte exactement ce type de shield ILI9486 de 3,5 pouces, avec une horloge DS3231 et des capteurs DHT22 et BMP280, et utilise l’emplacement microSD du shield pour un album d’environ un millier de photos converties en BMP. D’autres montages se passent carrément de capteurs. Sur le blog thesolaruniverse, un ESP32 doté d’un shield de 3,95 pouces de même conception récupère la météo sur OpenWeatherMap par Wi‑Fi et l’affiche via le bus 8 bits avec TFT_eSPI. Un projet Elektor de décembre 2023 fait de même sur une carte Makerfabs ESP32-S3 avec un ILI9488 de 3,5 pouces, et lit les réglages Wi‑Fi et la ville dans un fichier de la carte mémoire.

2. Un cadre photo

L’emplacement microSD fait presque à lui seul du shield un cadre photo. MCUFRIEND_kbv fournit un exemple showBMP qui lit les fichiers BMP directement sur la carte, via les broches 10 à 13, et indique le temps de chargement de chacun. Sur un ESP32, le pilote esp-idf-parallel-tft de nopnop2002 affiche des fichiers BMP, JPEG et PNG sur les shields de cette famille et calibre aussi leur film tactile. C’est dans les transitions, fondus ou volets, que le bus parallèle se rentabilise : chaque étape d’une transition redessine tout l’écran, et une image complète coûte 23 ms sur ce bus, contre un dixième de seconde ou plus en SPI.

3. Un lecteur vidéo

Notre propre test représente le cas le plus exigeant : du MJPEG lu sur une carte à 25 i/s. Pour partir d’une base toute faite, les exemples MJPEG de la bibliothèque Arduino_GFX affichent la fréquence d’images moyenne et ventilent le temps entre lecture, décodage et dessin, ce qui en fait un banc d’essai pratique pour n’importe quelle carte. Larry Bank, l’auteur de JPEGDEC, le décodeur qu’utilise notre lecteur, a piloté un vieux shield Uno ILI9486 de 3,5 pouces depuis un RP2040 via PIO et DMA, et y a affiché des GIF animés ; son compte rendu s’intitule Breathing new life into an old LCD shield.

4. Une console de jeu

Les jeux demandent exactement ce que ce bus sait bien faire : redessiner beaucoup de pixels plusieurs fois par seconde. Le projet ESP32-S3_Uno-nofrendo fait tourner l’émulateur NES nofrendo sur une carte ESP32-S3 au format Uno, avec un shield 8 bits ILI9488 enfiché directement dessus, et charge les ROM depuis la carte microSD ; il n’a encore ni joystick ni son. Dans un registre plus simple, un clone de Tetris pour Arduino Mega avec un shield ILI9486 tire sa musique d’un transmetteur FM pour voiture : pour l’entendre, il faut régler une radio sur 87,5 MHz. La série de tutoriels Dumblebots construit un logiciel de dessin façon Paint et un morpion sur le même type de shield de 3,5 pouces, film tactile compris.

5. Un panneau tactile mural

Un panneau domotique est l’usage évident d’un écran tactile de cette taille, et là, les cousins tout faits l’emportent généralement. Le WT32-SC01 Plus associe un ESP32-S3 à un écran de 3,5 pouces en 480 × 320 sur le même type de bus 8 bits. openHASP en fait un panneau commandé par MQTT et bâti sur LVGL, et avec un composant communautaire, ESPHome peut le piloter pour Home Assistant. AirQualitySensor-IDF transforme la même carte en moniteur de qualité de l’air : il lit des capteurs de particules, de CO₂, de température et d’humidité, et trace six heures d’historique avec LVGL. Si vous avez une imprimante 3D, vous possédez peut-être déjà un écran de cette catégorie : l’interface Color UI de Marlin tourne sur des écrans tactiles de 3,5 pouces en 480 × 320 comme le MKS TFT35, reliés au STM32 de l’imprimante par le bus parallèle FSMC.

6. Instruments de mesure

Une trace d’oscilloscope doit être redessinée plusieurs fois par seconde, ce qui convient à un bus rapide. Un projet open source associe un STM32F303 à un écran ILI9486 de 3,5 pouces pour un oscilloscope à 2 Méch/s avec un enregistrement de 4096 points. DLO-138, un firmware open source pour le populaire kit DSO-138, pilote le plus petit ILI9341 de ce kit sur un bus 8 bits et en fait un oscilloscope à deux voies, avec en plus deux voies numériques. Pour les jauges, les compteurs et les graphiques, TFT_eSPI propose tout un dossier d’exemples écrits pour le 480 × 320.

Encore quelques idées que d’autres ont déjà réalisées sur des écrans 480 × 320 :

Les cousins : le même écran sous d’autres formes

Le shield appartient à une grande famille. Si son format ou son bus ne convient pas à un projet, l’un de ses cousins fera peut-être l’affaire. Tous sont en 480 × 320, sauf les shields Uno plus petits :

ÉcranContrôleur et busBon à savoir
Shields Uno de 2,4 et 2,8 poucesILI9341 et autres ; parallèle 8 bitsMême brochage et mêmes bibliothèques, en 240 × 320
Modules SPI de 3,5 pouces, comme le MSP3520ILI9488 ; SPI 4 filsPeu de broches, tactile sur ses propres lignes SPI, trois octets par pixel
Shields Uno de 3,95 poucesILI9486 et autres ; parallèle 8 bitsDalle plus grande, même câblage
WT32-SC01 PlusST7796 ; parallèle 8 bits, ESP32-S3 intégréUn panneau tout prêt pour openHASP, ESPHome et LVGL
Makerfabs ESP32-S3 Parallel TFT, 3,5 poucesILI9488 ; parallèle 16 bits, ESP32-S3 intégréBus deux fois plus large
ESP32-3248S035, le Cheap Yellow Display de 3,5 poucesST7796 ; SPI, ESP32 intégréComplet et bon marché, mais en SPI
MKS TFT35ILI9488 ou ST7796 ; parallèle FSMCL’écran tactile de bien des imprimantes 3D

Forces et faiblesses

Points fortsPoints faibles
S’enfiche directement sur un Uno ou un MegaSur un Uno, il prend presque toutes les broches, I²C compris
480 × 320 avec tactile et microSD sur une seule carteILI9486 ou ILI9488 : la carte ne dit pas lequel, et elle peut être en écriture seule
Un bus 8 bits : une image complète en 23 ms à 20 MHz, fréquence vérifiéeTreize fils de signal sur tout hôte sur lequel il ne s’enfiche pas
Fonctionne avec des hôtes en 3,3 V : ESP32, RP2040, STM32Sans périphérique de bus matériel, l’essentiel de la vitesse est perdu
Vidéo plein écran à 25 i/s depuis un ESP32-S3Pas de signal de tearing effect sur les broches
Tactile sans puce supplémentaireLe film tactile partage des broches avec l’écran et a besoin de l’ADC de l’hôte
Un emplacement microSD sur des lignes SPI séparéesLe rétro-éclairage est toujours allumé, sans aucun moyen de le tamiser

Conclusion

Le shield TFT LCD de 3,5 pouces a tout d’une relique de l’ère de l’Arduino Uno, et sur un Uno, il se comporte comme tel : il prend presque toutes les broches et remplit l’écran au rythme d’un processeur 8 bits. Mais donnez-lui un hôte doté d’un vrai périphérique parallèle, et le vieux bus montre pourquoi il a survécu : un octet par coup d’horloge, une image complète de 480 × 320 en 23 ms, de la vidéo à 25 i/s.

Pour une station météo, un cadre photo, un panneau de commande ou un petit instrument de mesure, c’est largement suffisant, à condition que le premier essai parte d’une configuration éprouvée :

  1. Vérifiez l’absence de court-circuit sur 5V, 3V3 et GND, puis branchez d’abord GND et le 5 V sur la broche 5V.
  2. Câblez d’après le marquage au dos, jamais d’après la position, et maintenez LCD_RD à l’état haut dès le départ.
  3. Utilisez la séquence de l’ILI9488, COLMOD 0x66 et MADCTL 0x28, à 10 MHz au plus.
  4. Dessinez d’abord des aplats et des dégradés ; si l’image est délavée ou scintille, essayez la séquence de l’ILI9486.
  5. Augmentez l’horloge progressivement, jusqu’à 20 MHz sur un ILI9488.
  6. Ajoutez le film tactile et la carte microSD en dernier, l’un après l’autre.

Tout ce qui précède, et davantage, réuni dans un seul fichier : le guide de programmation de ce shield. Le brochage selon le marquage, la temporisation du bus et les limites des fiches techniques, les séquences d’initialisation des deux contrôleurs, les formats de pixel, la rotation, le tactile et la microSD, une procédure de mise en route et un guide de dépannage, chaque affirmation étant signalée comme vérifiée, probable ou inconnue. Confiez-le à un agent de programmation avant qu’il n’écrive la moindre ligne de code de pilote.