3,5-дюймовий TFT LCD-шилд: екран 480 × 320 на швидкій 8-бітній шині
Більшість невеликих аматорських дисплеїв працює по SPI: одна тактова лінія, одна лінія даних, і кожен байт протискається крізь неї по одному біту. Червоний 3,5-дюймовий шилд із цієї статті влаштований інакше. Переверніть його — і замість MOSI та SCK побачите вісім ліній даних, від LCD_D0 до LCD_D7, тож кожен такт переносить цілий байт. Додайте 480 × 320 пікселів, резистивну сенсорну плівку й слот microSD — і вийде один із найбільших екранів, що вставляються просто в Arduino Uno без жодного дроту.
Придивитися до нього варто, навіть якщо у вас ніколи не було Uno. Ми підключили його до ESP32-S3 з апаратним периферійним модулем для шини 8080, запустили шину на 20 МГц і відтворили повноекранне відео 480 × 320 з карти microSD зі швидкістю 25 кадрів на секунду — ролик є в розділі про швидкість. Далі — що стоїть на платі, як працює шина шилда і як його програмувати, звідки береться швидкість і де вона губиться, а також що на ньому зібрати: від метеостанції до фоторамки й настінної панелі.

Про яку саме плату йдеться
У магазинах його продають як «3.5 inch TFT LCD Shield for Arduino UNO/Mega», і схожі на вигляд плати випускають кілька фабрик, але компоненти на них різняться. У нашого примірника червона друкована плата з написом 3.5″ TFT LCD Shield на шовкографії та кодом дати 2026-01-27. Найпромовистіша деталь — у кутку: два квадратики з написами ILI9488 та ILI9486, і жодного не позначено. Сам контролер змонтовано за технологією chip-on-glass і сховано під панеллю, тож плата не каже, який із двох на ній стоїть.
Із послідовністю ініціалізації ILI9488 наш шилд показує правильну, стабільну картинку, тож, найімовірніше, на ньому саме ILI9488. Це робоча гіпотеза, а не точне визначення: базові команди в обох контролерів спільні, і з неправильною послідовністю картинка теж часто з’являється — лише з поганою контрастністю або мерехтінням. На іншій платі з того самого магазину може стояти інша мікросхема. На лицьовому боці — 4-провідна резистивна сенсорна плівка з чотириконтактним шлейфом уздовж верхнього краю, а на склі маркування H1454 7-3. Мікросхеми сенсорного контролера на платі немає ніде.


Технічні характеристики
| Вузол | Що це | На практиці |
|---|---|---|
| Панель | 3,5-дюймова TFT: рідний формат 320 × 480, в альбомному режимі 480 × 320 | 153 600 пікселів: вистачає на графік із підписами, фото чи кадр відео |
| Контролер | ILI9486 або ILI9488, chip-on-glass; наш поводиться як ILI9488 | Їм потрібні різні набори стартових команд; з неправильним картинка все одно є, тільки гірша |
| Інтерфейс | Паралельна шина в стилі Intel 8080: вісім ліній даних плюс CS, RS, WR, RD і RST | 13 виводів хоста; один байт за строб запису |
| Колір | RGB666, 262K кольорів, 3 байти на піксель: перевірено. RGB565, 65K кольорів, 2 байти: має працювати | Два байти на піксель скоротили б трафік на третину |
| Частота запису | 20 МГц перевірено на дротах-перемичках; даташит ILI9488 допускає до 25 МГц | Повний кадр за 23 мс із трьома байтами на піксель |
| Сенсор | 4-провідна резистивна плівка, без мікросхеми контролера | Хост вимірює її власним ADC через виводи, спільні з дисплеєм |
| Карта пам’яті | Слот microSD на SPI, виводи Uno D10–D13 | Фото, шрифти й відео просто на платі |
| Живлення | 5 В на вивід 5V; на платі стабілізатор AMS1117 на 3,3 В | Одне джерело для панелі, логіки та підсвітки |
| Логічні рівні | Логіку хоста 3,3 В перевірено; шилд створено під 5-вольтову логіку Uno | Працює з ESP32, RP2040 чи STM32, а також із платами на AVR |
| Підсвітка | Завжди ввімкнена; виводу керування немає | Програмно її не притлумити; щоб заощадити енергію, вимкніть 5 В |
| Форм-фактор | Шилд Arduino Uno R3, 28 виводів гребінки | Ставиться на Uno чи Mega; для будь-якого іншого хоста потрібні дроти-перемички |
Спершу трохи арифметики. Кадр — це 480 × 320 = 153 600 пікселів: 460 800 байтів, якщо на піксель припадає три байти, і 307 200 — якщо два. По 8-бітній шині за один строб запису йде один байт, тож на 20 МГц вона переносить 20 мільйонів байтів на секунду, і повний кадр займає 23 мс, а з двома байтами на піксель — 15,4 мс. SPI передає один біт за такт. На 20 МГц — межі, яку даташит ILI9488 встановлює для свого інтерфейсу SPI, — той самий кадр займає 184 мс, і навіть із розгоном до 40 МГц — 92 мс.
Виводи: підключайте за підписами
Шилд повторює розкладку Arduino Uno, але підписи важать більше, ніж номери Uno. Байт даних розділено так, що це багатьох дивує: лінії від LCD_D2 до LCD_D7 сидять на виводах Uno з D2 по D7, а LCD_D0 і LCD_D1 переїхали на D8 і D9, щоб D0 і D1 лишалися вільними для послідовного порту Uno.
| Вивід Uno | Підпис | Що робить |
|---|---|---|
| A0 | LCD_RD | Строб читання, активний рівень низький; тримайте його високим |
| A1 | LCD_WR | Строб запису, активний рівень низький; панель фіксує дані за його висхідним фронтом |
| A2 | LCD_RS | Вибір регістра: 0 — команда, 1 — дані; в інших бібліотеках D/C |
| A3 | LCD_CS | Вибір мікросхеми, активний рівень низький |
| A4 | LCD_RST | Скидання, активний рівень низький |
| D2–D7 | LCD_D2–D7 | Біти даних 2–7 |
| D8, D9 | LCD_D0, LCD_D1 | Біти даних 0 і 1 |
| D10 | SD_CS | Вибір карти microSD |
| D11 | SD_DI | Вхід даних microSD, MOSI |
| D12 | SD_DO | Вихід даних microSD, MISO |
| D13 | SD_SCK | Тактовий сигнал microSD |
| 5V, GND | 5V, GND | Живлення всієї плати |
| 3.3V | 3V3 | Куди він веде, невідомо; для живлення його не беріть |
Дві речі часто збивають з пантелику. Підписи надруковано лише на звороті, тож, коли екран дивиться на вас, лівий і правий ряди міняються місцями: підключайте строго за підписами, ніколи — за положенням. А на Uno шилд займає майже все. Лишаються D0 і D1, тобто послідовний порт, непідписаний A5 і виводи SPI, спільні з картою пам’яті. Шина I²C пропадає, бо A4, тобто SDA в Uno, — це LCD_RST. Тож метеостанції з парою датчиків потрібна Mega або, ще краще, 32-бітна плата на дротах-перемичках.
Як розмовляє 8-бітна шина
Шина — у стилі Intel 8080, даташит ILI9488 називає її DBI Type B. Тактового сигналу в розумінні SPI в неї немає: хост виставляє байт на D0–D7 і подає імпульс на WR, а панель забирає байт за висхідним фронтом. RS каже, що це за байт: 0 — команда, 1 — параметр або дані пікселів. CS окреслює межі транзакції, RST скидає контролер, а RD — строб читання.
| Сигнал | У спокої | Роль |
|---|---|---|
| CS | Високий | Низький, поки хост звертається до панелі |
| RS | Будь-який | 0 для байта команди, 1 для параметра або даних пікселів |
| WR | Високий | Один короткий імпульс низького рівня на байт; панель фіксує D0–D7 за висхідним фронтом |
| RD | Високий | Не повинен висіти в повітрі; тримається високим, поки немає читання |
| RST | Високий | Низький рівень скидає контролер |
| D0–D7 | — | Ними керує хост; панель керує ними лише тоді, коли RD низький |

Ось і весь протокол. Команда йде за низького RS, а її параметри — за високого. Пікселі нічим не відрізняються від параметрів: після команди RAMWR, 0x2C, кожен байт, надісланий за високого RS, потрапляє в пам’ять панелі, і потік може тривати стільки, скільки потрібно хосту.
Малювання: вікно й потік
Контролер тримає всю картинку у власній пам’яті й сам оновлює з неї зображення на склі, тож хост надсилає лише те, що змінюється. Щоб малювати, хост відкриває вікно: CASET, 0x2A, задає перший і останній стовпець, PASET, 0x2B, — перший і останній рядок. Після RAMWR пікселі заповнюють це вікно зліва направо й згори вниз, без жодних координат між ними. Для портування досить двох функцій шини — однієї для байта команди, другої для байтів даних:
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);
}
}
Саме на вікні швидкість виграють або втрачають. Передавайте в одному вікні якомога більше пікселів: окреме вікно на кожен піксель коштує одинадцять байтів команд і координат на кожні три байти кольору.
Формати пікселів і орієнтація
Вигляд картинки визначають два регістри. COLMOD, 0x3A, задає формат пікселя. 0x66 — це RGB666, три байти на піксель, де колір займає старші шість бітів кожного байта; саме так працює наша плата. 0x55 — це RGB565, два байти на піксель: обидва даташити вказують його для паралельної шини, і популярні бібліотеки на ній використовують саме його, але на цьому примірнику ми його ще не перевіряли. Якщо кількість байтів, які ви надсилаєте на піксель, не збігається з COLMOD, суцільні заливки виходять дрібними смужками неправильних кольорів, що вкривають лише частину вікна.
MADCTL, 0x36, задає орієнтацію та порядок кольорів. На цій платі 0x28 дає правильну, невіддзеркалену альбомну картинку 480 × 320, а біт BGR у цьому значенні — причина того, що кольори надсилаються у звичайному порядку R, G, B. Переплутані червоний і синій виправляють цим бітом, дзеркальне відображення — бітами MX і MY, переставлені осі — бітом MV, і ніколи — у коді застосунку.
| MADCTL | Картинка | На цій платі |
|---|---|---|
| 0x48 | Портретна, 320 × 480 | Стандартне значення, не перевірено |
| 0x28 | Альбомна, 480 × 320 | Перевірено |
| 0x88 | Портретна, догори дриґом | Не перевірено |
| 0xE8 | Альбомна, догори дриґом | Не перевірено |
ILI9486 чи ILI9488?
Теоретично контролер сам повідомляє, хто він: команда 0xD3 повертає фіктивний байт, а за ним 0x00, 0x94 і 0x86 або 0x88. На практиці багато шилдів цього сімейства працюють лише на запис. Їхні буфери шини пропускають сигнали тільки в один бік — від гребінки до панелі, тож ніщо з того, що каже панель, до хоста не доходить. Популярна бібліотека MCUFRIEND_kbv тоді зчитує назад власний байт команди й повідомляє ID як 0xD3D3; її тестовий скетч позначає такий випадок як шилд лише на запис (write-only).
На такій платі контролер визначають на око. Ініціалізуйте його послідовністю ILI9488 і намалюйте суцільні заливки, сірі й кольорові градієнти та сітку в один піксель, потім повторіть із послідовністю ILI9486 і залиште ту, що дає плавні градієнти й добру контрастність без мерехтіння. На нашій платі ми ID прочитати не пробували. З послідовністю ILI9488 картинка в неї правильна, тому нижче наведено саме цю послідовність.
Послідовність ініціалізації ILI9488, яка працює на цій платі
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
Кожен рядок — це команда, за якою йдуть байти її параметрів. Із COLMOD = 0x55 замість 0x66 панель очікувала б RGB565, який ми ще не перевіряли. Значення регістрів збігаються з драйвером ILI9488 у TFT_eSPI, за винятком того, що для паралельних шин бібліотека вибирає 0x55. Варіант для ILI9486 є в гайді з програмування наприкінці статті.
Звідки береться швидкість
SPI передає один біт за такт. А 8-бітна шина — байт. На тій самій частоті це у вісім разів більше даних, і саме тому цей старомодний інтерфейс досі живий: йому потрібно тринадцять виводів замість чотирьох-п’яти, зате великий екран він заповнює в рази швидше.

До того ж саме в цьому сімействі контролерів SPI у невигідному становищі. По SPI ILI9486 приймає повний колір лише у 18-бітному вигляді, і, хоча даташит ILI9488 вказує 16-бітний колір для 4-провідного режиму SPI, на практиці цим мікросхемам надсилають по три байти на піксель — саме так роблять популярні бібліотеки. Той самий даташит ставить для запису ILI9488 по SPI межу 20 МГц. Для паралельної шини допускається цикл запису 40 нс, тобто 25 МГц, тож наші 20 МГц у межах специфікації. ILI9486 повільніший: його даташит вимагає щонайменше 66 нс на запис, це близько 15 МГц. Якщо на вашій платі виявиться саме ця мікросхема, починайте з частоти, нижчої за цю.
Утім, шина швидка рівно настільки, наскільки швидкий хост, що нею керує. Якщо перемикати тринадцять виводів по одному через digitalWrite(), найшвидший інтерфейс на платі перетворюється на один із найповільніших. Запис цілих регістрів портів — набагато краще, а найкраще — апаратний периферійний модуль із DMA: LCD_CAM в ESP32-S3, PIO в RP2040 чи FSMC в STM32 самі відправляють байти, поки процесор готує наступні.
Наш тест: відео 25 fps з карти microSD
Хостом була ESP32-S3-CAM N16R8 з нашої попередньої статті, з’єднана із шилдом дротами-перемичками. На цій платі 13 ліній шини зайняли GPIO, якими зазвичай користується камера, тож камера в цьому тесті участі не брала. Шина працювала через драйвер esp_lcd i80 з ESP-IDF на периферійному модулі LCD_CAM в S3 з частотою запису 20 МГц, з послідовністю ILI9488, RGB666 і в альбомній орієнтації. Два DMA-буфери по 30 720 байтів, кожен на 10 240 пікселів, працюють по черзі: поки один іде до панелі, другий заповнюється.
Плеєр ділить роботу між двома ядрами. Одне читає файли MJPEG з карти microSD у власному слоті плати; друге декодує кожен кадр бібліотекою JPEGDEC і відправляє декодовані блоки просто в DMA-буфери, дорогою перетворюючи RGB565 на RGB666. Результат — стабільне повноекранне відео 480 × 320 із частотою 25 кадрів на секунду. Із 40 мс, відведених на кадр, шині потрібно 23. По SPI з розгоном до 40 МГц той самий кадр потребував би 92 мс лише на шині, тож 25 fps були б недосяжні ще до того, як декодовано хоча б один піксель.
Для налаштування шини потрібні дві структури. Ось як це робить наш драйвер. RD тут узагалі не бере участі: читання в esp_lcd немає, тож високий рівень на RD просто тримає звичайний GPIO.
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);
Далі esp_lcd_panel_io_tx_param() надсилає команди з параметрами, а esp_lcd_panel_io_tx_color() ставить дані пікселів у чергу на DMA й одразу повертає керування. У цьому ж і пастка: буфер не можна заповнювати знову, доки не завершилася його передача, інакше блоки картинки виходять пошкодженими.
Лишаються два обмеження. Зі звичайними налаштуваннями контролер оновлює зображення на склі зі своєї пам’яті приблизно 60 разів на секунду, а сигналу tearing effect, за яким хост міг би синхронізувати запис із цим оновленням, шилд назовні не виводить, тож на швидкому русі може з’являтися лінія розриву кадру. А повний кадровий буфер, 460 800 байтів у RGB666, вміщується лише в зовнішню PSRAM, тому наш драйвер натомість передає невеликі шматки з внутрішньої пам’яті.
Який хост, яка бібліотека
Шилд створювали для Uno, але Uno — найповільніший із можливих для нього хостів. Таблиця підсумовує звичні шляхи; обмеження щодо виводів для кожного з них є в гайді з програмування наприкінці.
| Хост | Шлях | На що зважати |
|---|---|---|
| Arduino Uno | Ставиться напряму. MCUFRIEND_kbv з Adafruit_GFX, плюс Adafruit TouchScreen для плівки | 2 КБ SRAM: кадрового буфера немає, зображення подаються потоком із карти. Байт даних розбито між двома портами, а це коштує часу |
| Arduino Mega | Ставиться напряму. MCUFRIEND_kbv | Виводи Uno лягають на розкидані порти Mega — це повільніше, ніж на Uno; пам’яті та вільних виводів удосталь |
| ESP32 | esp_lcd i80 через I2S, LovyanGFX, TFT_eSPI | GPIO34–39 працюють лише на вхід. Плати формату Uno, як-от Wemos D1 R32, виводять на них LCD_RS, LCD_CS і LCD_RST, тож ці три лінії доведеться підключити інакше |
| ESP32-S3 | esp_lcd i80 на LCD_CAM із DMA, як у нашому тесті; LovyanGFX і Arduino_GFX теж працюють через LCD_CAM | Будь-який GPIO годиться для будь-якого сигналу. TFT_eSPI теж працює, але на S3 він перемикає регістри GPIO без DMA |
| RP2040 | TFT_eSPI з PIO і DMA | D0–D7 мають стояти на GPIO поспіль |
| STM32 | FSMC або FMC у режимі 8080, де дозволяє корпус; інакше запис у порти | Виводи FSMC жорстко задані для кожного корпусу |
Незалежно від хоста, плануйте виводи з огляду на сенсор: плівка ділить лінії з дисплеєм, а її аналоговим кінцям потрібні виводи з ADC. Докладніше про це нижче.
На Uno найшвидший старт дає MCUFRIEND_kbv. Самі ми цей скетч на Uno не запускали: це стандартний шлях бібліотеки з одним доповненням для плат, що працюють лише на запис.
#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() {}
Сенсор без сенсорного контролера
Сенсорна плівка тут — класична 4-провідна резистивна: два резистивні шари, що стикаються там, де ви натискаєте. Мікросхеми XPT2046 чи подібної, яка б її зчитувала, немає. Натомість чотири електроди плівки підключено до ліній, якими вже користується дисплей, і хост вимірює їх власним ADC. Він подає напругу на один шар і зчитує, в якому місці до нього торкається другий, а потім міняє шари ролями для другої осі.
На яких лініях сидять електроди, залежить від плати, і на нашій ми їх ще не простежили. На шилдах цього сімейства аналогові кінці зазвичай виходять на LCD_WR, LCD_RS або LCD_CS, а цифрові — на лінії даних, як-от LCD_D6 і LCD_D7. Мультиметр знаходить їх за хвилину: на знеструмленій платі дві пари між лініями керування та лініями даних показують кілька сотень омів — близько 300 для одного шару і 500 для другого.
Тож щоб прочитати дотик, ці виводи доводиться позичати в дисплея. Дочекайтеся, поки шина звільниться, тримайте неактивною ту лінію керування, яка не є електродом, щоб панель ігнорувала шум, зробіть кілька вимірювань і перед наступною передачею поверніть кожному виводу його функцію в дисплеї. Пропустіть останній крок — і отримаєте випадкові пікселі та завислий екран. З апаратним периферійним модулем на кшталт LCD_CAM ще складніше, бо виводи треба відв’язати від модуля й під’єднати знову, тож вирішіть, як читатимете сенсор, ще до того, як зафіксуєте карту виводів. До того ж плівка любить великі цілі: кнопки завбільшки з кінчик пальця підходять їй куди краще, ніж інтерфейс на манер смартфона.
microSD, живлення та підсвітка
У слота microSD свої лінії SPI — SD_CS, SD_DI, SD_DO і SD_SCK на виводах Uno з D10 по D13, електрично відокремлені від шини дисплея. На будь-якому іншому хості його можна підключити до будь-яких виводів, придатних для SPI. На цьому примірнику ми його не перевіряли: для відео вище плата з ESP32-S3 читала карту з власного слота. Якщо слот не потрібен, залиште його лінії непідключеними або тримайте SD_CS у високому рівні.
Живлення 5 В подається на вивід 5V. Стабілізатор на платі робить із них 3,3 В для панелі й буферів, а хост на 3,3 В керує логікою напряму. Вивід 3V3 на гребінці не чіпайте: куди він веде, невідомо, і живлення 5 В він не замінює. Підсвітка не має виводу керування й світить, поки на платі є живлення, тож програмно її не можна ні притлумити, ні вимкнути; DISPOFF і SLPIN гасять зображення, а не світло. Струм ми не вимірювали. Як грубий орієнтир: специфікація панелі схожого 3,5-дюймового шилда для Uno дає типові 90 мА для підсвітки з шести світлодіодів, тож слабке USB-живлення чи маленький стабілізатор налагоджувальної плати варто перевірити амперметром.
Що на ньому зібрати
480 × 320 — зручний розмір: досить великий для графіка з розбірливими підписами, фото чи ряду кнопок завбільшки з кінчик пальця і досить малий, щоб швидко його заповнювати. Тому екрани цього класу постійно трапляються в проєктах — і саме цей шилд, і його родичі.

1. Метеостанція
Найпопулярніша збірка з усіх. У проєкті з Instructables Second Multi-functional Weather Station на Arduino Mega стоїть саме такий 3,5-дюймовий шилд з ILI9486 разом із годинником DS3231 і датчиками DHT22 та BMP280, а слот для карти шилда віддано під фотоальбом приблизно з тисячі зображень, перетворених на BMP. Інші збірки обходяться взагалі без датчиків. У блозі thesolaruniverse ESP32 із 3,95-дюймовим шилдом тієї самої конструкції отримує погоду з OpenWeatherMap через Wi‑Fi і малює її по 8-бітній шині за допомогою TFT_eSPI. Проєкт Elektor, опублікований у грудні 2023 року, робить те саме на платі Makerfabs ESP32-S3 з 3,5-дюймовим дисплеєм ILI9488 і читає налаштування Wi‑Fi та місто з файлу на карті пам’яті.
2. Фоторамка
Слот microSD майже сам собою перетворює шилд на фоторамку. У MCUFRIEND_kbv є приклад showBMP, який читає файли BMP просто з карти на виводах з 10 по 13 і виводить, скільки часу забрало завантаження кожного. На ESP32 драйвер esp-idf-parallel-tft від nopnop2002 показує файли BMP, JPEG і PNG на шилдах цього сімейства й заодно калібрує їхню сенсорну плівку. Переходи на кшталт плавного згасання чи шторки — саме той випадок, коли паралельна шина себе окуповує: кожен крок переходу перемальовує весь екран, а повний кадр коштує на цій шині 23 мс проти десятої частки секунди або й більше по SPI.
3. Відеоплеєр
Наш власний тест — найважчий випадок: MJPEG із карти на 25 fps. Як готова відправна точка підійдуть MJPEG-приклади бібліотеки Arduino_GFX: вони виводять середню частоту кадрів і розкладають час на читання, декодування та малювання, тож із них виходить зручний бенчмарк для будь-якої плати. Ларрі Бенк (Larry Bank), автор JPEGDEC — декодера, яким користується наш плеєр, — керував старим 3,5-дюймовим шилдом для Uno з ILI9486 від RP2040 через PIO і DMA та відтворював на ньому анімовані GIF; його допис називається Breathing new life into an old LCD shield.
4. Ігрова консоль
Іграм потрібне саме те, у чому ця шина сильна: перемальовувати багато пікселів багато разів на секунду. Проєкт ESP32-S3_Uno-nofrendo запускає емулятор NES nofrendo на платі ESP32-S3 формату Uno з 8-бітним шилдом на ILI9488, вставленим просто в неї, і завантажує ROM-файли з карти; джойстика й звуку в нього поки немає. Із простішого — клон Tetris для Arduino Mega із шилдом на ILI9486 бере музику з автомобільного FM-трансмітера, тож, щоб її почути, радіо треба налаштувати на 87,5 МГц. Серія уроків Dumblebots будує програму для малювання Paint і хрестики-нулики на такому самому 3,5-дюймовому шилді, разом із сенсорною плівкою.
5. Сенсорна панель на стіні
Панель розумного дому — очевидне завдання для сенсорного екрана такого розміру, і тут зазвичай виграють готові родичі. WT32-SC01 Plus поєднує ESP32-S3 з 3,5-дюймовим екраном 480 × 320 на такій самій 8-бітній шині. openHASP перетворює її на панель, керовану через MQTT і побудовану на LVGL, а з компонентом від спільноти ESPHome може керувати нею для Home Assistant. AirQualitySensor-IDF перетворює ту саму плату на монітор якості повітря: він зчитує датчики твердих частинок, CO₂, температури й вологості та малює історію за шість годин за допомогою LVGL. Якщо у вас є 3D-принтер, екран цього класу, можливо, у вас уже є: Color UI прошивки Marlin працює на 3,5-дюймових сенсорних екранах 480 × 320 на кшталт MKS TFT35, підключених до STM32 принтера паралельною шиною FSMC.
6. Прилади
Осцилограму доводиться перемальовувати багато разів на секунду, а це якраз робота для швидкої шини. Один відкритий проєкт поєднує STM32F303 з 3,5-дюймовим дисплеєм ILI9486 в осцилограф на 2 млн вибірок на секунду із записом на 4096 точок. DLO-138, відкрита прошивка для популярного набору DSO-138, керує меншим дисплеєм ILI9341 цього набору по 8-бітній шині й перетворює набір на двоканальний осцилограф із двома цифровими каналами на додачу. Для шкал, стрілочних індикаторів і графіків у TFT_eSPI є ціла тека прикладів, написаних під 480 × 320.
Ще кілька ідей, які люди вже втілили на екранах 480 × 320:
- Офлайн-навігатор GPS. IceNav-v3 малює офлайн-карти OpenStreetMap на ESP32-S3 і підтримує панелі ILI9488 по SPI, а також по 8- чи 16-бітній паралельній шині.
- Екран «Зараз грає». Пульт для Spotify від ThingPulse показує обкладинку альбому й підбирає колір тла під неї на 3,5-дюймовому ILI9488.
- Радіоприймач із переглядом спектра. Всехвильовий приймач на мікросхемі Si4735 і ESP32 малює спектр і «водоспад» на 4-дюймовому ILI9488 з роздільною здатністю 480 × 320.
Родичі: той самий екран в інших формах
Шилд належить до великого сімейства. Якщо його форм-фактор чи шина не підходять проєкту, може підійти хтось із родичів. Усі вони мають 480 × 320, крім менших шилдів для Uno:
| Дисплей | Контролер і шина | Варто знати |
|---|---|---|
| 2,4- і 2,8-дюймові шилди для Uno | ILI9341 та інші; 8-бітна паралельна | Та сама розпіновка й ті самі бібліотеки, але 240 × 320 |
| 3,5-дюймові модулі SPI, як-от MSP3520 | ILI9488; 4-провідний SPI | Мало виводів, сенсор на власних лініях SPI, три байти на піксель |
| 3,95-дюймові шилди для Uno | ILI9486 та інші; 8-бітна паралельна | Більше скло, та сама розводка |
| WT32-SC01 Plus | ST7796; 8-бітна паралельна, ESP32-S3 на платі | Готова панель для openHASP, ESPHome і LVGL |
| Makerfabs ESP32-S3 Parallel TFT, 3,5 дюйма | ILI9488; 16-бітна паралельна, ESP32-S3 на платі | Удвічі ширша шина |
| ESP32-3248S035, 3,5-дюймовий Cheap Yellow Display | ST7796; SPI, ESP32 на платі | Готовий і дешевий, але SPI |
| MKS TFT35 | ILI9488 або ST7796; паралельна FSMC | Сенсорний екран багатьох 3D-принтерів |
Сильні та слабкі сторони
| Плюси | Мінуси |
|---|---|
| Ставиться просто на Uno чи Mega | На Uno займає майже всі виводи, зокрема I²C |
| 480 × 320 із сенсором і microSD на одній платі | ILI9486 чи ILI9488: плата не каже, котрий, і вона може працювати лише на запис |
| 8-бітна шина: повний кадр за 23 мс на перевірених 20 МГц | Тринадцять сигнальних дротів до будь-якого хоста, на який він не ставиться напряму |
| Працює з хостами на 3,3 В: ESP32, RP2040, STM32 | Без апаратного периферійного модуля шини більша частина швидкості втрачається |
| Повноекранне відео 25 fps з ESP32-S3 | Сигналу tearing effect на гребінці немає |
| Сенсор без додаткової мікросхеми | Сенсорна плівка ділить виводи з дисплеєм і потребує ADC хоста |
| Слот microSD на окремих лініях SPI | Підсвітка завжди ввімкнена, притлумити її неможливо |
Підсумок
3,5-дюймовий TFT LCD-шилд схожий на релікт епохи Arduino Uno, і на Uno так і поводиться: займає майже всі виводи й заповнює екран у темпі 8-бітного процесора. Але дайте йому хост із повноцінним паралельним периферійним модулем — і стара шина покаже, чому вона вижила: байт за такт, повний кадр 480 × 320 за 23 мс, відео на 25 fps.
Для метеостанції, фоторамки, панелі керування чи невеликого приладу цього цілком досить — за умови, що перший запуск починається з перевіреної конфігурації:
- Перевірте 5V, 3V3 і GND на коротке замикання, потім першими підключіть GND і 5 В на вивід 5V.
- Підключайте за підписами на звороті, ніколи — за положенням, і від самого початку тримайте LCD_RD у високому рівні.
- Використайте послідовність ILI9488, COLMOD 0x66 і MADCTL 0x28 на частоті не вище 10 МГц.
- Спершу намалюйте суцільні заливки й градієнти; якщо картинка бліда або мерехтить, спробуйте послідовність ILI9486.
- Піднімайте частоту крок за кроком, до 20 МГц на ILI9488.
- Сенсорну плівку й карту microSD додавайте в останню чергу, по одній.
Усе сказане вище й навіть більше — в одному файлі: гайд із програмування для цього шилда. Розпіновка за підписами, часові параметри шини й межі з даташитів, послідовності ініціалізації для обох контролерів, формати пікселів, поворот, сенсор і microSD, порядок першого запуску та довідник несправностей — і кожне твердження позначено як перевірене, ймовірне або невідоме. Віддайте його агентові-програмісту, перш ніж той напише хоч рядок коду драйвера.