Arduino:Знакомство с Arduino/Знакомство с TFT-модулем Arduino

Материал из Онлайн справочника
Версия от 01:44, 14 декабря 2016; Myagkij (обсуждение | вклад) (Замена текста — «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">» на «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

{{#setlogo:ArduinoCommunityLogo.png}}

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Знакомство с TFT-модулем Arduino[1]

TFT-модуль Arduino – это TFT LCD дисплей с функцией подсветки и слотом для SD-карты (она расположен сзади). На этом дисплее можно рисовать текст, изображения и различные фигуры, и все это делается при помощи библиотеки TFT.

Распиновка TFT-модуля Arduino выполнена таким образом, чтобы соответствовать контактам на сокете Arduino Esplora и Arduino Robot. Впрочем, его можно использовать и с любой другой платой Arduino.

Библиотека TFT уже включена в IDE Arduino версии 1.0.5 и выше.

Библиотека

Библиотека Arduino TFT – это расширенная версия библиотек Adafruit GFX и Adafruit STL7735. Библиотека GFX отвечает за функции рисования, а STL7735 – за функции, характерные для экрана, которым оснащен TFT-модуль Arduino. Сверх этого разработчиками Arduino были внесены специальные дополнения, чтобы библиотека TFT работала максимально похоже на Processing API.

Библиотека TFT обладает обратной совместимостью, благодаря чему вы по-прежнему можете пользоваться функциями Adafruit, описанными здесь.

Кроме того, библиотека TFT полагается на библиотеку SPI, поэтому ее нужно подключать ко всем скетчам, где используется TFT-модуль. Если вы собираетесь использовать SD-карту, то вам, к тому же, нужно будет подключить библиотеку SD.

Особенности экрана

По умолчанию экран ориентирован так, что его ширина больше, чем высота. Верх экрана – это там, где находится надпись «SD CARD». В таком положении ширина экрана составляет 160 пикселей, а высота – 128 пикселей.

Чтобы понять, что такое координаты экрана, представьте решетку. Каждый квадратик в этой решетке – это пиксель, и координаты позволяют определить месторасположение этого пикселя, а также любого другого пикселя на экране. Точка в левом верхнем углу экрана имеет координаты «0, 0». Если бы эта точка переместилась в правый верхний угол экрана, у нее были бы координаты «0, 159». Если в левый нижний угол – «127, 0». Если в правый нижний – «127, 159».

Впрочем, экран можно использовать и в вертикальном (его также называют «портретным») режиме, и это делается вызовом функции setRotation(0). После того, как вы вызовете эту функцию, оси X и Y поменяются местами, а функции screen.width() и screen.height() – ролями.

Цвета

Экран способен показывать 16-битный цвет: глубина цвета для синего и красного составляет 5 бит (32 уровня), а для зеленого – 6 бит (64 уровня). Все вместе – как раз 16 бит. Чтобы оставаться совместимой с другими приложениями, библиотека работает с 8-битной глубиной цвета (для всех трех каналов – синего, красного и зеленого). Следовательно, цветовым диапазоном для всех трех цветов будет «0-255» (потому что 8 бит – это 256 уровней). Таким образом, библиотека как бы подтягивает 5 (для синего), 5 (для красного) и 6 (для зеленого) бит до необходимых 8 бит.

SPI-интерфейс – аппаратный и программный

Использование экрана можно настроить двумя способами. Первый – через аппаратный SPI-интерфейс Arduino. Второй – через ручное объявление всех необходимых контактов. Функциональной разницы между двумя этими методами нет, но если использовать аппаратный SPI-интерфейс, рисование происходит значительно быстрее.

Если вы планируете работать с SD-картой, то должны использовать именно аппаратный SPI-интерфейс.

Все примеры ниже написаны для аппаратного SPI-интерфейса.

Подключение экрана

Подключение к Esplora

Сокет для TFT-модуля находится в самом центре Esplora. Вставьте модуль в сокет таким образом, чтобы синяя надпись «SD CARD» была рядом с USB-портом.

Подключение к другим Arduino

Чтобы подключить TFT-модуль к другой плате Arduino, читайте это руководство.

Пишем первый скетч

Для начала попробуем написать скетч, который нарисует линию, а затем два разноцветных горизонтальных прямоугольника.

Сначала будут описаны инструкции для Uno, Leonardo и других подобных плат. Инструкции для Esplora будут описаны чуть ниже.

Итак, начинаем скетч. Первым делом объявляем контакты, которые будем использовать, подключаем необходимые библиотеки и создаем экземпляр TFT-библиотеки:

#include <TFT.h> // библиотека для используемого устройства
#include <SPI.h>

#define CS   10
#define DC   9
#define RESET  8  

// объявляем контакты для 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(). Она принимает 4 аргумента: стартовые координаты X и Y, а также конечные координаты X и Y. Чтобы нарисовать прямоугольник, воспользуемся функцией rect(). Она тоже принимает 4 аргумента: координаты 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); 
}

Если вы используете Esplora, структура скетча будет той же самой. Поскольку Esplora имеет сокет под TFT-модуль, контакты для дисплея – фиксированные. Кроме того, вы можете обращаться к дисплею, подключенному к Esplora, через объект EsploraTFT.

Никаких контактов объявлять не нужно, а объект EsplloraTFT создается автоматически.

#include <TFT.h> // библиотека для используемого устройства
#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 на мощном компьютере, то можете рисовать объекты с помощью функции draw() и затем стирать их функцией background(), а после снова рисовать эти объекты функцией draw(), но уже на новых позициях. Arduino, однако, работает не так быстро – ей нужно некоторое время, чтобы очистить экран вызовом функции background() из библиотеки TFT.

Таким образом, чтобы создать иллюзию движения, мы будем при каждом проходе через loop() проверять, двигается ли объект. Если двигается, то мы заливаем объект фоновым цветом, а затем перерисовываем его в новом месте. Таким образом, мы не обновляем все пиксели на экране, но иллюзия движения при этом все равно остается.

В примере ниже будет точка, прыгающая по экрану. Сначала мы настроим скетч (так же, как в примере выше), добавим несколько переменных – для того, чтобы с их помощью отслеживать текущие и предыдущие координаты точки, а также следить за ее скоростью и направлением движения.

#include <TFT.h> // библиотека для используемого устройства
#include <SPI.h>

#define CS   10
#define DC   9
#define RESET  8  

// контакты для 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 или Y вышли за пределы экрана, реверсируем направление:
  if(xPos >= 160 || xPos <= 0){
    xDir = xDir*-1;
  }
  if(yPos >= 128 || yPos <= 0){
    yDir = yDir*-1;
  }

  // обновляем предыдущее расположение точки:
  xPrev=xPos;
  yPrev=yPos;

  // делаем задержку в 33 миллисекунды – это значит, что экран будет обновляться 30 раз в секунду:
  delay(33);

}

А вот версия для 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 или Y находятся за пределами экрана, реверсируем направление точки:
  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 пикселей. Впрочем, эти размеры можно поменять на 10x16, 15x24 и 20х32.

Дополнительную информацию о возможностях шрифта читайте в этой статье о графических примитивах на сайте Adafruit.

В скетче-примере ниже мы создадим простенький счетчик, меняющий цифры на экране каждые полсекунды. Как и в других примерах, в самом начале – т.е. перед тем, как приступать к блоку setup() – мы подключим к скетчу необходимые библиотеки и переменные.

Далее переходим к setup() и указываем здесь статический текст, т.е. текст, который меняться не будет. С помощью функции setTextSize() можно увеличить некоторые символы, тем самым выделив их на фоне другого текста. Динамический текст следует хранить в символьном массиве. Лучше всего для этого подойдет класс String – c его помощью легко обновлять находящийся в массиве текст.

#include <TFT.h> // библиотека для используемого устройства (т.е. для TFT-модуля)
#include <SPI.h>

#define CS   10
#define DC   9
#define RESET  8   

// контакты для 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);
}

Код для Esplora:

#include <TFT.h> // библиотека для используемого устройства (т.е. для TFT-модуля)
#include <SPI.h>
#include <Esplora.h>

// переменная для отслеживания истекшего времени:
long 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 есть функционал для считывания с SD-карты BMP-файлов и их отображения на дисплее. Разрешение этих изображений может быть больше или меньше разрешения TFT-дисплея (160x128), однако в языке Arduino нет функции для того, чтобы подгонять показываемое изображение под экран. Таким образом, перед тем, как загружать на SD-карту какие-либо изображения, их нужно сначала вручную подогнать под нужное разрешение.

В примере ниже будет использован BMP-файл «arduino.bmp» c разрешением 160х128, хранящийся в корневой директории SD-карты. Соответственно, когда этот файл будет прочитан библиотекой и выведен на экран, он займет всю его площадь.

Вдобавок к библиотекам, которые вы указывали ранее (т.е. SPI и TFT), вам нужно будет также добавить библиотеку SD. Кроме того, для SD-слота нужно будет указать CS-контакт.

Для загрузки изображения используется класс PImage. Кроме того, с его помощью можно проверять, может ли файл быть прочитан библиотекой.

Будучи прочитанным, изображение будет показано на указанных вами координатах. В данном случае оно начнет рисоваться с левого верхнего края экрана.

// подключаем необходимые библиотеки:
#include <SPI.h>
#include <SD.h>
#include <TFT.h> // библиотека для используемого устройства (т.е. для TFT-модуля)

// Контакты для 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) {
    // ждем открытия порта (нужно для Leonardo)
  }

  // пытаемся получить доступ к SD-карте:
  Serial.print("Initializing SD card...");  // "Инициализация SD-карты..."
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!");  // "Неуспешно!"
    return;
  }
  Serial.println("OK!");

  // Инициализируем и очищаем LCD-экран:
  myScreen.begin();
  myScreen.background(255, 255, 255);

  // загружаем изображение с SD-карты:
  image = myScreen.loadImage("arduino.bmp");

  // проверяем, правильно ли загрузилось изображение:
  if (image.isValid() != true) {
    Serial.println("error while loading arduino.bmp");  //  "ошибка при загрузке arduino.bmp"
  }

  // рисуем изображение на экране:
  myScreen.image(image, 0, 0);
}

void loop(){
// тут ничего не происходит
}

Для Esplora:

// подключаем необходимые библиотеки:
#include <SPI.h>
#include <SD.h>
#include <TFT.h> // библиотека для используемого устройства (т.е. для TFT-модуля)
#include <Esplora.h>

// CS-контакт (т.е. контакт для сигнала «выбор кристалла») для SD-карты:
#define SD_CS    8

// эта переменная для изображения, которое будет нарисовано:
PImage image;

void setup() {
  // инициализируем последовательный порт:
  Serial.begin(9600);
  while (!Serial) {
    // ждем открытия последовательного порта
  }

  // пытаемся получить доступ к SD-карте
  Serial.print("Initializing SD card..."); // "Инициализация SD-карты..."
  if (!SD.begin(SD_CS)) {
    Serial.println("failed!"); // "Неуспешно!"
    return;
  }
  Serial.println("OK!");

  // инициализируем и очищаем LCD-экран:
  EsploraTFT.begin();
  EsploraTFT.background(255, 255, 255);

  // загружаем изображение с SD-карты:
  image = EsploraTFT.loadImage("arduino.bmp");

  // проверяем, правильно ли загрузилось изображение:
  if (image.isValid() != true) {
    Serial.println("error while loading arduino.bmp"); // "ошибка при загрузке arduino.bmp"
  }

  // рисуем изображение на экране:
  EsploraTFT.image(image, 0, 0);
}

void loop(){
// здесь ничего не происходит
}

Что дальше

Теперь, когда мы разобрались с базовым функционалом TFT-модуля, можно приступить к более углубленному изучению темы. Здесь можно почитать об API библиотеки TFT и найти другие скетчи-примеры. Здесь можно более подробно почитать о различных компонентах дисплея. Здесь можно прочесть о функциях графической библиотеки Adafruit, которые не были описаны в этом руководстве.

См.также

Внешние ссылки