Не остается в подменю

Так что всем привет. Я создаю простое меню с несколькими подменю на своем жидкокристаллическом экране. Но я столкнулся с небольшой проблемой, я не могу остаться в своем подменю. Когда я нажимаю кнопку выбора, он переходит в раздел подменю и через 1-2 секунды возвращается в главное меню.

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

LiquidCrystal_I2C lcd(0x27, 16, 2);

int upButton = 10;
int downButton = 11;
int selectButton = 12;
int menu = 1;

void setup() {
  lcd.begin();
  lcd.backlight();
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  updateMenu();
}

void loop() {
  if (!digitalRead(downButton)){
    menu++;
    updateMenu();
    delay(100);
    while (!digitalRead(downButton));
  }
  if (!digitalRead(upButton)){
    menu--;
    updateMenu();
    delay(100);
    while(!digitalRead(upButton));
  }
  if (!digitalRead(selectButton)){
    executeAction();
    updateMenu();
    delay(100);
    while (!digitalRead(selectButton));
  }
}

void updateMenu() {
  switch (menu) {
    case 0:
      menu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.print(">MenuItem1");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem2");
      break;
    case 2:
      lcd.clear();
      lcd.print(" MenuItem1");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem2");
      break;
    case 3:
      lcd.clear();
      lcd.print(">MenuItem3");
      lcd.setCursor(0, 1);
      lcd.print(" MenuItem4");
      break;
    case 4:
      lcd.clear();
      lcd.print(" MenuItem3");
      lcd.setCursor(0, 1);
      lcd.print(">MenuItem4");
      break;
    case 5:
      menu = 4;
      break;
  }
}

void executeAction() {
  switch (menu) {
    case 1:
      action1();
      break;
    case 2:
      action2();
      break;
    case 3:
      action3();
      break;
    case 4:
      action4();
      break;
  }
}

void action1() {
  lcd.clear();
  lcd.print(">Executing #1");
  delay(1500);
}
void action2() {
  lcd.clear();
  lcd.print(">Executing #2");
  delay(1500);
}
void action3() {
  lcd.clear();
  lcd.print(">Executing #3");
  delay(1500);
}
void action4() {
  lcd.clear();
  lcd.print(">Executing #4");
  delay(1500);
}

Спасибо заранее

, 👍0

Обсуждение

Вы понимаете код, который вы включили? Он делает именно то, что вы описываете. В вашем коде нет подменю, определенных в коде, есть только главное меню и действия (которые отображают что-то на экране и возвращаются в главное меню через 1,5 секунды). Вы также забыли задать вопрос., @StarCat

Да, я меняю подменю как действие. Мой вопрос в том, чего мне не хватает?, @Jānis

Что вы хотите, чтобы ваш код выполнял? Если вы хотите иметь подменю, вам следует добавить код для отображения подменю и просмотреть их., @StarCat

Я что, когда я перехожу к действию 1, я остаюсь в действии 1 (не выхожу из него через 1,5 с)., @Jānis

Вот почему я спросил, понимаете ли вы, что такое код. Каждое "пустое действие 1() .. действие 4 ()" отображает что-то и ожидает в течение 1,5 секунд (="задержка(1500);"), а затем немедленно возвращается в главное меню. Если вы хотите изменить это, вам следует изменить "действие 1 ()" на " действие 4 ()", чтобы делать то, что вы хотите., @StarCat

Как вы планируете выйти из actionx в главное меню? Если при нажатии выберите, затем поместите распаковку и нажмите внутри действия., @Dorian

Кстати, вам не нужно отменять отпирание кнопки. Поместите небольшую задержку в основной цикл., @Dorian


1 ответ


1

возьмите, например, одну из функций действия подменю

   void action1() {
      lcd.clear();
      lcd.print(">Executing #1");
      delay(1500);
    }

функция action1() будет вызвана, когда для параметра menu будет установлено значение 1.

Допустим, вы хотите 10 раз мигнуть светодиодом в функции action1 (). В функции action1() вы должны добавить необходимую логику / код для выполнения. после завершения выполнения кода элемент управления выйдет из функции action1 (). затем ваш код звучит примерно так:

   void action1() {
      lcd.clear();
      lcd.print(">Executing #1");
      for(int i =0; i<10; i++)
      {
         ledstate = !ledstate; //предположим, что начальное значение ledstate равно нулю
         digitalWrite(LED_BUILTIN, !ledstate);
         delay(500);
      }

    }

Если вы хотите остаться в функции action1() навсегда, вы можете сделать следующее:

   void action1() {
      lcd.clear();
      lcd.print(">Executing #1");
      while(1);
    }

Но вы видите, что контроль никогда не выйдет из этой функции. Это означает, что вы, возможно, не сможете снова прочитать состояние кнопки или перейти в другие меню. Я предполагаю, что вы не используете прерывания. это означает, что ваш код застрянет здесь навсегда. Чтобы выйти из этой функции, единственным способом будет сброс системы. Тем не менее, если это то, что вам нужно сделать, вы можете изучить функции сна для экономии энергии вместо функции while(1).

У вас должен быть план выхода из функции. Пока вы находитесь в функции action1 (), попробуйте следить за кнопками, если определенные кнопки нажаты, вы можете обнаружить это и затем выйти из цикла while

while(digitalRead(button1)
{
 //некоторые повторяющиеся действия по кодированию
}

как только кнопка 1 станет МЕНЬШЕ, условие в функции while завершится ошибкой.

Я надеюсь, что мой ответ дал вам несколько способов решить вашу проблему.

,