Выполнение цикла до наступления новых условий на входах.

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Заголовок темы должен отражать содержимое. Переформулируй или тема будет удалена.
Всем, доброго дня.
На автомобиле накрылся блок управления раздаточной коробкой. Аппаратно РКПП управляется обычным электродвигателем ( не шаговым), который через редуктор вращает шток в одну и другую сторону . Внутри имеются контактны с использованием которых можно знать в каком положении вилка и соответственно что включено.
Управление : нефиксируемые кнопки 4WD и LOW (пониженная передача).
С алгоритмом , наверное я понял что надо. Аппаратно реверс двигателя с использованием реле - управление через транзистор, включение контрольных ламп через транзистор не вызывает проблем.
Не могу решить задачу: нажатие кнопки 1 при наличии "1" на входах 2 3 5 ( по логике "И"), появляется "1" на вых 7 и эта единица сохраняется до появления "1" на входах 3 4 (по логике "И"). И вот таких 6 различных вариантов условий. Надеюсь немного понятно по скетчу , если его можно так назвать 😦
Плата MH-Tiny ( как Nano), дрова поставил, програмируется нормально, простые моргалки и т.д. проверил работает.
Заранее спасибо.
C++:
//  14  вход с кнопки 4WD  - кнопка 1
//  13   вход с кнопки LOW  -кнопка 2
// 2    вход 2 оранжево-белый провод от РКПП
//3    вход 3 коричнево-белый провод от РКПП
//4   вход 4 белый провод от РКПП
//5   вход 5 пурпурный от РКПП
//7    выход на реле двигателя для вращения вперед
//8    выход на реле двигателя для вращения назад
//10      выход на лампу 4WD серый провод
//11     выход на лампу LOW коричнево-белый провод
//25    выход на пищалку провод не штатный

void setup() {
  Serial.begin(9600);

  pinMode(7, OUTPUT);  //контакт 7 назначаем ВЫХОДОМ
  pinMode(8, OUTPUT);   //контакт 8 назначаем ВЫХОДОМ
  pinMode(10, OUTPUT); //контакт 10 назначаем ВЫХОДОМ
  pinMode(11, OUTPUT); //контакт 11 назначаем ВЫХОДОМ
  pinMode(25, OUTPUT); //контакт 25 назначаем ВЫХОДОМ
  pinMode(14, INPUT_PULLUP); //контакт 14 вход кнопки с неявным нулем
  pinMode(13, INPUT_PULLUP); //контакт 13 вход кнопки с неявным нулем
  digitalWrite(7, LOW); //устанавливаем сигнал 0 на выход ВПЕРЕД
  digitalWrite(8, LOW); //устанавливаем сигнал 0 на выход Назад
}

void loop() {
  boolean button1 = !digitalRead(14);
  boolean button2 = !digitalRead(13);

  // если кнопка 1 была нажата
  if (button1 == 1 && digitalRead(2) && digitalRead(3) && digitalRead(5))  //  переход от 2 WD  к 4 WD  если есть сигнал ВХоды 2 3 5
    do   {
      digitalWrite(7, HIGH);//включается двигатель вперед
    }
    while (digitalRead(3) && digitalRead(4)) ;// выполняем проверку  сигналов контактных колец до сигналов на 3 и 4
  digitalWrite(7, LOW);// остановка двигателя

  if (button1 == 1 && digitalRead(3) && digitalRead(4)) // переход от 4 WD  к 2 WD  если есть сигнал ВХоды  3 4
    do {
      digitalWrite(8, HIGH);//включается двигатель назад
    }
    while (digitalRead(2) && digitalRead(3) && digitalRead(5)); // выполняем проверку  сигналов контактных колец до сигналов на  2 3 5
  digitalWrite(8, LOW);// остановка двигателя

  if ( button1 == 1 && digitalRead(4) && digitalRead(5))  //  переход от 4 WD LOW  к 2 WD  если есть сигнал ВХоды 4 5
    do {
      digitalWrite(8, HIGH);//включается двигатель назад
    }
    while (digitalRead(2) && digitalRead(3) && digitalRead(5)) ;// выполняем проверку  сигналов контактных колец до сигналов на  2 3 5
  digitalWrite(8, LOW);// остановка двигателя

// если кнопка 2 была нажата

  if (button2 == 1 && digitalRead(2) && digitalRead(3) && digitalRead(5)) //  переход от 2 WD  к 4 WD LOW  если есть сигнал ВХоды 2 3 5
    do {
      digitalWrite(7, HIGH);//включается двигатель вперед
    }
    while (digitalRead(4) && digitalRead(5)); // выполняем проверку  сигналов контактных колец до сигналов на 4 и 5
  digitalWrite(7, LOW);// остановка двигателя

  if (button2 == 1 && digitalRead(3) && digitalRead(4)) //  переход от 4 WD  к 4 WD LOW если есть сигнал ВХоды  3 4
    do {
      digitalWrite(7, HIGH);//включается двигатель вперед
    }
    while (digitalRead(4) && digitalRead(5)); // выполняем проверку  сигналов контактных колец до сигналов на 4 и 5
  digitalWrite(7, LOW);// остановка двигателя

  if (button2 == 1 && digitalRead(4) && digitalRead(5)) //  переход от 4 WD LOW  к 4 WD  если есть сигнал ВХоды 4 5
    do {
      digitalWrite(8, HIGH);//включается двигатель назад
    }
    while  (digitalRead(3) && digitalRead(4)); // выполняем проверку  сигналов контактных колец до сигналов на 3 и 4
  digitalWrite(8, LOW); // остановка двигателя
}
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
581
175
Ваша задача содержит математическую и практическую составляющую.
Под практической составляющей я имею в виду: сколько "вариантов условий" надо обрабатывать одновременно, возможность одновременного возникновения разных вариантов, варианты имеют определенных последовательность или нет, наличие дребезга контактов, наличие наводок...
И по этой части, наверно лучше искать совет на автофорумах. Возможно там и готовые решения есть.

Без учета выше сказанного - вы не написали, что вас не устраивает в вашем коде из первого сообщения. Одно условие отрабатывает правильно? Если да, то два, потом три, потом ...
 

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Не выполняет условий. При нажатии на кнопку, подаёт сигнал на двигатель, но двигатель останавливается при исчезновении условий запуска , а должен крутить до наступления новых условий.
Про дребезг кнопок и контактных колец это уже после. Думаю сначала эта "🐟" пусть заработает.
 

viktor1703

★★★✩✩✩✩
9 Дек 2021
691
166
При нажатии на кнопку, подаёт сигнал на двигатель, но двигатель останавливается при исчезновении условий запуска
Ну так правильно, как указали так и работает. МК выполняет команды по очереди, строчка за строчкой. Давайте пройдемся так же:
C++:
if (button1 == 1 && digitalRead(2) && digitalRead(3) && digitalRead(5))  //  переход от 2 WD  к 4 WD  если есть сигнал ВХоды 2 3 5
    do   {
      digitalWrite(7, HIGH);//включается двигатель вперед
    }
    while (digitalRead(3) && digitalRead(4)) ;// выполняем проверку  сигналов контактных колец до сигналов на 3 и 4
  digitalWrite(7, LOW);// остановка двигателя
Переведите английские слова на русский и сразу станет проще понимать. Если (if) кнопка нажата, и на входе 2 высокий уровень, и на входе 3 высокий уровень, и на входе 5 высокий уровень, тогда делать (do) на выходе 7 единицу (включить мотор), пока (while) на входе 3 высокий уровень и на входе 4 высокий уровень. Но ведь пока не произошло переключение на входе 4 нет высокого уровня, условие в while не выполняется и начинает выполняться следующая команда на выходе 7 установить низкий уровень (выключить мотор). Как-то так.
 
  • Лойс +1
Реакции: Acris

Мишутк

✩✩✩✩✩✩✩
29 Мар 2025
35
6
Теперь граф состояний и переходов нарисуйте. Когда его построите, программирования минут на 10 останется.
 
  • Лойс +1
Реакции: Acris

bort707

★★★★★★✩
21 Сен 2020
3,168
934
должен крутить до наступления новых условий.
это в теории. Когда вы собираете практическое устройство, надо учитывать что в жизни бывает всякое. В частности, на практике ваше условие должно быть дополнено таймаутом, то есть оно должно звучать так: "подать ПЛЮС на пин 7 пока на пинах 3 и 4 не появится ХАЙ или пока не истечет одна минута".
Без тайм аута при любом форс-мажоре вы получите вечный цикл и зависание программы.

Что касается основого вопроса - на него @viktor1703, ответил полностью, Вам остается только внимательно вникнуть в то, что написано в сообщении #5
 
Изменено:
  • Лойс +1
Реакции: Acris

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
@viktor1703, вот именно. Как ему сказать, чтобы выполнял высокий сигнал на вых7, пока на входах 4и 3 не появятся 1? И не обращать внимания на всякие другие появления на входах . Там ведь в момент переключения разные комбинации могут вылетать в том числе дребезг.
 

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
@bort707, точно!!! Ведь я думал об этом, но не мог понять, что меня смущает. Ведь если цикл не выполнен, он встанет ни туда и ни сюда. Спасибо!!!
 

bort707

★★★★★★✩
21 Сен 2020
3,168
934
Как ему сказать, чтобы выполнял высокий сигнал на вых7, пока на входах 4и 3 не появятся 1?
у вас плохо с языком, похоже. Я имею в виду русский, а не язык программирования.

Вот смотрите - сейчас у вас в коде условие - "выполнять высокий сигнал на вых7, пока на входах 4 и 3 есть 1"
Вот эта строчка:
while (digitalRead(3) && digitalRead(4)) ;
А вам надо чтобы выполнял высокий сигнал на вых7, пока на входах 4и 3 не появятся 1 - почувствуйте разницу
 
  • Лойс +1
Реакции: Acris

BOT_Zilla

★✩✩✩✩✩✩
1 Апр 2022
21
12
Не выполняет условий.
Если я правильно понял, действие do-while должно выполняться, пока условие НЕверно:

while ( ! (digitalRead(3) && digitalRead(4)) ) ;// выполняем проверку сигналов контактных колец до сигналов на 3 и 4


т. е. крутить мотор нужно, пока на этих входах нули. И нули там на самом деле? В таблице прочерки стоят в процессе переключения. Входы в воздухе висят?
 
  • Лойс +1
Реакции: Acris

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Спасибо. Сейчас попробую. Прочерки в момент переключения, потому что там может быть все что угодно, вакханалия даже возможна. А вот когда появятся единицы на 3 и 4, а на других нули, значит включилась.
 

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Вакханалия, я имею ввиду, что в процессе перемещения вилок и контактных колец, там может меняться комбинация как угодно.
Например в самом нижнем цикле осуществляется проход через второй цикл насквозь ( по табличке которую я на листке писал).

C++:
 if (button1 == 1 && digitalRead(3) && digitalRead(4)) // переход от 4 WD  к 2 WD  если есть сигнал ВХоды  3 4
    do {
      digitalWrite(8, HIGH);//включается двигатель назад
    }
    while (!(digitalRead(2) && digitalRead(3) && digitalRead(5))); // выполняем проверку  сигналов контактных колец до сигналов на  2 3 5
  digitalWrite(8, LOW);// остановка двигателя
вот этот кусочек как будто заработал... на входы 3 и 4 подаю "1", кнопка 1 подаю "0", появляется "1" на вых 8.
-отключаю контакты 3 и 4 , вых 8 продолжает работать
-подаю "1" на вх5, потом на вх3, работает. продолжаю , подаю "1" на вх2, вых 8 потух.
Обрадовался, вот же ОНО. НО...
если начинаю имитировать процесс переключения контактных колец в другом порядке: подаю "1" на вх 2, то на вых 8 пропадает сигнал.
Т.Е. он считает, что условия выполнены как только на 2 появился высокий сигнал.
В коде попробовал поменять местами входы, сначала 3, потом 2 и 5. Все равно реагирует на 2. что то не очень получается логический элемент "И".
Как ему сказать чтобы на других входах еще поджидал нужные "0"? как сделать digitalRead чтобы он ждал "0"?
И чтобы ждал именно полной комбинации единиц и нулей на входах для прекращения действия? низкий сигнал на свободных входах можно подтянуть резисторами
 

Мишутк

✩✩✩✩✩✩✩
29 Мар 2025
35
6
Как ему сказать чтобы
State Machine, по русски Машина Состояний. Изучите, примените.

Иначе с вашим опытом и стилем программирования вы завязнете в отладке борясь с фантомными глюками (а скорее с собой). Больше посоветовать нечего.
 
  • Лойс +1
Реакции: Acris

bort707

★★★★★★✩
21 Сен 2020
3,168
934
подаю "1" на вх 2, то на вых 8 пропадает сигнал.
в той логике, что записана выше - такого быть не должно.
Либо вы ошиблись в коде в другом месте, либо у вас плавающие сигналы на пинах, так что у вас случайно "сами" замкнулись пины 3, 5 и 2. Такое вполне может быть, если у вас пины не притянуты к GND в выключенном состоянии.

не очень получается логический элемент "И".
поверьте, нет никаких сложностей с элементом "И" - ищите ошибки в коде и в схеме.
 
  • Лойс +1
Реакции: Acris

viktor1703

★★★✩✩✩✩
9 Дек 2021
691
166
действие do-while должно выполняться, пока условие НЕверно:

while ( ! (digitalRead(3) && digitalRead(4)) )
Для начала, чтобы не путаться, лучше пишите
C++:
digitalRead(3) == 1 && while (digitalRead(4) == 0)
Пока (на входе 3 высокий уровень И на входе 4 низкий уровень)
 
  • Лойс +1
Реакции: Acris

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Спасибо всем.
Сегодня уже дело к ночи. Завтра попробую на работу ноутбук взять. Спокойно в течение дня попробую варианты. Подтяну входы к нулям. Отчитаюсь по факту.
 

BOT_Zilla

★✩✩✩✩✩✩
1 Апр 2022
21
12
Попробуйте так, например переключение от 2WD к 4WD:
C++:
  if (button1==1 && digitalRead(2)==1 && digitalRead(3)==1 && digitalRead(5)==1) {  //условие для переключения
    digitalWrite(пин_мотор_вперед, HIGH);                                     //включаем мотор в нужную сторону
    while (digitalRead(3)==0 && digitalRead(4)==0) delay(10);         //ждем, пока не переключится в нужное состояние
    digitalWrite(пин_мотор_вперед, LOW);                                  //выключаем мотор
тут все просто и наглядно получается.
 
  • Лойс +1
Реакции: Acris

Николай Ск

✩✩✩✩✩✩✩
28 Мар 2023
5
1
Попробуй так без цыклов а через void yield(){ и кучу флагов
если будете умничать о правописании то помните чукча не читатель чукча писсссатель
и пишу не читая спать уже хочется
перепроверь все мог запутаться в твоих условиях





C++:
#include <EncButton.h>   //библиотека кнопок

Button a(14);         //вход с кнопки 4WD  - кнопка 1
Button b(13);        //вход с кнопки LOW  -кнопка 2
Button c(2);           //вход 2 оранжево-белый провод от РКПП
Button d(3);         //вход 3 коричнево-белый провод от РКПП
Button e(4);         //вход 4 белый провод от РКПП
Button f(5);         //вход 5 пурпурный от РКПП


#define pin_motor_up 7         //7    выход на реле двигателя для вращения вперед
#define pin_motor_down 8         //8    выход на реле двигателя для вращения назад
#define pin_led_4wd 7         //10      выход на лампу 4WD серый провод
#define pin_led_low 11       //11     выход на лампу LOW коричнево-белый провод
#define pin_bip 25           //25    выход на пищалку провод не штатный

//byte fl_motor_up = 0;             //флаг работы мотора вверх
//byte fl_motor_down = 0;           //флаг работы мотора вниз

byte fl_motor = 0;                  //флаг работы мотора вниз =-1  вверх =1 не раборает =0
byte fl_rab = 0;                    //флаг общий работы то есть идет процесс незаходи
byte fl_opera1 = 0;                 //флаг первого процесса
byte fl_opera2 = 0;
byte fl_opera3 = 0;
byte fl_opera4 = 0;
byte fl_opera5 = 0;
byte fl_opera6 = 0;



void setup() {
  Serial.begin(9600);

  pinMode(pin_motor_up, OUTPUT);             //контакт 7 назначаем ВЫХОДОМ
  pinMode(pin_motor_down, OUTPUT);           //контакт 8 назначаем ВЫХОДОМ
  pinMode(pin_led_4wd, OUTPUT);             //контакт 10 назначаем ВЫХОДОМ
  pinMode(pin_led_low, OUTPUT);             //контакт 11 назначаем ВЫХОДОМ
  pinMode(pin_bip, OUTPUT);                 //контакт 25 назначаем ВЫХОДОМ

}

void loop() {
// a.tick();        //активация кнопок если они нужны в этой фунции
// b.tick();
// c.tick();
// d.tick();
// e.tick();
// f.tick();
  delay(20);


  switch (fl_motor){
    case 0:
      digitalWrite(pin_motor_up,0);
      digitalWrite(pin_motor_down,0);          
    break;
    case 1:
      digitalWrite(pin_motor_up,1);
      digitalWrite(pin_motor_down,0);                
    break;
    case -1:
      digitalWrite(pin_motor_up,0);
      digitalWrite(pin_motor_down,1);
    break;
  }

}


void yield(){
  a.tick();    //вход с кнопки 4WD  - кнопка 1
  b.tick();    //вход с кнопки LOW  -кнопка 2
  c.tick();       //вход 2 оранжево-белый провод от РКПП
  d.tick();         //вход 3 коричнево-белый провод от РКПП
  e.tick();         //вход 4 белый провод от РКПП
  f.tick();          //вход 5 пурпурный от РКПП


  fl_rab = fl_opera1 || fl_opera2 || fl_opera3 || fl_opera4 || fl_opera5 || fl_opera6;   //флаг общей работы чтобы небыло входов пока процессы не завершон

  if(a.press()&&c.pressing()&&d.pressing()&&f.pressing()&&!fl_rab){   //условием начала процеса чегото первого
    fl_motor = 1;                 //подняли флаг вращения двигателя вверх
    fl_opera1 =1;              //я думаю нужна переменная флаг говорящий что идет первый процесс
    // t_opera1 = millis();     //также думаю нужна переменная времени нача первого процесса
  }
  if (fl_opera1 == 1&&c.pressing()&&e.pressing()){       //условие выхода из первого процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera1 = 0;               //выключили флаг первого процесса
  }


  if(a.press()&&d.pressing()&&e.pressing()&&!fl_rab){   //условием начала процеса второго
    fl_motor = -1;                 //подняли флаг вращения двигателя вниз
    fl_opera2 =1;              // флаг второго процесс
    // t_opera2 = millis();     //переменная времени нача второго процесса
  }
  if (fl_opera2 == 1&&c.pressing()&&d.pressing()&&f.pressing()){ //условие выхода из второго процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera2 = 0;               //выключили флаг второго процесса
  }

  if(a.press()&&e.pressing()&&f.pressing()&&!fl_rab){   //условием начала процеса третего
    fl_motor = -1;                 //подняли флаг вращения двигателя вниз
    fl_opera3 =1;              // флаг третьего процесс
    // t_opera3 = millis();     //переменная времени нача третьего процесса
  }
  if (fl_opera3 == 1&&c.pressing()&&d.pressing()&&f.pressing()){ //условие выхода из третьго процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera3 = 0;               //выключили флаг третьего процесса
  }

  if(b.press()&&c.pressing()&&d.pressing()&&f.pressing()&&!fl_rab){   //условием начала процеса четвертого
    fl_motor = 1;                 //подняли флаг вращения двигателя вверх
    fl_opera4 =1;              //я думаю нужна переменная флаг говорящий что идет первый процесс
    // t_opera4 = millis();     //также думаю нужна переменная времени начала  процесса
  }
  if (fl_opera4 == 1&&e.pressing()&&f.pressing()){       //условие выхода из первого процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera4 = 0;               //выключили флаг первого процесса
  }

  if(b.press()&&d.pressing()&&e.pressing()&&!fl_rab){   //условием начала процеса четвертого
    fl_motor = 1;                 //подняли флаг вращения двигателя вверх
    fl_opera5 =1;              //я думаю нужна переменная флаг говорящий что идет первый процесс
    // t_opera5 = millis();     //также думаю нужна переменная времени начала  процесса
  }
  if (fl_opera5 == 1&&e.pressing()&&f.pressing()){       //условие выхода из первого процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera5 = 0;               //выключили флаг первого процесса
  }

  if(b.press()&&e.pressing()&&f.pressing()&&!fl_rab){   //условием начала процеса четвертого
    fl_motor = 1;                 //подняли флаг вращения двигателя вверх
    fl_opera6 =1;              //я думаю нужна переменная флаг говорящий что идет первый процесс
    // t_opera6 = millis();     //также думаю нужна переменная времени начала  процесса
  }
  if (fl_opera6 == 1&&d.pressing()&&e.pressing()){       //условие выхода из первого процесса
    fl_motor = 0;                  //выключили флаг вращения двигателя
    fl_opera6 = 0;               //выключили флаг первого процесса
  }
}
 
  • Лойс +1
Реакции: Acris

BOT_Zilla

★✩✩✩✩✩✩
1 Апр 2022
21
12
Еще один вариант:
State Gear:
// Обзовем все используемые пины через константы, чтобы легче читались
const int PIN_LOW_BTN = 13;
const int PIN_4WD_BTN = 14;
const int PIN_IN2 = 2;
const int PIN_IN3 = 3;
const int PIN_IN4 = 4;
const int PIN_IN5 = 5;

const int PIN_MOTOR_FWD = 7;
const int PIN_MOTOR_REV = 8;
const int PIN_LAMP_4WD = 10;
const int PIN_LAMP_LOW = 11;
const int PIN_BUZZER = 25; //???

/*
/ Логика таблицы отслеживает только три состояния коробки, в которых двигатель всегда СТОП.
/ Состояния (по таблице):
/Входы (2–3–4–5)    Состояние
/       1 1 0 1        2WD
/       0 1 1 0        4WD
/       0 0 1 1        4WD LOW
/ Из состояния 2WD двигатель можно включить только вперед, из состояния 4WD LOW - только назад.
/ Из состояния 4WD можно включить в обе стороны.
/ Контрольные состояния соберем в перечисление, а разбирать будем через switch-case
*/
enum GearState
{
    UNKNOWN,
    STATE_2WD,
    STATE_4WD,
    STATE_4WD_LOW
};

/* Функция для опроса состояния входов, вернет текущее состояние
/ или UNKNOWN, если процесс переключения не завершен или завершен не успешо,
/ например, сгорел двигатель в коробке, или что-то заклинило.
/ Здесь этот вариант не обрабатывается.
*/
GearState currentState()
{
    bool in2 = digitalRead(PIN_IN2);
    bool in3 = digitalRead(PIN_IN3);
    bool in4 = digitalRead(PIN_IN4);
    bool in5 = digitalRead(PIN_IN5);

    if (in2 && in3 && !in4 && in5)
        return STATE_2WD;
    if (!in2 && in3 && in4 && !in5)
        return STATE_4WD;
    if (!in2 && !in3 && in4 && in5)
        return STATE_4WD_LOW;

    return UNKNOWN;
}

// опрос кнопки
bool isPressed(int pin)
{
    return digitalRead(pin) == LOW; // Если кнопки с PULLUP, без PULLUP "==LOW" убрать
}

void setup()
{ // настройка пинов
    pinMode(PIN_MOTOR_FWD, OUTPUT);
    pinMode(PIN_MOTOR_REV, OUTPUT);
    pinMode(PIN_LAMP_4WD, OUTPUT);
    pinMode(PIN_LAMP_LOW, OUTPUT);
    pinMode(PIN_BUZZER, OUTPUT);

    pinMode(PIN_LOW_BTN, INPUT_PULLUP); // это если вход подтянут к питанию,
    pinMode(PIN_4WD_BTN, INPUT_PULLUP); // если к земле через внешний резистор, то просто INPUT
    pinMode(PIN_IN2, INPUT);
    pinMode(PIN_IN3, INPUT);
    pinMode(PIN_IN4, INPUT);
    pinMode(PIN_IN5, INPUT);

    digitalWrite(PIN_MOTOR_FWD, LOW);
    digitalWrite(PIN_MOTOR_REV, LOW);
}

void loop()
{
    bool lowBtn = isPressed(PIN_LOW_BTN); // опрашиваем состояние кнопок
    bool wdBtn = isPressed(PIN_4WD_BTN);

    if (lowBtn && wdBtn)
        return; // защита от дурака: одновременное нажатие — ничего не делаем

    GearState state = currentState(); // получаем текущее состояние входов

    switch (state)
    {
    case STATE_2WD:
        /*
        / Из этого состояния может двигаться только вперед,
        / к положению 4WD, поэтому проверяем только одну кнопку
        */
        if (wdBtn)
        {
            // Если нажата кнопка 4WD, переключаемся 2WD -> 4WD (вперёд)
            digitalWrite(PIN_MOTOR_FWD, HIGH); // включаем мотор вперед
            while (state != STATE_4WD)
            {
                state = currentState(); // получаем текущее состояние входов
                delay(10);
            }
            digitalWrite(PIN_MOTOR_FWD, LOW);
            digitalWrite(PIN_LAMP_4WD, HIGH);
            digitalWrite(PIN_LAMP_LOW, LOW);
        }
        break;

    case STATE_4WD:
        /*
        / Из этого положения можем двигаться как вперед к 4WD LOW,
        / так и назад к 2WD, поэтому контролируем обе кнопки
        */
        if (wdBtn)
        {
            // Переход 4WD -> 2WD (назад)
            digitalWrite(PIN_MOTOR_REV, HIGH);
            while (state != STATE_2WD)
            {
                state = currentState();
                delay(10);
            }
            digitalWrite(PIN_MOTOR_REV, LOW);
            digitalWrite(PIN_LAMP_4WD, LOW);
            digitalWrite(PIN_LAMP_LOW, LOW);
        }
        else if (lowBtn)
        {
            // Переход 4WD -> 4WD LOW (вперёд)
            digitalWrite(PIN_MOTOR_FWD, HIGH);
            while (state != STATE_4WD_LOW)
            {
                state = currentState();
                delay(10);
            }
            digitalWrite(PIN_MOTOR_FWD, LOW);
            digitalWrite(PIN_LAMP_4WD, HIGH);
            digitalWrite(PIN_LAMP_LOW, HIGH);
        }
        break;

    case STATE_4WD_LOW:
        /*
        / Из этого положения можем двигаться только назад, к положению 4WD,
        / контролируем только одну кнопку
        */
        if (lowBtn)
        {
            // Переход 4WD LOW -> 4WD (назад)
            digitalWrite(PIN_MOTOR_REV, HIGH);
            while (state != STATE_4WD)
            {
                state = currentState();
                delay(10);
            }
            digitalWrite(PIN_MOTOR_REV, LOW);
            digitalWrite(PIN_LAMP_4WD, HIGH);
            digitalWrite(PIN_LAMP_LOW, LOW);
        }
        break;

    default:
        // В переходном или ошибочном состоянии ничего не делаем
        break;
    }
}
 
  • Лойс +1
Реакции: Acris

Acris

✩✩✩✩✩✩✩
20 Апр 2025
12
0
Уже сменил :) действительно как-то обозвал тему сначала кривенько, не понятно было чего ищу.
@BOT_Zilla,
ЗАРАБОТАЛО!!!
Все отрабатывает как положено. СПАСИБО. Теперь буду добивать Ваш код. Его "рыбой" назвать неудобно, такой колоссальный труд.
Буду пытаться втолкнуть зуммер в момент работы исполнительного механизма .
Не понятно как будет реагировать если алгоритм, если при переключении все встанет "ни туда, ни сюда". Т.Е. получится вечный цикл по while.
 

BOT_Zilla

★✩✩✩✩✩✩
1 Апр 2022
21
12
встанет "ни туда, ни сюда"
в цикле while запустите таймер, по истечении которого сделайте break. Выше об этом уже напоминали.
В частности, на практике ваше условие должно быть дополнено таймаутом, то есть оно должно звучать так: "подать ПЛЮС на пин 7 пока на пинах 3 и 4 не появится ХАЙ или пока не истечет одна минута".
Без тайм аута при любом форс-мажоре вы получите вечный цикл и зависание программы.
 
  • Лойс +1
Реакции: Acris