Подключение шилда 2.4" TFT LCD |
![]() |
Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||
Купил на AliExpress шилд Arduino с индикатором 2.4" TFT LCD, и при попытке его запустить столкнулся с проблемами.
Параметры индикатора: · 2.4" диагональ, LCD TFT, разрешение 240 x 320 точек. Поначалу решил воспользоваться библиотеками 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 [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).
Подключение к карте SD через порт SPI на плате Arduino Mega2560: Не модифицированный 24-битный BMP-файл 320x240 загружается в экран примерно за 2.8 секунды. Оптимизированный файл (обработанный утилитой bmp2lcd2 [4]) загружается около 1.3 секунды. Исправленный исходный код, скомпилированную утилиту можете скачать в архиве [5]. Общее впечатление от индикатора - свою цену он оправдывает, однако мало подходит для высокопроизводительных приложений на платформе AVR / Arduino. Вывод на индикатор медленный (по крайней мере с этой библиотекой), занимает много процессорного времени, и задействовано слишком много выводов портов. [Тачскрин] Библиотека такскрина от Adafruit [6] дает нам две координаты X и Y, которые относятся к точке касания на экране, и координату Z, которая показывает прикладываемое давление. Эти координаты совпадают с параметром поворота экрана LCD по умолчанию, когда коннектор USB платы Arduino находится вверху, и при необходиости это Вам нужно будет подстроить самостоятельно. Возможная область возникновения проблем с тачскрином - тот факт, что тачскрин использует общие выводы с LCD:
Поэтому если Вы вызовете методы из библиотеки тачскрина, затем сделаете вызовы функций из библиотеки 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. |