Работа с TouchScreen

Некоторые дисплеи оснащены сенсорным экраном (TouchScreen - дословно переводится как трогать экран), который позволяет получать координаты точки прикосновения. Используя эти координаты, можно рисовать кривые или использовать их для имитации клавиатуры.

В настоящее время разработано множество сенсорных экранов, которые фиксируют прикосновение и получают координаты различными способами: резистивные, матричные, емкостные, инфракрасные, оптические, тензометрические, пьезоэлектрические, индукционные и даже ультразвуковые.

В данной статье речь пойдёт о резистивных сенсорных экранах.

Общие сведения:

Резистивный TouchScreen состоит из двух прозрачных панелей. Одна панель - стеклянная (находится со стороны дисплея), вторая панель - из эластичного пластика (находится с внешней стороны, именно на неё мы и нажимаем), она выполняет роль мембраны. На внутренние поверхности обеих панелей (которые «смотрят» друг на друга) нанесён тонкий токопроводящий слой, имеющий однородное сопротивление. С противоположных сторон панелей присутствуют выводы, по два на каждую панель (см. рисунок ниже). Между панелями существует небольшой зазор заполненный микро-изоляторами (диэлектрическими микро-шариками), гарантирующими, что панели электрически не соединены. При касании мембраны, токопроводящие слои на мембране и на стекле соприкасаются друг с другом, электрически соединяясь. Сопротивление между выводами обеих панелей зависит от координат точки их соприкосновения.

На большинстве дисплеев выводы TouchScreen являются выводами двойного назначения. Они объединяют две функции: получение координат с сенсора и вывод данных на дисплей. Двойное назначение выводов стало возможным благодаря тому, что вывод данных на дисплей и чтение координат с сенсора, выполняются в разные промежутки времени.

Получение координат касания:

Для получения координат, нужно сконфигурировать два вывода Arduino подключённые к одной панели в режим входа, а два вывода Arduino подключённые к другой панели, в режим выхода. На выходы, подать разные логические уровни (на один LOW на другой HIGH), а с одного из входов, считать уровень напряжения.

Получение координаты по оси X:
  • Выводы Arduino к которым подключены выводы X+ и X- (с напыления на стекле) переводятся в режим выхода.
  • На вывод X+ (XP) подаётся уровень HIGH, а на вывод X- (XM) подаётся уровень LOW.
  • Выводы Arduino к которым подключены выводы Y+ и Y- (с напыления мембране) переводятся в режим входа.
  • Данные полученные функцией analogRead, со входа Y+ (YP) будут обратно пропорциональны координате касания по оси X.
  • Вывод Y- (YM) находится в состоянии высокого импеданса, так как мы перевели его в режим входа.
Получение координат по оси X с сенсорного экрана Напряжение снимаемое с выхода Y+ (YP) зависит от горизонтального делителя (R левее и правее точки касания).
Вертикальный делитель не влияет на уровень снимаемого напряжения (R выше точки касания лишь ограничивает ток, а R ниже точки касания вообще не участвует в схеме, т.к. вывод Y- (YM) находится в состоянии высокого импеданса («висит» как не подключённый).
Получение координаты по оси Y:
  • Выводы Arduino к которым подключены выводы Y+ и Y- (с напыления на мембране) переводятся в режим выхода.
  • На вывод Y+ (YP) подаётся уровень HIGH, а на вывод Y- (YM) подаётся уровень LOW.
  • Выводы Arduino к которым подключены выводы X+ и X- (с напыления на стекле) переводятся в режим входа.
  • Данные полученные функцией analogRead, со входа X- (XM) будут обратно пропорциональны координате касания по оси Y.
  • Вывод X+ (XP) находится в состоянии высокого импеданса, так как мы перевели его в режим входа.
Получение координат по оси X с сенсорного экрана Напряжение снимаемое с выхода X- (XM) зависит от вертикального делителя (R выше и ниже точки касания).
Горизонтальный делитель не влияет на уровень снимаемого напряжения (R правее точки касания лишь ограничивает ток, а R левее точки касания вообще не участвует в схеме, т.к. вывод X+ (XP) находится в состоянии высокого импеданса («висит» как не подключённый).

Если на выводы пластины, к которой подаётся напряжение, вместо LOW подать HIGH, а вместо HIGH подать LOW (поменять местами уровни выводов), то считанное значение будет не обратно, а прямо пропорционально координате касания.

Читать данные можно с любого вывода той пластины, на которую не подавалось напряжение (уровни LOW и HIGH), но так как обычно один из выводов соединён с аналоговым выводом Arduino, а другой с цифровым, то и читать данные приходится только с того вывода, который подключён к аналоговому выводу Arduino.

После чтения координат, все выводы нужно сконфигурировать в тот режим, который был установлен до чтения, для нормальной работы с дисплеем.

Со всеми этими задачами успешно справляется библиотека TouchScreen. Она не только возвращает уровни напряжений прямо пропорциональные точкам касания, но еще и уровень силы нажатия.

Пример:

//  Подключаем библиотеки:
    #include <UTFT.h>                                      // Подключаем библиотеку для работы с дисплеем
    #include <TouchScreen.h>                               // Подключаем библиотеку для работы с TouchScreen
//  Определяем выводы используемые для управления дисплеем 2.8" TFT 320x240 UNO:
    const uint8_t RS   = A2;                               // 
    const uint8_t WR   = A1;                               // 
    const uint8_t CS   = A3;                               // 
    const uint8_t RST  = A4;                               // 
    const uint8_t SER  = A0;                               // 
//  Определяем выводы используемые для чтения данных с TouchScreen:
    const uint8_t YP   = A2;                               // Вывод Y+ должен быть подключен к аналоговому входу
    const uint8_t XM   = A3;                               // Вывод X- должен быть подключен к аналоговому входу
    const uint8_t YM   = 8;                                // Вывод Y-
    const uint8_t XP   = 9;                                // Вывод X+
//  Определяем экстремумы для значений считываемых с аналоговых входов при определении точек нажатия на TouchScreen:
    const int tsMinX   = 210;                              // соответствующий точке начала координат по оси X
    const int tsMinY   = 205;                              // соответствующий точке начала координат по оси Y
    const int tsMaxX   = 930;                              // соответствующий максимальной точке координат по оси X
    const int tsMaxY   = 915;                              // соответствующий максимальной точке координат по оси Y
    const int mipPress = 10;                               // соответствующий минимальной степени нажатия на TouchScreen
    const int maxPress = 1000;                             // соответствующий максимальной степени нажатия на TouchScreen
//  Создаём объекты библиотек:
    UTFT        myGLCD(TFT28UNO, RS, WR, CS, RST, SER);    // Создаём объект для работы с дисплеем
    TouchScreen ts     = TouchScreen(XP, YP, XM, YM);      // Создаём объект для работы с TouchScreen
                                                           //
void setup(void){                                          //
    Serial.begin(9600);                                    // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек
    myGLCD.InitLCD();                                      // Инициируем работу с TFT дисплеем
    myGLCD.clrScr();                                       // Чистим экран дисплея
}                                                          //
void loop(){                                               //
//  Считываем показания с TouchScreen:
    TSPoint p = ts.getPoint();                             // Считываем координаты и интенсивность нажатия на TouchScreen в структуру p
//  Возвращаем режим работы выводов:
    pinMode(XM, OUTPUT);                                   // Возвращаем режим работы вывода X- в значение «выход» для работы с дисплеем
    pinMode(YP, OUTPUT);                                   // Возвращаем режим работы вывода Y+ в значение «выход» для работы с дисплеем
//  Если зафиксировано нажатие на TouchScreen, то ...
    if(p.z>mipPress && p.z<maxPress){                      // Если степень нажатия достаточна для фиксации координат TouchScreen
//      Выводим «сырые» показания TouchScreen:
/////// Serial.println((String) "X="+p.x+",\tY="+p.y);
//      Преобразуем значения полученные с TouchScreen в координаты дисплея:
        p.x = map(p.x, tsMinX, tsMaxX, 0, 320);            // Преобразуем значение p.x от диапазона tsMinX...tsMaxX, к диапазону 0...320
        p.y = map(p.y, tsMinY, tsMaxY, 0, 240);            // Преобразуем значение p.y от диапазона tsMinY...tsMaxY, к диапазону 0...240
//      Выводим преобразованные показания TouchScreen:
/////// Serial.println((String) "("+p.x+","+p.y+")");
//      Выводим точку на экране по координатам с TouchScreen:
        myGLCD.fillCircle(p.x,p.y,3);                      // Прорисовываем окружность диаметром 3 пикселя с центром в точке координат считанных с TouchScreen
    }
}

Калибровка:

Для калибровки в скетче предусмотрены 4 константы: tsMinX, tsMinY, tsMaxX и tsMaxY, хранящие экстремумы (крайние значения) читаемых уровней с аналоговых входов для осей X и Y.

Дело в том, что библиотека TouchScreen возвращает прочитанные уровни, а не значения координат. Для того чтоб они стали координатами, их нужно преобразовать от диапазона уровней к диапазону координат, что и происходит в скетче в разделе «Преобразуем значения полученные с TouchScreen в координаты дисплея». Диапазон координат нам известен: для оси X от 0 до ширины дисплея, для оси Y от 0 до высоты дисплея, в пикселях. А диапазон читаемых уровней зависит от типа TouchScreen. Для того чтоб узнать этот диапазон, нужно разкомментировать строку в разделе «Выводим «сырые» показания TouchScreen», загрузить скетч и открыть монитор последовательного порта.

Грубая калибровка:

При каждом нажатии на экран, в мониторе будут отображаться координаты нажатия X и Y. Понажимайте возле каждого края экрана, при этом запомните или запишите как самое максимальное, так и самое минимальное значение для каждой оси. После чего присвойте эти значения, в разделе «Определяем экстремумы» (в начале скетча), для каждой константы: tsMinX, tsMinY, tsMaxX и tsMaxY. И загрузите скетч заново.

Точная калибровка:

После того как TouchScreen был грубо откалиброван, может понадобиться более точная калибровка.

Расположите экран так, как это показано на самом первом рисунке данной статьи (начало координат обеих осей слева сверху).

  • Плавно проведите линию по экрану от центра влево.
    • Если выводимая на дисплее линия опережает точку нажатия, то значение tsMinX нужно уменьшить.
    • Если Выводимая на дисплее линия отстаёт от точки нажатия, то значение tsMinX нужно увеличить.
  • Плавно проведите линию по экрану от центра вправо.
    • Если выводимая на дисплее линия опережает точку нажатия, то значение tsMaxX нужно увеличить.
    • Если Выводимая на дисплее линия отстаёт от точки нажатия, то значение tsMaxX нужно уменьшить.
  • Плавно проведите линию по экрану от центра вверх.
    • Если выводимая на дисплее линия опережает точку нажатия, то значение tsMinY нужно уменьшить.
    • Если Выводимая на дисплее линия отстаёт от точки нажатия, то значение tsMinY нужно увеличить.
  • Плавно проведите линию по экрану от центра вниз.
    • Если выводимая на дисплее линия опережает точку нажатия, то значение tsMaxY нужно увеличить.
    • Если Выводимая на дисплее линия отстаёт от точки нажатия, то значение tsMaxY нужно уменьшить.

Описание функций библиотеки:

Подключение библиотеки:
#include <TouchScreen.h>                                                                       // Подключаем библиотеку
TouchScreen ts = TouchScreen( ВЫВОД_X+ , ВЫВОД_Y+ , ВЫВОД_X- , ВЫВОД_Y- [ , СОПРОТИВЛЕНИЕ ] ); // Создаём объект ts для работы с TouchScreen, указывая номера его выводов
                                                                                               // необязательный параметр СОПРОТИВЛЕНИЕ в Омах (между выводами Y+ и Y-) позволяет более точно определять степень нажатия
Функция getPoint();
  • Назначение: получение «сырых» данных о точке нажатия
  • Синтаксис: getPoint();
  • Параметры: Нет
  • Возвращаемые значения: Структура из трёх переменных типа int16_t
    • x - значение с аналогового входа, прямопропорциональное координате нажатия по оси X
    • y - значение с аналогового входа, прямопропорциональное координате нажатия по оси X
    • z - значение соответствующее степени нажатия на TouchScreen
  • Примечание: Каждое значение можно получить по отдельности, воспользовавшись функциями описанными ниже
  • Пример:
TSPoint p = ts.getPoint(); // Определяем структуру «p» с тремя переменными типа int16_t, которые хранят значение координат и интенсивность нажатия
Функция readTouchX();
  • Назначение: получение «сырого» значения соответствующего точке нажатия по оси X
  • Синтаксис: readTouchX();
  • Параметры: Нет
  • Возвращаемые значения: число типа int
  • Примечание: Полученное значение требуется преобразовать от диапазона «сырых» значений к диапазону ширины экрана
  • Пример:
int i = ts.readTouchX(); // Получаем «сырое» значение соответствующее координате X
Функция readTouchY();
  • Назначение: получение «сырого» значения соответствующего точке нажатия по оси Y
  • Синтаксис: readTouchY();
  • Параметры: Нет
  • Возвращаемые значения: число типа int
  • Примечание: Полученное значение требуется преобразовать от диапазона «сырых» значений к диапазону высоты экрана
  • Пример:
int i = ts.readTouchY(); // Получаем «сырое» значение соответствующее координате Y
Функция pressure();
  • Назначение: получение значения соответствующего степени нажатия на TouchScreen
  • Синтаксис: pressure();
  • Параметры: Нет
  • Возвращаемые значения: число типа int
  • Пример:
int i = ts.pressure(); // Получаем значение соответствующее степени нажатия на TouchScreen

Примечание:

Координаты сенсора должны совпадать с координатами дисплея. Если Вы будете выводить данные на дисплей библиотекой не UTFT, то возможно Вам придется изменить название осей, поменяв местами номера выводов X и Y при создании объекта библиотеки.

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

Ссылки:

Обсуждение

Присоединяйся

На главную