Метеостанція на кольоровому TFT: ILI9341, TFT_eSPI і DHT22
Кольоровий дисплей 2.8″ 320×240 по SPI перетворює ESP32 на гарну панель. Налаштовуємо TFT_eSPI через User_Setup.h, малюємо рамки й шкали, вирівнюємо текст через datum і оновлюємо цифри без мерехтіння завдяки padding.
Про проєкт
Монохромний OLED гарний, але кольоровий TFT 2.8″ на ILI9341 (320×240, 65 тисяч кольорів) — зовсім інший рівень: панелі приладів, графіки, міні-інтерфейси. На ESP32 для нього найкраща бібліотека — TFT_eSPI від Bodmer, вона вміє апаратний SPI й DMA. Робимо метеостанцію: температура й вологість із DHT22, кольорові цифри та шкали.
Що знадобиться
- ESP32 DevKit
- TFT-модуль 2.8″ ILI9341 SPI (червона плата; сенсорна версія теж підійде)
- Датчик DHT22
- Бібліотеки TFT_eSPI і DHT sensor library
Схема
| TFT | ESP32 |
|---|---|
| VCC | 3V3 |
| GND | GND |
| CS | GPIO15 |
| RESET | GPIO4 |
| DC (D/C, RS) | GPIO2 |
| MOSI (SDI) | GPIO23 |
| SCK | GPIO18 |
| LED (підсвітка) | 3V3 (або GPIO з ШІМ для яскравості) |
| MISO (SDO) | не обов'язково |
DHT22: VCC → 3V3, GND → GND, DATA → GPIO27.
MOSI 23 і SCK 18 — апаратна шина VSPI. Саме вони дають швидкість 40 МГц, а на інших виводах буде програмний SPI, у рази повільніший.
Налаштування TFT_eSPI
TFT_eSPI бере виводи й драйвер не зі скетча, а з файлу User_Setup.h у папці бібліотеки (або з User_Setup_Select.h). Для цієї схеми в ньому мають бути розкоментовані:
#define ILI9341_DRIVER
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST 4
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define SPI_FREQUENCY 40000000
Після оновлення бібліотеки файл перезаписується, тому збережіть свою копію.
Прийоми, які варто знати
- Datum визначає точку прив'язки тексту:
MC_DATUM— центр,TC_DATUM— центр верхнього краю,ML_DATUM— лівий край посередині. Центрувати заголовок у рамці — один рядок коду. - Padding. Фоновий колір у
setTextColor(колір, фон)затирає старий текст, але коротше число («9.5» після «10.5») залишає «хвіст».setTextPadding(ширина)заповнює фоном всю задану ширину. - Не очищайте весь екран щоразу:
fillScreen()на 320×240 триває ~30–40 мс і мерехтить. Намалюйте статичну рамку один раз уsetup(), а вloop()перемальовуйте тільки змінні частини. - Кольори — 16-бітні RGB565: готові
TFT_RED,TFT_SKYBLUEтощо абоtft.color565(r, g, b).
Код
// Метеостанція: ILI9341 2.8" з TFT_eSPI + DHT22
#include <TFT_eSPI.h>
#include <DHT.h>
TFT_eSPI tft = TFT_eSPI(); // виводи задає User_Setup.h: MOSI 23, SCLK 18, CS 15, DC 2, RST 4
DHT dht(27, DHT22);
// статична частина екрана: малюється один раз
void drawFrame() {
tft.fillScreen(TFT_BLACK);
tft.fillRect(0, 0, 320, 34, TFT_NAVY);
tft.setTextColor(TFT_WHITE, TFT_NAVY);
tft.setTextDatum(ML_DATUM);
tft.drawString("ESP32 weather", 10, 17, 2);
tft.drawRoundRect(8, 44, 148, 150, 10, TFT_DARKGREY);
tft.drawRoundRect(164, 44, 148, 150, 10, TFT_DARKGREY);
tft.setTextDatum(TC_DATUM);
tft.setTextColor(TFT_LIGHTGREY, TFT_BLACK);
tft.drawString("Temperature", 82, 54, 2);
tft.drawString("Humidity", 238, 54, 2);
}
// колір цифр залежно від температури
uint16_t tempColor(float t) {
if (t < 10) return TFT_CYAN;
if (t < 25) return TFT_GREEN;
if (t < 30) return TFT_ORANGE;
return TFT_RED;
}
void drawBar(int x, int y, int w, int h, float frac, uint16_t color) {
frac = constrain(frac, 0.0, 1.0);
int filled = (int)(w * frac);
tft.fillRoundRect(x, y, w, h, 4, TFT_DARKGREY);
if (filled > 8) tft.fillRoundRect(x, y, filled, h, 4, color);
}
void setup() {
Serial.begin(115200);
dht.begin();
tft.init();
tft.setRotation(3); // альбомна орієнтація 320×240, виводи зліва
drawFrame();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setTextDatum(MC_DATUM);
tft.drawString("Sensor error", 160, 215, 2);
delay(2000);
return;
}
tft.setTextDatum(MC_DATUM);
tft.setTextPadding(tft.textWidth("-88.8", 4)); // padding затирає попереднє значення
tft.setTextColor(tempColor(t), TFT_BLACK);
tft.drawFloat(t, 1, 82, 108, 4);
tft.setTextColor(TFT_SKYBLUE, TFT_BLACK);
tft.drawFloat(h, 0, 238, 108, 4);
tft.setTextPadding(0);
tft.setTextColor(TFT_LIGHTGREY, TFT_BLACK);
tft.drawString("C", 82, 138, 2);
tft.drawString("%", 238, 138, 2);
drawBar(20, 165, 124, 14, (t + 10) / 50.0, tempColor(t)); // шкала −10…+40 °C
drawBar(176, 165, 124, 14, h / 100.0, TFT_SKYBLUE);
Serial.printf("%.1f C %.0f %%\n", t, h);
delay(2000);
}
Типові проблеми
- Білий екран. Не збігаються виводи в
User_Setup.hзі схемою, або обрано не той драйвер (ST7789 замість ILI9341). - Дзеркальне чи зсунуте зображення. Спробуйте інший
setRotation(). Для «дзеркальних» клонів у User_Setup єTFT_INVERSION_ON/OFFіTFT_RGB_ORDER. - Нічого не видно, хоча код працює. Не підключено LED (підсвітку).
- Кирилиця. Вбудовані шрифти лише латинські. Для української потрібні згенеровані smooth-шрифти (
loadFont()) із потрібними символами.