Работа с Touch TFT дисплеем в FEZ Panda II

В данной статье я хочу рассказать о том, насколько легко работать в среде .NET Micro Framework с LCD Touch панелями.
Фирмой GHI Electronics выпускается дисплей FEZ Touch: GHI-FTOUCH-262
Внешний вид самого дисплея:
FEZ Touch LCD
Дисплей обеспечивает разрешение 240x320 QVGA при 16 битном цвете. Он сенсорный и содержит Touch контроллер.
Также как и плата FEZ Panda II он выпускается фирмой GHI Electronics и вся прелесть в том, что подключение максимально простое: FEZ Touch просто «втыкается» в 40-пиновый разъем платы Panda 2 и на этом все!

В репозитарии TinyCLR под данный дисплей имеется много различного ПО включая генераторы шрифтов и прочее.

В своем проекте я использовал библиотеку FEZ TOUCH UI CONTROLS
Библиотека позволяет выводить на дисплей различные элементы форм. Вкратце опишу некоторые из форм:
Label — выводит на дисплей обычное текстовое поле
MomentaryButton — кнопка
StateButton — кнопка фиксирующаяся после нажатия
Slider — горизонтальная или вертикальная полоса прокрутки
RadioButton — кнопка выбора (единичный выбор)
CheckBox — кнопка выбора (множественный выбор)
ListBox — группировка чекбоксов
TextArea — текстовое поле
LED — индикатор On/Off

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

В данной статье я хочу показать пример взаимодействия Touch-дисплея и RGB-светодиода. При помощи сенсорного ввода мы будем управлять яркостью свечения трех цветов RGB LED: красным, зеленым и синим.

Подключение

Как я писал выше, подключения Touch-дисплея очень простое: просто вставляем экранчик в 40-pin разъем FEZ Panda II. Полноцветный RGB-светодиод я использовал с общим катодом.
Фото подключения
Общий катод подключается к GND
Зеленый pin светодиода подключается к Di8
Синий pin светодиода подключается к Di9
Красный pin светодиода подключается к Di10
Управлять яркостью цветами RGB-светодиода будем при помощи ШИМ.

Программное обеспечения

Как я уже сказал выше, для работы с дисплеем я использовал одну из библиотек: FEZ TOUCH UI CONTROLS.
После создания стандартного приложения под FEZ Panda II, необходимо подключить два класса:

using GHIElectronics.NETMF.Hardware;
using FEZTouch.UIControls;

Также, нам понадобится 2 файла: FEZ_Components_FEZTouch.cs и fez-touch-ui-controls.cs
Их необходимо скопировать в папку проекта, а также подключить. Для этого, в обозревателе решений правой клавишей мышки щелкаем по названию вашего проекта и выбираем «Добавить->Существующий элемент… Shift+Alt+A»
В ссылках не забудьте добавить библиотеку GHIElectronics.NETMF.Hardware
Обозреватель решений Visual Studio Express

Полный код программы:

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
using FEZTouch.UIControls;

namespace LCD_Control_LED
{
    public class Program
    {
        public static FEZ_Components.FEZTouch ft;       // FEZTouch
        public static Slider horiz_slider_Red;          // Горизонтальный слайдер
        public static Slider horiz_slider_Green;
        public static Slider horiz_slider_Blue;
        public static Label lbl_Red;                    // Текст
        public static Label lbl_Green;
        public static Label lbl_Blue;
        public static Random rnd = new Random(100);

        public static PWM Green = new PWM((PWM.Pin)FEZ_Pin.PWM.Di8);        // ШИМ
        public static PWM Blue = new PWM((PWM.Pin)FEZ_Pin.PWM.Di9);
        public static PWM Red = new PWM((PWM.Pin)FEZ_Pin.PWM.Di10);

        public static void Main()
        {
            FEZ_Components.FEZTouch.LCDConfiguration lcd_config = new FEZ_Components.FEZTouch.LCDConfiguration(
                FEZ_Pin.Digital.Di28,
                FEZ_Pin.Digital.Di20,
                FEZ_Pin.Digital.Di22,
                FEZ_Pin.Digital.Di23,
                new FEZ_Pin.Digital[8] { FEZ_Pin.Digital.Di51, FEZ_Pin.Digital.Di50, FEZ_Pin.Digital.Di49, FEZ_Pin.Digital.Di48, FEZ_Pin.Digital.Di47, FEZ_Pin.Digital.Di46, FEZ_Pin.Digital.Di45, FEZ_Pin.Digital.Di44 },
                FEZ_Pin.Digital.Di24,
                FEZ_Pin.Digital.Di26
                );

            FEZ_Components.FEZTouch.TouchConfiguration touch_config = new FEZ_Components.FEZTouch.TouchConfiguration(
                SPI.SPI_module.SPI2, FEZ_Pin.Digital.Di25, FEZ_Pin.Digital.Di34
            );

            ft = new FEZ_Components.FEZTouch(lcd_config, touch_config);
            ft.FillRectangle(0, 0, 240, 320, FEZ_Components.FEZTouch.Color.Black);  // Clear screen with black BG

            //////////  Red  //////////
            
            Label lbl_Red_txt = new Label(30, 15, ft, 30, 10, "Red:");      // Надпись

            lbl_Red = new Label(60, 15, ft, 30, 10, "0");                   // Значение ШИМ (0-100)

            horiz_slider_Red = new Slider(20, 35, ft, 150, 0, 100, Slider.eOrientation.Horizontal);         // Отображаем горизонтальный слайдер
            horiz_slider_Red.ValueChanged += new Slider.ValueChangedDelegate(slider_Red_ValueChanged);      // Событие, которое вызывается при изменении ползунка
            horiz_slider_Red.HandleColor = FEZ_Components.FEZTouch.Color.Red;       // Цвет ползунка слайдера
            horiz_slider_Red.Refresh();         // Обновляем, чтобы отобразить цвет слайдера

            //////////  Green  //////////
            Label lbl_Green_txt = new Label(30, 70, ft, 30, 10, "Green:");

            lbl_Green = new Label(78, 70, ft, 30, 10, "0");

            horiz_slider_Green = new Slider(20, 90, ft, 150, 0, 100, Slider.eOrientation.Horizontal);
            horiz_slider_Green.ValueChanged += new Slider.ValueChangedDelegate(slider_Green_ValueChanged);
            horiz_slider_Green.HandleColor = FEZ_Components.FEZTouch.Color.Green;
            horiz_slider_Green.Refresh();

            //////////  Blue  //////////
            Label lbl_Blue_txt = new Label(30, 125, ft, 30, 10, "Blue:");

            lbl_Blue = new Label(70, 125, ft, 30, 10, "0");

            horiz_slider_Blue = new Slider(20, 145, ft, 150, 0, 100, Slider.eOrientation.Horizontal);
            horiz_slider_Blue.ValueChanged += new Slider.ValueChangedDelegate(slider_Blue_ValueChanged);
            horiz_slider_Blue.HandleColor = FEZ_Components.FEZTouch.Color.Blue;
            horiz_slider_Blue.Refresh();

            //////////  Кнопки  //////////
            MomentaryButton all_Off = new MomentaryButton(20, 200, ft, 80, 15, "All Off");      // Добавляем кнопку Off
            all_Off.Pressed += new MomentaryButton.ButtonPressedDelegate(all_Off_Pressed);      // Событие, при нажатии на кнопку

            MomentaryButton all_On = new MomentaryButton(120, 200, ft, 80, 15, "All On");
            all_On.Pressed += new MomentaryButton.ButtonPressedDelegate(all_On_Pressed);

            MomentaryButton btn_Rand = new MomentaryButton(73, 230, ft, 80, 15, "Random");
            btn_Rand.Pressed += new MomentaryButton.ButtonPressedDelegate(btn_Rand_Pressed);

            //////////  DEMO-надпись  //////////
            Label lbl_elabs_txt = new Label(45, 300, ft, 30, 10, "electronics-lab.ru");         // Выводим надпись
            lbl_elabs_txt.TextColor = FEZ_Components.FEZTouch.Color.Magneta;                    // Задаем цвет надписи
            lbl_elabs_txt.Refresh();
        }

        static void slider_Red_ValueChanged(int val)
        {
            lbl_Red.Text = val.ToString();  // Обновляем значение ШИМ на экранчике
            Red.Set(5000, (byte)val);       // Обновляем значение ШИМ на Output пине
        }
        static void slider_Green_ValueChanged(int val)
        {
            lbl_Green.Text = val.ToString();
            Green.Set(5000, (byte)val);
        }
        static void slider_Blue_ValueChanged(int val)
        {
            lbl_Blue.Text = val.ToString();
            Blue.Set(5000, (byte)val);
        }
        static void all_Off_Pressed()
        {
            horiz_slider_Red.Value = 0;     // Устанавливаем все значения в минимум
            horiz_slider_Green.Value = 0;
            horiz_slider_Blue.Value = 0;
        }
        static void all_On_Pressed()
        {
            horiz_slider_Red.Value = 100;   // Устанавливаем все значения в максимум
            horiz_slider_Green.Value = 100;
            horiz_slider_Blue.Value = 100;
        }
        static void btn_Rand_Pressed()
        {
            horiz_slider_Red.Value = rnd.Next(100);     // Устанавливаем случайные значения 0-100
            horiz_slider_Green.Value = rnd.Next(100);
            horiz_slider_Blue.Value = rnd.Next(100);
        }
    }
}

Итак, в начале программы мы задаем конфигурацию дисплея (указываем подключенные пины) и инициализируем дисплей.
Затем, командой FillRectangle мы делаем заливку экрана черным цветом.

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

Также добавим три кнопки On, Off и Random и надпись сайта. В результате получится вот что:
Элементы управления на LCD Touch экранчике

Разберем некоторые элементы управления более подробно.
Класс Label:
public Label(
	int x,    // Координата X на LCD
	int y,    // Координата Y на LCD
	FEZTouch ft,    // Объект FEZTouch
	int w,    // Ширина метки
	int h,    // Высота метки
	string txt    // Отображаемый текст
)


Класс Slider:
public Slider(
	int x,    // Координата X на LCD
	int y,    // Координата Y на LCD
	FEZTouch ft,    // Объект FEZTouch
	int sz,    // Размер слайдера
	int min,   // Минимальное значение
	int max,   // Максимальное значение
	Slider.eOrientation orient    // Горизонтальное (Horizontal) или вертикальное (Vertical) отображение слайдера
)

В строке
horiz_slider_Blue.ValueChanged += new Slider.ValueChangedDelegate(slider_Blue_ValueChanged);
мы задаем функцию, которая будем выполняться при изменении значения на экранчике. В данном случае, при каждом изменении слайдера будет вызываться функция slider_Blue_ValueChanged():

static void slider_Blue_ValueChanged(int val)
{
    lbl_Blue.Text = val.ToString();
    Blue.Set(5000, (byte)val);
}

Здесь мы обновляем содержимое метки и выводим значение слайдера на вывод ШИМ с частотой 5 кГц.

Класс MomentaryButton:
public MomentaryButton(
	int x,    // Координата X на LCD
	int y,    // Координата Y на LCD
	FEZTouch ft,    // Объект FEZTouch
	int width,    // Ширина кнопки
	int height,    // Высота кнопки
	Color pc,      // Цвет кнопки, когда она нажата
	Color rc,      // Цвет кнопки, когда она отпущена
	string txt     // Текст кнопки
)

Также, как и для слайдера при нажатии кнопки задаем функцию:
all_On.Pressed += new MomentaryButton.ButtonPressedDelegate(all_On_Pressed);
В данном случае, при нажатии кнопки «All On» будет вызываться функция all_On_Pressed()

Вроде бы все, а на последок небольшое видео работы:


Как видно из видео, видна большая инерционность дисплея и заторможенность. Процессор в FEZ Panda II хоть и работает на частоте 72 МГц, но он уже не тянет такой вот дисплей. Для более серьезных задач нужен контроллер с аппаратным ускорением, либо более мощный процессор.

Скачать файл проекта и библиотеки

1 комментарий

avatar
То что GUI уже есть — несомненный плюс. Тормоза не из-за слабого процессора или отсутствия аппаратного ускорения, а из-за отсутствия оптимизации драйверов и типа подключения дисплея. GUI uс OS II на дешёвых китайских платках за 33$ (вместе с 3,2 дюймовым дисплеем) на STM32F1x (72 МГц) летает…
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.