меню на ардуино lcd 1602 i2c с кнопками
LiquidMenu: Arduino библиотека для создания меню на LCD дисплее
Библиотека LiquidMenu обертывает Arduino библиотеку LiquidCrystal с возможностью создания меню. Она упрощает процесс создания меню, абстрагируя элементы меню в иерархически организованные классы.
Пример использования библиотеки LiquidMenu
Содержание
Особенности
Требования
Загрузка
Скачать библиотеку можно по ссылке ниже:
Быстрый старт
Организация классов
Для представления различных элементов меню данная библиотека использует иерархически структурированные классы.
Базовая схема иерархии классов Полная схема иерархии классов
Класс LiquidLine представляет собой строку текста/чисел на дисплее. Чтобы создать новый объект LiquidLine используйте конструктор.
Класс LiquidScreen представляет собой набор строк, которые одновременно отображаются на дисплее (т.е. «текущий экран»).
Класс LiquidMenu объединяет экраны для формирования меню. Данный класс используется для управления меню (переключение экранов, выбор строк, вызов функций и т.д.).
Создание меню
Навигация по меню
Навигация по меню осуществляется из объекта LiquidMenu или, если имеется несколько меню, из объекта LiquidSystem. Экраны могут быть зациклены вперед и назад или конкретный экран может быть указан его объектом или номером:
Фокус и функции обратного вызова
Строки текста/чисел, показанные на дисплее, могут быть интерактивными. Каждая строка обладает прикрепленными к ней функциями обратного вызова (по умолчанию до 8 штук). Они прикрепляются с помощью числа, указанного пользователем:
Чтобы вызвать прикрепленную к строке функцию, необходимо, чтобы на строку был наведен фокус (строка была выбрана). Для циклического перемещения фокуса по строкам, показанным на экране, используйте метод:
Когда строка выбрана, может быть вызвана одна из прикрепленных функций с помощью:
number указывает, какая из прикрепленных функций дожна быть вызвана.
Простое меню на Arduino и ЖК дисплее
В разнообразных проектах на основе платы Arduino достаточно часто возникает задача создания меню, отображаемого на экране ЖК дисплея 16х2 и управляемого с помощью кнопок. В данной статье мы рассмотрим один из самых простых способов создания подобного меню (какой я только нашел в интернете). В этом проекте мы с помощью данного меню будем управлять светодиодом, но его легко можно адаптировать под любые другие электронные проекты на основе платы Arduino.
Необходимые компоненты
Внешний вид компонентов, необходимых для сборки проекта, показан на следующем рисунке.
Схема проекта
Схема проекта меню на основе платы Arduino и ЖК дисплея 16х2 представлена на следующем рисунке.
На следующем рисунке эта схема показана применительно к ее сборке на макетной плате.
Далее на нескольких рисунках последовательно представлен процесс сборки этой схемы на макетной плате.
Сначала подключаем ЖК дисплей – питание и общий провод.
Затем подключаем контакты для передачи данных ЖК дисплея. Здесь использован 8-битный способ подключения ЖК дисплея к плате Arduino, но можно упростить схему, использовав 4-битный режим.
Подключаем контакт 16 ЖК дисплея на землю, а к контакту 15 дисплея подключаем резистор сопротивлением 1 Ом. Автор проекта (ссылка на оригинал приведена в конце статьи) рассчитал сопротивление данного резистора исходя из даташита на используемую им модель ЖК дисплея (LMB 162ABC). Если фоновая подсветка дисплея (Backlight) вам не нужна, то эти контакты можно оставить неиспользованными.
Далее подключаем светодиод к контакту 9 платы Arduino через токоограничивающий резистор 220 Ом.
Далее подключаем кнопочную панель согласно ранее представленной схемы, либо же вместо нее вы можете использовать 3 обычные кнопки. В результате получаем следующий внешний вид собранной конструкции проекта.
Исходный код программы (скетча)
Автор проекта разработал его код таким образом, чтобы его можно было легко адаптировать (изменять) под другие проекты. Схема меню, реализуемая кодом программы, показана на следующем рисунке.
При первоначальном нажатии кнопки вы можете выбрать пункт Navigate (навигация) или Execute (исполнение).
Пункт Execute (исполнение) : в этом пункте мы будем управлять светодиодом – включать/выключать, плавно угасать или мигать.
Пункт Navigate (навигация) : этот пункт меню мы будем использовать для навигации с помощью кнопок.
На следующем рисунке видно как автор проекта с помощью ленты подписал названия кнопок для упрощения навигации по меню.
Далее представлен исходный код программы для реализации меню.
Энкодер управление меню на дисплее
Рассмотрим, как сделать меню с энкодером Ардуино на дисплее LCD 1602 I2C. Мы представим два примера: меню для включения светодиодов и меню на дисплее с управлением от энкодера яркостью светодиодов. Рекомендуем вам ознакомиться с подключением к Arduino дисплея LCD 1602 Arduino и модуля энкодер Ардуино. Если вы уже подключали данные модули, то можно приступать к этому мини проекту.
Меню на Ардуино LCD 1602 с энкодером
Примеры меню с модулем энкодера и жк дисплеем, размещенные на этой странице, вы сможете адаптировать под свои нужды. Во многих проектах на Ардуино требуется для пользователя создать возможность для настройки или управления устройством на микроконтроллере. Энкодер позволяет сделать простое и нативное меню на LCD дисплее для управления светодиодами, микро серво Ардуино или для других задач.
Как сделать меню с энкодером на дисплее
Для этого проекта нам потребуется:
Скетч. Управление энкодером меню дисплея LCD
В первом, более простом примере, в меню дисплея имеется три пункта которые можно менять с помощью вращения ручки энкодера. При нажатии на тактовую кнопку энкодера, включается выбранный цвет RGB светодиода. В зависимости от положения курсора на дисплее, при помощи условного оператора if включается нужный цвет. Соберите схему, как показано на картинке выше и загрузите следующую программу.
Пояснения к коду:
Скетч. Двухуровневое меню с энкодером Ардуино
В следующем примере меню имеет второй уровень для регулировки яркости каждого светодиода отдельно. Переход из одного меню в другое происходит при нажатии кнопки энкодера, при котором меняется значение глобальной переменной w в скетче. Схема подключения светодиодов и модулей к микроконтроллеру остается прежней, как на картинке выше, следует лишь загрузить в плату следующий код программы.
Пояснения к коду:
Заключение. Мы рассмотрели два примера создания меню с энкодером на дисплее 1602 IIC Arduino. Если вы уловили всю суть управления меню с помощью энкодера (датчик угла поворота), то легко сможете использовать представленные примеры в своих собственных проектах с дисплеем на Ардуино. Если у вас еще остались вопросы по данной теме, то вы можете их оставлять в комментариях к этой записи.
Панель оператора (HMI) с шиной I2C для Arduino
В рамках работы с неким ардуино-совместимым оборудованием(о нем в конце) понадобился мне экран с кнопками для управления и отображения текущей информации. То есть, была нужна панель оператора, она же HMI.
Решено было сделать HMI самостоятельно, а в качестве интерфейса использовать «квадратную» шину i2c.
Если интересен процесс разработки и программирования подобных девайсов, добро пожаловать под кат.
Характеристики:
Конечно, можно было у тех же китайцев купить готовый шилд c дисплеем и клавиатурой и типа такого:
К этому шилду можно припаять 2 платки FC-113 и получится функционально то же самое, что и у меня: дисплей с клавиатурой, работающие по i2c. Цена набора составит от 4$.
Но на этой плате меня не устраивает размер кнопок, а мне хотелось большие, с возможностью установки разноцветных колпачков. Подключать Arduino к HMI мне хотелось не на соплях, а через нормальный разъем DB9F, а значит нужно было делать соединительную плату. А в этом случае какая разница, делать одну плату или две? Кроме того, у меня уже было в запасе несколько дисплеев 1602, а потому мне нужно было потратить всего 1.02$ для покупки на Алиэкспресс платы FC-113 (0.55$) и расширителя портов PCF8574P (0.47$).
Ну а самое главное- если имеешь дело с Ардуино, то самостоятельное изготовление шилдов для него это само собой разумеющееся дело, правда ведь?
В сфере АСУ ТП, где я работаю, HMI для связи с устройствами используют интерфейсы цифровой передачи данных RS-232,RS-485, CAN и т.д. Поэтому для меня логично, что моя самодельная HMI будет вся работать по интерфейсу передачи данных, в данном случае по i2c.
Если бы я смастерил устройство, где дисплей работает по квадратной шине, а кнопки идут напрямую на входа Ардуино, это бы вызывало у меня чувство глубокого неудовлетворения. Как представлю эту картину: из панели торчит отдельно шнурок на интерфейс, отдельно провода на входа, брррр…
Кроме того, различие между платой кнопок, которые идут напрямую ко входам Ардуино, и платой кнопок с интерфейсом i2c, заключается только в микросхеме PCF8574P(0.47$), конденсаторе и двух резисторах.
Кнопки у меня слева направо имеют такие функции: вверх, вниз, отмена, ввод, редактирование.
Кнопка «редактирование» отнесена от остальных чуть в сторону для акцентирования своей функции- изменение значений логических параметров(вкл/выкл) или переход в режим редактирования в случае параметров числовых.
Всего кнопок 5, хотя микросхема на плате клавиатуры позволяет подключить до 8 штук.
Достаточно было бы обойтись четырьмя кнопками и функционал бы не пострадал- «ввод» и «редактирование» можно совместить в одной кнопке. Но мне просто жалко стало, что из 8 ног микросхемы расширителя порта половина будет не задействована.
Еще отдельная кнопка «редактирование» может быть полезна, если я решу в одной строке выводить несколько параметров. Тогда этой кнопкой можно будет переключаться между параметрами, указывая, какой именно из них нужно изменить. Примерно так работает кнопка «SET» в популярных китайских HMI OP320.
Если первые две кнопки означают вверх и вниз, то почему бы их не разместить вертикально, как, например, сделано в указанном выше китайском шилде?
Лично для меня удобнее, когда все кнопки находятся по горизонтали, тогда во время работы пальцы перемещаются только в одной плоскости.
Железо
1. Самодельная соединительная плата с разъемом DB9F. Так, как питание +5V для расширителей портов и дисплея берем с Ардуино, на плате поставил предохранитель 0.1 А.
2. Всем нам хорошо известный дисплей 1602 с припаянной платой FC-113, которая подключает дисплей к шине i2c.
3. Самодельная клавиатурная плата с микросхемой PCF8574P, которая будет читать состояния кнопок и передавать их по шине i2c. Кстати, «дисплейная» плата FC-113 тоже основана на микросхеме PCF8574, только с индексом T, т.е. планарная, а не DIP, как PCF8574P.
Кнопки я поставил 12х12мм с квадратным толкателем- на них можно надеть большие разноцветные колпачки.
Стоит сказать пару слов про микросхему PCF8574P, на основе которой я сделал клавиатурную плату.
PCF8574P это расширитель портов с интерфейсом i2c. Всего в нем 8 портов, каждый из которых можно сконфигурировать на работу в качестве входа или выхода. Для этой микросхемы и обвязки как таковой не требуется(вспомните, к примеру, max232), я только на всякий случай поставил конденсатор по питанию.
Адрес микросхемы PCF8574P задается с помощью адресных ног A0, A1, A2, которые подтягивают к земле или к питанию через резистор 10 кОм.
На клавиатурной плате я все адресные ноги PCF8574P поставил на землю, поэтому адрес жестко настроен как 0x20 и поменять его нельзя.
Как я уже писал, в качестве разъема для HMI я выбрал DB9F. На него от Ардуино поступают сигналы +5 V, GND, SDA, SCL.
Провод для связи по i2c Ардуино и HMI сделал длинной 1.4 м, работает без глюков.
Платы нарисовал в Sprint Layout 6, методом ЛУТ перенес на текстолит и вытравил в растворе перекиси и лимонной кислоты.
В сети есть много рецептов травления лимонной кислотой плат на фольгированном стеклотекстолите.
Я делал такой раствор: 100 мл перекиси водорода 3%, 50 г лимонной кислоты, 3 чайные ложки соли. Баночку с перекисью подогрел в кастрюле с водой до температуры где-то 70 градусов.
Погружаем плату в раствор рисунком вниз, как рекомендуют при травлении перекисью.
Через пару десятков секунд начинается бурный процесс. Выделяется много пара, вдыхать который не рекомендуется. Наверное.
Потом процесс стихает. Переворачиваем плату.
Корпус сделал у друга из оргстекла 4 мм на станке лазерной резки.
Купить готовый корпус или сделать самому? Немного подумав, решил делать сам. Те, что видел в продаже, мне не подходили или по цене, или по эстетическим соображениям, или были на DIN-рейку, что тоже меня не устраивало.
Изначально корпус хотел выпилить из фанеры. Но потом вспомнил, что у меня есть замечательный друг и, по большой для меня радости, директор фирмы по производству спортивных наград. У него имеются всякие там станки, в том числе и для лазерной резки.
Обратился за помощью и друг не отказал- за пару минут лазером нарезали деталей.
Пользуясь случаем, хочу сказать, спасибо тебе, Коля! Иначе мне пришлось бы еще целый день пилить и шлифовать фанеру, а результат едва бы был таким блистательным.
Программирование
С точки зрения Ардуино, данная HMI представляет из себя 2 устройства, которые работают по шине i2c: дисплей(LCD) с адресом 0x27 и клавиатура с адресом 0x20. Соответственно, работать Arduino будет отдельно с клавиатурой и отдельно с LCD.
Работа с LCD осуществляется через специальную библиотеку «LiquidCrystal_I2C.h», ее нужно установить в Aduino IDE.
Работа с клавиатурой осуществляется через стандартную библиотеку «Wire.h», которая изначально имеется в Aduino IDE.
Подключаем HMI к Ardiuno.
1. Для начала проверим, видит ли Ардуино наш HMI. Для этого загружаем в нее программу, которая будет сканировать шину i2c на предмет нахождения на ней устройств.
Во время выполнения этой программы, Ардуино будет писать результаты сканирования шины i2c в последовательный порт. Для просмотра этих данных, в Arduino IDE заходим Инструменты-> Монитор порта.
Видим, что Ардуино на шине i2c определило два устройства с адресами 0x20 и 0x27, это клавиатура и LCD соответственно.
2. Теперь посмотрим, как работает наша клавиатура. Создадим программу, которая будет опрашивать состояние кнопок и выводить его на LCD.
3. Наконец можно переходить к тому, ради чего все затевалось- созданию многоуровневого меню в Ардуино. Через меню будем не только смотреть информацию, но и управлять выходами самого Ардуино.
В нете много информации по созданию многоуровневого меню на C++, а для Ардуино даже видел какие-то библиотеки. Но я решил в своей программе написать меню самостоятельно. Во-первых, чем меньше левых библиотек в проекте, тем спокойнее. А во-вторых, это просто.
Получилась у меня очередная вариация древовидного меню. Меню позволяет выводить в каждой строке одновременно статический текст и значение переменной. Например, можно вывести название параметра и его значение.
Для вывода на экран переменных, применяю принцип тегов- определенным образом оформленных текстовых меток в тексте, вместо которых при отображении текста на экране выводится значение.
Параметры можно изменять нажатием кнопки «Edit». Причем, в теге каждого параметра указывается, доступен ли он для редактирования или только для чтения. Если текущий параметр только для чтения, в начале строки указатель будет ‘*’, если редактирование параметра разрешено, указатель станет ‘+’.
LCD 1602 и языковой вопрос
Отдельно нужно затронуть вопрос русификации.
В знакогенераторе некоторых LCD 1602 нет русских букв, а вместо них прошиты японские кракозябры. Перепрошить знакогенератор невозможно. Поэтому придется или писать на экране слова латинскими буквами, или в программе формировать русские буквы самому, т.к. в LCD 1602 есть возможность создавать и хранить в ОЗУ LCD собственные символы. Но, в последнем случае, можно выводить на экран не больше восьми «самодельных» символов за раз.
В принципе, нет ничего страшного, если писать на LCD русские слова английскими буквами. Вон, даже почтенная французская компания Shneider Electric(та самая, что еще до революции продавала гаубицы царю) за полтора десятилетия не сподобилась внедрить в свои знаменитые программируемые реле Zelio русский язык. Но это не мешает активно торговать ими на просторах всего СНГ. Причем, канальи, испанский и португальский языки ввели.
На многих наших заводах эти Zelio общаются с персоналом фразами типа «NASOS 1 VKL».
Когда непонятно, есть ли русские буквы в конкретном LCD, нужно вывести на экран все символы его знакогенератора. Если кириллица есть, она начинается со 160 позиции.
Но даже если ваш LCD 1602 русифицирован, вывести на экран русские слова не так просто. По крайней мере, используя библиотеку «LiquidCrystal_I2C.h» при работе с LCD по шине i2c.
Если просто выводить русский текст, например инструкцией lcd.print(«Привет. »), то вместо «Привет. » на экране появится какая-то белиберда.
Это потому, что русские буквы Arduino IDE переводит в двухбайтный код UTF-8, а в LCD все символы однобайтные.
Та же проблема, кстати, наблюдается при передаче русских текстов из Ардуино в монитор порта Arduino IDE. Ардуино передает в последовательный порт русские буквы в двухбайтной кодировке UTF-8, а монитор порта Arduino IDE пытается их читать в однобайтной кодировке Windows-1251 (cp1251). Хотя cp1251 тоже 8-битная, как и кодировка LCD 1602, но с ней не совпадает.
Можно формировать русские тексты через коды символов. К примеру, строку ‘ЖК дисплей’ на русифицированный LCD получится вывести так:
Но мне такой подход не нравится.
Чтобы корректно отображать русский текст на русифицированных LCD 1602, для Ардуино придумали несколько библиотек. Но почитав отзывы я увидел, что многие жалуются на глюки при их использовании.
Поэтому я в своей программе многоуровневого меню сам написал простую функцию преобразования UTF-8 в коды LCD. Правда, сделал это только для заглавных русских букв, что меня вполне устраивает.
На этом про самодельную HMI с шиной i2c у меня все.
Ах да, в начале статьи я писал, что делаю HMI не совсем для Ардуино, а для ардуино-совместимого оборудования. Это я про ПЛК CONTROLLINO MAXI, который программируется из среды Arduino IDE (и многих других).
CONTROLLINO MAXI это фактически Arduino + куча шилдов и все оформлено как промышленный ПЛК. Но про него в следующий раз.
→ Архив со схемами, скетчами и печатной платой в формате lay6
→ Ардуино-совместимый ПЛК СONTROLLINO, работа с которым вдохновила на создание HMI i2c
→ Расширитель портов PCF8574 и подключение его к Arduino
→ Плата FC-113 для работы LCD 1602 по шине i2c и подключение ее к Arduino
→ Многоуровневое древовидное меню, общие принципы создания на Си
→ Кодировка UTF-8
→ Кодировка Windows-1251
Простое меню для Arduino
И так, пока ждем посылки из Китая со всеми компонентами. Сделаем простенькое меню для Arduino и LCD Keyboard шилда.
Как выглядит готовый результат:
Программировать я больше привык в Visual Studio (сейчас у меня версия communit 2015) + Arduino для Visual Studio
Меню у меня просто плоское, без вложенных подменю, мне кажется так проще и понятнее, у каждого наименования параметра есть код, который поможет описать его в инструкции или документации. Для начала у меня только параметры настройки даты и времени, которые будут сохраняться в модуль реального времени, при нажатии “save & exit”. Код получился простой и я надеюсь понятный.
Итак, готовая прошивка для простого меню с комментариями:
Надеюсь, этот код кому-то сэкономит время, прошу не стесняться комментировать =)
20 thoughts on “ Простое меню для Arduino ”
Пытаюсь использовать ваш код но выдает что переменнные не задекларированы
MenuSaveRam’ was not declared in this scope
Это проблема компилятора, я когда-то сталкивался с такой, надо объявление функций и структур вынести в заголовочный файл (.h)
подскажите для чайников как это сделать или где про это почитать. Спасибо!
Мне даже сложно указать на источник, это нюансы самого компилятора и языка си. Я думаю лучше начать с изучения синтаксиса языка http://cppstudio.com/cat/274/. Потом просто учиться по примеру других программ, благо для ардуино много примеров и уроков, тут пользуясь гуглом думаю не промажешь =)
Мне не помогло. Печально
Приветствую, хорошее меню. А можно ли его реализовать на дисплее LCD 1602 I2C и подключеным отдельно на макете кнопкам, если да то что поменять?
Конечно можно, нужно поменять обработку клавиш в этом месте на вашу, читая значение пинов к которым присвоены кнопки в этом месте
if (ButtonPress == 0) < // Если кнопки не были нажаты ранее
int ButtonPinValue = analogRead(0); // Проверяем значение, не нажата ли кнопка
if (ButtonPinValue
А приведёте пример изменения такой записи на 4-5 кнопок, сравнительно с вашим подключением кнопок на шилд (какие команды будут это заменять )? Буду очень благодарен! ^_^
Не совсем понятно как с int ButtonPinValue = analogRead(0) сделать приём с 4-5 выходов Ардуинки.
Ну если это не аналоговый вход а цифровые, тогда надо пользоваться digitalRead()
Ну как-то так:
if (ButtonPress == 0) < // Если кнопки не были нажаты ранее
if (digitalRead(pinButton1)) ButtonPress = 4; // Нажата [+]
else if (digitalRead(pinButton2)) ButtonPress = 2; // Нажата [Prev]
else if (digitalRead(pinButton3)) ButtonPress = 3; // Нажата [Next]
else if (digitalRead(pinButton4)) ButtonPress = 5; // Нажата [-]
else if (digitalRead(pinButton5)) ButtonPress = 1; // Нажата [Menu]
> else …
где pinButton соответственно пин к которому подключена конкретная кнопка
1) У функции void MenuSaveRam(int Concat) < …>потерялась закрывающая фигурная скобка
2)Для того чтобы sprintf(str_format, …) могла отображать результат во всю ширину экранчика, длина массива str_format должна быть 17 (на 1 длиннее ширины экранчика – для хранения нуля, завершающего строку)
Не совсем так =)
1) Скобочка закрывающая есть, одна после if… а вторая после процедуры
2) Длинна и так в 17, так как размерность у массив начинается с 0. От 0 до 16 – 17 символов.
Не получается запустить Ваш скетч. Пишет кучу ошибок:
menu:46: error: ‘MenuSaveRam’ was not declared in this scope
menu:47: error: ‘SettingDateDay’ was not declared in this scope
menu:48: error: ‘SettingDateMonth’ was not declared in this scope
menu:49: error: ‘SettingDateYear’ was not declared in this scope
menu:50: error: ‘SettingTimeHour’ was not declared in this scope
menu:51: error: ‘SettingTimeMin’ was not declared in this scope
C:\Users\Р?ван\Documents\Arduino\menu\menu.ino: In function ‘void loop()’:
menu:80: error: ‘pinButton11’ was not declared in this scope
menu:81: error: ‘pinButton8’ was not declared in this scope
C:\Users\Р?ван\Documents\Arduino\menu\menu.ino: In function ‘void MenuSaveRam(int)’:
menu:127: error: a function-definition is not allowed here before ‘<‘ token
menu:131: error: a function-definition is not allowed here before ‘<‘ token
menu:135: error: a function-definition is not allowed here before ‘<‘ token
menu:139: error: a function-definition is not allowed here before ‘<‘ token
menu:143: error: a function-definition is not allowed here before ‘<‘ token
menu:145: error: expected ‘>’ at end of input
Помогите запустить.
мм круто, но лучше бы вы показали, и не потому что лень разбираться самим….
действительно одна фигурная скобка лишняя:
void MenuSaveRam(int Concat) < // SAVE & EXIT
if (Concat == 1) < //TODO Сохранение параметров в RAM >;
MenuEnter = false; // Выход из меню
>
А если всё, после “// Функции вызываемые для изменения значений переменных” перенести по тексту выше, до “// Главный цикл” то всё заработает.
точнее перенести выше “// Тип структуры данных описывающих пункт меню”, до описания пунктов меню
Спасибо! Скобка реально потерялась ))
Здравствуйте! Подскажите пожалуйста – после того как Вы скомпилировали код в VS, как и чем(как я понимаю что не через ардуино ИДЕ) его загружаете в контроллер? (Писать код в VS действительно удобней).