Кнопки и светодиод

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
Добрый день. В ардуино новичок и пока мало в чем разбираюсь, но желание как говорится имеется)
В общем не могу сообразить как сделать следующее условие:
Есть 2 кнопки и 2 светодиода. Суть в том, что при нажатии одной кнопки должен гореть 1 светодиод и блокироваться (игнорироваться) нажатие второй кнопки. Т.е. если кнопка 1 нажата, то горит светодиод 1 и игнорируется нажатие кнопки 2. Вроде понимаю, что тут явное if else, но вот построить конструкцию что то не получается
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,262
1,300
Москва
if (кнопка1нажата)
{
естьзапретнанажатиекнопки_2;
//обрабатывается нажатие кнопки 1
}
else
нетзапретананажатиекнопки_2;
if (нетзапретананажатиекнопки2 && кнопка_2нажата)
{
//обрабатывается нажатие кнопки 2.
}
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
C++:
if (btn1 && (! btn2)) {digitalWrite(LED1, HIGH);}
if ((! btn1) && btn2) {digitalWrite(LED2, HIGH);}
if (! btn1)  {digitalWrite(LED1, LOW);}
if (! btn2)  {digitalWrite(LED2, LOW);}
где btn == true - кнопка нажата
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
Видимо я не очень четко изложил мысль)
Диод должен гореть пока держу кнопку.
Сейчас при нажатии кнопок диоды горят по очереди, а при нажатии двух кнопок оба тухнут. А нужно чтобы пока горит один, я не мог включить второй.
Кнопка:
int btn1 = 11; // кнопка №1 — порт 11
int btn2 = 12; // кнопка №2 — порт 12
int led1 = 13; // порт 13, для светодиода
int led2 = 14; // порт 14, для светодиода

void setup()
{
  // Установим порты кнопок как входящие:
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);

  // Установим порт светодиода как исходящий:
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}

void loop()
{
  int button1State, button2State; // переменные для сохранения состояния кнопок

  button1State = digitalRead(btn1);
  button2State = digitalRead(btn2);

  if (button1State && (!button2State))
  {
    digitalWrite(led1, HIGH);
  }
  if ((!button1State) && button2State)
  {
    digitalWrite(led2, HIGH);
  }
  if (!button1State)
  {
    digitalWrite(led1, LOW);
  }
  if (!button2State)
  {
    digitalWrite(led2, LOW);
  }
}
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@Flickster, нужен полный алгоритм.
1. Кнопка 1 не нажата - светодиод 1 не горит.
1.1. Кнопка 2 не нажата - светодиод 2 не горит. Реагируем на нажатие кнопки 1 и кнопки 2.
1.2. Кнопка 2 нажата - светодиод 2 горит. Реагируем на отпускание кнопки 2.
2. Кнопка 2 не нажата - светодиод 2 не горит.
2.1. Кнопка 1 не нажата - светодиод 1 не горит. Реагируем на нажатие кнопки 1 и кнопки 2.
2.2. Кнопка 1 нажата. Реагируем на отпускание кнопки 1.
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@poty, я бы сказал вот так:
1. Кнопка 1 не нажата - светодиод 1 не горит.
1.1. Кнопка 2 не нажата - светодиод 2 не горит. Реагируем на нажатие кнопки 1 и кнопки 2.
1.2. Кнопка 2 нажата - светодиод 2 горит. Реагируем на отпускание кнопки 2 и не реагируем на нажатие кнопки 1.
2. Кнопка 2 не нажата - светодиод 2 не горит.
2.1. Кнопка 1 не нажата - светодиод 1 не горит. Реагируем на нажатие кнопки 1 и кнопки 2.
2.2. Кнопка 1 нажата. Реагируем на отпускание кнопки 1 и не реагируем на нажатие кнопки 2 .
Т.е. мне нужна схема в которой кто первый нажал, тот свой светодиод и зажег
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@poty,
Кнопка 1 нажимается и загорается светодиод 1. В течении 15 секунд он горит (например). Пока горит светодиод 1, данные с кнопки 2 игнорируются.
Соответственно так же с кнопкой 2: пока горит диод 2 кнопка 1 игнорируется
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@bort707, не совсем понял вопрос. У меня кнопка от обычного пк. Подключена через резистор в разрыв
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@bort707, с gnd идёт на монтажная плату на "-". В "-" подключен резистор одной ногой, а вторая нога идёт на кнопку (её белый провод). Второй провод от кнопки на панели 11 посажен. Кнопки две. Вторая аналогично на 12 посажена
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
вот это и называется "замыкается на GND". Это означает, что у вас при нажатии кнопки на ней LOW, а у меня - я специально вам написал в примечании - код для замыкания на HIGH
Инвертируйте логику и проверьте снова
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@bort707, буду знать. Все заработал! Благодарен Вам за помощь. Не обращал на это внимание при изучении уроков Гайвера.
Еще вопросы по той же схеме:
1. Есть ли логическая функция игнора или ее имитация. Может отключение пина или что то похожее. Сейчас когда нажимаю две кнопки светодиоды оба гаснут.
2. Как сделать так, чтобы светодиод горел после нажатия кнопки еще N мс и это не тормозило всю программу. millis я так понимаю дадут мне паузу после выполнения действия, а не время выполнения действия
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
1 нет
2 используйте миллис, он для этого

Сорри за краткость, с телефона пишу
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
1. Есть ли логическая функция игнора или ее имитация. Может отключение пина или что то похожее. Сейчас когда нажимаю две кнопки светодиоды оба гаснут.
В этом нет необходимости, это просто реализуется через логику - если кнопка 1 нажата, вторую просто не опрашиваете.

2. Как сделать так, чтобы светодиод горел после нажатия кнопки еще N мс и это не тормозило всю программу. millis я так понимаю дадут мне паузу после выполнения действия, а не время выполнения действия
При отпускании кнопки запоминаете время, когда это произошло. Даллее в цикле, если текущее время >= запомненного + дельта, выключаете.
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@Flickster, это значительно отличается от первоначальной постановки задачи. В первой постановке задачи было 4 состояния, в текущей постановке задачи с задержкой выключения их целых 16! И что-то я не видел ни одной Вашей попытки хоть что-то написать самому. К чему тогда писать в раздел "Программирование"?
Фигня с кнопками:
int btn1 = 11;    // кнопка №1 — порт 11
int btn2 = 12;    // кнопка №2 — порт 12
int led1 = 13;    // порт 13, для светодиода
int led2 = 14;    // порт 14, для светодиода
                // статусы состояний
#define B1HOLD    B00000001    // нажата первая кнопка
#define B2HOLD    B00000010    // нажата вторая кнопка
#define B1TO    B00000100    // у первой кнопки произошёл таймаут
#define B2TO    B00001000    // у второй кнопки произошёл таймаут
                // таймеры кнопок
unsigned long timer1;
unsigned long timer2;

byte flags = 0;    // флаг состояния

void setup()
{
    // Установим порты кнопок как входящие:
    pinMode(btn1, INPUT_PULLUP);
    pinMode(btn2, INPUT_PULLUP);

    // Установим порт светодиода как исходящий:
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
   
    // Выключим светодиоды
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
}

void loop()
{
    if (digitalRead(btn1)) {
        // первая кнопка не нажата
        switch (flags) {
            case 0:    // никаких событий не зафиксировано, кнопка 1 проверена, проверяем вторую кнопку
                if (!digitalRead(btn2)) {
                    // вторая кнопка только что нажата - сохраняем, включаем, взводим таймер
                    flags |= B2HOLD;
                    digitalWrite(led2, HIGH);
                    timer2 = millis();
                }
                break;
            case B2TO|B1TO|B2HOLD|B1HOLD:
                // таймаут обеих кнопок, (оба LED выключены) первая кнопка отжимается, выключаем таймаут,
                // обрабатываем отпускание кнопки 1 без таймаута
            case B1TO|B2HOLD|B1HOLD:
                // кнопка 1 в таймауте (LED1 выключен), отжимается, вторая кнопка нажата (LED2 включен) -
                // выключаем таймаут кнопки 1, отрабатываем отпускание кнопки 1 без таймаута
            case B1TO|B1HOLD:
                // кнопка 1 в таймауте (LED1 выключен), кнопка 2 отжата (LED2 выключен),
                // отжимается кнопка 1 - выключаем таймаут и отрабатываем отпускание кнопки без таймаута
                flags &= ~B1TO;
            case B2TO|B2HOLD|B1HOLD:
                // таймаут второй кнопки (LED2 выключен), первая кнопка нажата (LED1 включен)
                // отжимается первая кнопка отжата - отрабатываем отжатие
            case B1HOLD:
                // кнопка 1 нажата (LED1 включен), отжимается кнопка 1 - сохраняем, выключаем
                flags &= ~B1HOLD;
                digitalWrite(led1, LOW);
                break;
            case B2HOLD:
                // кнопка 2 нажата (LED2 включен), проверяем изменение кнопки 2
                if (digitalRead(btn2)) {
                    // кнопку 2 отжали - сохраняем, выключаем
                    flags &= ~B2HOLD;
                    digitalWrite(led2, LOW);
                } else {
                    // кнопка 2 удержана
                    if (millis() - timer2 >= TIMEOUT) {
                        // таймаут кнопки 2 - сохраняем, выключаем
                        flags |= B2TO;
                        digitalWrite(led2, LOW);
                    }
                }
                break;
            case B2TO|B2HOLD:
                // таймаут второй кнопки (LED2 выключен), проверяем изменение кнопки 2
                if (digitalRead(btn2)) {
                    // отжата вторая кнопка - сохраняем
                    flags &= ~(B2TO|B2HOLD);
                }
                break;
        /* с этого момента можно удалить */
            case B2HOLD|B1HOLD:
                // нажаты две кнопки без таймаута - невозможная комбинация
            case B1TO:
                // таймаут первой кнопки, но кнопка не нажата - невозможная комбинация
            case B1TO|B2HOLD:
                // таймаут первой кнопки, нажата вторая кнопка, но первая кнопка не нажата
                // невозможная комбинация
            case B2TO:
                // таймаут второй кнопки, но она не нажата - невозможная комбинация
            case B2TO|B1HOLD:
                // таймаут второй кнопки, но она не нажата, первая кнопка нажата -
                // невозможная комбинация
            case B2TO|B1TO:
                // произошёл таймаут обеих кнопок без их нажатия - невозможная комбинация
            case B2TO|B1TO|B1HOLD:
                // произошёл таймаут обеих кнопок без нажатия второй кнопки - невозможная комбинация
            case B2TO|B1TO|B2HOLD:
                // произошёл таймаут обеих кнопок без нажатия первой кнопки - невозможная комбинация
                break;
        /* до этого момента можно удалить */
        }
    else {
        // первая кнопка нажата
        switch (flags) {
            case B2TO|B2HOLD:
                // таймаут второй кнопки (LED2 выключен), отрабатываем нажатие кнопки 1
            case 0:
                // никаких событий не зафиксировано, первая кнопка только что нажата
                // сохраняем, включаем, взводим таймер
                flags |= B1HOLD;
                digitalWrite(led1, HIGH);
                timer1 = millis();
                break;
            case B2TO|B2HOLD|B1HOLD:
                // произошёл таймаут второй кнопки, она была нажата, первая кнопка была нажата
            case B1HOLD:
                // удерживаем кнопку 1 (LED1 включен), проверяем таймаут
                if (millis() - timer1 >= TIMEOUT) {
                    // произошёл таймаут нажатия кнопки - сохраняем, выключаем
                    flags |= B1TO;
                    digitalWrite(led1, LOW);
                }
            case B1TO|B2HOLD|B1HOLD:
                // таймаут кнопки 1 (LED1 выключен), кнопка 2 нажата (LED2 включен)
            case B2HOLD:
                // нажата вторая кнопка (LED2 включен)
                if (digitalRead(btn2)) {
                    // вторая кнопка отжата - сохраняем, выключаем
                    flags &= ~B2HOLD;
                    digitalWrite(led2, LOW);
                } else {
                    if (millis()-timer2 >= TIMEOUT) {
                        // произошёл таймаут нажатия кнопки 2 - сохраняем, выключаем
                        flags |= B2TO;
                        digitalWrite(led2, LOW);
                    }
                }
                break;
            case B1TO|B1HOLD:
                // таймаут кнопки 1 (LED1 выключен) - разрешено нажать вторую кнопку
                if (!digitalRead(btn2)) {
                    // вторая кнопка нажата
                    flags |= B2HOLD;
                    digitalWrite(led2, HIGH);
                    timer2 = millis();
                }
                break;
            case B2TO|B1TO|B2HOLD|B1HOLD:
                // произошёл таймаут обеих кнопок и они обе нажаты, кнопка 1 проверена
                if(digitalRead(btn2)) {
                    // вторая кнопка отжата
                    flags &= ~(B2TO|B2HOLD);
                }
                break;
        /* с этого момента можно удалить */
            case B1HOLD|B2HOLD:
                // были нажаты две кнопки и не было таймаута - невозможная комбинация
            case B1TO:
                // произошёл таймаут первой кнопки, но кнопка не нажата - невозможная комбинация
            case B1TO|B2HOLD:
                // произошёл таймаут первой кнопки, удерживается вторая кнопка, но первая кнопка не нажата
                // невозможная комбинация
            case B2TO:
                // произошёл таймаут второй кнопки, но она не нажата - невозможная комбинация
            case B2TO|B1HOLD:
                // произошёл таймаут второй кнопки, но она не нажата, первая кнопка нажата -
                // невозможная комбинация
            case B2TO|B1TO:
                // произошёл таймаут обеих кнопок без их нажатия - невозможная комбинация
            case B2TO|B1TO|B1HOLD:
                // произошёл таймаут обеих кнопок без нажатия второй кнопки - невозможная комбинация
            case B2TO|B1TO|B2HOLD:
                // произошёл таймаут обеих кнопок без нажатия первой кнопки - невозможная комбинация
                break;
        /* до этого момента можно удалить */
        }      
    }
}
Предупреждаю, код не проверен!
 

Flickster

✩✩✩✩✩✩✩
2 Июн 2021
10
0
@poty, за код спасибо, буду изучать его. Попытки написать самому я вот уже 3 ночи делаю. Просто в голове куча разрозненной информации и полное непонимание как её собрать воедино. Пробую строчку за строчкой...

@rGlory, Немного изменил код и перешел на кейсы. 2й момент я победил. Но есть одно но; проскакивают короткие так сказать горения светодиодов минуя милис.
По поводу первого не совсем понял как это реализовать.

Кнопки:
int btn1 = 11;    // кнопка №1 — порт 11
int btn2 = 12;    // кнопка №2 — порт 12
int led1 = 13;    // порт 13, для светодиода
int led2 = 14;    // порт 14, для светодиода

// статусы состояний
#define B1HOLD    B00000001    // нажата первая кнопка
#define B2HOLD    B00000010    // нажата вторая кнопка
#define B1TO    B00000100    // у первой кнопки произошёл таймаут
#define B2TO    B00001000    // у второй кнопки произошёл таймаут

// таймеры кнопок
unsigned long timer1;
unsigned long timer2;

#define DEBOUNCE 300
unsigned long debounceTimer;

byte flags = 0;    // флаг состояния

void setup()
{
  Serial.begin(9600); //включаем com порт

  // Установим порты кнопок как входящие:
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);

  // Установим порт светодиода как исходящий:
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  // Выключим светодиоды
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
}

void loop()
{
  if (!digitalRead(btn1))
    flags = B1HOLD;
  if (!digitalRead(btn2))
    flags = B2HOLD;

  switch (flags) {
    case 0: 
      break;

    case B1HOLD:
      if (millis() - debounceTimer > DEBOUNCE) {
        digitalWrite(led1, HIGH);
        Serial.println("B1HOLD");
        flags = B1TO;
        debounceTimer = millis();
      }
      break;

    case B2HOLD:
      if (millis() - debounceTimer > DEBOUNCE) {
        digitalWrite(led2, HIGH);
        Serial.println("B2HOLD");
        flags = B2TO;
        debounceTimer = millis();
      }
      break;

    case B1TO:
      if (millis() - timer1 >= 4000) {
        digitalWrite(led1, LOW);
        flags = 0;
        Serial.println("B1TO");
        timer1 = millis();
      }
      break;

    case B2TO:
      if (millis() - timer2 >= 4000)
      {
        digitalWrite(led2, LOW);
        flags = 0;
        Serial.println("B2TO");
        timer2 = millis();
      }
      break;
  }
}
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Резистор здесь не нужен. Кнопка включается между портом Ардуино и GND
сомнительное заявление.
Представьте - вы случайно приписываете этот порт на выход и подаете HIGH, замыкаете кнопку - и можете попращаться с портом. Или еще проще - прошиваете в эту плату другой код...
Хорошей практикой будет ВСЕГДА подключать кнопку через резистор 300-500 Ом
 
  • Лойс +1
Реакции: rGlory