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

Я пытаюсь начать разработку системы меню для моего 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)
    }
    //И так далее для остальных ваших коммутаторов.
}
,

Проголосовал за предоставление «фактического» решения., @Michel Keijzers

Точка зрения Эдгара об обнаружении ИЗМЕНЕНИЯ состояния переключателя является хорошей, как и его точка зрения о том, что вам нужно устранить дребезг ваших кнопок. В своих проектах я создал что-то похожее на класс Bounce. Мои кнопки могут быть либо чувствительными к краю, либо чувствительными к состоянию., @Duncan C

Я не уверен, что устранение дребезга действительно важно здесь ... кажется, что пункты меню «тусклые», «яркие», «средние» ... так что не имеет значения, видна ли кнопка два или двадцать раз (результат будет еще тусклый или яркий). Это имеет значение, когда он используется для увеличения/уменьшения или выполнения действия, когда количество нажатий кнопки имеет значение., @Michel Keijzers


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(), они не помогут с мясистым часть кода, т.е. реагирующая на нажатия. Там я бы предпочел кнопка должна иметь описательные имена.

,

Я не уверен, что устранение дребезга действительно важно здесь ... кажется, что пункты меню «тусклые», «яркие», «средние» ... так что не имеет значения, видна ли кнопка два или двадцать раз (результат будет еще тусклый или яркий). Это имеет значение, когда он используется для увеличения/уменьшения или выполнения действия, когда количество нажатий кнопки имеет значение., @Michel Keijzers

@MichelKeijzers: это имеет значение для последовательного вывода. По общему признанию, это не может быть важным функционалом..., @Edgar Bonet

Проголосовал ... вы правы ... однако я думал, что Serial.println предназначен только для целей отладки., @Michel Keijzers