Цветной IPS-дисплей 1.69», 240×280 (ST7789)
Дисплей IPS 1.69 ST7789
Различные виды жидкокристаллических дисплеев часто применяются в DIY-проектах для отображения символьной и графической информации. И если самые простые дисплеи умеют отображать только чёрное и белое, то более продвинутые могут работать с цветом.
Матрицы, используемые в ЖК-дисплеях (TFT) бывают разных типов: TN, VA, IPS и пр. За этими буквами скрывается технология организации жидких кристаллов, от которой зависят разные параметры дисплея. Так, дисплеи с IPS-матрицей отличаются большими углами обзора, более высоким уровнем контраста и точной цветопередачей.
В этой инструкции мы будем работать как раз с таким дисплейным модулем. В основе модуля — матрица IPS с диагональю 1,69 дюйма (около 43 мм). Особенность этой матрицы — закругленные края.
Характеристики
напряжение питания: от 3,3 до 5 В;
интерфейс: 4-проводной SPI;
разрешение: 240 x 280 точек;
контроллер: ST7789V2;
размеры матрицы: 27,97 x 32,63 мм (1,69 дюйма по диагонали);
размеры модуля: 31 x 49 мм.
Примечание
Контроллер ST7789, как и большинство его аналогов, может работать только с 16-разрядным цветом. Этот факт накладывает ограничение на отображение привычных 24-разрядных цветов.
Список необходимых компонентов
Для выполнения всех экспериментов в данном уроке, кроме самого модуля IPS-дисплея, потребуются: отладочная плата UNO2, либо любая другая Arduino-совместимая плата. Отладочная плата с CircuitPython для примера на python. Беспаечная макетная плата и немного проводов вилка-розетка.
Компонент |
Назначение |
|---|---|
IPS-дисплей 240×280, 1.69» |
Цветной IPS-модуль на ST7789V2 |
Графит-S3 (ESP32-S3, N8) |
Отладочная плата с CircuitPython |
UNO2 (Arduino-совместимая) |
Базовая Arduino-совместимая плата с QIIC и USB |
Беспаечная макетная плата T-400 |
Сборка схемы без пайки |
Провода вилка-вилка, 40 шт., L=10 см |
Соединительные провода |
Подключение
Дисплей подключается по интерфейсу SPI4, а значит нужно соединить четыре сигнальные линии, две линии питания и выключатель подсветки:
SCK — синхроимпульс;
MOSI — данные от контроллера (Master Out) к устройству (Slave In);
CS — выбор устройства (Chip Select);
RS (D/C) — линия для передачи команд устройству;
RST — сброс памяти дисплея;
VCC — питание;
GND — земля;
BK — контакт для контроля подсветки.
Примечание
В наших экспериментах мы не управляем подсветкой, так что этот контакт никуда подключать не будем.
Подключение к плате UNO2 (ATmega328)
UNO2 — это аналог классической Arduino Uno R3, так что для SPI используем стандартные контакты: MOSI-11, MISO-12, SCK-13. Остальные контакты дисплея можно подключить к любым свободным GPIO контактам отладочной платы.
UNO2 |
5V |
G |
10 |
9 |
8 |
13 |
11 |
— |
|---|---|---|---|---|---|---|---|---|
Дисплей IPS 1.69 |
VCC |
G |
CS |
RST |
RS |
SCK |
MO |
BK |
Подключение к Графит-S3 (ESP32)
Аналогичным образом дисплей подключается к отладочной плате Графит-S3. У данной платы SPI-интерфейс, по умолчанию, привязан к контактам: MISO-2, MOSI-9, SCK-10.
Графит-S3 |
3.3 |
GND |
6 |
5 |
4 |
10 |
9 |
— |
|---|---|---|---|---|---|---|---|---|
Дисплей IPS 1.69 |
VCC |
G |
CS |
RST |
RS |
SCK |
MO |
BK |
Arduino IDE
Для работы с дисплеем будем использовать библиотеку Adafruit-ST7735-Library (ссылка в конце статьи). Эта библиотека описывает протокол обмена сразу с двумя распространёнными контроллерами дисплеев: ST7735 и ST7789. Нам будет интересен последний из них.
Пусть первая программа выведет в центре дисплея текст «Hello world!».
Сразу после подключения библиотеки, создадим объект класса Adafruit_ST7789 с именем tft. При создании объекта укажем номера контактов отладочной платы, к которым мы ранее подключили линии CS, RS и RST дисплея:
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_RS, TFT_RST);
При запуске программы необходимо инициализировать дисплей. Делаем это при помощи функции tft.init. У функции два аргумента: ширина и высота матрицы в пикселах. Для нашего дисплея они будут равны 240 и 280:
tft.init(240, 280);
Далее можем вызывать разные функции объекта tft, для построения графики или вывода текста на дисплей. Полный код программы:
#include <Adafruit_ST7789.h>
#define TFT_CS 10
#define TFT_RST 9
#define TFT_RS 8
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_RS, TFT_RST);
void setup(void) {
tft.init(240, 280);
tft.fillScreen(ST77XX_BLACK); // закрашиваем экран чёрным цветом
tft.setTextSize(2); // размер шрифта - 2
tft.setTextColor(ST77XX_MAGENTA); // цвет - маджента
tft.setCursor(45, 130); // координаты текста
tft.print("Hello world!");
}
void loop() {
}
Загружаем программу на UNO2 и получаем вывод:
Геометрия и цвета
В следующей программе изобразим палитру. Используем функцию fillRect, которая рисует закрашенный прямоугольник.
В начале программы определим 12 цветов. Помним, что контроллер ST7789 использует только 16 разрядов для хранения цвета точки, следовательно, нам потребуется переменная типа uint16_t, а вернее массив таких переменных.
Затем строим в цикле двенадцать прямоугольников с заданными в массиве цветами.
#include <Adafruit_ST7789.h>
#define TFT_CS 10
#define TFT_RST 9
#define TFT_RS 8
#define BOX_HEIGHT 280/2
#define BOX_WIDTH 240/6
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_RS, TFT_RST);
uint16_t colors[12] = {
0x0000, // чёрный
0xFFFF, // белый
0xBDF7, // светло серый
0x7BEF, // серый
0xF800, // красный
0xFFE0, // жёлтый
0xFBE0, // оранжевый
0x79E0, // коричневый
0x7E0, // зелёный
0x7FF, // голубой
0x1F, // синий
0xF81F // розовый
};
void setup(void) {
tft.init(240, 280);
tft.fillScreen(ST77XX_BLACK);
byte color = 0;
for(byte y=0; y<2; y++){
for(byte x=0; x<6; x++){
tft.fillRect(2+x*BOX_WIDTH, 2+y*BOX_HEIGHT, BOX_WIDTH, BOX_HEIGHT, colors[color]);
color++;
}
}
}
void loop() {
}
Загружаем программу на UNO2 и получаем такую картину:
CircuitPython
Примеры для CircuitPython будем запускать на отладочной плате Графит-S3.
Для работы с дисплеем используем библиотеку adafruit_st7789, которую можно скачать по ссылке в конце урока. Всё, что нам нужно сделать для её установки — это скопировать файл adafruit_st7789.mpy в папку lib на накопителе CIRCUITPY.
Совет
Более подробно о работе с библиотеками CircuitPython мы разбирались в одном из ранних уроков по CircuitPython.
Установка зависимостей
Для работы примеров понадобятся вспомогательные библиотеки, которые помогают работать с текстом и графикой:
adafruit_display_textadafruit_display_shapes
Все эти библиотеки есть в сборнике от Adafruit. Точно также, копируем их на накопитель CIRCUITPY.
Вывод текста
Для составления программы используем среду разработки Mu.
Пусть, самая первая наша программа будет выводить текст «Hello world!». Начнём с подключения всех необходимых библиотек. Помним, что в python это делается с помощью команды import.
Кроме adafruit_st7789 и adafruit_display_text нам будут нужны ещё несколько библиотек:
board— предоставляет интерфейс для работы с периферией отладочной платы;terminalio— отсюда возьмем стандартный шрифт;displayio— нужна для работы с графическими абстрактами.
import board
import terminalio
import displayio
from displayio import FourWire
from adafruit_display_text import label
from adafruit_st7789 import ST7789
Обязательно вызываем функцию release_displays для освобождения шины:
displayio.release_displays()
Теперь инициализируем шину SPI и дисплей. Особое внимание следует обратить на аргументы конструктора ST7789: ширина матрицы — 240 точек, высота — 280 точек. Значение аргумента rowstart определяется особенностями конкретного дисплея. Также здесь можно передать четвертый аргумент — rotation, который укажет поворот дисплея в градусах (90, 180, 270).
spi = board.SPI()
tft_cs = board.D6
tft_dc = board.D4
tft_rst = board.D5
display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)
display = ST7789(display_bus, width=240, height=280, rowstart=20)
А теперь приступим к выводу текста.
Примечание
Графическая библиотека displayio, которая часто используется в CircuitPython, работает не совсем привычно. Она требует, чтобы все графические объекты были организованы в иерархию. Такой подход может показаться более сложным, чем обычный процедурный. В действительности, это сильно упрощает работу со сложной графикой, такой как, например, в играх.
# создание корневой группы
splash = displayio.Group()
display.root_group = splash
# создание группы для размещения текста
text_group = displayio.Group(scale=2, x=45, y=125)
text = "Hello World!"
text_area = label.Label(terminalio.FONT, text=text, color=0xFF00FF)
text_group.append(text_area) # размещаем текст в его группе
splash.append(text_group) # размещаем текстовую группу в корневой группе
Вся программа целиком:
import board
import terminalio
import displayio
from displayio import FourWire
from adafruit_display_text import label
from adafruit_st7789 import ST7789
displayio.release_displays()
spi = board.SPI()
tft_cs = board.D6
tft_dc = board.D4
tft_rst = board.D5
display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)
display = ST7789(display_bus, width=240, height=280, rowstart=20)
splash = displayio.Group()
display.root_group = splash
text_group = displayio.Group(scale=2, x=45, y=125)
text = "Hello World!"
text_area = label.Label(terminalio.FONT, text=text, color=0xFF00FF)
text_group.append(text_area)
splash.append(text_group)
while True:
pass
Сохраняем программу на Графит и смотрим результат.
Геометрия и цвета (CircuitPython)
В следующей программе изобразим палитру. Используем функцию Rect из библиотеки adafruit_display_shapes, которая рисует закрашенный прямоугольник.
В начале программы определим 12 цветов. В CircuitPython мы задаём их как 24-разрядные числа в шестнадцатеричном формате: #FF00FF. Однако, помним, что контроллер ST7789 использует только 16 разрядов для хранения цвета точки, так что эти 24-разрядные цвета позже будут конвертированы в 16-разрядные с потерей информации.
Затем строим в цикле двенадцать прямоугольников с заданными в массиве цветами. Каждый прямоугольник обязательно добавляем в корневую группу.
import time
import board
import terminalio
import displayio
from displayio import FourWire
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
from adafruit_st7789 import ST7789
displayio.release_displays()
spi = board.SPI()
tft_cs = board.D6
tft_dc = board.D4
tft_rst = board.D5
display_bus = FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)
display = ST7789(display_bus, width=240, height=280, rowstart=20)
# Make the display context
splash = displayio.Group()
display.root_group = splash
# определяем палитру из 12 цветов
palette = displayio.Palette(12)
palette[0] = 0x000000 # чёрный
palette[1] = 0xFFFFFF # белый
palette[2] = 0xC0C0C0 # светло серый
palette[3] = 0x808080 # серый
palette[4] = 0xFF0000 # красный
palette[5] = 0xFFFF00 # жёлтый
palette[6] = 0xFF8000 # оранжевый
palette[7] = 0x804000 # коричневый
palette[8] = 0x00FF00 # зелёный
palette[9] = 0x00FFFF # голубой
palette[10] = 0x0000FF # синий
palette[11] = 0xFF00FF # маджента
BOX_HEIGHT = int(280/2-2)
BOX_WIDTH = int(240/6-4)
# генерируем 12 прямоугольников с разными цветами из палитры
color_idx = 0
for y in range(2):
for x in range(6):
rect = Rect(x=2+x*(BOX_WIDTH+4), y=2+y*(BOX_HEIGHT+4),
width=BOX_WIDTH, height=BOX_HEIGHT, fill=palette[color_idx])
splash.append(rect)
color_idx += 1
while True:
pass
Сохраняем программу на отладочную плату и смотрим результат.
Схемы
Принципиальная схема модуля.