1 реле, 8 кнопок

Здравствуйте, уважаемые господа. Помогите решить задачу:
есть одно реле, 4 кнопки включения этого реле и 4 кнопки выключения. Кнопки сгруппированы попарно. При нажатии на кнопку реле включается и отключится только при нажатии на определенную кнопку выключения. Нажатия на другие кнопки никакого результата не дает. То же самое и с остальными тремя группами кнопок. Попробовал доработать код на управление реле двумя кнопками тупа добавив еще кнопок, но результат огорчил, реле отключается при нажатии на любую кнопку отключения. Подскажите, куда смотреть…

boolean button1WasUp = true;
boolean button2WasUp = true;
boolean button3WasUp = true;
boolean button4WasUp = true;
boolean button5WasUp = true;
boolean button6WasUp = true;
boolean button7WasUp = true;
boolean button8WasUp = true;
boolean button9WasUp = true;
boolean button10WasUp = true;
boolean button11WasUp = true;
boolean button12WasUp = true;

void setup() {
   pinMode(10, OUTPUT);
   digitalWrite(10, LOW);

   pinMode(2, INPUT_PULLUP);//вкл  1
   pinMode(3, INPUT_PULLUP);//выкл  2
   pinMode(4, INPUT_PULLUP);//вкл  3
   pinMode(5, INPUT_PULLUP);// выкл  4
   pinMode(6, INPUT_PULLUP);//вкл  5
   pinMode(7, INPUT_PULLUP);//выкл  6
   pinMode(8, INPUT_PULLUP);//вкл  7
   pinMode(9, INPUT_PULLUP);//выкл  8
   pinMode(11, INPUT_PULLUP);
   pinMode(12, INPUT_PULLUP);

   
}

void loop() {
   // узнаем, отпущены ли две кнопки сейчас
   boolean button1IsUp = digitalRead(2);
   boolean button2IsUp = digitalRead(3);

   // если кнопка 1 была отпущена и не отпущена
   if (button1WasUp && !button1IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 1
      button1IsUp = digitalRead(2);
      if (!button1IsUp) { digitalWrite(10, LOW); }
   }

   // если кнопка 2 была отпущена и не отпущена
   if (button2WasUp && !button2IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 2
      button2IsUp = digitalRead(3);
      if (!button2IsUp) { digitalWrite(10, HIGH); }
   }

   // запоминаем состояние двух кнопок ардуино
   button1WasUp = button1IsUp;
   button2WasUp = button2IsUp;
   
   // узнаем, отпущены ли две кнопки сейчас
   boolean button3IsUp = digitalRead(4);
   boolean button4IsUp = digitalRead(5);

   // если кнопка 1 была отпущена и не отпущена
   if (button3WasUp && !button3IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 1
      button3IsUp = digitalRead(4);
      if (!button3IsUp) { digitalWrite(10, LOW); }
   }

   // если кнопка 2 была отпущена и не отпущена
   if (button4WasUp && !button4IsUp) {
      delay(10);
      // повторно считываем сигнал с кнопки 2
      button4IsUp = digitalRead(5);
      if (!button4IsUp) { digitalWrite(10, HIGH); }
   }

   // запоминаем состояние двух кнопок ардуино
   button3WasUp = button3IsUp;
   button4WasUp = button4IsUp;
}

Начать с того, что подробно расписать требуемый алгоритм работы по-русски.

1 лайк

Так в Вашей программе так и написано. Если хотите по другому, запоминайте какую кнопку включения-выключения Вы нажимали последней и включайте ёё в логическое выражение под if()
Но есть нюанс, который Вы потом поймёте. Он возникает из за того, что Вам лень написать нормальный алгоритм.

@Zona_Kem
Во-первых, нужно читать не состояние кнопок, а их изменение. И переключать что-то только тогда, когда в этом цикле кнопка нажата, а в прошлом была отпущена. Иначе у вас будут ложные срабатывания.

Во-вторых, как уже сказали ранее - нужен четко описанный алгоритм. Когда включаем нагрузку. Когда выключаем. Что делать, если кнопка включения нажата второй раз при включенной нагрузке? Что делать, если несколько кнопок нажаты одновременно?

Извините, если непонятно расписал алгоритм. Попробую сделать более подробно:
1 реле, 4 кнопки включения (1,3,5,7); 4 кнопки выключения (2,4,6,8)

При нажатии кнопки 1 реле включается и остается включенным до нажатия кнопки выключения 2. После нажатия кнопки 2 реле выключается.

Нажатия на любую другую кнопку (3,4,5,6,7,8) никакого результата не дает.

При нажатии кнопки 3 реле включается и остается включенным до нажатия кнопки выключения 4. После нажатия кнопки 4 реле выключается.

Нажатия на любую другую кнопку (1,2,5,6,7,8) никакого результата не дает.

При нажатии кнопки 5 реле включается и остается включенным до нажатия кнопки выключения 6. После нажатия кнопки 6 реле выключается.

Нажатия на любую другую кнопку (1,2,3,4,7,8) никакого результата не дает.

При нажатии кнопки 7 реле включается и остается включенным до нажатия кнопки выключения 8. После нажатия кнопки 8 реле выключается.

Нажатия на любую другую кнопку (1,2,3,4,5,6) никакого результата не дает.

Запоминать номер нажатой кнопки и при нажатии отключающей проверять, можно ли выключить или проигнорировать

тогда довольно просто. Заведите две переменные - одну булеву, показывающую, включено реле или нет. И вторую цифровую, запоминающую номер кнопки, которой реле включалось последний раз.

Включаете реле любой кнопкой 1 3 5 7, если оно выключено.
Выключаем только кнопкой, чей номер на 1 больше номера кнопки включения.

Вся логика строк 15, не более

1 лайк

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

Ок.

Еще можно состояние реле запихать в ту же переменную, что и номер кнопки. Если реле включено - в переменной номер кнопки, если выключено - ноль или -1.

но это уже мелочи

1 лайк

Согласен.
Но нагляднее, наверное, через массив состояний?

возможно, но это к Евгению Петровичу, я в теории не особо :slight_smile:

Так то если следовать строго задаче, то и запоминать ничего не надо.
Все в 8 строк через while

А давайте, Вы не так сделаете, а нарисуете таблицу. В строках будут кнопки включения, а в столбцах - кнопки выключения. На пересечении ставите 0 (если эта кнопка выключения не выключает реле, включённое этой кнопкой включения) и 1 - если выключает.

Когда у Вас будет такая таблица - Вам не составит труда её запрограммировать. А пока Вы пытаетесь сказать текстом, Вы неминуемо “в четырёх кнопках запутываетесь”.

1 лайк

Как то так:

byte pinOnArr[4]={2,4,6,8};
byte pinOffArr[4]={3,5,7,9};
const byte relayPin=10;

void setup(){
    for(int i=0;i<4;i++){
        pinMode(pinOnArr[i],INPUT_PULLUP);
        pinMode(pinOffArr[i],INPUT_PULLUP);
    }
    pinMode(relayPin,OUTPUT);
}

void loop(){
    for(int i=0;i<4;i++){
        if(!digitalRead(pinOnArr[i])){
            while(digitalRead(pinOffArr[i])){
                digitalWrite(relayPin,true);
            }
            digitalWrite(relayPin,false);
        }
    }
    delay(50);
}

1 лайк

Увы, что-то не работает. Реле включено постоянно и отключается только при нажатии на кнопку 2. На остальные не реагирует ((

и не будет, пины надо привести в соответствие, да и подтяжку внутреннюю Kakmyc не учитывал.

племяннику дал вашу задачу, за 40 минут написал (немного кривовато) и схему в Wokwi сделал

Да, программирование - это не мое!!! Раз в 3 месяца пытаюсь что-то запрограммировать, 2-3 бессонные ночи и результат нулевой (((. Вот спаять что-нибудь - это да. Господа, а кто-нибудь может такую программку написать?

схему Вашу можете показать, не из интернета, не было когда то так, а схему которая сейчас и тут!

Схему чего? Как кнопки к ардуино подключаются, или фотку монтажной платы?

схему того к каким пинам и как кнопки подключены.
фотку тоже желательно