Меню на LCD Keypad Shield
- Войдите на сайт для отправки комментариев
Пт, 13/09/2013 - 20:03
Пытаюсь сделать меню, вот пример:
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ lcd.begin(16, 2); // запускаем библиотеку } void loop(){ if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; } } else { lcd.print("NaNaNaNaNa"); } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }
При нажатии на кнопку "Select" заходит в меню (пока для примера выводится надпись).
Вопросы:
1) Почему выводит вместо "NaNaNaNaNa" 10 первых ячеек, весь дисплей заполняется этими буквами?
2) Почему спустя 1-2 минуты (обычно даже меньше) выкидывает из меню обратно на время? (вроде переменная key_menu не должна позволить сделать это, она ведь жестко устанавливается в значение true при нажатии)
ps: есть примеры 2х-3х уровневого меню?
Точнее даже не 1-2 минуты, а 20 секунд постоянно, а потом скидываеь, как будето происходит рестарт.
Еще один вопрос: 3) Как можно вывести примерно такую конструкцию, вроде в c++ так работает, а тут нет:
Ну и еще один: 4) Можно ли среду ардуины подключить к MSVSC++? Существую ли отладчики, для прогонки кода ардуины на выявление косяков?
>1) Почему выводит вместо "NaNaNaNaNa" 10 первых ячеек, весь дисплей заполняется этими буквами?
А сколько раз у вас вызвается " lcd.print("NaNaNaNaNa"); ? Куда по вашему должны выводится все последующие вызовы?
посмотрите на функцию printTimeToLCD(), там же этой проблемы нет. Сыграйте в игру "найди 10-ть отличий". Разберите построчно что происходит в этой функции.
Кстати ответ на этот вопрос поможет вам и с
> Как можно вывести примерно такую конструкцию
Только тут как раз наоборот нужно воспользоватся этим эффектом, а не устранять его.
>вроде в c++ так работает,
Нет у нас тут конкатенации сишных строк.
P.S. Отформатируйте код отступами, невозможно же читать где какой if начался, где закончился. Ну хотя-бы ctrl+T нажмите в ArdinoIDE
С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка
С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка
>А вот почему выкидывает обратно на часы
А хрен его знает. Может действитель перегружается.
Добавте в loop() что-то такое:
И смотрите в сериал монитор. Если цифры сбрасываются на ноль - значит таки перезагрузки. Заодно увидите и "через какое время" точно.
Можете еще попробовать
lcd.print(
"NaNaNaNaNa"
);
закоментить. возможно этот беконечный print сносит башню библиотеке, она где-то выскакивает за границу памяти своей и перетирает вам значение key_menu
Прикол получается в том, что добавив действие в loop (например, ваш счетчик выше) из меню перестает выкидывать. Возможно дело в том, что если в loop ничего не меняется, ардуина думает что повисла и перезагружается? Хотя бред..
Вот таким образом из меню не выкидывает, а надпись чуть заметно мерцает (добавил lcd.clear()):
А вот если без вашего кода, которые вызывает большую задержку (или я хз), надпись начинает мерцать очень сильно (что понятно из-за lcd.clear) и выкидыват на время:
Если например добавить задержку delay(100), то мерцание становится не таким сильным (почти как в первом случае, еле заметное), но из меню попрежнему выкидывает спустя 25 секунд...
надпись начинает мерцать очень сильно (что понятно из-за lcd.clear) и выкидыват на время:
применяйте lcd.clear только для lcd.print нового значения - смысл лупить в индикатор одно и то же значение?
Дак я например могу вообще заменять clear на допустим lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.
смысл лупить в индикатор одно и то же значение?
В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.
Дак я например могу вообще заменять clear на допустим lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.
Я не особо вникал в ваш код, но в принципе не могу понять вкуда вас может выкидывать - меню есть переменная, которую вы печатаете на экран, какое бы значение ваша переменная не приняла, должно отображаться хоть что-то.
В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.
меню экрана есть реакция на изменение или сама переменная - нет изменения, нет print, нет мигания.
Можно сказать хочу сделать часы с настройками. По дефолту на экране отображается только время. При нажатии на кнопку Select открывается текстовое меню. В нём хочу переключаться между пунктами и заходить в нужный.. Это цель.
Время выводит нормльно. Когда я жму кнопку Select меня как бы забрасывает в меню (в примере выше, просто на текстовое поле "Na.."), дальше мне нужно ждать дальнейших нажатий клавишь, попросту ничего не делать. Дак вот, отсюда меня и выкидывает обратно на время (по видемому рестартится ардуина).
---
А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение...
Возможно с помощью прерываний это делается?
изменения состояния кнопок нужно писать в переменные - тогда и не будет выбрасывать.
считайте, что у вас есть консольная прога без гуя вообще, прога реагирует на нажания кнопок, что делают кнопки? - изменяют своё состояние и, если это состояние зависит от количества нажатий, копбинаций, прочего, то это состояние не просто LOW/HIGH, а 0, 1, 2, 3, ...
Значит - кнопка Select должна менять переменную Select с "0" на "1" при первом нажатии и обратно при повторном нажатии.
Кнопы DOWN, UP и прочие навигационные изменять переменную, допустим, "menu" с "0" до "5"(если у вас шесть строк меню)
т.е. DOWN увеличивает переменную menu на 1, UP - уменьшает.
все новые значения обновляются и запоминаются, изменения сравниваются с предыдущими, если выявляется разница - печатается в индикатор.
в итоге - Select вас будет забрасывать/выбрасывать из меню, DOWN/UP - навигация вверх/вниз по меню, может понадобится кнопа типо "ENTER" для запоминания/ввода значения.
Это типо концептуальный набросок логики.
Вопрос не в логике (с ней думаю сам разберусь), а совсем в другом. Посмотрите повнимательнее.
А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение...
Не нужно ничего ждать - контроллер гоняет программу по кругу, вам остаётся только рулить на поворотах на полной скорости.
примерно так:
*Лешак раскритикует, но я это так понимаю.
>*Лешак раскритикует, но я это так понимаю.
А то :) Где отступы? Зачем же новичков учить так писать? Так - он уже умеет :)
>А существуют ли функции ожидания ответа (нажатия клавиши)?
Не существует. Зато существует прикрепленная ветка Работа с кнопками. В помощь новичку.
>А вот если без вашего кода, которые вызывает большую задержку
Не вызывает он большой задержки. Ну несколько микросекунд на вызов millis() и раз в секунду на выполенение println
Можете попробовыть выкинуть мой код еще сделать lcd.print("RESET"); delaa(2000) в самом setup(). Тогда никаких "задержке" не будет, зато будет видно когда контроллер перегрузился.
>Можно сказать хочу сделать часы с настройками.
Хе-хе... я тоже тем же занимаюсь... с описанием процесса в блоге. Только ОЧЕНЬ медленно. Только по выходным, да и то не каждым удается продвинутся по чуть-чуть... :( Мне вообще-то даже что-то знакомое/родное почудилось в функции printTimeToLCD() ;)
Вот кусок дальнейшей моей логики прикинул:
Имелось ввиду вот так:
Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия..
Так и есть, у меня второй день знакомства с ардуиной пошел)
>Имелось ввиду вот так:
Нет. Смысл в таком коде? Что вы сделали: при включении задержку (вместо того что-бы запустить библиотеку). Вывели надпись... и все.
Какую дополнительную информацию, для размышления вы получили в результате этого кода? А никакой.
вам нужно было.
Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.
Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.
А вот как решить такую проблему, я хз.
Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия..
Так и есть, у меня второй день знакомства с ардуиной пошел)
Ну значит "я не ошибся" :) Но явно "чуток под себя подпилии" ее ;)
Я тоже буду делать (возможно сегодня) выставление времени с помощью кнопок.
Только... вначале хочу вообще по другому чтение кнопок сделать. С антидребезгом, что-бы кнопки читались не толкько шилдовые, но и еще добавлять можно было. На A1,A0, обычные цифровые кнопки и т.п.. И что-бы "стиль" чтения кнопок был похожим на обычный digitalRead. Тогда все "приемы" которые описаны в ветках типа "учимся работать с кнопками" - можно будет применять "в лоб". Ну и еще хочется ловить вещи типа "длинное нажатие/удержание" и т.п. Вообщем - наполеоновские планы ;)
Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.
Тот код что вы привели - не может ничего сказать о рестартах. Он выводит надпись при СТАРТЕ и все. Надпись висит. В момент РЕСТАРТА - ничего видимого происходить у вас не будет.
Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.
А вот как решить такую проблему, я хз.
Учитывая что "рестартится" вы диагностировали не верно. Сделайте две вещи:
1. Дайте код с моей добавкой которую вы запускали
2. Постарайтесь детально описать "что вы видите/делаете": "вывелась надпись.... повисела 2 сек... исчезла... нажал кнопку.... увидел то-то..... через какое-то время.... увидел то-то...".
Постарайтесь ничего не упускать, типа "открыл сериал монитор" и т.п.
Будет пропадать надпись на 2 секунды)) она это и делает...
Ну вот по твоему:
1) Ничего не делаю - показывает время
2) Нажал на кнопку Селект - открылось меню с двумя пунктами: Т1 и Т2
3) Жду 20-30 сек и рестарт происходит (на время выкидывает)
---
Кароче, рестарт происходит даже когда время на экране идет.. не заходя в меню..
А вот при просмотре порта перезагрузка не происходит (об этом я уже писал выше):
Бред (
Я в #17 зачем-то взял и написал кусок кода. Наверное от нефиг делать. Вы же вставили "что-то свое". Которое оставляет гореть надпись ST, следовательно узнать о том произошел или нет рестарт микроконтроллера может телепатически. Вы так уверено говорите "происходит рестарт" - а с чего вы это взяли? Я такими методами диагностики - не владею.
>1) Ничего не делаю - показывает время
Все. Дальше можете ничего не говорить. Либо у вас ардуина работает на каких-то квантовых эффектах и почему-то не выполняет setup(), либо вы пускаете какой-то другой скетч. Ваш код и "как вы описываете его поведение" - явно не совпадают. А через плечо - вам никто заглянуть не может. Следовательно - и помочь тоже. Остается только причитать "не знаю что делать".
Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.
ps: в 17 посте просмотрел строчку lcd.clear().. но даже так видно будет там..
Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.
Ну так это же еще модуль часов нужно подключать.... лениво.... эх, ну ладно....
Залил. Вообще в меню не выходит. Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.
Поправил на
Все заработало. Меню нарисовало. Ушел пить кофе. Вернулся через 5-ть минут - меню на месте. Подождал еще 10-ть минут - без изменений.
P.S. По поводу "неправильно кнопка". Думал что вы где-то "отсебятину сделали". Ан нет - все точно как в примере производителя те же значения. Загрузил пример производителя - тоже нерпавильно детектит кнопки SELECT,LEFT. Причем, пару недель назад - все правильно он у меня детектил. Это не приятно. Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Кароче, я вроде понял в чём у меня баг был... В питании, походу не хватает от usb. От внешнего блока запитал и перестало ресетится. Так что надо взять на заметку это дело.
Вообщем дайте не свою умозаключение "происходит рестарт", а симптомы дайте (у меня они не воспроизводятся).
Происходит у вас повторый вывод RST перед тем как "выкидывает на время" или нет?
"выкидывает на время" - это результат. мы ищем причину. пытаемся понять почему это происходит. Поэтому когда вы ставите знак равно между "выкидавает на время"=="рестартанулось" - это нулевая информация. Факт рестарта - нужно доказать. Вот если мы увидим что RST выводится повторно перед тем как "выкинуло на время" - вот только тогда можно сделать вывод "выкидывание на время означает рестарт". И искать причину рестарта. А до этого... это не более чем голословное утверждение. И боротся с рестартом если его нет... потеря времени. Точно так же как и "искать ошибку в логике", когда происходят рестарты. Вообщем мы на развилке, и пока вы не дадите намеков "куда идти нужно..." - шансы что-то поправить - малы.
100% это были рестарты и на 90% уверен что из-за питания. Т.к. переключил на чуть мощнее блок, чем usb и всё гладко. Так что вопрос снимается. Думаю стоит взять это на заметку, кто собирается работать на этом шилде.
Еслиб можно было залить видео для примера, показал бы.
Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Это партнёры из оплота демократии под покровом ночи коды запуска сменили - так, чисто противотеррористическая профилактика.
Что там такого с плывущими параметрами интересно?
Что там такого с плывущими параметрами интересно?
Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.
analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.
Ну вот набросал часть меню, еще таймер доделать надо.. Жду советов, багов..
ps: кнопки конечно не очень мягко говоря, поэтому приходится нажимать четко, не торопясь.
Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.
analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.
У меня иногда случается слепое пятно, если увижу явно странное - считаю, что это я не так понял мудрый замысел.
Рулетка какая-то получается с кнопками на analogRead.
Ведь кнопка при таком подключении может отработать все значения в диапазоне подтяжки, заставляя срабатывать другие кнопки, попадающие в этот диапазон... даже, если считать, что ничего не плывёт.
Просто из-за неидеальности механического контакта, т.е.:
разомкнуто - сопротивление всегда стремится к бесконечности.
замкнуто - сопротивление уменьшается от бесконечности к нулю за определённый промежуток времени, но не мгновенно и не всегда к нулю... в процессе дребезга может принимать любые значения в диапазоне подтяжки.
*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50
*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50
Да все правильно вы поняли. Конечно у кнопки есть и дребезг, есть и время срабатывания. И фронт изменения никогда не будет абсолютно вертикальным. Но это не так смертельно. Вертикальных фронтов - их почти нигде никогда нет. В принципе - работают же эти кнопки. Довольно стабильно. Проблема возникла только когда СУЩЕСТВЕННО поменялись внешние условия. Причем начало не "принимать любые значения в диапазоне", а "стало принимать другие значения". Значит время сработки кнопки существенно меньше чем время замера АЦП (он же тоже - не моментальный). Ну а станет ощутимо - ну так "антидребезг" ничего не мешает прикрутить :) Думаю в любом случае буду его делать. Вероятность что описываемая вами проблема "вылезет" с износом кнопок - далеко не нулевая.
......
Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.
Поправил на
......
P.S. По поводу "неправильно кнопка". Думал что вы где-то "отсебятину сделали". Ан нет - все точно как в примере производителя те же значения. Загрузил пример производителя - тоже нерпавильно детектит кнопки SELECT,LEFT. Причем, пару недель назад - все правильно он у меня детектил. Это не приятно. Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Как выяснилось - я сам себе злобный буратино. Дожди, фаза луны.... все оказалось банальней. Версия шилда. V1.0 и V1.1 - отличаются тем какие значение возвращает analogRead()
На самом шилде - не написана версия :(. Видимо когда купил его - проверил (и в чеке увидел правильную версию), а потом - забыл :( Был уверен что у меня V1.1. До тех пор пока не померял.
Самое интерестно, что по схеме - номиналы резисторов у V1.0 и V1.1 - не отличаются. Должны вести себя идентично. Мне кажется просто при производстве хомутнули - и поставили не те резисторы. Отличные от указаных в схематике. Потом спохватились и "правильную" партию решили назвать "V1.1" :)
Кстати, возможно будет интерестно. Я тут нагрофоманил как эти кнопки работают, почему именно такие цифры в коде Леший в мире Ардуины: Читаем аналоговые кнопки. Часть 1, свои танцы с выяснением какая версия шилда, ну и описание альтернативного подхода к чтению этих кнопок. Не как "в примере от производителя", а максимально близко к тому как мы читаем обычные цифровые кнопки с помощью digitalRead()
P.S. Кстати буду благодарен, если кто-то запустит у себя "калибровочный" скетч из статьи, и скажет какие показания на analogRead() он у него намерял. Хочу все это в види библиотеки оформить и нужны дефолтные значения, которые подходят как можно большему количеству людей.