if(val == 0) игнорируется, когда он содержит другой вложенный оператор if()

c++

Проблема: В следующем примере, несмотря на то, что complexManoeuvre == 3, Serial.print(CTA5: "); ... выполняется.

void loop()  {
  if(complexManoeuvre == 0) {
    if(timeisup == true && goingForwards == 1)  {   // Если время истекло при движении вперед, предположим, что оно застряло
      goingForwards = 0;
      Serial.print("CTA4: "); stuck(stk);
    }
    if(timeisup == true && goingForwards != 1)  {   
      Serial.print("CTA5: "); Serial.print(complexManoeuvre); forward(fwd);
    }
  }
}

Однако, если я включу первое условие в другие два утверждения if(), то это сработает:

if(complexManoeuvre == 0 && (deltaBegan >= manoeuvreFor) && goingForwards == 1) {
  goingForwards = 0;
  Serial.print("CTA4: "); Serial.print(complexManoeuvre); stuck(stk);
}
if(complexManoeuvre == 0 && (deltaBegan >= manoeuvreFor) && goingForwards != 1) {
  //Serial.print("complexManoeuvre == "); Serial.println(complexManoeuvre);
  Serial.print("CTA5: "); Serial.print(complexManoeuvre); forward(fwd);
}

Будучи полностью озадаченным, я заподозрил проблему с компилятором, поэтому я переустановил Arduino, чтобы очистить оболочку Meguno-link avrdude, но проблема остается.

Полный код (для робота-пылесоса) выглядит следующим образом, максимально сокращенный для упрощения чтения:

const int fwd = 12000;            // длительность мс
const int stk = 1600;
unsigned long beganManoeuvre;     // миллис время начала маневра
int manoeuvreFor;                 // Длительность
unsigned long lastStuck;
byte goingForwards;               // Да или нет
byte complexManoeuvre;            // 0 = нет, 1 = центр, 2 = застрял, 3 = прогресс
byte progress;                    // Прогресс сложного управления

void setup() {
  Serial.begin(9600);
  Serial.print(F("CTA0: ")); spinR(4800);     // Вращение на 360 градусов
}

void loop() {  
  bool timeisup = false;
  if((millis() - beganManoeuvre) >= manoeuvreFor) {
    timeisup = true;
  }
  
  if(complexManoeuvre != 0 && timeisup == true)  {          // Если часть пути через a в сложном
    switch(complexManoeuvre)  {                             // ..маневр (например; застрял)
    case 1:
      // делать другое()
      break;
    case 2: 
      Serial.print(F("CTA2: ")); stuck(manoeuvreFor);       // возврат к сложному маневру
      break;
    }
  }
  
// если(сложный маневр == 0 && timeisup == true && Движение вперед == 1) {
// Движение вперед = 0;
// Serial.print("CTA4: "); Serial.print(сложный процесс); застрял (stk);
//  }
// если(complexManoeuvre == 0 && timeisup == true && Вперед!= 1) {
// //Serial.print("complexManoeuvre == "); Serial.println(complexManoeuvre);
// Serial.print("CTA5: "); Serial.print(complexManoeuvre); вперед (fwd);
//  }
  if(complexManoeuvre == 0) {
    if(timeisup == true && goingForwards == 1)  {   // Если timeisup при движении вперед, предположим, что застрял
      goingForwards = 0;
      Serial.print("CTA4: "); stuck(stk);
    }
    if(timeisup == true && goingForwards != 1)  {   // Если закончен еще один маневр, двигайтесь вперед
      if(complexManoeuvre != 0) Serial.println("What the?!");
      Serial.print("CTA5: "); Serial.print(complexManoeuvre); forward(fwd);
    }
  }
}

void stuck(int dur)  {
  Serial.print(F("void stuck(int dur == "));  Serial.println(dur);
  switch(progress) {                   
  case 0:
    Serial.print(F("CTA26: ")); 
    complexManoeuvre = 2;
    reverse(dur);
    progress = 1;
    break;
  case 1:
    Serial.print(F("CTA27: ")); 
    spinR(dur);
    progress = 2;
    break;
  case 2:                     // Сброс
    progress = 0;
    complexManoeuvre = 0;
    lastStuck = millis();
    break;
  }
}

void forward(int dur)  {
  Serial.print(F("void forward(int ")); Serial.print(dur); 
  if(goingForwards != 1) {
      Serial.print(F(") >> if(goingForwards != 1) then do"));
      goingForwards = 1;
      beganManoeuvre = millis();
      manoeuvreFor = dur;
      digitalWrite(9, HIGH);
      digitalWrite(10, LOW);
      digitalWrite(11, HIGH);
      digitalWrite(12, LOW);
  }
  Serial.println();
}

void reverse(int dur)  {
  Serial.print(F("void reverse(int dur == "));  Serial.println(dur);
  beganManoeuvre = millis();
  manoeuvreFor = dur;
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  digitalWrite(11, LOW);
  digitalWrite(12, HIGH);
}

void spinR(int dur) {
  Serial.print(F("void spinR(int dur == "));  Serial.println(dur);
  beganManoeuvre = millis();
  manoeuvreFor = dur;
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, LOW);
}

Сомнительный последовательный вывод таков:

1) 19:59:31.964 -> CTA0: void spinR(int dur == 4800
2) 19:59:36.765 -> CTA5: 0void forward(int 12000) >> if(goingForwards != 1) then do
3) 19:59:48.771 -> CTA4: void stuck(int dur == 1600
4) 19:59:48.811 -> CTA26: void reverse(int dur == 1600
5) 20:11:12.695 -> What the?!
6) 19:59:48.851 -> CTA5: 2void forward(int 12000) >> if(goingForwards != 1) then do
7) 20:00:00.854 -> CTA2: void stuck(int dur == 12000
8) 20:00:00.894 -> CTA27: void spinR(int dur == 12000
9) 20:00:12.860 -> CTA2: void stuck(int dur == 12000
10) 20:00:12.900 -> CTA4: void stuck(int dur == 1600
...

Редактировать, чтобы добавить: Версия Arduino 1.8.13, Win7, протестирована на Nano Atmega168PA и Mega2560

, 👍2

Обсуждение

if(timeisup == true) эквивалентно if(true == true), что является избыточным... if (timeisup) - это то же самое, @jsotola


1 ответ


1

Ваша пустота застряла() { ... }, который вызывается внутри первого if (timeisup == true && goingForwards == 1) { ... } может установить complexManoeuvre в ненулевое значение, прежде чем будет достигнуто второе if (timeisup == true && goingForwards != 1) { ... } (тот, у которого "Что за?!").

,

точно Serial.print(F("CTA26: ")); complexManoeuvre = 2; recerse(dur);, @Juraj

Но, если я не ошибаюсь, это нужно сделать для того, чтобы процесс вернулся к stuck(), чтобы продолжить через переключатель (прогресс)., @lsbyte

Это не совсем "может установить", он установит его равным 2, @KIIV

Измените инструкции if() на вторую версию, и все будет работать так, как должно. Но... вот чего я не понимаю., @lsbyte

@lsbyte Возможно, ему нужно это сделать, но после завершения заблокированного вызова он продолжит обработку команд после этого вызова. Это означает, что он выходит из первого вложенного блока if {}, и угадайте что, другой вложенный if находится сразу после этого первого., @KIIV

Но разве прогресс не должен увеличиваться только один раз каждый раз, когда процесс посещает stuck()? Я не понимаю, как изменение операторов if() в цикле может повлиять на поведение переключателя (прогресс), @lsbyte

@lsbyte Вы делаете в значительной степени это int a = 0; if (a == 0) { a = 2; } if (a != 0) { Serial.println("но почему?"); } и вы спрашиваете, почему a не равно нулю, после вы изменили его на 2. У `застрявшего" есть "побочные эффекты", и один из них - изменение "Сложного маневра"., @KIIV

Давайте [продолжим это обсуждение в чате] (https://chat.stackexchange.com/rooms/115843/discussion-between-lsbyte-and-kiiv )., @lsbyte