Программирование AVR Подключение шилда 2.4" TFT LCD Thu, December 05 2019  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Подключение шилда 2.4" TFT LCD Печать
Добавил(а) microsin   

Купил на AliExpress шилд Arduino с индикатором 2.4" TFT LCD, и при попытке его запустить столкнулся с проблемами.

TFT LCD shield 24 top TFT LCD shield 24 bottom

Параметры индикатора:

· 2.4" диагональ, LCD TFT, разрешение 240 x 320 точек.
· Подсветка из 4 белых светодиодов, которая может управляться через транзистор от цифрового порта.
· Поддержка 18-битного цвета 262000 оттенков.
· 4-проводный резистивный тачскрин.
· Контроллер предположительно SPFD5408 со встроенным ОЗУ видеобуфера картинки.
· Параллельный 8-битный интерфейс, с 4 линиями управления. Для этого используются цифровые порты 5-13 Arduino и аналоговые 0-3. Это означает, что Вы можете использовать цифровые порты 2, 3 и аналоговые 4 и 5. Порт 12 доступен, если не используется карта micro-SD.
· Интерфейс совместим с уровнями логики 5V и 3.3V.
· Имеется встроенный LDO-регулятор 3.3V 300mA.
· Размер 71 x52 x 7 мм, вес около 31 грамм.

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

[LCD_ID_Reader]

В Интернете нашел замечательный проект [1], который позволяет определить тип контроллера и библиотеку для индикатора. Это скетч Arduino, который не использует сам по себе никакую библиотеку, и поэтому может работать с любым индикатором. Скетч считывает идентификатор контроллера, выводит его в консоль монитора, и дает рекомендацию, где искать библиотеку для индикатора.

Как определить тип индикатора, процесс по шагам (подразумевается, что Arduino IDE уже установлена):

1. Скачайте архив LCD_ID_Reader.zip с сайта [1], распакуйте его в любую папку.

2. В среде Arduino IDE скетч LCD_ID_Reader.ino, скомпилируйте его и запустите на плате Arduino с подключенным индикатором.

Я проверял этот скетч на платах Arduino Uno (ATmega328) и Arduino Mega 2560 (ATmega2560). Если все нормально, то скетч заполнит экран красным цветом, и выведет ID индикатора. У моего индикатора оказался ID 0x9325 (контроллер ILI9325 [7]), скетч вывел в монитор следующие сообщения:

Initializing LCD...
Reading ID...0x9325
Loading LCD registers...
Filling the screen...
Done filling...
If your screen filled red, you may be able to use the library at http://misc.ws

По совету этого сообщения начал искать библиотеку на сайте misc.ws, и нашел библиотеку TFTLCD.zip (см. [2, 3]).

HX8347-A 240x320 ID=0x8347 new Untested
ILI9320 240x320 ID=0x9320
ILI9325 240x320 ID=0x9325
ILI9327 240x400 ID=0x9327
ILI9329 240x320 ID=0x9329
ILI9335 240x320 ID=0x9335
ILI9341 240x320 ID=0x9341
ILI9481 320x480 ID=0x9481
ILI9486 320x480 ID=0x9486
ILI9488 320x480 ID=0x9488
LGDP4535 240x320 ID=0x4535
RM68090 240x320 ID=0x6809
R61505V 240x320 ID=0xB505
R61505W 240x320 ID=0xC505 new Untested
R61509V 240x400 ID=0xB509
—– S6D0139 240x320 ID=0x0139 removed due to lack of tester
S6D0154 240x320 ID=0x0154
SPFD5408 240x320 ID=0x5408
—– SSD1963 800x480 ID=0x1963 new Untested
SSD1289 240x320 ID=0x1289
ST7781 240x320 ID=0x7783
ST7789V 240x320 ID=0x7789

[TFTLCD.zip]

Как использовать библиотеку TFTLCD.zip (скачайте эту библиотеку из статьи [2], или см. архив [5]):

1. Добавьте библиотеку через меню Скетч -> Подключить библиотеку -> Добавить .ZIP библиотеку... -> выберите TFTLCD.zip. Библиотека установится в среду Arduino IDE вместе с примерами кода.

2. Для Arduino Mega 2560 загрузите по ссылке из статьи [3] исправленный модуль TFTLCD.cpp, и перепишите его в каталог C:\имяпользователя\Documents\Arduino\libraries\TFTLCD\, заменив старый файл TFTLCD.cpp.

3. Внесите исправление в файле библиотеки glcdfont.c (он находится в каталоге j:\имяпользователя\user\Documents\Arduino\libraries\TFTLCD\), после static нужно добавить const:

static unsigned char  font[] PROGMEM -> static const unsigned char  font[] PROGMEM

4. Загрузите скетч примера через меню Файл -> Примеры -> TFTLCD -> graphicstest.

5. Скомпилируйте скетч и запустите через меню Скетч -> Загрузка (Ctrl+U).

Скетч выведет проверочный текст, после чего начнет выводить тест графики.

Если graphicstest выводит текст с инверсией направления, то нужно раскомментировать соответствующие строки в файле TFTLCD.cpp:

//#define INVERT_X
//#define INVERT_Y

С моим экранчиком пришлось раскомментировать строку #define INVERT_X.

Есть еще одна особенность работы с индикатором: после вызова initDisplay() необходима минимальная задержка перед тем, как начинать заполнять экран, иначе скраю экрана будут оставаться артефакты. Для своего экрана я подобрал эту задержку, получилось 25 мс:

tft.initDisplay(); 
delay(25);

[Проблема tft.println и tft.print]

На этом проблемы не закончились, обнаружился баг - функции println и print (когда они работают в объекте TFTLCD) при работе с индикатором выводят только один символ. Причем функция drawString в тех же условиях работает нормально:

tft.fillScreen(BLACK);
tft.setCursor(0, 20);
tft.setTextColor(color);
tft.setTextSize(1);
// Выводится только один красный символ H:
tft.print("Hello World!");
// Нормально выводится весь текст "Hello World!":
tft.drawString(0, 40, "Hello World!", GREEN, 1);

Функции println и print и выводят текст через size_t TFTLCD::write(uint8_t c), причем она работает нормально, этот код выводит буквы "ABC" друг за другом:

//Выведется текст "ABC":
tft.write('A');
tft.write('B');
tft.write('C');

Функцию write использует модуль hardware\arduino\avr\cores\arduino\Print.cpp (находится в каталоге установки Arduino):

/* Реализация по умолчанию: может быть переопределена */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    if (write(*buffer++)) n++;
    else break;
  }
  return n;
}

Тут же в комментарии есть подсказка - надо в классе TFTLCD переопределить функции println и print. К сожалению, я не большой спец в иерархии классов библиотек Arduino, поэтому просто взял готовые реализации функций вывода на печать из модуля Print.cpp, и сделал их аналоги в классе TFTLCD. Возможно, это не самый лучший вариант решения проблемы, потому что чреват дублированием кода при совместном использовании классов Serial и TFTLCD:

class TFTLCD : public Print {
public:
   TFTLCD(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t reset);
   uint16_t Color565(uint8_t r, uint8_t g, uint8_t b);
   ...
   // Добавлено:
   //size_t print(const __FlashStringHelper *);
   size_t print(const String &);
   size_t print(const char[]);
   size_t print(char);
   size_t print(unsigned char, int = DEC);
   size_t print(int, int = DEC);
   size_t print(unsigned int, int = DEC);
   size_t print(long, int = DEC);
   size_t print(unsigned long, int = DEC);
   size_t print(double, int = 2);
   //size_t print(const Printable&);
   //size_t println(const __FlashStringHelper *);
   size_t println(const String &s);
   //size_t println(const char[]);
   size_t println(char const*);
   size_t println(char);
   size_t println(unsigned char, int = DEC);
   size_t println(int, int = DEC);
   size_t println(unsigned int, int = DEC);
   size_t println(long, int = DEC);
   size_t println(unsigned long, int = DEC);
   size_t println(double, int = 2);
   //size_t println(const Printable&);
   size_t println(void);
    
private:
   void drawCircleHelper(uint16_t x0, uint16_t y0, uint16_t r,
                         uint8_t corner, uint16_t color);
   void fillCircleHelper(uint16_t x0, uint16_t y0, uint16_t r,
                         uint8_t corner, uint16_t delta, uint16_t color);
   // Добавлено:
   size_t printNumber(unsigned long n, uint8_t base);
   size_t printFloat(double number, uint8_t digits);
   ...
};

Исправленную библиотеку можно скачать по ссылке [5]. Конечно, можно обойти проблему другим способом - функции print и println для индикатора не использовать, для вывода текста пользоваться только функцией drawString.

[Слот карты microSD]

Пробовал скетч MyBitmapExperiment.ino [2] на Arduino Uno (ATmega328) и на Arduino Mega 2560 (ATmega2560). Скетч заработал только на Arduino Uno, проблема с библиотекой SD - на Arduino Mega 2560 карта microSD не инициализировалась. Причина в том, что у Arduino Mega 2560 выводы SPI привязаны к цифровым портам 50..53 вместо 10..13 у Arduino Uno, и эти порты SPI находятся совсем на другом разъеме.

Утилита bmp2lcd2 [4] преобразует 24-битную RGB BMP-картинку в формат 16-бит RGB (R5G6B5), который использует контроллер индикатора, благодаря чему можно ускорить вывод растрового изображения на экран.

В утилите bmp2lcd2 я нашел и исправил некоторые ошибки. Выходной файл там ошибочно открывался как текстовый, по этой причине некоторые картинки, в которых имелись байты 0x0A, сохранялись с ошибками (0x0A это конец строки в стиле Unix, и в текстовом режиме этот байт заменялся на 2 байта 0x0D 0x0A).

Сигнал Шилд Arduino Uno Arduino Mega 2560 Функция
~SS SD_SS port 10 ~SS (PB2) port 53 ~SS (PB0) Выборка карты, активный 0.
MOSI SD_DI port 11 MOSI (PB3) port 51 MOSI (PB2) Данные, выход AVR, вход карты.
MISO SD_DO port 12 MISO (PB4) pin 50 MISO (PB3) Данные, вход AVR, выход карты.
SCK SD_SCK port 13 SCK (PB5) pin 52 SCK (PB1) Такты, выход AVR, вход карты.

Подключение к карте SD через порт SPI на плате Arduino Mega2560:

Arduino Mega 2560 SD card connection

Не модифицированный 24-битный BMP-файл 320x240 загружается в экран примерно за 2.8 секунды. Оптимизированный файл (обработанный утилитой bmp2lcd2 [4]) загружается около 1.3 секунды.

Исправленный исходный код, скомпилированную утилиту можете скачать в архиве [5].

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

[Тачскрин]

Библиотека такскрина от Adafruit [6] дает нам две координаты X и Y, которые относятся к точке касания на экране, и координату Z, которая показывает прикладываемое давление. Эти координаты совпадают с параметром поворота экрана LCD по умолчанию, когда коннектор USB платы Arduino находится вверху, и при необходиости это Вам нужно будет подстроить самостоятельно.

Возможная область возникновения проблем с тачскрином - тот факт, что тачскрин использует общие выводы с LCD:

Тачскрин Шилд Порт Arduino Uno
YP (Y+) LCD_WR A1 (аналоговый порт)
XM (X-) LCD_RS A2 (аналоговый порт)
YM (Y-) LCD_D7 7 (цифровой порт)
XP (X+) LCD_D6 6 (цифровой порт)

Поэтому если Вы вызовете методы из библиотеки тачскрина, затем сделаете вызовы функций из библиотеки LCD, то можете получить неожиданные результаты, потому что библиотека тачскрина не всегда оставляет в правильном состоянии ножки микроконтроллера, и библиотека LCD не переводит эти ножки в правильное состояние перед тем, как начать свою работу. Более новые библиотеки Adafruit могут учитывать это обстоятельство, автор [2] решил эту проблему самостоятельно.

Еще одна из возможных проблем - дебонсинг нажатий, чтобы избежать дублирования событий нажатия. Один из способов улучшенной обработки нажатий показан в статье [2]. Последняя версия библиотеки тачскрина от Adafruit [6] содержит макроопределение NUMSAMPLES, которое подстраивает способ обработки дебоунсинга.

Для того, чтобы правильно работал скетч tftpaint из примеров библиотеки TFTLCD [2], необходимо вызвать функцию инициализации тачскрина TouchScreen, где в последнем параметре должно быть указано сопротивление между контактами тачскрина X+ и X-. Это сопротивление можно измерить обычным мультиметром. Мой тачскрин имел сопротивление между Y+ и Y- 343 Ома, и между X+ и X- 661 Ом.

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 661);

Также нужно подобрать значение параметров минимума и максимума координат тачскрина, это следующие макроопределения:

// Подберите эти значения, чтобы они соответствовали Вашему экрану:
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

[Ссылки]

1. LCD Touch Screen Information site:misc.ws.
2. Touch Screen Shield for Arduino UNO site:misc.ws.
3. Touch Screen on the Arduino Mega 2560 site:misc.ws.
4. Bitmap Converter for Arduino LCD site:misc.ws.
5190318graphicstest.zip - исходный код, документация.
6. Adafruit_TouchScreen site:github.com.
7. ILI9325: контроллер графики TFT LCD 240x320.

 

Добавить комментарий


Защитный код
Обновить

Top of Page