- Лоботрясы

Поиск
Перейти к контенту

Главное меню:

Статьи по AVR

Читать в Яндекс.Подписках



   Формирование стрелки на дисплее
Просмотров: 1716

    Многие из вас ещё помнят старые добрые магнитофоны ''Весна-212 С-4'' и подобные, в которых применялись стрелочные индикаторы уровня записи. Мне всегда в далёком деццтве доставляло удовольствие наблюдать, как стрелка двигается в такт музыке. Всё это давно стало архаизмом, но всё равно стрелочные приборы мозолят нам глаза каждый день – начиная от механических или кварцевых часов производства китайских товарищей и заканчивая приборной панелью вашего автомобиля.
    А что, если придать электронной разработке некий «механический» привкус, контролируя какие-нибудь параметры на TFT/OLED дисплее с помощью «электронной» стрелки?! 
    Реализация этой возможности не так уж и сложна, как кажется, надо всего лишь вспомнить школьный курс тригонометрии…Итак, начнём-с!
На рисунке ниже представлен экран графического LCD-дисплея, у которого, например, начальная позиция осей x и y находится в левом нижнем углу.

    Оси x и y  дисплея можно рассматривать как прямоугольную систему координат.
    Предположим, нам необходимо, чтобы стрелка указывала некое значение в диапазоне о 0 до 255 (FF) в секторе от 0º до 180º. Исходными данными для вывода стрелки у нас будут координаты начала стрелки x1 и y1, длина стрелки len (в пикселях) и некоторое значение value, которое и должна символизировать стрелка, приняв соответствующее положение.
    Угол a наклона стрелки к оси можно определить с помощью обычной пропорции:
a=(180/FF)· value
    Теперь определим проекции стрелки на оси x и y ( катеты   прямоугольного треугольника ).
shift_x=len·cosa
shift_y=len·sina

    И найдём координаты конца стрелки:
x2=x1- shift_x
y2=y1+ shift_y

    Теперь, используя функцию построения линии, которая приводится практически в каждой библиотеке на TFT или OLED-дисплей, и задаваясь координатами начала (x1 и y1) и конца (x2 и y2) стрелки, рисуем её на экране.
    Achtung! Пример кода, который здесь приводится, рассчитан на работу с дисплеем LPH9135 (телефоны Siemens), библиотеку для работы с которым вы можете найти тут, однако по образу и подобию код легко портировать под любой другой дисплей.


#include <math.h> //Подключаем стандартную библиотеку математических функций CVAVR



//**********************************************************
//        Функция рисования стрелки на дисплее
//**********************************************************
// value - число от 0 до 255
void cursor (unsigned char x1, unsigned char y1, unsigned char value, unsigned char len, unsigned char width, unsigned int t_color, unsigned int b_color)
{
unsigned char x2, y2, shift_x, shift_y;
unsigned int a;
// Угол
static unsigned char last_x2, last_y2;
static bit flag=0; //Флаг, разрешающий после первого вывода стрелки стирать её предыдущее положение

//Задаём начало отсчёта осей Х и У дисплея - левый нижний угол
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x80);

a = (180.0/255.0)*value;
//Определяем угол, соответствующий значению value
//Смещение по оси х и y относительно начала стрелки, т.е. определяем проекцию стрелки на ось х и y

shift_x = len * cos(a * 3.14 / 180.0);
//Предварительно переводим угол a из градусов в радианы (стандартная функция cos и sin  в CVAVR в качестве параметра принимает значение в радианах)
shift_y = len * sin(a * 3.14 / 180.0);
//Определяем координату конца стрелки
x2=x1-shift_x;
y2=y1+shift_y;

if(flag) LCD_FillLine (x1, y1, last_x2, last_y2, width, b_color); //Окрашиваем предыдущее положение линии (стрелки) под цвет фона
LCD_FillLine (x1, y1, x2, y2, width, t_color); //Рисуем новую линию (стрелку) от начала до конца стрелки  
last_x2=x2; last_y2=y2; //Запоминаем новое положение конца стрелки
flag=1;

//Начало отсчёта осей Х и У дисплея - левый верхний угол дисплея (большинство функций библиотеки LPH9135 рассчитаны на такую адресацию осей)
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
}

    Небольшое пояснения к коду.
void LCD_FillLine (char tx1, char ty1, char tx2, char ty2, char width, int color); - функция вывода линии шириной width из библиотеки для дисплея LPH9135 (её несложно переработать под библиотеку любого другого дисплея).

    А как же теперь нарисовать саму шкалу значений? Тоже несложно!
    Для этого я создал небольшую функцию, инициализирующую шкалу:

//**********************************************************
//          Функция инициализации шкалы
//**********************************************************
// mark - количество делений на шкале, mark_len и width - соответственно, длина и ширина риски, len - расстояние до начала риски

void scale_init (unsigned char x1, unsigned char y1, unsigned char mark, unsigned char mark_len, unsigned char len, unsigned char width, unsigned int color)
{
unsigned char x2, y2, x3, y3, shift_x, shift_y, count;
float a, angle;
//Задаём начало отсчёта осей Х и У дисплея - левый нижний угол
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x80);

a=180.0/(mark-1.0);
//Рассчитываем угол между двумя соседними рисками шкалы

for (angle=0, count=0; count<mark; count++, angle+=a)
{
  //Смещение по оси х и y относительно начала стрелки, т.е. определяем проекцию стрелки на ось х и y
 shift_x = len * cos(angle * 3.14 / 180.0);
 shift_y = len * sin(angle * 3.14 / 180.0);
 
//Определяем координату конца стрелки
  x2=x1-shift_x;
  y2=y1+shift_y;   

  //Смещение по оси х и y относительно начала стрелки, т.е. определяем проекцию стрелки на ось х и y
  shift_x = (mark_len+len) * cos(angle * 3.14 / 180.0);
  shift_y = (mark_len+len) * sin(angle * 3.14 / 180.0);
  //Определяем координату конца стрелки
  x3=x1-shift_x;
  y3=y1+shift_y;

  LCD_FillLine (x2, y2, x3, y3, width, color);
//Рисуем линию от начала до конца стрелки
}

//Начало отсчёта осей Х и У дисплея - левый верхний угол дисплея (большинство функций библиотеки LPH9135 рассчитаны на такую адресацию осей)
Send_to_lcd(CMD, 0x36);
Send_to_lcd(DAT, 0x00);
}

    Данные примеры, конечно, не оптимизированы, однако вполне работоспособны ;-)

    Для чего я рассмотрел всю эту хрень? Да просто вынашиваю планы сделать красивые псевдоаналоговые часы на цветном ЖКИ-индикаторе, и попеременно рассматриваю разные реализации кода.

Опубликовано 27.09.2014

©
Igoryosha, 2014

 
 
Назад к содержимому | Назад к главному меню