Подключение универсального дисплейного модуля TE-ULCD к Arduino

В этой статье описывается схема подключения TE-ULCD к Arduino и его совместное использование с платой расширения Ethernet Shield v2. В процессе изучения модуля получилась библиотека и небольшой скетч получающий из сети Internet и отображающий время в формате UTC, состояние дорожного траффика в Москве, с помощью сервиса Яндекс.пробки, и погоду, с использованием сервиса информеров GisMeteo.

Данный модуль выбран мной как одно из немногих доступных в РФ готовых решений на базе SPI интерфейса, т. е. не требующее много (16-32) пинов для управления.

TE-ULCD выпускается ООО “Терраэлектроника”. Модуль выполнен на основе 3,5” (или 5,6”) цветного графического дисплея с сенсорным экраном и 32-разрядного ARM-7 микроконтроллера. Обслуживание цветного графического дисплея с помощью специализированного микроконтроллера позволяет разделить функции отображения информации и управления и дает возможность обеспечить интерфейс «человек-машина» в различных информационно-управляющих системах. В память программ микроконтроллера на этапе изготовления загружается библиотека графических функций. Функции могут быть вызваны из прикладной программы при помощи SPI-команд. Это значительно упрощает формирование изображения на TFT-дисплее, а также обслуживание сенсорного экрана. Предусмотрена возможность обновления загруженной библиотеки. Для хранения картинок в формате BMP используется карта памяти microSD.

Необходимые компоненты

  1. Любая Arduino, например Arduino Uno.
  2. Плата расширения Ethernet Shield v2 или совместимые с ней.
  3. Монтажная плата (Breadboard) для удобного подключения.
  4. Пара 10-пиновых шлейфов для подключения к модулю TE-ULCD (можно использовать гибкие перемычки типа мама-папа).
  5. Три сопротивления номиналом 1,7 КОм (для делителя напряжения).
  6. Три сопротивления номиналом 3,3 КОм (для делителя напряжения).
  7. Четыре штырьковых соединителя (для подключения TE-ULCD к монтажной плате).
  8. Универсальный дисплейный модуль TE-ULCD35 или TE-ULCD56 (разница только в размерах экрана 320х240 или 640х480).

Подключение

Питание дисплейного модуля осуществляется от 5 вольт постоянного тока, в руководстве пользователя производитель указывает номинальный ток 0,2 А. Я измерил потребляемый ток с помощью цифрового блока питания получилось стабильно 0,299 А, так что стоит ориентироваться на 0,3 А. При питании TE-ULCD от ардуино, преобразователь напряжения установленный на плате грелся довольно сильно, поэтому на всякий случай я запитал дисплейный модуль от USB персонального компьютера взяв шнурок от старой мышки. Разъем Х8 TE-ULCD предназначен для подачи питания и имеет следующую распиновку: PIN 1, 3, 7 и 9 - вход 5 В, PIN 2, 4, 6, 8, 10 - GND, PIN5 используется как ключ для контроля правильности подключения. Подавать питание можно на один любой пин +5 В и GND. Подключение ардуино выполняется к разъему Х6 дисплейного модуля, согласно схеме представленной на рисунке. SPI TE-ULCD функционирует с уровнем 3,3 В, поэтому следует согласовать уровни дисплейного модуля и ардуино с помощью простого делителя на резисторах. Так как планируется использовать TE-ULCD и плату расширения Ethernet Shield совместно, для выбора управляемых (ведомых) устройств будут использоваться PIN9 и PIN10 соответственно. PIN9 выбран изходя из удобства подключения и можно использовать любой другой свободный поменяв значение slaveSelectPin в скетче.

Команды записи и чтения TE-ULCD соответствуют настройкам SPI CPOL=1 и CPHA=1, что соответствует SPI_MODE3 для ардуино. Для платы расширения Ethernet Shield v2 настройки SPI соответствуют SPI_MODE0. Эти настройки понадобятся для обращения к соответствующему модулю.

Описание программы

Программа описанная в статье использует специально подготовленную для ардуино библиотеку ULCD. Картинки для TE-ULCD следует записать на microSD.

Описание команд, регистров и сообщений графического модуля TE-ULCD использованные в библиотеке ULCD взяты мной из руководства оператора на модули TE-ULCD35/56. Модуль TE-ULCD поддерживает два режима работы: терминальный и режим работы с использованием библиотеки графических функций (представлен в данном примере).

В настоящее время набор встроенных виджетов (примитивов графического интерфейса пользователя) TE-ULCD включает в себя:

  • Frame (0х01). Является обязательным, используется для размещения виджетов.
  • Window (0х00). Предназначено для размещения виджетов, обладает заданным набором свойств.
  • Panel (0х06). Предназначена для размещения виджетов, обладает заданным набором свойств.
  • StaticLine (0х12). Представляет собой линию с тенью, может быть использован для отделения одних компонентов от других.
  • Button (0х0А). Позволяет разместить кнопку и выполнить какие-либо действия при нажатии на нее.
  • Text (0х07). Служит для отображения текста на экране.
  • Bitmap (0х05). Предназначен для вывода на экран изображения в формате bmp.
  • RotateControl (0х0В). Предназначен для вывода на экран изображения регулятора в виде вращающегося "колесика".
  • Slider (0х0С). Предназначен для вывода на экран изображения регулятора в виде "ползунка".

Использование библиотеки ULCD

В библиотеке ULCD для ардуино реализованы следующие процедуры для работы с универсальным дисплейным модулем TE-ULCD:

  • ULCD() - конструктор;
  • void RESET() - программный сброс модуля;
  • void digitalPortWrite(byte value) - отправка одного байта от ардуино к TE-ULCD;
  • void LOAD_FONT(byte R, String FileName) - загрузка шрифта из флеш-памяти TE-ULCD в регистр TE-ULCD;
  • void LOAD_PICTURE(byte R, String FileName) - загрузка картинки в формате BMP с microSD карты в регистр TE-ULCD;
  • void LOAD_TEXT(byte R, String Text) - загрузка текстовой строки из ардуино в регистр TE-ULCD;
  • void LOAD_SCRIPT(byte R, byte Number) - загрузка скрипта из ардуино в регистр TE-ULCD;
  • void SET_SIZE(int X, byte Y) - установка размера виджета;
  • void SET_POS(int X, byte Y) - установка позиции (левого нижнего угла) виджета;
  • void SET_BACK_COLOR(byte R, byte G, byte B) - установка цвета фона виджета;
  • void SET_FONT_COLOR(byte R, byte G, byte B) - установка цвета шрифта виджета;
  • void SET_FONT(byte R) - установка шрифта виджета из регистра TE-ULCD;
  • void SET_MAIN(byte R) - установка виджета главным (применяется только для фрейма);
  • void SET_SCALE(byte min, byte max, byte pos) - задание минимального, максимального и значения по умолчанию виджета (для слайдера и "колесика");
  • void SET_SCRIPT(byte R) - установка скрипта для виджета (действия которое будет выполнено TE-ULCD при заданном событии) из регистра TE-ULCD;
  • void SET_TEXT(byte R) - установка строки для виджета из регистра TE-ULCD;
  • void SET_PICTURE(byte R) - установка картинки в формате BMP для виджета из регистра TE-ULCD;
  • void SEND_REG(byte R1, byte R2) - переслать содержимое регистра R2 в R1;
  • void WRITE_REG(byte R, byte value) - запись значения в указанный регистр TE-ULCD;
  • void CR_WID(byte WidType) - создание виджета указанного типа (из списка встроенных виджетов TE-ULCD);
  • byte READ(byte R) - чтение содержимого регистра TE-ULCD;
  • void REPAINT_TEXT(byte R1, byte R2, String Text) - заменить (перерисовать) текст виджета хранящегося в регистре R1, на текст передаваемый в переменной Text, сохранить текст в регистре R2;
  • void REPAINT_BMP(byte R1, byte R2) - перерисовать картинку виджета хранимого в регистре R1 на картинку хранимую в регистре R2;

Например фоновый рисунок в программе устанавливается следующим образом:

#include <ULCD.h>
 
ULCD lcd;
 
// ...
lcd.LOAD_PICTURE(1, "back.bmp");  //Загружаем картинку с microSD в регистр R1
lcd.CR_WID(5);                    //Создаем виджет BitMap (для фона)
lcd.SET_SIZE(320, 240);           //Устанавливаем размер BitMap равным размеру экрана TE-ULCD35
lcd.SET_POS(0, 0);                //Устанавливаем позицию BitMap
lcd.SET_PICTURE(1);               //устанавливаем картинку для виджета из регистра R1       

Для удобства пользователя TE-ULCD располагает 32-мя регистрами (R0-R31) общего назначения для хранения указателей на виджеты (картинки, текст, скрипты). При желании указатели можно хранить в ардуино.

Получение состояния дорожного траффика

Сделать свой светофор захотелось сразу после того как увидел подобный в Яндексе, только там он управлялся с ПК, а хочется все таки автономный - только ардуино и Ethernet Shield. Напрямую запрос о состоянии трафика с сервера Яндекс.пробки получить нельзя. Письмо в техподдержку команду Я.пробки тоже не помогло: “Благодарим за внимание к нашему сервису. Мы не поставляем такую информацию. Попробуйте, подключить модуль пробок и использовать элемент управления "Пробки".”

Для получения состояния дорожного трафика я воспользовался информером, точнее картинкой которая передается в нем. Алгоритм действий следующий:

  1. Подключаемся к серверу (info.maps.yandex.net);
  2. Посылаем запрос на получение картинки информера:
  3. Анализируем полученную картинку, она передается в стандарте PNG (0xFF 0xA4 0x00 желтый, 0x3F 0xBB 0x00 зеленый, 0xFF 0x2A 0x00 красный ), наличие цветов уникально для каждого состояния зеленый-желтый-красный (даже более того, считая количество пикселей каждого цвета можно определить балл пробок, а не только цвет);
  4. Отображаем картинку на экране TE-ULCD.

Запрос картинки информера имеет следующий вид:

 GET http://info.maps.yandex.net/traffic/moscow/current_traffic_88.gif HTTP/1.1
 Accept: image/gif
 Accept-Language: en-US;
 Cache-Control: max-age=0
 Host: info.maps.yandex.net
 User-Agent: Chrome

Данный запрос подходит для Москвы, но можно запрашивать состояние траффика в любом городе для которого работает сервис информеров Я.пробки. Данный блок с небольшой доработкой можно использовать для управления собственным светофором с помощью ардуино и реле, будет как в Яндексе :).

Получение времени

Самый простой и легкий способ получения времени в формате UTC - послать запрос на какой либо сервер (сначала я использовал гугл, но потом для экономии памяти перешел на сервер яндекс.пробки) и разобрать ответ, получаемая таким образом строка имеет вид:

Wed, 10 Aug 2011 09:48:43 GMT.

В настоящий момент запрос для получения времени выглядит так:

 GET http://info.maps.yandex.net/traffic/moscow HTTP/1.1

Точность такого времени не высока - до минут, но для простых часов подходит.

Получение прогноза погоды

Для получения прогноза погоды на ближайшие сутки я использовал сервис получения информера от GisMeteo в XML формате. Данные о погоде представляют из себя подробную сводку по всем метеопараметрам, с шагом 6 часов и заблаговременностью одни сутки. Тут все просто, указываем в запросе город и получаем в ответ для него прогноз погоды, разбираем его и отображаем на экране прогноз на ближайшие 6 часов.

Пример запроса погоды для города Москвы:

 GET http://informer.gismeteo.ru/xml/27612_1.xml

Дальнейшее усовершенствование

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

Возможные дальнейшие шаги:

  1. Добавить отображение балла Яндекс.пробок.
  2. Заменить ардуино и Ethernet Shield на Arduino Ethernet PoE, тогда останется только шнур Ethernet.
  3. Добавить оповещение о новых письмах и твитах.
  4. Попробовать вариант с Wi-Fi модулем, тогда останется только шнур питания.
  5. Подключить внешние датчики и отображать их состояние (температура и влажность, давление, освещенность).
  6. Отображать RSS и курсы валют.
  7. Будильник (можно настраиваемый через интернет), потребуется добавить баззер или пьезо-пищалку.

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

int freeRam () {
   extern int __heap_start, *__brkval; 
   int v; 
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Если кто то подскажет как можно улучшить программу буду благодарен :), для обсуждений есть ветка форума на Амперке.