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

Acris

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

viktor1703

★★★✩✩✩✩
9 Дек 2021
691
164
При нажатии на кнопку, подаёт сигнал на двигатель, но двигатель останавливается при исчезновении условий запуска
Ну так правильно, как указали так и работает. МК выполняет команды по очереди, строчка за строчкой. Давайте пройдемся так же:
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 установить низкий уровень (выключить мотор). Как-то так.
 

Мишутк

✩✩✩✩✩✩✩
29 Мар 2025
34
3
Теперь граф состояний и переходов нарисуйте. Когда его построите, программирования минут на 10 останется.
 

bort707

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

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

Acris

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

Acris

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

bort707

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

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

BOT_Zilla

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

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


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

Acris

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

Acris

✩✩✩✩✩✩✩
20 Апр 2025
9
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
34
3
Как ему сказать чтобы
State Machine, по русски Машина Состояний. Изучите, примените.

Иначе с вашим опытом и стилем программирования вы завязнете в отладке борясь с фантомными глюками (а скорее с собой). Больше посоветовать нечего.
 

bort707

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

не очень получается логический элемент "И".
поверьте, нет никаких сложностей с элементом "И" - ищите ошибки в коде и в схеме.
 

viktor1703

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

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

Acris

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

BOT_Zilla

✩✩✩✩✩✩✩
1 Апр 2022
18
8
Попробуйте так, например переключение от 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);                                  //выключаем мотор
тут все просто и наглядно получается.
 

Николай Ск

✩✩✩✩✩✩✩
28 Мар 2023
5
0
Попробуй так без цыклов а через 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;               //выключили флаг первого процесса
  }
}