Мини меню.

Тема в разделе "Arduino & Shields", создана пользователем varvik85, 8 май 2015.

  1. varvik85

    varvik85 Нерд

    Здравствуйте!
    Стоит задача сделать простое меню,без вложенных подменю.
    Само меню представляет собой определенные параметры,из которых нужно выбраать.
    Всего параметров 3шт. (у меня они называются "Menu 1","Menu 2","Menu 3")
    4 кнопки чтоб можно было войти в меню листать вверх вниз и кнопка "ок"
    Т.е алгоритм такой,нажимаю на меню,листаю вверх вниз перелистывая эти три параметра,нашел тот что нужен,нажал ок,все дальше выбранный параметр обрабатывает другой кусок программы.

    Вроде как понимаю что нужно создать массив из этих трех параметров,создать переменную и каждый раз проверять значение переменной,в зависимости от нажатия кнопки и ее значения переходить вверх или вниз по параметрам.Но вот что то как это сделать не могу понять.Уже сломал свой маленький мозг.:( Не поможете,знающие люди?
    Код (Text):
    char* MainMenu[] = {
    "Menu 1",
    "Menu 2",
    "Menu 3",
    };
    byte KEY_UP = 27;
    byte KEY_DOWN = 22;
    byte menu_number = 0; //Номер текущего меню.
    byte menu_offset = 0; //Позиция в текущем меню.
    int KEYS_DELAY = 100;

    void setup() {
    pinMode(KEY_UP, INPUT); //кнопка
    digitalWrite(KEY_UP, HIGH); //подтягиваем резистор
    pinMode(KEY_DOWN, INPUT); //кнопка
    digitalWrite(KEY_DOWN, HIGH); //подтягиваем резистор

    }

    void loop() {

    if (digitalRead(KEY_DOWN) == LOW) {

        if (menu_offset < MainMenu[1]) {
          menu_offset++;
         delay(KEYS_DELAY);
        }
      }
    }
     
  2. vvr

    vvr Инженерище

    вы же смотрели библиотеку MyMenu - по примеру сделайте,а то выдернули где то кусок кода и не знаете что с ним делать
     
  3. varvik85

    varvik85 Нерд

    Нашел таки подходящее
    Код (Text):
    //Пример простого меню для Arduino
    //В меню используется 4 экрана
    //за номер отображаемого экрана отвечает переменная m

    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>

    LiquidCrystal_I2C lcd(0x27,16,2);  //инициализируем 2х строчный дисплей

    int m=0; // переменная для экранов меню
    int p1=0; // переменная для примера 1
    int p2=0; // переменная для примера 2
    int p3=0; // переменная для примера 3

    #define nextPin 6 // кнопка меню на 6 входе
    #define prevPin 7 // кнопка возврата
    #define upPin 9 // увеличение значения отображаемого параметра
    #define downPin 10 // уменьшение значения
    #define ledPin 13 // Светодиод

    boolean buttonnextWasUp = true;
    boolean buttonprevWasUp = true;
    boolean buttonupWasUp = true;
    boolean buttondownWasUp = true;

    boolean ledEnabled = false;

    void setup()
    {

    // Установка пинов как входов

    pinMode(nextPin, INPUT);
    pinMode(prevPin, INPUT);
    pinMode(upPin, INPUT);
    pinMode(downPin, INPUT);

    pinMode(ledPin, OUTPUT);



    lcd.init();            // инициализация LCD
    lcd.backlight();        // включаем подсветку

    // Вывод приветствия
    lcd.print( "DEMO MENU!" );
    // задержка
    delay (500);
    }


    void loop ()
    {
      boolean buttonnextIsUp = digitalRead(nextPin);
      boolean buttonprevIsUp = digitalRead(prevPin);
      boolean buttonupIsUp = digitalRead(upPin);
      boolean buttondownIsUp = digitalRead(downPin);

    //Обработка нажатия кнопки меню
    if (buttonnextWasUp && !buttonnextIsUp)
    {
    delay(10);
    buttonnextIsUp = digitalRead(nextPin);
    if (!buttonnextIsUp)
    {
    m++;
    if (m>3)
    {
    m=0;
    }
    delay(100);
    lcd.clear();
    }
    }

    //Обработка нажатия кнопки назад
    if (buttonprevWasUp && !buttonprevIsUp)
    {
    delay(10);
    buttonprevIsUp = digitalRead(prevPin);
    if (!buttonprevIsUp)
    {
    m--;
    if (m<0)
    {
    m=3;
    }
    delay(100);
    lcd.clear();
    }
    }


    // Обработка нажатия для р1 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==1)
    {
    p1++;
    if (p1>10)
    {
    p1=0;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }


    // Обработка нажатия для р1 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==1)
    {
    p1--;
    if (p1<0)
    {
    p1=10;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }


    // Обработка нажатия для р2 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==2)
    {
    p2++;
    if (p2>10)
    {
    p2=0;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }

    // Обработка нажатия для р2 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==2)
    {
    p2--;
    if (p2<0)
    {
    p2=10;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }

    // Обработка нажатия для р3 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==3)
    {
      ledEnabled = !ledEnabled;
      digitalWrite(ledPin, ledEnabled);
      p3 = ledEnabled;
    }
    }


    // Обработка нажатия для р3 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==3)
    {
      ledEnabled = !ledEnabled;
      digitalWrite(ledPin, ledEnabled);
      p3 = ledEnabled;
    }
    }


    //вывод меню

    if (m==0)
    {
    lcd.setCursor(0, 0);
    lcd.print( "Main Menu" );
    lcd.setCursor(0, 1);
    lcd.print( "P1=" );
    lcd.print(p1);
    lcd.print( " P2=" );
    lcd.print(p2);
    lcd.print( " LED=" );
    lcd.print(p3);
    }
    else if (m==1)
    {
    lcd.setCursor(0, 0);
    lcd.print( "Parametr-1" );
    lcd.setCursor(0, 1);
    lcd.print( "P1 = " );
    lcd.print(p1);
    }
    else if (m==2)
    {
    lcd.setCursor(0, 0);
    lcd.print( "Parametr-2" );
    lcd.setCursor(0, 1);
    lcd.print( "P2 = " );
    lcd.print(p2);
    }
    else if (m==3)
    {

    lcd.setCursor(0, 0);
    lcd.print( "LED Control" );
    lcd.setCursor(0, 1);
    lcd.print( "LED = " );
    lcd.print(p3);
    }

    buttonupWasUp = buttonupIsUp;
    buttondownWasUp = buttondownIsUp;
    buttonnextWasUp = buttonnextIsUp;
    buttonprevWasUp = buttonprevIsUp;

    }
    Работает,все понятно.Но мне не нужно,чтоб на дисплее постоянно отображалось одно меню.Хотелось бы на дисплей выводить другую информацию,а меню вызывать тогда,когда оно нужно,тогда когда хочется изменить параметры.Соответственно появился вопрос над которым сижу весь день,даже аппетит пропал:confused:.Как вызывать меню и прятать его обратно?Можно как то его прятать в отдельную функцию и вызывать ее когда нужно?Если да то как?Несколько функций Void создать?а как вызывать нужную? Как ее правильно вызывать?Где размещать,до или после основной функции loop?Есть примеры,правила?
     
    Последнее редактирование: 10 май 2015
  4. vvr

    vvr Инженерище

    Сделайте меню в виде функции и вызывайте её по необходимости
     
  5. varvik85

    varvik85 Нерд

    Подскажите пожалуйста как?Как ее правильно вызывать?Где размещать,до или после основной функции loop?Есть примеры,правила?
     
    Последнее редактирование: 10 май 2015
  6. varvik85

    varvik85 Нерд

    Код обработки меню вложил в функцию void Mymenu() теперь могу вызывать меню командой Mymenu(),а как его прятать обратно?Выключать так скажем?
     
  7. mracer

    mracer Нерд

    Меню рисовать одной функцией, отображаемую информацию - другой. Вызывать из loop по необходимости.
     
    varvik85 нравится это.
  8. varvik85

    varvik85 Нерд

    Я то ее вызову,а как прятать обратно,в случае если у меня несколько функций с которыми нужно работать?неудобно.Хорошо бы сделать переменную вроде boolean флаг,которой бы можно было включать и выключать меню.Если я буду с ее помощью включать переменную m и собственно разрешать вывод меню на дисплей.Переменные с данными меню будут сбрасываться?Нужно их в eeprom закидывать?Как грамотнее сделать?Может в чьем-то проекте можно подсмотреть?
     
    Последнее редактирование: 11 май 2015
  9. DrProg

    DrProg Вечный нерд

    Не понял что значит прятать функцию обратно. Создается в любом месте до или после loop, я делаю после, чтобы не загромождать. Вызывается из программы по мере нужды. Выбранные пункты и прочие параметры объявляются как глобальные переменные и пропадать не будут пока устройство работает.
     
  10. varvik85

    varvik85 Нерд

    Здравствуйте!Спасибо за ответ.Я возможно не правильно выражаюсь,не программист все же.Я имею в виду следующее - на дисплей кроме меню я собираюсь выводить и другие вещи,постоянно весящее меню в нем мне не нужно.К тому-же есть и другие функции которые будут работать,как вызвать меню я знаю,а как его теперь ,как бы отключать,чтоб дать возможность работе другим функциям и освободить тем самым дисплей под другие задачи,но при том переменные измененные с помощью меню чтоб не обнулялись.Я думаю создать еще одну переменную которая будет включать и выключать переменную m и которая будет разрешать вывод на дисплей меню,на сколько корректно?
    Код (Text):
    #include <Wire.h>
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(4, 5, 10, 11, 12, 13);  //инициализируем 2х строчный дисплей

    int m=0; // переменная для экранов меню
    int p1=0; // переменная для примера 1
    int p2=0; // переменная для примера 2
    int p3=0; // переменная для примера 3

    #define vhodmenu 33 // кнопка входа в меню
    #define nextPin 6 // кнопка меню на 6 входе
    #define prevPin 7 // кнопка возврата
    #define upPin 9 // увеличение значения отображаемого параметра
    #define downPin 10 // уменьшение значения
    #define ledPin 13 // Светодиод

    boolean buttonnextWasUp = true;
    boolean buttonprevWasUp = true;
    boolean buttonupWasUp = true;
    boolean buttondownWasUp = true;
    boolean   = true;
    boolean ledEnabled = false;
    void setup() {


    // Установка пинов как входов
    pinMode(vhodmenu,INPUT);
    pinMode(nextPin, INPUT);
    pinMode(prevPin, INPUT);
    pinMode(upPin, INPUT);
    pinMode(downPin, INPUT);
    pinMode(ledPin, OUTPUT);

    // Вывод приветствия
    lcd.print( "DEMO MENU!" );
    // задержка
    delay (500);
    }

    void loop() {
    boolean buttvhodvmenu = digitalRead(vhodmenu);
    void Mymenu ();
    }
    void Mymenu ()
    {
      boolean buttonnextIsUp = digitalRead(nextPin);
      boolean buttonprevIsUp = digitalRead(prevPin);
      boolean buttonupIsUp = digitalRead(upPin);
      boolean buttondownIsUp = digitalRead(downPin);

    //Обработка нажатия кнопки меню
    if (buttonnextWasUp && !buttonnextIsUp && buttvhodvmenu)
    {
    delay(10);
    buttonnextIsUp = digitalRead(nextPin);
    if (!buttonnextIsUp)
    {
    m++;
    if (m>3)
    {
    m=0;
    }
    delay(100);
    lcd.clear();
    }
    }

    //Обработка нажатия кнопки назад
    if (buttonprevWasUp && !buttonprevIsUp)
    {
    delay(10);
    buttonprevIsUp = digitalRead(prevPin);
    if (!buttonprevIsUp)
    {
    m--;
    if (m<0)
    {
    m=3;
    }
    delay(100);
    lcd.clear();
    }
    }


    // Обработка нажатия для р1 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==1)
    {
    p1++;
    if (p1>10)
    {
    p1=0;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }


    // Обработка нажатия для р1 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==1)
    {
    p1--;
    if (p1<0)
    {
    p1=10;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }


    // Обработка нажатия для р2 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==2)
    {
    p2++;
    if (p2>10)
    {
    p2=0;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }

    // Обработка нажатия для р2 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==2)
    {
    p2--;
    if (p2<0)
    {
    p2=10;
    }
    delay (100);
    lcd.setCursor(5, 1);
    lcd.print("  ");
    }
    }

    // Обработка нажатия для р3 +
    if (buttonupWasUp && !buttonupIsUp)
    {
    delay(10);
    buttonupIsUp = digitalRead(upPin);
    if (!buttonupIsUp && m==3)
    {
      ledEnabled = !ledEnabled;
      digitalWrite(ledPin, ledEnabled);
      p3 = ledEnabled;
    }
    }


    // Обработка нажатия для р3 -
    if (buttondownWasUp && !buttondownIsUp)
    {
    delay(10);
    buttondownIsUp = digitalRead(downPin);
    if (!buttondownIsUp && m==3)
    {
      ledEnabled = !ledEnabled;
      digitalWrite(ledPin, ledEnabled);
      p3 = ledEnabled;
    }
    }


    //вывод меню

    if (m==0 && buttvhodvmenu)
    {
    lcd.setCursor(0, 0);
    lcd.print( "Main Menu" );
    lcd.setCursor(0, 1);
    lcd.print( "P1=" );
    lcd.print(p1);
    lcd.print( " P2=" );
    lcd.print(p2);
    lcd.print( " LED=" );
    lcd.print(p3);
    }
    else if (m==1 && buttvhodvmenu )
    {
    lcd.setCursor(0, 0);
    lcd.print( "Parametr-1" );
    lcd.setCursor(0, 1);
    lcd.print( "P1 = " );
    lcd.print(p1);
    }
    else if (m==2 && buttvhodvmenu)
    {
    lcd.setCursor(0, 0);
    lcd.print( "Parametr-2" );
    lcd.setCursor(0, 1);
    lcd.print( "P2 = " );
    lcd.print(p2);
    }
    else if (m==3 && buttvhodvmenu )
    {

    lcd.setCursor(0, 0);
    lcd.print( "LED Control" );
    lcd.setCursor(0, 1);
    lcd.print( "LED = " );
    lcd.print(p3);
    }

    buttonupWasUp = buttonupIsUp;
    buttondownWasUp = buttondownIsUp;
    buttonnextWasUp = buttonnextIsUp;
    buttonprevWasUp = buttonprevIsUp;

    }
    В этом коде попробовал реализовать следующее - если нажать и удерживать кнопку vhodmenu то можно зайти в меню и работать с ним,если ее отпустить то меню пропадет.Глупо?Можно это сделать правильнее?Планирую ввести дальше счетчик,который бы после нажатия на кнопку входа в меню и если не было нажатий на другие кнопки выходил бы из меню.
     
    Последнее редактирование: 12 май 2015
  11. DrProg

    DrProg Вечный нерд

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

    И вот еще вариант воспользоваться готовой наработкой.
     
  12. varvik85

    varvik85 Нерд

    Все это хозяйство нужно для устройства управления тремя баками,в которые будет накачиваться воздух.Будет использовано три датчика которые будут отслеживать давление в каждом и по мере необходимости отрезать их от магистрали и выключать компрессор.Меню будет вызываться кнопкой,а все остальное время дисплей будет занят выводом информации о давлении в каждом баке,возможных ошибках,сбоях,перепадах и тп.Понятно что код выше не удобен,но это только набросок,переменная vhodmenu будет чем то вроде флага,который будет говорить о том что запущенно меню или о том что меню выключенно и можно работать дальше.Так то конечно я могу запустить меню вызвав функцию void Mymenu (); но как ее после отключить,чтоб она дальше не мешала другим функциям,а то будет чередоваться непонятно что.
     
  13. DrProg

    DrProg Вечный нерд

    Функция с меню закончилась, экран почистился, программа вернулась на обычный режим и выводит показания как всегда.
     
  14. varvik85

    varvik85 Нерд

    как то так?
    if (buttvhodvmenu или что другое)
    {
    void Mymenu ();
    }
    else
    {
    lcd.clear;
    }
     
  15. DrProg

    DrProg Вечный нерд

    Можно и без else. А lcd.clear последней строкой в Mymenu чтобы подтирало за собой. )
     
    varvik85 нравится это.
  16. varvik85

    varvik85 Нерд

    Спасибо!Буду пробовать!
     
  17. mracer

    mracer Нерд

    if (buttvhodvmenu или что другое)
    {
    lcd.clear;
    void Mymenu ();
    }
    else
    {
    lcd.clear;
    Void Mydata();
    }

    Или lcd.clear вставить в функции...
     
  18. mracer

    mracer Нерд

    if (buttvhodvmenu или что другое)
    {
    lcd.clear;
    void Mymenu ();
    }
    else
    {
    lcd.clear;
    Void Mydata();
    }

    Или lcd.clear вставить в функции...
     
    varvik85 нравится это.
  19. varvik85

    varvik85 Нерд

    Спасибо большое!