Использование switch case с 5-позиционным переключателем и последовательным выходом

lcd button array switch

Я пытаюсь начать разработку системы меню для моего LCD1602. У меня есть 5-позиционный переключатель параллакса (вверх, вниз, влево, вправо, по центру), и я хотел бы связать их.

Я пытался заставить код работать, но что-то запутался. У меня не так много опыта работы с Arduino, и я мог бы воспользоваться некоторыми советами. Я понимаю, что есть версия 1602 с клавиатурой, встроенной в схему, но у меня нет этой модели. У меня обычный экран и отдельный 5-позиционный переключатель.

Я также знаю, что самый простой способ добиться того, чего я хочу, — это сеть резисторов и сопоставление значений АЦП. Однако я не хочу делать аналоговый переключатель, я хочу сделать цифровой переключатель.

Можно ли как-нибудь взять контакты и поместить их в массив, а затем преобразовать это в оператор case switch?

Я попробовал несколько разных идей, но ничего не работает. Простите пример кода, он собран вместе.

ниже мой код

*/

// константы не изменятся. Они используются здесь для установки номеров контактов:
char buttonChar1 = 'a';     // номер вывода кнопки
const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int ledPin =  13;      // номер вывода светодиода

// переменные изменятся:
int buttonState1 = 0; // переменная для чтения статуса кнопки
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int pinsArray[5] = {2, 3, 4, 5, 6};
void setup() {
  // инициализируем вывод светодиода как выход:
  pinMode(ledPin, OUTPUT);
  // инициализируем контакт кнопки как вход:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
}

void loop() {
  // прочитать состояние значения кнопки:
  buttonState1 = digitalRead(buttonPin1) == 2;
  buttonState2 = digitalRead(buttonPin2) == 3;
  buttonState3 = digitalRead(buttonPin3) == 4;
  buttonState4 = digitalRead(buttonPin4) == 5;
  buttonState5 = digitalRead(buttonPin5) == 6;
  // проверяем, нажата ли кнопка. Если да, то состояние кнопки ВЫСОКОЕ:

  switch (pinsArray[5]) {
    case 2:    //
      digitalWrite(ledPin, HIGH);
      Serial.println("button1");
      break;
    case 3:     //
      digitalWrite(ledPin, HIGH);
      Serial.println("dim");
      break;
    case 4:    //
      Serial.println("medium");
      break;
    case 5:    //
      Serial.println("bright");
      break;
  }
  }

, 👍1

3 ответа


1

В следующий раз выровняйте свой код с помощью Ctrl-K (после выбора).

И да, вы можете значительно оптимизировать свой код (для удобства сопровождения) с помощью массивов:

Вместо

const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;

использовать

const int buttonPins[] = { 2, 3, 4, 5, 6 };

В разработке программного обеспечения обычно начинают с индекса 0 (например, индекс массива).

Для состояний кнопки:

int buttonState1 = 0; // переменная для чтения статуса кнопки
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;

вы можете использовать

boolean buttonStates[5];
for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
    buttonStates[buttonIndex]= false;
}

Вместо того, чтобы устанавливать режимы булавки:

pinMode(buttonPin1, INPUT); pinMode(кнопкаPin2, ВХОД); pinMode(кнопкаPin3, ВХОД); pinMode(кнопкаPin4, ВХОД); pinMode(кнопкаPin5, ВВОД);

Используйте цикл for:

for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
   pinMode(buttonPins[buttonIndex], INPUT);
}

Вы можете объединить два цикла for выше с одним.

Чтобы прочитать состояния кнопки:

buttonState1 = digitalRead(buttonPin1) == 2;
buttonState2 = digitalRead(buttonPin2) == 3;
buttonState3 = digitalRead(buttonPin3) == 4;
buttonState4 = digitalRead(buttonPin4) == 5;
buttonState5 = digitalRead(buttonPin5) == 6;

Использовать

for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
   buttonStates[buttonIndex] = digitalRead(buttonPins[buttonIndex]) == buttonPinds[buttonIndex]) ? true : false;
}

Что касается переключателя, я думаю, вам нужно оставить его, так как он отличается для каждого контакта.

И вместо использования значения 5 используйте, например:

const uint8_t NR_OF_BUTTONS = 5;

и везде используйте константу NR_OF_BUTTONS.

Примечание. У меня нет под рукой компилятора, так что простите меня за возможные ошибки компилятора.

Кроме того, вместо нескольких массивов (каждый длиной NR_OF_BUTTONS) вы можете использовать массив структур, содержащих номер контакта и состояние, но это, возможно, выходит за рамки ваших знаний в области программирования. Использование массивов уже является огромным улучшением.

,

1

Майкл уже дал вам несколько отличных советов по очистке вашего кода.

Ваше выражение switch не имеет особого смысла. Вы переключаетесь на основе индекса вне допустимого диапазона в массив констант.

После того как вы прочитаете состояния всех кнопок, описанные Майклом, ваш цикл должен решить, что делать с состоянием каждого переключателя.

Это переключатель типа джойстика, когда пользователь может задействовать только одно направление за раз? Или можно нажать 2 переключателя сразу?

Если это ромб из 5 переключателей с переключателем посередине, пользователь может одновременно нажимать любую комбинацию переключателей.

Я бы предложил такой код:

void loop() {
    if buttonStates[0] == HIGH {
       //код для обработки нажатия кнопки 0 (контакт 2)
    }

    if buttonStates[1] == HIGH {
       //код для обработки нажатия кнопки 0 (контакт 3)
    }
    //И так далее для остальных ваших коммутаторов.
}
,

2

Если вы хотите выполнять действия в ответ на нажатие кнопок, следует позаботиться о реагировании на края сигнала, а не на уровни. Другими словами, вы выполняете действие только тогда, когда сигнал изменяется с От LOW до HIGH, а не каждый раз, когда вы видите HIGH.

Вы также должны прочитать о дребезге кнопок и либо реализовать свои собственные устранение дребезга или использование существующей библиотеки. Ниже приведен пример использования Bounce2, но есть и другие варианты:

#include <Bounce2.h>

const uint8_t pinDim    = 3;
const uint8_t pinMedium = 4;
const uint8_t pinBright = 5;

Bounce buttonDim, buttonMedium, buttonBright;

void setup() {
    buttonDim.attach(pinDim, INPUT);
    buttonMedium.attach(pinMedium, INPUT);
    buttonBright.attach(pinBright, INPUT);
}

void loop() {
    buttonDim.update();
    buttonMedium.update();
    buttonBright.update();

    if (buttonDim.rose()) {
        Serial.println("dim");
    }
    if (buttonMedium.rose()) {
        Serial.println("Medium");
    }
    if (buttonBright.rose()) {
        Serial.println("bright");
    }
}

Вы также можете, как предложено в ответе Мишеля Кейзерса, использовать массивы для булавки и объекты Bounce. Хотя это помогло бы рационализировать вызовы attach() и update(), они не помогут с мясистым часть кода, т.е. реагирующая на нажатия. Там я бы предпочел кнопка должна иметь описательные имена.

,