Урок 9 – тачскрин ads7843

Разрабатываем крутой GUI на esp8266 с библиотекой uGFX

В многих проектах для esp8266 я использую TFT экран с тачскрином. В зависимости, от проекта интерфейс может быть простым, например, текстовая консоль, выводящая лог работы приложения или просто график изменения входного сигнала. А в некоторых — сложный GUI, с несколькими экранами, графическими кнопками, строками ввода текста и даже виртуальной клавиатурой.

В этой статье хочу поделиться опытом, как можно подключить экран с тачскрином к esp8266 и реализовать графический интерфейс в среде Arduino.

Видео-тизер:

Итак, приступим

Первая часть, аппаратная

Выбор модели экрана

Сейчас на рынке, читай на aliexpress, продается огромное количество моделей TFT экранов — разных размеров, с разными разрешениями, с тачскрином или без.

TFT экраны отличаются способом подключения — есть экраны, которые подключаются по шине SPI, а другие по параллельной шине.

Минимально, для подключения по шине SPI, требуется всего 4 сигнальных вывода (GPIO), а для подключения по параллельной шине — минимум 10 (и это без учета контроллера тачскрина). Подключение по параллельной шине дает большую скорость, т.к. за один такт передается сразу 8 бит информации, а у SPI — только 1 бит.

Однако, у подключения по SPI, есть другое преимущество — меньшее количество задействованных выводов. У esp8266 количество требуемых выводов является решающим фактором: количество свободных GPIO ограничено.

Я бы выделил такие наиболее популярные модули TFT экранов с SPI интерфейсом:

  1. ili9341, 320×240, 2.4″, с контроллером тачскрина ссылка
  2. ili9225, 176×220, 2.2, без тачскрина ссылка
  3. st7735, 160×128, 1.8″, без тачскрина ссылка

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

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

ВыводАльтернативные названияПодключение к esp8266Назначение
SCLK SCK,SCL GPIO14 Тактирование шины SPI
SDA MOSI GPIO13 Передача данных SPI от процессора к экрану
CS SS GPIO5 Выбор чипа (к шине SPI может быть подключено несколько устройств)
A0 RS,D/C GPIO15 Выбор режима передача данных/команд
RESET RST VCC Аппаратный сброс
SDO MISO Передача данных от экрана к процессору (опционально)
LED+ LED VCC Включение подсветки
VSS VCC VCC Питание экрана, +3.3V
GND GND Земля

Выводы RESET и LED+ можно подключить к шине питания +3.3 вольта, однако, при желании их можно подключить к GPIO esp8266, и получить возможность программного управления сбросом и подсветкой экрана.

Выводы CS и A0 можно подключить к любым удобным GPIO esp8266.

Самая важная часть — выводы SCLK и SDA. Они отвечают за передачу данных по шине SPI. Их нужно подключить к соответствующим выводам контроллера SPI esp8266. Это GPIO14 и GPIO13 соответственно.

Если у экрана есть тачскрин контроллер, его так же следует подключить к шине SPI:

ВыводПодключение к esp8266Назначение
T_CLK GPIO14 Тактирование шины SPI
T_DIN GPIO13 Передача данных SPI от процессора к контроллеру тачскрина
T_CS GPIO16 Выбор чипа (к шине SPI может быть подключено несколько устройств)
T_DO GPIO12 Передача данных от контроллера к процессору
T_IRQ GPIO4 Признак нажатия на тачскрин

Обратите внимание, выводы esp8266 GPIO14 и GPIO13 подключены параллельно к экрану и контроллеру тачскрина. Дело в том, что к шине SPI можно подключить несколько устройств. Выбор устройства происходит установкой уровня логического 0 на выводе CS требуемого устройства.

Схема подключения экрана ili9341 к esp8266

Часть вторая, программная

Мы определились с экраном и схемой подключения, теперь пора перейти к программной части. В первую очередь — выберем графическую библиотеку, с которой мы будем реализовывать GUI.

Попробовав несколько десятков библиотек, я остановил свой выбор на библиотеке uGFX. На мой взгляд, это одна из лучших графических библиотек для микроконтроллеров.

Богатая функциональность сочетается с модульностью и в проект включаются только требуемые компоненты. Библиотека open source и бесплатна для не коммерческого использования.

У библиотеки есть качественная документация, доступная на сайте проекта.

Большим плюсом библиотеки uGFX является развитый движок рендеринга шрифтов, с поддержкой utf8. В комплект входит программа генерации шрифтов из ttf файлов, в том числе и с кириллицей.

Библиотека кросс-платформенна — это означает, что GUI часть приложения можно собрать под любой процессор, в том числе и esp8266.

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

Кроме этого, в комплект uGFX входит uGFX studio — WYSWIG редактор интерфейса, в котором можно визуально подготовить макеты интерфейсы, а uGFX studio автоматически сгенерирует код и разложит ресурсы. К сожалению, сейчас uGFX studio еще в статусе beta версии, и чтобы получить бетку, нужно написать разработчикам на форуме.

И, финальная вишенка на торт: GUI код приложения, можно собрать под десктоп (Linux/Windows/OSX) и посмотреть прямо на компьютере, как будет выглядеть интерфейс.

Подключаем uGFX к проекту

Библиотека использует свою систему сборки, которая “из коробки” не поддерживается системой сборки Arduino. Но это ограничение можно обойти. В качестве reference использовал эту статью

Текст ниже предполагает, что среда для разработки Arduino с поддержкой esp8266 уже установлена и настроена. Если еще нет, то про установку и настройку среды можно прочитать в этой статье на geektimes

Теперь по шагам, как подключить библиотеку:

  1. Найти папку Libraries от среды Arduino. В зависимости от платформы, она может располагаться в таких местах:

  • OSX — /Users//Documents/Arduino/libraries/
  • Windows — C:Users\My DocumentsArduinoLibraries
  • Linux -/home//Documents/Arduino/libraries

  1. Склонировать или скопировать uGFX в папку Libraries. Скачать можно отсюда — версию, с уже встроенными кириллическими шрифтами.

  2. Сделать библиотеку “обертку”, которая будет содержать реализацию ввода/вывода для драйверов экрана и тачскрина, а так же подключать к сборке нужные нам компоненты uGFX. Для этого, в папке Libraries нужно создать подпапку uGFXesp, с примерно таким содержимым:

uGFXesp
├── library.properties
└── src ├── board_ILI9341.cpp ├── board_ILI9341.h ├── gdisp_lld_config.h ├── gdisp_lld_ili9341.c ├── gfxconf.h ├── gfxlib.c ├── gmouse_lld_ADS7843.c ├── gmouse_lld_ADS7843_board.cpp └── gmouse_lld_ADS7843_board.h

  • Файл library.properties — это описание библиотеки для среды Arduino:

Содержимое library.propertiesname=uGFXesp
version=1.0.0
author=Oleg V. Gerasimov
maintainer=Oleg V. Gerasimov
sentence=UI features of esp
paragraph=This library add support screen and touch panel of esp board
Requires uGFX library
category=Display
architectures=esp8266
includes=gfx.h
url=http://github.com

  • Файлы gdisp_lld_ili9341.c, gmouse_lld_ADS7843.c, gdisp_lld_config.h — подключение к сборке драйверов контроллера тачскрина и экрана.
  • Файл gfxlib.c — подключение к сборке самой библиотеки
  • Файл gfxconf.h — конфигурация, с которой собирается библиотека uGFX — в нем можно включать/отключать требуемую функциональность
  • Файл board_ILI9341.cpp — реализация ввода/вывода по SPI для драйвера экрана. Остновлюсь на нем подробнее, это самая важная часть интеграции графической библиотеки с esp8266

Содержимое board_ILI9341.cpp#include
#include extern “C” {
#include “user_interface.h”
}
// Pin, к которому подключен вывод RS экрана
#define ESP_LCD_RS 15
// Pin, к которому подключен вывод CS экрана
#define ESP_LCD_CS 5 // Скорость работы SPI с экраном в момент инициализации: 1мбит/сек
#define SPILOWSPEED 1000000 // Скорость работы SPI с экраном: 32мбит/сек
#define SPIHIGHSPEED 32000000 static SPISettings spiSettings(SPILOWSPEED, MSBFIRST, SPI_MODE0); // Включить режим команд экрана
static inline void cmdmode() { digitalWrite(ESP_LCD_RS, 0);
} // Включить режим данных экрана
static inline void datamode() { digitalWrite(ESP_LCD_RS, 1);
} // Инициализация драйвера
extern “C” void esp_lcd_init_board(void) { SPI.begin(); pinMode(ESP_LCD_CS, OUTPUT); digitalWrite(ESP_LCD_CS, 1); pinMode(ESP_LCD_RS, OUTPUT); datamode();
} // Пост-инициализации драйвера – переводим SPI на нормальную скорость
extern “C” void esp_lcd_post_init_board(void) { spiSettings = SPISettings(SPIHIGHSPEED, MSBFIRST, SPI_MODE0);
} static int aquire_count = 0; // Захватить шину SPI: устанавливаем 0 на выводе CS и начинаем транзакцию SPI на выбранной скорости
extern “C” void esp_lcd_aquirebus(void) { if (!aquire_count++) { SPI.beginTransaction(spiSettings); digitalWrite(ESP_LCD_CS, 0); }
} // Отпустить шину SPI: устанавливаем 1 на выводе CS и завершаем транзакцию SPI
extern “C” void esp_lcd_releasebus(void) { if (aquire_count && !–aquire_count) { digitalWrite(ESP_LCD_CS, 1); SPI.endTransaction(); }
} // Передать команду
extern “C” void esp_lcd_write_index(uint16_t cmd) { cmdmode(); SPI.write(cmd); datamode();
} // Передать байт данных
extern “C” void esp_lcd_write_data(uint16_t data) { SPI.write(data);
}

  • Файл gmouse_lld_ADS7843_board.cpp — реализация ввода/вывода по SPI для драйвера экрана. Так же остановлюсь на нем подробнее:

Содержимое gmouse_lld_ADS7843_board.cpp#include
#include extern “C” {
#include “user_interface.h”
} // Pin, к которому подключен вывод TC_IRQ контроллера тачскрина
#define ESP_TC_IRQ 4
// Pin, к которому подключен вывод CS контроллера тачскрина
#define ESP_TC_CS 16 // Скорость работы SPI с контроллером тачскрина 2Мбит/сек
#define SPISPEED 2000000 static SPISettings spiSettings(SPISPEED, MSBFIRST, SPI_MODE0); // Инициализация драйвера
extern “C” int esp_gmouse_init_board() { pinMode(ESP_TC_CS, OUTPUT); digitalWrite(ESP_TC_CS, 1); pinMode(ESP_TC_IRQ, INPUT); return 1;
} // Проверка состояния вывода TC_IRQ (признак нажатия на тачскрин)
extern “C” int esp_getpin_pressed() { // В этом месте мы сбрасываем watch dog, что бы esp8266 не перезагрузился system_soft_wdt_feed (); // Флаг нажатия инверсный return digitalRead (ESP_TC_IRQ)==0;
} static int aquire_count = 0; // Захватить шину SPI: устанавливаем 0 на выводе CS и начинаем транзакцию SPI на выбранной скорости
extern “C” void esp_aquire_bus() { if (!aquire_count++) { SPI.beginTransaction(spiSettings); digitalWrite(ESP_TC_CS, 0); }
} // Отпустить шину SPI: устанавливаем 1 на выводе CS и завершаем транзакцию SPI
extern “C” void esp_release_bus() { if (aquire_count && !–aquire_count) { digitalWrite(ESP_TC_CS, 1); SPI.endTransaction(); }
}
// Считать значение координаты из контроллера
extern “C” uint16_t esp_read_value(uint16_t port) { SPI.write (port); return SPI.transfer16(0);
}

Собственно, на этом подготовительные работы закончены. Набор файлов исходников есть на гитхабе

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

Разрабатываем скетч с GUI

В прошлой статье я написал про “умный” удлинитель для новодней елочки. GUI у скетча состоит из двух экранов

  • заставка с елочкой
  • экран с кнопками включения/выключения гирлянд:

Ниже по тексту несколько “снипетов” из кода, как реализовано GUI в этом проекте:

Определение переменных// Окно контейнер
GHandle ghContainerMain;
// Кнопки
GHandle ghButton1,ghButton2,ghButton3,ghButton4,ghButtonAll,ghButtonVoice,ghButtonTree;
// Картинки
gdispImage ballImg,bearImg,candleImg,microphoneImg,treeImg,bigTreeImg,lightsImg;
// Слушатель событий
GListener glistener; // Кастомная функция отрисовки кнопки с картинкой и подписью
extern “C” void gwinButtonDraw_ImageText(GWidgetObject *gw, void *param);

Функция инициализации GUIvoid guiCreate(void) { gfxInit(); // Создаем “слушателя” события geventListenerInit(&glistener); geventAttachSource(&glistener, ginputGetKeyboard(0), 0); gwinAttachListener(&glistener); // Устанавливаем дефолтные стили GUI gwinSetDefaultFont(gdispOpenFont(“DejaVuSans16”)); gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE); gwinSetDefaultColor(HTML2COLOR(0x000000)); gwinSetDefaultBgColor(HTML2COLOR(0xFFFFFF)); // Загружаем картинки, они должны находиться в файловой системе SPIFFs gdispImageOpenFile(&ballImg, “ball.bmp”); gdispImageOpenFile(&bearImg, “bear.bmp”); gdispImageOpenFile(&candleImg, “candle.bmp”); gdispImageOpenFile(µphoneImg, “music.bmp”); gdispImageOpenFile(&treeImg, “tree.bmp”); gdispImageOpenFile(&lightsImg, “lights.bmp”); gdispImageOpenFile(&bigTreeImg, “bigtree.bmp”); // Создаем сами элементы GUI GWidgetInit wi; gwinWidgetClearInit(&wi); wi.g.x = 0; wi.g.y = 0; wi.g.width = 176; wi.g.height = 220; wi.g.show = TRUE; ghContainerMain = gwinContainerCreate(0, &wi, 0); wi.g.parent = ghContainerMain; wi.customDraw = gwinButtonDraw_ImageText; wi.customStyle = 0; wi.customParam = &bigTreeImg; wi.g.x = 0; wi.g.y = 0; wi.text = “”; ghButtonTree = gwinButtonCreate(0, &wi); wi.g.show = FALSE; wi.customParam = &ballImg; wi.g.width = 88; wi.g.height = 73; wi.text = “Шарики”; ghButton1 = gwinButtonCreate(0, &wi); wi.customParam = &candleImg; wi.g.x = 88; wi.g.y = 0; wi.text = “Свечки”; ghButton2 = gwinButtonCreate(0, &wi); wi.customParam = &bearImg; wi.g.x = 0; wi.g.y = 73; wi.text = “Мишки”; ghButton3 = gwinButtonCreate(0, &wi); wi.customParam = &lightsImg; wi.g.x = 88; wi.g.y = 73; wi.text = “Огоньки”; ghButton4 = gwinButtonCreate(0, &wi); wi.customParam = &treeImg; wi.g.x = 0; wi.g.y = 146; wi.text = “Все”; ghButtonAll = gwinButtonCreate(0, &wi); wi.customParam = µphoneImg; wi.g.x = 88; wi.g.y = 146; wi.text = “Музыка”; ghButtonVoice = gwinButtonCreate(0, &wi);
}
Обработка событийstatic bool screenSaver = false;
// Переключение экрана между кнопками и скринсэвером
void switchScreen (bool flag) { gwinSetVisible (ghButton1,flag); gwinSetVisible (ghButton2,flag); gwinSetVisible (ghButton3,flag); gwinSetVisible (ghButton4,flag); gwinSetVisible (ghButtonAll,flag); gwinSetVisible (ghButtonVoice,flag); gwinSetVisible (ghButtonTree,!flag); screenSaver = !flag;
} static unsigned long timeLastActivity =0;
void loop() { unsigned long now = millis(); // Проверяем наличие событий от библоитеки GEvent* pe = geventEventWait(&glistener, 2); if (pe && pe->type == GEVENT_GWIN_BUTTON) { GEventGWinButton *we = (GEventGWinButton *)pe; if (we->gwin == ghButton1) {/* Действие по кнопке */} if (we->gwin == ghButton2) {/* Действие по кнопке */} if (we->gwin == ghButton3) {/* Действие по кнопке */} if (we->gwin == ghButton4) {/* Действие по кнопке */} if (we->gwin == ghButtonAll) {/* Действие по кнопке */}; if (we->gwin == ghButtonVoice) {/* Действие по кнопке */}; if (we->gwin == ghButtonTree) {switchScreen (true); startRecognize();} timeLastActivity = now; } // Проверяем если ничего не нажимали 10 секунд, то запускаем скринсэйвер if (!screenSaver && now – timeLastActivity > 10000) { switchScreen (false); } delay (10);
}

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

Исходники на гитхабе: сам скетч

Реализация отрисовки графиков

Tetris

Исходники на гитхабе: tetris

исходники скетча с первого видео

Итого, в этой статье у нас получилось сделать удобное и красивое GUI решение, с использованием доступных в Open Source библиотек.

Источник: https://habr.com/post/346276/

Цветной графический TFT-экран 240×320 / 2,4” , Сенсорный

Цветной графический дисплей 2.4 TFT 240×320 (с Touch-screen) — предназначен для вывода текстов и графики. На обратной стороне дисплея, есть слот для SD карты, на которой можно хранить графические данные. Дисплей оснащен резистивным сенсорным экраном (TouchScreen) с интегрированным в модуль контроллером сенсорных функций. 

Характеристики

  • Контроллер: ILI9341
  • Диагональ: 2,4 дюйма
  • Напряжение питания: 3,3 … 5 В
  • Напряжение LED подсветки: 3,3 В
  • Напряжение сигналов: 3,3 В
  • Разрешение: 240×320 (RGB)
  • Интерфейс: SPI
  • Размер экрана: 60×42 мм
  • Размер модуля: 77×43 мм

Подключение

  • Питание логики 3,3 или 5 В, подаётся на выводы Vcc и GND дисплея.
  • Питание подсветки 3,3 В подаётся на выводы LED и GND дисплея.
  • Выводы SD-карты (SD_CS, SD_MOSI, SD_MISO, SD_SCK) подключаются к аппаратной шине SPI, если аппаратный вывод CS(SS) Arduino занят, то вывод SD_CS SD-карты можно подключить к любому другому выводу Arduino, указав его номер в скетче.
  • Выводы контроллера TouchScreen (T_IRQ, T_OUT, T_DN, T_CS, T_CLK) подключаются к любым выводам Arduino.
  • Подключение остальных выводов дисплея к Arduino зависит от используемой библиотеки и реализации шины SPI. При использовании библиотеки UTFT дисплей можно подключать к любым выводам Arduino указав их номера при объявлении объекта библиотеки UTFT:UTFT myGLCD(TFT01_24SP, SDI/MOSI, SCK, CS, RESET, DC/RS);
  • Например: UTFT myGLCD(TFT01_24SP, 5, 4, 8, 7, 6);

Уровень логической «1» на входах дисплея ≤ 3,3 В. Если Вы используете 5 В логику, то подключайте входы дисплея через делители, инструкция по подключению.

Питание

Входное напряжение питания 5 В или 3,3 В, постоянного тока подаётся на выводы Vcc и GND. Если дисплей питается от напряжения 3,3 В, то нужно замкнуть перемычку J1 на обратной стороне платы, а если дисплей питается от 5 В, нужно проверить что эта перемычка разомкнута. Напряжение подсветки дисплея 3,3 В постоянного тока, подаётся на выводы LED и GND.

Подробнее о дисплее

В действительности правильнее сказать, что дисплей имеет разрешение 320×240, а не 240×320, так как у него по оси X 320 точек, а по оси Y 240, но разработчик указал размеры 240×320 шелкографией на плате модуля.

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

Помимо матрицы, в модуль интегрирован слот под SD карту памяти и резистивный сенсорный экран (TouchScreen) с передачей данных через контроллер сенсорных функций HR2046 (XPT2046, ADS7843), работа с которым описана в разделе Wiki – работа с TouchScreen по последовательной шине данных.

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

Комплектация

  • 1х Цветной графический дисплей 2.4 TFT 240×320 (с Touch-screen);

Ссылки

Источник: http://iarduino.ru/shop/Displei/cvetnoy-graficheskiy-tft-ekran-240-320—2-4-rdquo.html

Тачскрин – что это такое? Использование и калибровка тачскрина для телефона или планшета :

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

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

Рассмотрим, что такое тачскрин, какие его виды бывают и как провести их калибровку.

Виды сенсоров

С самого начала давайте дадим определение тачскрину. Тачскрин – это устройство ввода какой-либо информации в телефон или планшет. Он предназначается для адекватного восприятия устройством приказов. Часто тачскрин (или сенсор) путают с экраном, но это абсолютно две разные вещи.

Рынок на сегодняшний день предлагает 4 основных вида сенсоров для мобильных устройств:

  • резистивный;
  • индукционный;
  • емкостной;
  • инфракрасный.

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

Резистивный тачскрин

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

Что это плохой показатель – ничего не сказать. Все дело в самом нажатии, по причине которого очень сильно портится экран.

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

Индукционный тачскрин

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

Емкостной тачскрин

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

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

Недостатком является невозможное управление сторонними предметами и пальцами в перчатках.

Инфракрасный тачскрин

Эти сенсоры работают по принципу инфракрасной сетки. Инфракрасные тачскрины являются универсальными. Они не портят изображение, но, в свою очередь, имеют длительный отклик и низкую точность.

Примерно в 80% сенсорных устройств используется емкостной сенсор. Он максимально удобен, стоит недорого и при этом имеет высокие показатели скорости отклика. Резистивный реже встречается, но и он также применяется в мобильных устройствах по причине своей дешевизны.

Калибровка тачскрина

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

Калибровка тачскрина – это процедура настройки сенсора, которая проводится для повышения точности реакции на касание к устройству.

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

Если взамен выбранного варианта появился на экране другой знак – требуется проведение калибровки.

Калибровка резистивных сенсоров

Как правило, резистивные сенсорные экраны сразу при первом включении требуют откалибровать тачскрин. Что это нужная ежемесячная процедура – практически все забывают после первого включения. Также калибровку нужно проводить при замене экрана, сбое ПО, после падения или удара.

Резистивный сенсор откалибровать довольно просто благодаря «вшитой» утилите под названием ts_calibrate. Для ее запуска в самом меню телефона или планшета нужно зайти в раздел «Настройки». Далее выбрать пункт «Настройки телефона» и здесь нажать на «Калибровка». В результате этих действий экран станет черным и на нем появится крестик с красной точкой, расположенной по центру.

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

Калибровка емкостного сенсора

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

Проведение калибровки требуется начинать с загрузки утилиты TouchScreen Tune. Она легко определяет и настраивает сам тачскрин. Что это даст? Просто в случаях сбоя ПО или замены сенсора невозможно самостоятельно точно выставить сетку, которая бы работала адекватно. Вот благодаря такой программке можно подогнать все под нужные значения.

Дополнительно стоит отметить сбои в работе G-сенсора, который определяет положение смартфона или планшета в пространстве. В некоторых случаях он ведет себя неадекватно и очень сильно усложняет использование гаджета.

Для проведения калибровки акселерометра устройства под ОС Андроид требуется:

  1. Зайти в инженерное меню и одновременно нажать кнопку выключения и снижения уровня громкости.
  2. После появления меню на экране, при помощи той же кнопки громкости, нужно перелистать позиции и найти пункт Test Report.
  3. В открывшемся списке выбрать G-Sensor cali.

После этого просто положите гаджет на ровную поверхность и нажмите на Do Calibration. Нужно подождать, пока на экране перестанут появляться цифровые значения. Затем два раза нажать на кнопку увеличения громкости и выбрать Reboot. Калибровка акселерометра проведена.

Меры предосторожности

Калибровать резистивный тачскрин для планшета и телефона нужно обязательно раз в месяц, так как при активном использовании устройства быстро нарушается вся сетка. Если этого не делать, можно в результате получить неадекватный отклик на нажатие и неудобство в использовании. Но, как правило, с проведением калибровки в этом случае не возникает проблем.

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

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

Что это значит? Это полная потеря функциональности устройства, которую практически невозможно восстановить даже в сервисных центрах. Следовательно, проведение калибровки емкостного сенсора нужно лишь в том случае, когда вы уверены в своих силах и навыках.

Источник: https://www.syl.ru/article/162898/new_tachskrin—chto-eto-takoe-ispolzovanie-i-kalibrovka-tachskrina-dlya-telefona-ili-plansheta

Записки мастера. Выбираем запчасть. Тачскрин и дисплей — android.mobile-review.com

Facebook

Twitter

Вконтакте

Google+

Привет!

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

О том, где взять запчасти, есть отдельный материал.

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

Итак, как же выбрать тачскрин, или дисплейный модуль?

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

Все устройства можно разделить на две основных категории:

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

Соответственно, если у вас первый вариант, то есть возможность купить детали по отдельности.

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

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

Для начала желательно выяснить, применяется ли подобная деталь в каком-нибудь еще устройстве, кроме того, которое есть у вас. Для устройств нижнего ценового сегмента характерна взаимозаменяемость деталей – один и тот же тачскрин может применяться в планшетах целого ряда производителей. Например, вот такой «универсальный солдат»:

Тачскрин для teXet TM-9720

Подходит для планшетов:

  • Ritmix RMD-1055
  • rolsen rtb 9.4 d guru 3g
  • teXet TM — 9720 / TM-9740
  • IconBIT NetTab Space
  • Explay Informer 921
  • Newsmy NewPad S97
  • Digma IDs10
  • Gemei G9
  • Flytouch H08S
  • VOYO Q907
  • HAPAD X2 / X10
  • Ployer MOMO 11
  • Neo 9.7
  • iRU

Почему так происходит? Просто все дело в том, что многие китайские производители не заморачиваются разработкой устройства «с нуля», а собирают свои модели из уже существующих комплектующих. Так, с одной стороны, мы получаем универсальность и простоту подбора, с другой – головную боль с совместимостью.

Поэтому, если не нашлось запчасти на вашу модель, стоит поискать информацию о совместимости с запчастью от других моделей и производителей.

Следующим подводным камнем может стать любовь многих производителей выпускать так называемые ревизии одних и тех же устройств.

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

В качестве примера можно привести наделавший в свое время проблем дисплейный модуль для Meizu M3 Note. Существует две версии модулей, L681H и M681H/M681C.

Обратите внимание, у модулей различаются форма и тип шлейфов, что делает невозможной замену одного другим. И таких сюрпризов может быть масса. Узнать, какой именно у вас модуль, зачастую можно только разобрав устройство и посмотрев маркировку на детали.

Иногда, как в случае с Meizu M3 Note, отличия очевидны, иногда же различие кроется в элементах, используемых при производстве запчастей. И тогда внешне полностью идентичная запчасть не будет работать в устройстве другой ревизии.

Хороший пример – дисплейный модуль от Galaxy S7 Edge для европейской версии устройства, в которой не будет должным образом работать материнская плата от американской версии S7 Edge. Вернее, работать будет всё, кроме сотовой сети. Телефон просто не будет видеть сеть.

Всё дело в нижнем шлейфе, который предназначен для взаимодействия с процессором Exynos и не предназначен для работы с процессором Snapdragon. Поэтому даже при внешней одинаковости необходимо сверять так называемый «партномер» — маркировку, нанесенную на саму деталь.

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

Кроме всего прочего, выбирая запчасть, например, на любимом многими AliExpress, обращайте внимание на маркировку в названии, а точнее, на последнюю букву. Часто этой буквой обозначается цвет. Например, W(white) – белый, B(black) – черный. Таким образом вы убережете себя от недобросовестного продавца, поленившегося либо не захотевшего размещать в описании товара актуальные фотографии.

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

Для уменьшения рисков покупки такого товара в поиске пишите после названия буквы «OEM» либо слово «Original». Многие продавцы на таких ресурсах, как AliExpress, хитрят и используют в описании фразу «brand new». Это часто значит только то, что запчасть новая и фирменная.

Вот только о том, какой именно она «фирмы», продавец умалчивает.

Еще одним признаком качества когда-то были буквы А, ААА, А+ в скобочках после описания. Дело в том, что это общепризнанное обозначение качества и класса запчасти сегодня не является гарантией и может означать как качество, так и то, что просто продавцу самому очень нравится его товар.

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

Все это поможет вам понять, что за запчасть перед вами.

Заключение

Вот, пожалуй, и всё, на что лично я обращаю внимание при покупке запчастей.

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

Поэтому для покупки действительно важной запчасти для дорогого устройства лучше всего использовать магазины запчастей в своем городе. Так у вас будет шанс оценить всё на месте и даже попробовать запчасть в деле, подкинув ее «на соплях».

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

Источник: http://android.mobile-review.com/articles/52487/

STM32F4. Урок 9 – Тачскрин ADS7843

Эта библиотека используется для считывания прикосновения по шине 4-wire с контроллером ADS7843 (Также данная библиотека работает с контроллерами Zilltek UH7843 или XPTEK XPT2046).

Контроллер может управляться через шину SPI, но в данном примере используемые выводы не связанны с шиной SPI процессора. Работа была реализована на GPIO процессора, так как “красивый” способ не являлся самым удобным.

Сам тачскрин работает не очень хорошо, при слабом нажатии дает неточные результаты. Для калибровки есть функция, с последовательным касанием трех точек на экране, после этого тачскрин работает максимально точно (формула для этого была взята из спецификации ATMEL).

Калибровку можно выполнить только один раз, получив калибровочные значения через отладчик и записав их непосредственно в C-File.

Таймер 5 используется для циклического считывания прикосновений (каждые 50 мс) и сохраняет полученные данные в структуру “Touch_Data”. Эта структура может быть легко запрошена в основной программе (В H-файл может быть настроен отдельный таймер для автоматического опроса структуры).

Библиотека имеет 4 функции для опроса событий дисплея:

  • “OnPressed” – true, пока прикосновение не закончится
  • “OnClick” – true, только в момент нажатия на тачскрин
  • “OnRelease” – true, после окончания прикосновения
  • “OnDoubleClick” – true, при двойном клике

Пример работы:

Используемые выводы:

PA15 -> ADS7843_ChipSelect PB1 -> ADS7843_DIN PB4 -> ADS7843_Clk PB5 -> ADS7843_DOUT PB15 -> ADS7843_PEN

PC2 -> ADS7843_BUSY (в данном коде не используется)

Требования:  Подключаемые модули CooCox-IDE: GPIO, TIM, MISC.

 Поддерживаемые библиотеки: STM32_UB_LCD_ST7783.

Функции:

ErrorStatus UB_Touch_Init(void); // Инициализация тачскрина
ErrorStatus UB_Toch_Calibrate(void); // Калибровка тачскрина
bool UB_Touch_OnPressed(void); // Событие “OnPressed” bool UB_Touch_OnClick(void); // Событие “OnClick”
bool UB_Touch_OnRelease(void); // Событие “OnReleased”
bool UB_Touch_OnDoubleClick(void); // Событие “OnDoubleClick”

Пример использования:

//————————————————————–
// File : main.c
// Datum : 15.08.2013
// Version : 1.1
// Autor : UB
// EMail : mc-4u(@)t-online.de
// Web : www.mikrocontroller-4u.de
// CPU : STM32F4
// IDE : CooCox CoIDE 1.7.0
// Module : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der Touch-Library
// Hinweis : Diese zwei Files muessen auf 8MHz stehen
// “cmsis_boot/stm32f4xx.h”
// “cmsis_boot/system_stm32f4xx.c”
//————————————————————– #include “main.h”
#include “stm32_ub_lcd_st7783.h”
#include “stm32_ub_touch_ads7843.h” int main(void)
{ SystemInit(); // Инициализация настроек кварца UB_LCD_Init(); // Инициализация дисплея UB_Touch_Init(); // Инициализация тачскрина // Цвет экрана – синий UB_LCD_FillScreen(RGB_COL_BLACK); while(1) { // Касание тачскрина if(Touch_Data.status==TOUCH_PRESSED) { // Когда происходит прикосновение, // нарисовать пиксель по координатам прикосновения UB_LCD_SetCursor2Draw(Touch_Data.pos.xp,Touch_Data.pos.yp); LCD_RAM=RGB_COL_RED; } }
}

В приложении проект CooCox и отдельная библиотека для использования в других проектах. Автор оригинала статьи просит задавать вопросы на его сайте на немецком или английских языках.

Оригинал статьи

Прикрепленные файлы:

RoughОпубликована: 05.09.20140Вознаградить Я собрал 0 0

x

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография

Источник: http://cxem.gq/mc/mc314.php

Калибровка резистивного тачскрина

Сегодня поговорим о такой коварной штуке, как тачскрин. Конструктивно это две пленки на которых нанесен резистивный состав, в точке нажатия рабочие поверхности соприкасаются и получается некое подобие делителя напряжения по каждой из осей X и Y.

Напряжение, снятое с этих делителей, измеряется либо любым доступным АЦП, либо специализированным контроллером, в котором, помимо двух каналов АЦП, обычно есть дополнительные плюшки.

Например, в контроллере XPT2046 (китайский функциональный аналог ADS7843) есть встроенный термодатчик, внешний канал для измерения напряжения, допустим, батареи, и, что самое главное, сигнал запроса на прерывание при нажатии.

Размер тачскрина всегда больше размера видимой области дисплея на которую он устанавливается, из-за чего координаты полученные в точке соответствующей угловому пикселю экрана, не будут равны нулю.

 Кроме того, разрешение координатной сетки тача пропорционально разрядности АЦП и явно больше разрешения экрана.

Из 12 бит АЦП используется 11 реальных, то есть 2048 отсчетов. В моем случае реальные значения координат лежали в диапазоне от 150-200 до 1800. Еще одна интересная особенность тачскрина, с которым пришлось работать – начало координат расположено в правом верхнем углу, а не в левом как мы привыкли. На рисунке выше я это обозначил.

Ну хорошо, а что тут сложного, спросите вы? Снимаем координаты угловых точек (достаточно даже двух по диагонали), вычисляем рабочий диапазон, считаем коэффициент, на который нужно поделить координаты тачскрина, чтобы получить привязку к пикселям дисплея. Не забываем про отступы от начала координат и о том что координаты по оси X надо пересчитать в обратном порядке, то есть слева направо. Т.е. в результате имеем такой набор формул:

x_coord = 239 – ((x – x_offset)/x_slope),

y_coord = (y – y_offset)/y_slope,

где x_coord и y_coord – полученные координаты в масштабе дисплея (у меня 240*320), x и y – исходные координаты полученные с контроллера, x_offset и y_offset отступы от начала координат, x_slope и y_slope – коэффициенты пропорциональности координатных сеток дисплея и тачскрина. Для калибровки по двум диагональным точкам расчет этих коэффициентов выглядит так:

x_slope = (x_top_left – x_bot_right)/240,

y_slope = (y_top_left – y_bot_right)/320.

Таким образом, для работы нам нужно всего 4 константы, вычисленные на этапе калибровки – два значения отступа по осям, и два коэффициента пересчета.

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

А если нет? Старение или износ резистивного слоя, попадание жидкостей, нарушение технологии производства, да мало ли какие могут быть причины. 

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

Отклик по оси Y пострадал не особо, а вот коэффициент x_slope стал сильно отличатся в верхней и в нижней частях экрана. Кроме того, изменился и отступ координат. С этим нужно было что то делать, погрешность местами достигала 60 пикселей. Некоторое время спустя родилась функция калибровки версии 2.0.

Теперь измерение координат проводится по 4-м точкам в углах и на выходе имеем больший набор констант. К основным добавляются еще 4 коэффициента, которые учитывают изменения отступа по обоим осям относительно начального, и изменения наклона характеристик (x_slope иy_slope).

 Итак: void XPT_Calibrate(void) {

uint32_t  x_top_left, y_top_left, x_bot_right, y_bot_right;

uint32_t  x_top_right, y_top_right, x_bot_left, y_bot_left;
float  x_slope_top, x_slope_bot, y_slope_left, y_slope_right;
uint32_t  x_offset_top, x_offset_bot, y_offset_left, y_offset_right;

        while(x_top_left == 0) // Top left corner
{
LCD_clr();
TFT_DrawString(“Press red circle”, 35, 150, 1, RED);
TFT_FillCircle(9, 9, 8, RED);
while(XPT_isPressed() == 0);
XPT_GetPosition(&x_top_left, &y_top_left);
while (XPT_isPressed()) delay(1);
};

while(x_top_right == 0) // Top right corner
{
LCD_clr();
TFT_DrawString(“Press red circle”, 35, 150, 1, RED);
TFT_FillCircle(230, 9, 8, RED);
while(XPT_isPressed() == 0);
XPT_GetPosition(&x_top_right, &y_top_right);
while (XPT_isPressed()) delay(1);
};

while(x_bot_left == 0) // Bottom left corner
{
LCD_clr();
TFT_DrawString(“Press red circle”, 35, 150, 1, RED);
TFT_FillCircle(9, 310, 8, RED);
while(XPT_isPressed() == 0);
XPT_GetPosition(&x_bot_left, &y_bot_left);
while (XPT_isPressed()) delay(1);
};

while(x_bot_right == 0) // Bottom right corner
{
LCD_clr();
TFT_DrawString(“Press red circle”, 35, 150, 1, RED);
TFT_FillCircle(230, 310, 8, RED);
while(XPT_isPressed() == 0);
XPT_GetPosition(&x_bot_right, &y_bot_right);
while (XPT_isPressed()) delay(1);
};

/*********** TOP ***************/

if(x_top_left > x_top_right)
{
x_slope_top = ((float)x_top_left – (float)x_top_right)/220;
x_offset_top = x_top_right – 10*x_slope_top;
x_offset = x_offset_top;
x_slope = x_slope_top;
};

/*************** LEFT **************/
if(y_top_left > y_bot_left)
{
y_slope_left = ((float)y_top_left – (float)y_bot_left)/300;
y_offset_left = y_bot_left – 10*y_slope_left;
y_offset = y_offset_left;
y_slope = y_slope_left;
};

/************* BOTTOM ***************/

if(x_bot_left > x_bot_right)
{
x_slope_bot = ((float)x_bot_left – (float)x_bot_right)/220;
x_offset_bot = x_bot_right – 10*x_slope_bot;
};

/************** RIGHT ***************/
if(y_top_right > y_bot_right)
{
y_slope_right = ((float)y_top_right – (float)y_bot_right)/300;
y_offset_right = y_bot_right – 10*y_slope_right;
};

/************** COEFFICIENTS ***************/
kxs = ((float)x_slope_top – (float)x_slope_bot)/320;   //Изменение x_slope
kys = ((float)y_slope_left – (float)y_slope_right)/240;  //Изменение y_slope
kxo = ((float)x_offset_top – (float)x_offset_bot)/320;   //Изменение x_offset
kyo = ((float)y_offset_left – (float)y_offset_right)/240;  //Изменение y_offset
       //Далее, вычисленные константы сохраняются во FLASH-память микроконтроллера } Внимательный читатель заметит, что при расчете коэффициентов привязки к разрешению дисплея константы не равны 240 и 320. Для удобства нажатия пальцем или стилусом, я сделал отступ контрольных точек от углов на 10 пикселей, следовательно расстояние между ними уменьшилось на 20 пикселей по каждой из осей. Расчет координат: x_coord = 239 – ( (x – (x_offset – (kxo*((y – y_offset)/y_slope)))) / (x_slope – (kxs*((y – y_offset)/y_slope))) ); y_coord = (y – (y_offset – (kyo*((x – x_offset)/x_slope)))) / (y_slope – (kys*((x – x_offset)/x_slope))); Конечно же, такой способ не сможет исправить сильные нелинейные отклонения, и, возможно, было бы лучше применить алгоритм табличной коррекции, но данная реализация меня полностью устраивает. Сейчас погрешность в худшем случае достигает 5-7 пикселей, что при нажатии пальцем не заметно.

Источник: http://roker1.blogspot.com/2015/12/blog-post.html

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}