ARDUINO на практике часть 3 меню пользователя

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

ARDUINO на практике часть 3 меню пользователя

Вспомним, что SHIELD-LCD16х2 представляет собой плату расширения касательно присущих Arduino функциональных возможностей. Конструкция состоит из модуля ЖК-дисплея (две строки, по 16 знаков), четыре кнопки и восемь линий GPIO. Сама плата оснащена микроконтроллером PIC обменивающимся информацией с Arduino UNO посредством интерфейса TWI. Применение на практике функций, предлагаемых библиотекой, значительно упрощают рабочий процесс с модулем, как профессионалу в данном направлении, так и новичку.

Arduino основы функционирования примерного меню на практике

Данное решение выделяется среди иных предложений наличием ряда особенных функций, приспосабливающиеся под личные нужды, как и Arduino. В рассматриваемом примере будет применяться SHIELD-LCD16х2, где, поменяв некоторые определения, можно настроить функции меню для применения с символьным дисплеем разного разрешения (4 строки, где в каждой 20 знаков, 1 строка с 16 знаками и далее). В процессе выполнения программы меню, необходимо воспользоваться расширенными составляющими языка С. Но для начала разберёмся, как функционирует меню.

Пример: меню из 4 строк, отображение происходит посредством двухстрочного дисплея, по 16 знаков в каждой.

Управляется 4-я кнопками, где:

  • нумерация кнопок осуществляется с левой стороны;
  • первая кнопка (№1): используется для перемещения маркера строки меню вниз;
  • кнопка «2»: применяется для перемещения маркера вверх;
  • кнопка «3»: позволяет оказаться от выбора. Она не применяется, если это не многоуровневое меню. Иными словами, применяется приложением произвольным образом;
  • кнопка (№4): подтверждает сделанный выбор. Это по сути кнопка, как на компьютере «Enter».

Экран ЖК-модуля — 2 строки по 16 знаков. Учитывая то, что меню нашего примера имеет 4 строки, оно всё не будет показано на экране. Учитывая это, стоит разделить его на фрагменты, по две строки в каждом. После включения или перезагрузки микроконтроллера на экране отображаются строки меню (1 и 2), но маркер будет установлен на первой строке.

Для перемещения маркера на вторую строку нажмите кнопку «вниз». При повторном нажатии данной кнопки, маркер всё так же будет числиться на 2 строке, но при этом будет отображаться меню строк 2 и 3. Нажимая «вниз» ещё раз, на экране отобразится строки меню 3 и 4, маркер будет числиться на 2 строке, указывая на меню четвёртого пункта. Вернуться в первоначальное меню можно нажав «вниз» ещё раз.

Принцип работы кнопки «вверх» такой же, но перемещение маркера происходит в иную сторону. Нажимая «вверх» при запуске рабочего процесса программы, маркер оказывается на второй строке экрана, а отображаются при этом строки меню 3 и 4. Дополнительное нажатие кнопки переместит маркер на 1 строку, а отображаться будет информация со строк меню 3 и 4. Ещё нажатие позволит отобразить строки 2 и 3, а сам маркер всё так же останется на строке номер один.

В одной строке могут быть последовательно отображены 16 знаков, где 2 - это символы маркера («>» и «<»), из-за этого, в итоге, надпись меню состоит из 14 знаков. По идее количество пунктов может быть произвольным, но на практике это значение ограничивается размером памяти программы и емкостью переменных.

При нажатии на кнопку 4 функция User_Menu вернёт номер выбранного пункта или ноль при некорректном выборе или его отсутствии.

Основные элементы меню Arduino

Определить параметры дисплея, присущее ему количество пунктов и суть сообщений, возможно при помощи имеющихся переменных и определений. Изначально указываются пункты меню (их количество). Согласно примеру, меню состоит из 4 строк, значит, menuoptions равно 4.

#define menuoptions 4

Далее разбираемся со свойством языка С, который является основой для компилятора Arduino. Язык С характеризуется тем, что последовательность символов обязательно будет окончена нулевым байтом. Именно в такой способ происходит оповещение компилятора о том, что последовательность закончена в данном месте.

При написании информации с 14 символами оно будет определено как char-сообщение. Знак «0» может быть добавлен в конце некоторыми компиляторами, что будет свидетельствовать о завершении последовательности. Другие компиляторы могут этого не делать, а рассматривать определение не как надпись, а как строку чисел.

Arduino не добавляет ноль, из-за этого в процессе резервирования места для string такой длины возникает необходимость в написании собственной функции, которая сможет отобразить конкретную величину знаков, без проверки на окончание последовательности на «0» или же продумать ситуацию с одним символом больше, чем нужно для сообщения.

Учитывая вышеуказанное, menuitemlen должно быть равно максимально допустимому количеству знаков на экране минус 1, но не 2, как изначально кажется, ведь 2 знака заняты ">" и "<". #define menuitemlen 15

Следующее определение lcd_lines тривиальное. Задача заключается в необходимости определения строк дисплея, для отображения меню. На рассматриваемом примере это будет так: #define lcd_lines 2

На следующем этапе определяется элемент меню, содержащий параметры отдельной строки меню:

  • menu_message: описываются сроки меню (до 14 знаков);
  • whereisptr: константа, показывающая значение смещения указателя на массив, для отображения информации двух строк. Можно заметить, что первые две строки уменьшаются на дисплее, поэтому константа равна «0», но потом увеличивается на «1» для последующей строки;
  • у0: предоставляет сведения о месте нахождения маркера.

Более детально ознакомиться со структурами можно посредством специальной литературы по языку С. В данном случае больше внимания уделим практическому использованию структуры. Так же можно столкнуться с тем, что структуру могут называть ещё записью или кортежем.

Процесс создания массива menu_lines в пространстве констант программы (const) основан на применении определённого типа данных. Такой массив содержит полное определение меню и его неотъемлемой частью являются menuoptions элементы, где каждый — это структура, связывающая поля определения отдельной строки меню.

Для данного примера характерны значительные общие сообщения для строк меню. Иными словами, 1 строка содержит часть сообщения "First menu line", 2 — "Second menu line", 3 — "Third menu line", а 4 — "Fourth menu line".

const menuitem menu_lines[menuoptions]=

{{"First menu lin", 0, 1},

{"Second menu li", 0, lcd_lines},

{"Third menu lin", 1, lcd_lines},

{"Fourth menu li", 2, lcd_lines}};

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

menuitem*menu_lines_ptr;

signed char menu_position;

char user_choice;

int pressed;

Одним очень полезным типом переменных является указатель, значительно упрощающий процесс программирования. Если на рассматриваемом нами примере указатель находится на 1 элементе массива, то при добавлении «1» без необходимости какого-либо подсчёта байтов и определения размера элементов он укажет на позицию под №2.

Практическое применение меню Arduino

Определив элементы меню, они вызываются в нашей программе. Для начала функции void setup() присваивается начальное значение переменной, определяющее текущую позицию в меню (menu_position = 0;). Отображаем меню при помощи вызова функции Display_Menu(). Считывание номера нажатой кнопки в функции void loop() осуществляется вызовом: pressed = Number_of_Button();

При нажатии любой кнопки, кроме «0», предоставляется возможность вызова функции User_Menu(pressed); где параметр номер кнопки, содержащей адекватную реакцию. Кнопка «1» перемещает маркер вниз, «2» — вверх, а при помощи «4» можно выбрать нужный пункт меню.

Выбранный пункт возвращается функцией, что позволяет его обработать, например, при помощи switch… case или if. Для нашего примера для организации процесса иллюстрации работы меню необходимо вызвать функции, способные изменить яркость подсветки фона дисплея, или любые иные на усмотрение программиста.

void loop()

{

pressed = Number_of_Button();

if (pressed > 0) user_choice = User_Menu(pressed);

switch (user_choice)

{

case 1:

//действие 1

break;

case 2:

//действие 2

break;

case 3:

//действие 3

break;

case 4:

//действие 4

break;

}

}

Уникальная информация по созданию меню для Arduino

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

В основном это происходит при их хаотичном использовании, без комментариев, с обозначением неизвестных переменных. Так же можно прямо указывать на области памяти и осуществлять с ними действия, что представляет собой мощнейший механизм языка С. Более детально ознакомимся с указанным далее примером:

char x = 1, y = 2, z[5];

char* указатель;

указатель =&x; //переменная указатель указывает на x

y =*указатель; //теперь переменная y имеет значение 1

*указатель = 0; //теперь переменная x имеет значение 0

указатель = &z[0] //переменная указатель указывает на первый элемент массива z

Для объявления указателя нужен символ звёздочка (*), выступающий в роли т.н. оператора косвенной адресации. Такой оператор языка С может быть использован к указателю. Тем самым можно будет получить содержимое определённого объекта. Для языка С присущ дополнительный способ присвоения указателей конкретной переменной. На одноаргументный оператор & возложены функции по возврату адреса переменной. Синтаксису объявления указателя должен быть присуще наследование элемента, на который допустимо указание.

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

В результате вся процедура требует массу места в оперативной памяти (ОП). Говоря о программах для ПК в этом нет проблем, но что касается микроконтроллера, то ОП чаще всего маленькая. Работая с переменными, что указывают на список параметров, в том числе длинные массивы, могут быть переданы посредствам указания адреса памяти, с месторасположением такой переменной.

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

void Замена (int*Tx, int *Ty)

{

int temp;

temp =*Tx;

*Tx = *Ty;

*Ty = temp;

}

void main(void)

{

int A = 10, B = 20;

Замена (&A,&B); //замена значений переменных A и B

}

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

Любая операция, где участвуют указатели, приводит к размеру конкретных объектов. Арифметика для таких указателей очень лёгкая. Если на начало массива элементов типа int указывает указатель Т, то ему тоже присущ тип *int. Тогда операция Т=Т+1; спровоцирует перемещение указателя на иной элемент массива. Не происходит никакого добавле6ния 1 или 2 к адресу указателя, ведь для int присуща длина в 2 байта.

Применение на практике данных указателей позволит реализовать такие операции:

  • прибавление и вычитание указателя и целого числа;
  • объектам одинакового типа присвоение указателей;
  • отнимание или сравнение 2-х указателей с элементами одинакового массива;
  • приравнивание или присвоение указателю значения «0».

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

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

typedef struct параметры

{

int x;

int y;

int высота;

}

параметры*указатель;

указатель->x; обеспечивает обращение к полю x

указатель->высота; обеспечивает обращение к полю высота

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

параметры массив_параметров[10]; //определение массива-списка параметров

параметры*указатель = &tablica_parametrów[0]; //теперь указатель указывает

//на начало массива

(указатель+5)->x; //укажет на поле x пятого элемента массива

//позволяя получение или изменение переменной;

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

SHIELD-LCD16X2 Дочерняя плата; LCD-дисплей; I2C,UART

Arduino UNO REV3 Arduino; ATMEGA328; GPIO,I2C,PWM,SPI,UART

Другие новости

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