Меню и Lcd шилд
- Войдите на сайт для отправки комментариев
Ср, 06/08/2014 - 13:11
Меню для дисплея 16х2 и кнопок на цифровых пинах работает.
Возникла необходимость сделать меню для кнопок на одном аналоговом пине. Пример работает.
#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 int lcd_key = 0; int adc_key_in = 0; int adc_key_prev = 0; void setup() { lcd.begin(16, 2); lcd.setCursor(0,0); lcd.print("Push A Button!"); lcd.setCursor(10,1); lcd.print("A="); } void loop() { adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) { lcd.setCursor(12,1); lcd.print(" "); lcd.setCursor(12,1); lcd.print(adc_key_in); } lcd.setCursor(0,1); switch (lcd_key) { case btnRIGHT: { lcd.print("RIGHT "); break; } case btnLEFT: { lcd.print("LEFT "); break; } case btnUP: { lcd.print("UP "); break; } case btnDOWN: { lcd.print("DOWN "); break; } case btnSELECT: { lcd.print("SELECT"); break; } case btnNONE: { lcd.print("NONE "); break; } } } int read_LCD_buttons() { adc_key_in = analogRead(0); delay(5); int k = (analogRead(0) - adc_key_in); if (5 < abs(k)) return btnNONE; if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 195) return btnUP; if (adc_key_in < 380) return btnDOWN; if (adc_key_in < 555) return btnLEFT; if (adc_key_in < 790) return btnSELECT; return btnNONE; }
Зато теперь при попытке создать меню при нажатии кнопки (любой) сразу проскакивают все меню
case btnRIGHT:
{
if ( A == 10 || A == 15 || A == 20 )
A = A + 5;
break;
}
Как сделать, чтобы при нажатии кнопки выполнялось только одно действие.
прочитать прекрепленную тему про кнопки.
И подумать чем отличаются состояния и события.
СОСТОЯНИЯ кнопки: нажата, не нажата
и СОБЫТИЯ кнопки: нажатие кнопки, отпускание кнопки
Вналаче не на програмнном. Вначале на бытовом уровне нужно осозднать эту разницу. И как наблюдая за состояними, делать вывод о наступлении какого-то события.
На примере.
Предположим ваша жена каждое утро заглядывает вам в кошелек.
И может наблюдать два два СОСТОЯНИЯ кошелька:
1. "бабла немерянно"
2. и "в кармане вошь на аркане".
Каждое утро глядя в кошелек, она может сделать выводы о наступлении двух событий кошелька:
1. Была "получка"
2. Вчера все пробухал.
Как она делает подобные выводы? Какой цепочкой рассуждений?
Вот ваше read_lcd_button() - это чтение "состояний", а после вам "нужно подумать" и решить "какое событие наступило".
И бегать по меню, в соотвествии с событиями, а не состояними...
И, все-таки лучше с этим освоиться на основании одной кнопки. Цифровой. А уж потом браться за адаптацию под аналоговые кнопки.
Ввёл переменную для определения состояния кнопки - теперь работает как хотелось.
leshak, спасибо.
Честно говоря, хоть в теме про кнопки и показан пример про с "flag" - мне не очень нравится он.
Вот когда читаешь такое код, то уследить за этими флагами (и не забыть их сбросить) - трудновато.
Да и вообще, само имя "flag" - слишком малоговорящие.
Вот если бы вы, все-таки с женой рассуждения привели, то у вас бы получилось что-то такое "если вчера (при прошлой проверке) кошелек был пустой, а сегодня - полный, то значит наступило событие "получка").
Значит нужно просто запоминать результаты проверки и тоже ими пользоваться при детектировании события.
Рассуждения вида "кнопка была не нажата, а теперь нажата" - IMHO как-то более органичны чем "кнопка нажата и флаг сброшен".
Все го-то и нужно, завести переменную prev_lcd_key и сохранять в нее, в конце loop() какай lcd_key был при этом проходе loop().
И тогда, сами "действия на события" не захламляются никакими flag=1, flag=0
Как так.... хотя. Стоп... вот хотел уже пример писать, но... у вас же изначально ужеть есть переменная adc_key_prev.
Только вот строчку
adc_key_prev=lcd_key; - я бы в конец loop() пихнул, как-то там оно "более интуитивно" (но с точки зрения работоспособности, и в начале, как у вас, все в порядке).
Значит переменная с "прошлым значением", у нас уже есть.
Значит осталось только условие "кнопка была не нажата, а теперь нажата" записать в виде кода. Практически дословно.
или, раз часть проверки adc_key_prev=btnNone у нас для всех кнопок одинакова, то можно "вынести ее за скобки", и воспользоваться вашим изначальным switch, просто обернув его в провеку, что "раньше кнопка была не нажата".
Вообщем, как видите, размышления "на бытовом уровне", иногда, все-таки позволяет в итоге проще код писать.
Просто вначале "в голове уложить", а потом в код перевести.
Ещё раз спасибо за толковый и познавательный комменарий