Меню на lcd 20х4
- Войдите на сайт для отправки комментариев
Пт, 26/04/2013 - 01:49
Делаю себе простой интерфейс для дисплея 20х4. Готовых решений за два вечера не нашёл и решил попробовать самостоятельно. Есть основное меню mainMenu(). Для первой строчки подменю upMenu() и от него ещё два субдменю speedMenu() и accelMenu(). Курсор бегать вверх вниз заставил и из главного меню в подменю перехожу при выставлении курсора и нажатии кнопки Enter. А вот как записать условие для перехода в субменю придумать знаний не хватает. Если пишу if (pos == 0 && upMenu()) компилятор ругается. Как правильно написать подобное условие в моём случае?
void mainMenu()
{
blankLcd();
lcd.setCursor(1,0);
lcd.print("up");
lcd.setCursor(1,1);
lcd.print("down");
lcd.setCursor(1,2);
lcd.print("left");
lcd.setCursor(1,3);
lcd.print("right");
}
void upMenu()
{
blankLcd();
lcd.setCursor(1,0);
lcd.print("speed");
lcd.setCursor(1,1);
lcd.print("accel");
}
void speedMenu()
{
blankLcd();
lcd.setCursor(1,0);
lcd.print("speed val");
}
void accelMenu()
{
blankLcd();
lcd.setCursor(1,0);
lcd.print("accel val");
}
//menu key ok
if (buttonEnterState==HIGH) {
if (pos == 0) {
upMenu();
pos = 0;
}
blanklcd() - очистка экрана
if (pos == 0 && upMenu()) компилятор ругается. --- у Вас функция upMenu() ничего не возвращает (void) от того и ругается, возвращаемого значения нет
А как правильно сформулировать условие перехода в подменю?
По всей видимости Вам в первую очередеь необходимо описать дерево (структуру) меню, максимальный уровень вложенности и тд...
Как описать - решение за Вами. Например как нумеруются пункты в документе: 1.2.3 - глава 1 раздел 2 параграф 3. Тогда будете знать в каком месте структуры меню вы находитесь и как реагировать на внешние события....
Доработал код. Теперь по меню бегаю как мне нужно. Но возникла другая проблема. Меню из четырёх строчек, а подменю из двух и не получается заставить курсор в подменю опускаться только на вторую строку. Если вариант
//menu key down
if (buttonRightState==HIGH) {
pos++;
lcd.setCursor(0, (pos - 1));
lcd.print(" ");
if ((pos >= 4) && ( menuStatus = 0))
{
pos = 4;
}
}
курсор всё время бегает по четырём строкам и в подменю получаются глюки.
Код для кнопки down
//menu key down if (buttonRightState==HIGH) { pos++; lcd.setCursor(0, (pos - 1)); lcd.print(" "); if ((pos >= 4) && ( menuStatus = 0)) { pos = 4; } else if((menuStatus = 1) || (menuStatus = 2) || (menuStatus = 3) || (menuStatus = 4)) { if( pos >= 1) { pos = 1; } } }В приведённом варианте в подменю курсор бегает по двум строкам, но и в главном меню только по двум и теперь в главном меню глюки.
код для всех кнопок
////////////////////////////// кнопки /////////////////////////////////// //menu key down if (buttonRightState==HIGH) { pos++; lcd.setCursor(0, (pos - 1)); lcd.print(" "); if ((pos >= 4) && ( menuStatus = 0)) { pos = 4; } else if((menuStatus = 1) || (menuStatus = 2) || (menuStatus = 3) || (menuStatus = 4)) { if( pos >= 1) { pos = 1; } } } ///////////////////////////////////////////////////////////////////////// /* if (buttonRightState==HIGH && ((menuStatus = 5) || (menuStatus = 6) || (menuStatus = 7) || (menuStatus = 8))) { pos++; lcd.setCursor(0, (pos - 1)); lcd.print(" "); if (pos >= 1) { pos = 1; } } else if (buttonRightState==HIGH && (menuStatus = 5)) { pos++; lcd.setCursor(0, (pos - 1)); lcd.print(" "); if( pos >= 4) { pos = 4; } }*/ /////////////////////////////////////////////////////////////////////////// //menu key up if (buttonLeftState==HIGH) { pos--; lcd.setCursor(0, (pos + 1)); lcd.print(" "); if (pos <= 0) { { pos = 0; } } } //menu key ok if (buttonEnterState==HIGH) { menu_execute(); } //menu key back if ( buttonEscState==HIGH) { mainMenu(); // сразу в главное меню menuStatus = 0; pos = 0; } } //действия по кнопке KEY_OK void menu_execute() { //Определение текущего меню switch (menuStatus) { case 0: //Для MainMenu switch(pos) { //выбор действий case 0: //Вызов подменю 1 PanMenu(); menuStatus = 1; pos = 0; break; case 1: TiltMenu(); menuStatus = 2; pos = 0; break; case 2: RotMenu(); menuStatus = 3; pos = 0; break; case 3: DzMenu(); menuStatus = 4; pos = 0; break; }//switch break; case 1: //Для SubMenu1 switch(pos) { //выбор действий case 0: //блинк SpeedPanMenu(); menuStatus = 5; break; case 1: RampPanMenu; menuStatus = 6; break; }//switch break; case 2: //Для SubMenu2 switch(pos) { //выбор действий case 0: //блинк SpeedTiltMenu(); menuStatus = 7; break; case 1: // RampTiltMenu(); menuStatus = 8; break; }//switch break; case 3: //Для SubSubMenu1 switch(pos) { //выбор действий case 0: // SpeedRotMenu(); menuStatus = 9; break; case 1: //блинк RampRotMenu(); menuStatus = 10; break; }//switch break; case 4: //Для SubSubMenu1 switch(pos) { //выбор действий case 0: // DzPanMenu(); menuStatus = 11; pos = 0; break; case 1: // DzTiltMenu(); menuStatus = 12; pos = 0; break; }//switch break; } //switch MenuSelect }Прошу совета и помощи.
Вот тут написано как меню организовать http://avrproject.ru/publ/menu_on_a_microcontroller_avr/1-1-0-33
Сделал пример по вышеприведённой ссылке только на две кнопки. Меню не переводится. Подскажите пожалуйста, в чём ошибка.
#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); const int buttonPinLeft = 18; const int buttonPinRight = 14; const int buttonPinEsc = 12; const int buttonPinEnter = 11; int lastButtonPushed = 0; int lastButtonEnterState = LOW; int lastButtonEscState = LOW; int lastButtonLeftState = LOW; int lastButtonRightState = LOW; long lastEnterDebounceTime = 0; long lastEscDebounceTime = 0; long lastRightDebounceTime = 0; long lastLeftDebounceTime = 0; long debounceDelay = 150; int A; int reading; void setup() { pinMode(buttonPinLeft, INPUT); pinMode(buttonPinRight, INPUT); pinMode(buttonPinEnter, INPUT); pinMode(buttonPinEsc, INPUT); lcd.begin(20, 4); lcd.clear(); A = 10; } void loop() { int buttonEnterState=LOW; int buttonEscState=LOW; int buttonLeftState=LOW; int buttonRightState=LOW; reading = digitalRead(buttonPinEnter); if (reading != lastButtonEnterState) { lastEnterDebounceTime = millis(); } if ((millis() - lastEnterDebounceTime) > debounceDelay) { buttonEnterState=reading; lastEnterDebounceTime=millis(); } lastButtonEnterState = reading; reading = digitalRead(buttonPinEsc); if (reading != lastButtonEscState) { lastEscDebounceTime = millis(); } if ((millis() - lastEscDebounceTime) > debounceDelay) { buttonEscState = reading; lastEscDebounceTime=millis(); } lastButtonEscState = reading; reading = digitalRead(buttonPinRight); if (reading != lastButtonRightState) { lastRightDebounceTime = millis(); } if ((millis() - lastRightDebounceTime) > debounceDelay) { buttonRightState = reading; lastRightDebounceTime =millis(); } lastButtonRightState = reading; reading = digitalRead(buttonPinLeft); if (reading != lastButtonLeftState) { lastLeftDebounceTime = millis(); } if ((millis() - lastLeftDebounceTime) > debounceDelay) { buttonLeftState = reading; lastLeftDebounceTime=millis(); } lastButtonLeftState = reading; if (buttonEnterState==HIGH){ lastButtonPushed=buttonPinEnter; } else if(buttonEscState==HIGH){ lastButtonPushed=buttonPinEsc; } else if(buttonRightState==HIGH){ lastButtonPushed=buttonPinRight; } else if(buttonLeftState==HIGH){ lastButtonPushed=buttonPinLeft; } else{ lastButtonPushed=0; } ////////////////////////////// кнопки /////////////////////////////////// //menu key down if (buttonRightState==HIGH ) { if((A = 10) || (A = 20) || (A = 30)) { A = A + 10; } } /////////////////////////////////////////////////////////////////////////// //menu key up if (buttonLeftState==HIGH) { if((A = 20) || (A = 30) || (A =40)) { A = A - 10; } } if (A = 10) { lcd.setCursor(1,0); lcd.print("up"); lcd.setCursor(1,1); lcd.print("down"); lcd.setCursor(1,2); lcd.print("left"); lcd.setCursor(1,3); lcd.print("right"); } else if (A = 20) { lcd.setCursor(1,0); lcd.print("speed"); lcd.setCursor(1,1); lcd.print("accel"); } else if (A = 30) { lcd.setCursor(1,0); lcd.print("speed val"); } else if (A = 40) { lcd.setCursor(1,0); lcd.print("accel val"); } }Особо не вникал. В некоторых условиях IF вы не сравниваете значение, а приравниваете его. Например строка 91 должна выглядеть так:
Спасибо Evgen, работает! Только одна проблемка - перехожу в четвёртую строку меню (в трёх всё отлично) и всё зависает, не работает никакая кнопка. Уже задолбался перепроверять. Может свежий взгляд увидет ошибку .
#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); const int buttonPinLeft = 18; // Up button const int buttonPinRight = 14; // Down button const int buttonPinEsc = 12; // Esc button const int buttonPinEnter = 11; // Enter button int lastButtonPushed = 0; int lastButtonEnterState = LOW; int lastButtonEscState = LOW; int lastButtonLeftState = LOW; int lastButtonRightState = LOW; long lastEnterDebounceTime = 0; long lastEscDebounceTime = 0; long lastLeftDebounceTime = 0; long lastRightDebounceTime = 0; long debounceDelay = 150; int A ; int reading; int valSPEED = 0; int valRAMP = 0; int valDzPan = 0; int valDzTilt = 0; void setup() { pinMode(buttonPinLeft, INPUT); pinMode(buttonPinRight, INPUT); pinMode(buttonPinEnter, INPUT); pinMode(buttonPinEsc, INPUT); lcd.begin(20, 4); lcd.clear(); A = 10; } void loop() { if (A == 10) { lcd.setCursor(0, 0); lcd.print("*"); lcd.setCursor(1,0); lcd.print("Pan "); lcd.setCursor(0,1); lcd.print(" Tilt "); lcd.setCursor(0,2); lcd.print(" Rot "); lcd.setCursor(0,3); lcd.print(" Dead zone "); } else if (A == 20) { lcd.setCursor(0, 1); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Pan "); lcd.setCursor(1,1); lcd.print("Tilt "); lcd.setCursor(0,2); lcd.print(" Rot "); lcd.setCursor(0,3); lcd.print(" Dead zone "); } else if (A == 30) { lcd.setCursor(0, 2); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Pan "); lcd.setCursor(0,1); lcd.print(" Tilt "); lcd.setCursor(1,2); lcd.print("Rot "); lcd.setCursor(0,3); lcd.print(" Dead zone "); } else if (A == 40) { lcd.setCursor(0, 3); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Pan "); lcd.setCursor(0,1); lcd.print(" Tilt "); lcd.setCursor(0,2); lcd.print(" Rot "); lcd.setCursor(1,3); lcd.print("Dead zone "); return; } else if (A == 11) // PanMenu() { lcd.setCursor(0, 0); lcd.print("*"); lcd.setCursor(1,0); lcd.print("Speed Pan "); lcd.setCursor(0,1); lcd.print(" Ramp Pan "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 12) { lcd.setCursor(0, 1); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Speed Pan "); lcd.setCursor(1,1); lcd.print("Ramp Pan "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 21) // TiltMenu() { lcd.setCursor(0, 0); lcd.print("*"); lcd.setCursor(1,0); lcd.print("Speed Tilt "); lcd.setCursor(0,1); lcd.print(" Ramp Tilt "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 22) { lcd.setCursor(0, 1); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Speed Tilt "); lcd.setCursor(1,1); lcd.print("Ramp Tilt "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 31) // RotMenu() { lcd.setCursor(0, 0); lcd.print("*"); lcd.setCursor(1,0); lcd.print("Speed Rot "); lcd.setCursor(0 ,1); lcd.print(" Ramp Rot "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 32) { lcd.setCursor(0, 1); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Speed Rot "); lcd.setCursor(1,1); lcd.print("Ramp Rot "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 41) // DzMenu() { lcd.setCursor(0, 0); lcd.print("*"); lcd.setCursor(1,0); lcd.print("Dead zone Pan "); lcd.setCursor(0,1); lcd.print(" Dead zone Tilt "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 42) { lcd.setCursor(0, 1); lcd.print("*"); lcd.setCursor(0,0); lcd.print(" Dead zone Pan "); lcd.setCursor(1,1); lcd.print("Dead zone Tilt "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 110) /// SpeedPanMenu() { lcd.setCursor(0,0); lcd.print(" S P E E D "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valSPEED); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 120) /// RampPanMenu() { lcd.setCursor(0,0); lcd.print(" R A M P "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valRAMP); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 210) ///// SpeedTiltMenu() { lcd.setCursor(0,0); lcd.print(" S P E E D "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valSPEED); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 220) /////// RampTiltMenu() { lcd.setCursor(0,0); lcd.print(" R A M P "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valRAMP); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 310) /////// SpeedRotMenu() { lcd.setCursor(0,0); lcd.print(" S P E E D "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valSPEED); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 320) ////// RampRotMenu() { lcd.setCursor(0,0); lcd.print(" R A M P "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valRAMP); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 410) ////// DzPanMenu() { lcd.setCursor(0,0); lcd.print(" Dead zone Pan axis "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valDzPan); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } else if (A == 420) //// DzTiltMenu() { lcd.setCursor(0,0); lcd.print(" Dead zone Tilt "); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(8,2); lcd.print(valDzTilt); lcd.print(" "); lcd.setCursor(0,3); lcd.print(" "); } int buttonEnterState=LOW; int buttonEscState=LOW; int buttonLeftState=LOW; int buttonRightState=LOW; reading = digitalRead(buttonPinEnter); if (reading != lastButtonEnterState) { lastEnterDebounceTime = millis(); } if ((millis() - lastEnterDebounceTime) > debounceDelay) { buttonEnterState=reading; lastEnterDebounceTime=millis(); } lastButtonEnterState = reading; reading = digitalRead(buttonPinEsc); if (reading != lastButtonEscState) { lastEscDebounceTime = millis(); } if ((millis() - lastEscDebounceTime) > debounceDelay) { buttonEscState = reading; lastEscDebounceTime=millis(); } lastButtonEscState = reading; reading = digitalRead(buttonPinRight); if (reading != lastButtonRightState) { lastRightDebounceTime = millis(); } if ((millis() - lastRightDebounceTime) > debounceDelay) { buttonRightState = reading; lastRightDebounceTime =millis(); } lastButtonRightState = reading; reading = digitalRead(buttonPinLeft); if (reading != lastButtonLeftState) { lastLeftDebounceTime = millis(); } if ((millis() - lastLeftDebounceTime) > debounceDelay) { buttonLeftState = reading; lastLeftDebounceTime=millis(); } lastButtonLeftState = reading; if (buttonEnterState==HIGH){ lastButtonPushed=buttonPinEnter; } else if(buttonEscState==HIGH){ lastButtonPushed=buttonPinEsc; } else if(buttonRightState==HIGH){ lastButtonPushed=buttonPinRight; } else if(buttonLeftState==HIGH){ lastButtonPushed=buttonPinLeft; } else{ lastButtonPushed=0; } ////////////////////////////// кнопки /////////////////////////////////// /////////////////////////menu key down if (buttonRightState==HIGH ) { if((A == 10) || (A == 20) || (A == 30)) { A = A + 10; } else if((A == 11) || (A == 21) || (A == 31) || (A == 41)) { A = A + 1; } } //////////////////////////menu key up if (buttonLeftState==HIGH) { if((A == 20) || (A == 30) || (A == 40)) { A = A - 10; } else if((A == 12) || (A == 22) || (A == 32) || (A == 42)) { A = A - 1; } } /////////////////////////////menu key ok if (buttonEnterState==HIGH) { if((A == 10) || (A == 20) || (A == 30) || (A == 40)) { A = A + 1; } else if((A == 11) || (A == 12) || (A == 21) || (A == 22) || (A == 31) || (A == 32) || (A == 41) || (A == 42)) { A = A * 10; } } ////////////////////////////////menu key back if ( buttonEscState==HIGH) { if((A == 11) || (A == 12)) { A = 10; } else if((A == 21) || (A == 22)) { A = 20; } else if((A == 31) || (A == 32)) { A = 30; } else if((A == 41) || (A == 42)) { A = 40; } else if(A >100) { A = A/10; } } }Строчка 86 точно нужна?
И еще, вложенные друг в друга if else if else... лучше заменить на конструкцию switch..case. Нагляднее будет.
Ещё раз спасибо Evgen, вы меня просто выручили. В строчке 86 и был косячок. Буду дальше наращивать.