Плата расширения Arduino TFT
Arduino TFT - это плата расширения для Ардуино, которая содержит TFT-экран с подсветкой и разъем для карты памяти формата microSD. С помощью специальной библиотеки TFT на экран можно выводить текст, изображения или геометрические фигуры.
Расположение внешних выводов платы расширения соответствует специальным разъемам на Arduino Esplora и Arduino Robot, что облегчает подключение экрана к этим устройствам. Однако, TFT-дисплей можно использовать с любой моделью Ардуино.
Библиотека TFT включается в состав среды разработки Ардуино. начиная с версии 1.0.5.
Библиотека
Библиотека Arduino TFT разработана на основе библиотек Adafruit GFX и Adafruit ST7735, и значительно расширяет их возможности. Библиотека GFX в основном содержит процедуры отрисовки графики, в том время, как ST7735 - функции для взаимодействия с TFT-экраном. Те дополнения библиотек, которые касаются Ардуино, спроектированы таким образом, чтобы максимально соответствовать API языка Processing.
Библиотека имеет обратную совместимость, что позволяет вам использовать в программах функции Adafruit (подробнее о них см. здесь).
Методы библиотеки TFT опираются на функции библиотеки SPI, поэтому во всех программах, работающих с TFT-экраном, должна быть объявлена библиотека SPI. Соответственно, при работе с SD-картой памяти - необходимо объявить библиотеку SD.
Организация экрана
По умолчанию экран имеет горизонтальную ориентацию, соответственно, его ширина - больше, чем высота. Верхняя часть экрана находится с той стороны платы, где указана надпись "SD CARD". При такой ориентации, разрешение экрана составляет 160 х 128 пикселей.
Систему координат дисплея лучше всего представить в виде сетки, каждая ячейка которой является отдельным пикселем. Местоположение пикселя задается парой координат. Точка в левом верхнем углу экрана будет иметь координаты 0,0. Если эта точка сместится в верхний правый угол, то ее координаты будут равны 0, 159; в левый нижний угол - 127,0; в правый нижний - 127, 159.
Дисплей можно использовать и в вертикальном положении (также известном как "портретная ориентация"). Для этого достаточно вызвать функцию setRotation(0), после чего оси x и y поменяются местами. После вызова этого метода, функции screen.width() и screen.right() станут возвращать уже другие значения.
Цвета
Экран позволяет передавать цвет глубиной 16 бит. Красная и синяя составляющие цвета могут принимать 32 различных значения (разрядность 5 бит), а зеленая составляющая - 64 значения (разрядность 6 бит). Однако, с целью совместимости с другими программами, библиотека все равно работает с 8-битными значениями красного, зеленого и синего каналов (0 - 255), пропорционально масштабируя их в необходимый диапазон.
Аппаратный и программный интерфейс SPI - что лучше?
Организовать работу с TFT-экраном можно двумя способами. Первый способ - использовать аппаратную шину SPI Ардуино, второй - вручную объявить расположение необходимых выводов. С точки зрения функциональности экрана, нет никакой разницы между первым и вторым способом. Однако скорость работы аппаратного интерфейса SPI значительно выше.
Если на TFT-модуле планируется использование SD-карты памяти, то взаимодействовать с модулем необходимо только через аппаратный интерфейс SPI. Он используется во всех примерах к данной библиотеке.
Подключение экрана
На лицевой стороне Arduino Esplora есть специальный разъем для подключения экрана. Вставьте экран Ардуино в этот разъем так, чтобы синяя надпись "SD Card" была расположена возде порта USB.
Подключение к другим платам Ардуино
Чтобы узнать, как подключать экран к другим моделям Ардуино, прочтите это руководство.
Пишем первую программу
Для начала работы с TFT-экраном, сперва попробуем написать программу, которая будет отрисовывать простую линию. После этого напишем программу, формирующую 2 цветных прямоугольника, пересекающие экран по горизонтали.
В примерах вначале будут приведены листинги программ для Arduino Uno, Leonardo и др. моделей. Листинги для Arduino Esplora будут приведены ниже.
Итак, в начале программы, объявим выводы Ардуино, которые будут использоваться для взаимодействия с экраном, импортируем необходимые библиотеки и создадим экземпляры основных классов библиотеки TFT:
#include <TFT.h> // библиотека для работы с TFT #include <SPI.h> #define CS 10 #define DC 9 #define RESET 8 // объявление выводов для Arduino Leonardo // #define CS 7 // #define DC 0 // #define RESET 1 TFT myScreen = TFT(CS, DC, RESET);
В блоке setup() необходимо запустить библиотеку функцией begin() и очистить экран, установив черный цвет фона с помощью функции background().
void setup(){ myScreen.begin(); myScreen.background(0,0,0); // очищаем экран, заливая его черным цветом delay(1000); // небольшая интригующая пауза }
В блоке loop(), для отрисовки прямой линии на экране необходимо вызвать функцию line(). Функция line() принимает четыре аргумента: начальные координаты x и y, конечные координаты x и y. Чтобы нарисовать прямоугольник, необходимо вызвать функцию rect(), которая также принимает четыре параметра: координаты x и y левого верхнего угла, ширина и высота прямоугольника в пикселях. Между вызовами этих функций можно изменить цвет выводимой фигуры с помощью функций stroke() или fill(). Функция stroke() изменяет цвет линии или контура геометрической фигуры, а функция fill() - изменяет цвет заливки фигуры. После вызова функции noStroke() библиотека не будет отрисовывать границы выводимых фигур. Чтобы отменить действие этой функции, достаточно вызвать метод stroke().
void loop(){ myScreen.stroke(255, 0, 0); // устанавливаем красный цвет кисти myScreen.line(0, 10, myScreen.width(), 10); // рисуем линию через весь экран delay(1000); myScreen.noStroke(); // не будем рисовать контуры вокруг будущего прямоугольника myScreen.fill(0,255,0); // устанавливаем зеленый цвет заливки myScreen.rect(0,20,myScreen.width(),10); //рисуем прямоугольник через экран delay(1000); myScreen.fill(0,0,255); // устанавливаем синий цвет заливки myScreen.stroke(255,255,255); // обводим прямоугольник белой линией myScreen.rect(0,45,myScreen.width(),45); // рисуем плоский прямоугольник delay(1000); myScreen.background(0,0,0); // очищаем экран перед тем, как все нарисовать снова delay(1000); }
Структура программы для Arduino Esplora практически ничем не отличается. В Arduino Esplora предусмотрен отдельный разъем для подключения TFT-экрана, поэтому выводы, взаимодействующие с ним, заданы аппаратно и не подлежат изменению. В программе в этом случае необходимо использовать специальный класс EsploraTFT для работы с экраном.
Именно поэтому в программе не нужно указывать выводы Ардуино, которые будут взаимодействовать с экраном; эта информация автоматически содержится внутри создаваемого объекта:
#include <TFT.h> // библиотека для работы с TFT #include <SPI.h> #include <Esplora.h> void setup(){ EsploraTFT.begin(); EsploraTFT.background(0,0,0); // очищаем экран, заливая его черным цветом delay(1000); // небольшая интригующая пауза } void loop(){ EsploraTFT.stroke(255, 0, 0); // устанавливаем красный цвет кисти EsploraTFT.line(0, 10, EsploraLCD.width(), 10); // рисуем линию через весь экран delay(1000); EsploraTFT.noStroke(); // не будем рисовать контуры вокруг будущего прямоугольника EsploraTFT.fill(0,255,0); // устанавливаем зеленый цвет заливки EsploraTFT.rect(0,20,EsploraTFT.width(),20); //рисуем прямоугольник через экран delay(1000); EsploraTFT.fill(0,0,255); // устанавливаем синий цвет заливки EsploraTFT.stroke(255,255,255); // обводим прямоугольник белой линией EsploraTFT.rect(0,45,EsploraTFT.width(),50); // рисуем плоский прямоугольник delay(1000); EsploraTFT.background(0,0,0); // очищаем экран перед тем, как все нарисовать снова delay(1000); }
Перемещения по экрану
Иллюзия движения или анимация создается путем быстрого стирания и отрисовки изображения на экране. При использовании языка Processing на мощном компьютере, для очистки экрана и отрисовки картинки в новой позиции можно вызывать функцию background() перед каждым вызовом функции draw(). Однако производительность Arduino, по сравнению с настольным ПК, весьма ограничена, поэтому выполнение функции background() из библиотеки TFT занимает определенное время.
В условиях ограниченного быстродействия, для создания иллюзии движения лучше проверять положение объекта в цикле loop(). Если положение объекта изменилось, то необходимо закрасить его фоновым цветом, а затем перерисовать объект в новой позиции. Благодаря тому, что в данном случае обновляется не весь экран, а лишь некоторые его пиксели, процесс обновления картинки ускоряется и создается иллюзия движения.
В примере ниже показана программа перемещения точки по экрану. Структура программы похожа на пример, показанный в предыдущем разделе, за исключением нескольких переменных для хранения текущей и предыдущей позиций точки, а также переменных для хранения скорости и направления движения точки.
#include <TFT.h> // библиотека для работы с TFT #include <SPI.h> #define CS 10 #define DC 9 #define RESET 8 // объявление выводов, работающих с экраном, для Arduino Leonardo // #define CS 7 // #define DC 0 // #define RESET 1 TFT myScreen = TFT(CS, DC, RESET); // Начальная позиция точки - это середина экрана int xPos = 80; int yPos = 64; // направление и скорость int xDir = 1; int yDir = 1; // переменные для отслеживания позиции точки int xPrev = xPos; int yPrev = yPos; void setup(){ myScreen.begin(); myScreen.background(0,0,0); // очистка экрана }
В цикле loop() мы вначале обновляем позицию точки, добавляя к переменным x и y величину направления движения. После этого проверяем, отличается ли текущее и предыдущее положение точки. Если отличается, то стираем предыдущую точку, закрашивая ее фоновым цветом, а затем рисуем новую точку в необходимой позиции. Если точка "долетает" до границы экрана - инвертируем направление движения.
void loop(){ // обновляем позицию точки xPos = xPos + xDir; yPos = yPos + yDir; // проверяем, отличается ли текущее положение точки от предыдущего if(xPos != xPrev || yPos != yPrev){ myScreen.stroke(0,0,0); // задаем черный цвет кисти myScreen.point(xPrev, yPrev); // цвет в предыдущей позиции } // рисуем точку в новой позиции myScreen.stroke(255,255,255); myScreen.point(xPos, yPos); // если x или позиция по x достигла границы экрана, то меняем направление на противоположное if(xPos >= 160 || xPos <= 0){ xDir = xDir*-1; } if(yPos >= 128 || yPos <= 0){ yDir = yDir*-1; } // обновляем предыдущую позицию точки xPrev=xPos; yPrev=yPos; // задержка в 33 мс означает, что экран обновляется 30 раз в секунду delay(33); }
Версия этой программы для Arduino Esplora приведена ниже:
#include <TFT.h> // библиотека для работы с TFT #include <SPI.h> #include <Esplora.h> // Начальная позиция точки - это середина экрана int xPos = 80; int yPos = 64; // направление и скорость int xDir = 1; int yDir = 1; // переменные для отслеживания позиции точки int xPrev, yPrev; void setup(){ EsploraTFT.begin(); EsploraTFT.background(0,0,0); void loop(){ // обновляем позицию точки xPos = xPos + xDir; yPos = yPos + yDir; // проверяем, отличается ли текущее положение точки от предыдущего if(xPos != xPrev || yPos != yPrev){ EsploraTFT.stroke(0,0,0); // задаем черный цвет кисти EsploraTFT.point(xPrev, yPrev); // цвет в предыдущей позиции } // рисуем точку в новой позиции EsploraTFT.stroke(255,255,255); EsploraTFT.point(xPos, yPos); // если x или позиция по x достигла границы экрана, то меняем направление на противоположное if(xPos >= 160 || xPos <= 0){ xDir = xDir*-1; } if(yPos >= 128 || yPos <= 0){ yDir = yDir*-1; } // обновляем предыдущую позицию точки xPrev=xPos; yPrev=yPos; // небольшая пауза delay(33); }
Выводим текст
В библиотеке TFT содержится базовый шрифт для вывода текста на экран. По умолчанию, размер символов составляет 5х8 пикселей (5 - в ширину, 8 - в высоту). В библиотеке предусмотрена возможность изменения размера шрифта на 10x16, 15x24 или 20x32. Для получения дополнительной информации о шрифтах см. страницу Adafruit о работе с графическими примитивами.
Итак, в нижеследующем примере попробуем создать простой счетчик, который будет увеличиваться на единицу каждые полсекунды. Для этого, как и в предыдущих примерах, подключим необходимые библиотеки и объявим нужные переменные в блоке setup().
В этом же блоке отобразим на экране статический текст, который не будет меняться в процессе работы программы. С помощью функции setTextSize() можно увеличить размер шрифта, чтобы выделить на экране самые важные элементы. Динамический текст, который будет отображаться на экране, должен храниться в символьном массиве. Упросить работу с массивами позволяет класс String.
#include <TFT.h> // Библиотека для работы с TFT-экраном #include <SPI.h> #define CS 10 #define DC 9 #define RESET 8 // объявление выводов, работающих с экраном, для Arduino Leonardo // #define CS 7 // #define DC 0 // #define RESET 1 TFT myScreen = TFT(CS, DC, RESET); // переменная для хранения прошедшего времени int counter = 0; // массив символов для вывода времени на экран char printout[4]; void setup(){ myScreen.begin(); myScreen.background(0,0,0); // очистка экрана myScreen.stroke(255,0,255); // выводим статический текст myScreen.text("Running for",0,0); myScreen.text("seconds",0,30); // увеличиваем размер шрифта для текста, выводимого в блоке loop() myScreen.setTextSize(3); }
В блоке loop() будем получать текущее время, прошедшее с момента запуска программы, и сохранять его в массив символов для последующего вывода в текстовом виде. На каждой итерации цикла будем стирать написанный ранее текст, чтобы выводимые цифры не накладывались друг на друга.
void loop(){ // получаем текущее время, прошедшее с момента запуска программы counter = millis(); // преобразовываем его в строку String elapsedTime = String(counter/1000); // добавляем в массив elapsedTime.toCharArray(printout,4); // выводим на экран и стираем myScreen.stroke(255,255,255); myScreen.text(printout,0,10); delay(1000); myScreen.stroke(0,0,0); myScreen.text(printout,0,10); }
Тот же самый код для Arduino Esplora:
#include <TFT.h> // Библиотека для работы с TFT-экраном #include <SPI.h> // переменная для хранения прошедшего времени int counter = 0; // массив символов для вывода времени на экран char printout[4]; void setup(){ EsploraTFT.begin(); EsploraTFT.background(0,0,0); // очистка экрана EsploraTFT.stroke(255,0,255); // выводим статический текст EsploraTFT.text("Running for",0,0); EsploraTFT.text("seconds",0,30); // увеличиваем размер шрифта для текста, выводимого в блоке loop() EsploraTFT.setTextSize(3); } void loop(){ // получаем текущее время, прошедшее с момента запуска программы counter = millis(); // преобразовываем его в строку String elapsedTime = String(counter/1000); // добавляем в массив elapsedTime.toCharArray(printout,4); // выводим на экран и стираем EsploraTFT.stroke(255,255,255); EsploraTFT.text(printout,0,10); delay(1000); EsploraTFT.stroke(0,0,0); EsploraTFT.text(printout,0,10); }
Выводим изображение из файла, находящегося на SD-карте памяти
Библиотека TFT позволяет считывать .bmp-файлы с SD-карты памяти и выводить их содержимое на экран. Причем отображаемые картинки могут не соответствовать разрешению TFT-экрана (160x128). Следует иметь ввиду, что Ардуино не может модифицировать изображения, поэтому все необходимые манипуляции с графическими файлами (такие, как масштабирование, обрезка и т.д.) необходимо сделать до их "заливки" на SD-карту.
В следующем примере показана работа с графическим файлом "arduino.bmp", расположенном в корне SD-карты памяти, и содержащим изображение размером 160x128 пикселей. В программе осуществляется считывание файла и вывод его на экран с помощью библиотеки TFT.
Помимо уже знакомых вам библиотек, в этом примере понадобится подключить еще одну библиотеку - SD. Также необходимо объявить вывод CS, связанный с разъемом SD-карты.
Класс PImage используется для загрузки изображения (этот класс может также использоваться для проверки формата графического файла на предмет его совместимости с библиотекой TFT).
После того, как файл будет прочитан, Ардуино выведет изображение в указанных вами координатах. В данном случае картинка будет выведена, начиная с левого верхнего угла экрана.
// подключаем необходимые библиотеки #include <SPI.h> #include <SD.h> #include <TFT.h> // Библиотека для работы с TFT-экраном // объявление выводов для Arduino Uno #define SD_CS 11 #define LCD_CS 10 #define DC 9 #define RESET 8 // объявление выводов для Leonardo // #define SD_CS 8 // #define LCD_CS 7 // #define DC 0 // #define RESET 1 TFT myScreen = TFT(LCD_CS, DC, RESET); // эта переменная описывает изображение, которое будет выводиться на экран PImage image; void setup() { // инициализируем последовательный интерфейс передачи данных Serial.begin(9600); while (!Serial) { // ожидаем готовности последовательного порта // - необходимо для Arduino Leonardo } // пробуем обратиться к SD-карте памяти Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); return; } Serial.println("OK!"); // инициализируем и очищаем GLCD-экран myScreen.begin(); myScreen.background(255, 255, 255); // загружаем изображение с SD-карты image = myScreen.loadImage("arduino.bmp"); // проверяем, корректно ли загружена картинка if (image.isValid() != true) { Serial.println("error while loading arduino.bmp"); } //выводим изображение на экран myScreen.image(image, 0, 0); } void loop(){ // здесь ничего не делаем }
Тот же самый код для Arduino Esplora: :
// подключаем необходимые библиотеки #include <SPI.h> #include <SD.h> #include <TFT.h> // Библиотека для работы с TFT-экраном #include <Esplora.h> // Номер вывода для активации SD-карты #define SD_CS 8 // эта переменная описывает изображение, которое будет выводиться на экран PImage image; void setup() { // инициализируем последовательный интерфейс передачи данных Serial.begin(9600); while (!Serial) { // ожидаем готовности последовательного порта } // пробуем обратиться к SD-карте памяти Serial.print("Initializing SD card..."); if (!SD.begin(SD_CS)) { Serial.println("failed!"); return; } Serial.println("OK!"); // инициализируем и очищаем GLCD-экран EsploraTFT.begin(); EsploraTFT.background(255, 255, 255); // загружаем изображение с SD-карты image = EsploraTFT.loadImage("arduino.bmp"); // проверяем, корректно ли загружена картинка if (image.isValid() != true) { Serial.println("error while loading arduino.bmp"); } //выводим изображение на экран EsploraTFT.image(image, 0, 0); } void loop(){ // здесь ничего не делаем }
Что дальше?
Теперь, когда вы разобрались с принципами работы дисплея, загляните в справку по библиотеке TFT - там вы найдете информацию об API библиотеки, а также дополнительные примеры кода. Для получения дополнительной технической информации, см. страницу с описанием платы расширения Arduino TFT. Также не помешает посетить страницу с описанием графической библиотеки Adafruit - там можно найти дополнительную информацию о функциях, не освещенных в данном руководстве.