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

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,167
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,167
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,167
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);                                  //выключаем мотор
тут все просто и наглядно получается.