Многократная проверка нескольких операторов "if"

Этот код является частью длинного кода для робота, который одновременно избегает препятствий и дистанционного управления. Я пытаюсь получить код, чтобы проверить оба оператора "if", когда кодовый номер FF807F получен с ИК-пульта дистанционного управления. Когда кодовый номер получен , программа проверяет оба оператора "if" и выполняет тот, который является истинным. Я хочу, чтобы программа, как только она закончит выполнять истинный оператор "if", снова проверила оба оператора "if".

void loop () {
if (My_Decoder.value==0xFF807F){
 if (cm<6)
 {
  motor_stop();
  digitalWrite(backlights, HIGH);
  delay(2000);
  motor_backward();
  digitalWrite(backlights, HIGH);
  Serial.println("backward");
  delay(2000);
  motor_stop();
  digitalWrite(backlights, HIGH);
  delay(900);
  motor_right();
  digitalWrite(backlights, LOW);
  Serial.println("right");
  delay(1000);
}
if (cm>6)
 {
  motor_forward();
  digitalWrite(backlights, LOW);
  Serial.println("forward");
}
}
}       

, 👍1

Обсуждение

Что меняет My_Decoder.value? Если cm ровно 6, вы ничего не хотите делать, верно?, @Nick Gammon


4 ответа


1

У вас отсутствует случай, когда "cm == 6".

Вам не нужно делать два "если"; одного "если-еще" достаточно, потому что это либо одно, либо другое.

Вам не нужно/не нужно проверять дважды; "cm" не меняется внутри "если". Но я вас хочу, используйте функции:

void loop () {
  if (My_Decoder.value == 0xFF807F) {
    doSomething();
    doSomething();
  }
}

void doSomething() {
  if (cm < 6) {
    motor_stop();
    digitalWrite(backlights, HIGH);
    // ...
    delay(1000);
  } else {
    motor_forward();
    digitalWrite(backlights, LOW);
    Serial.println("forward");
  }
}
,

Приведенный выше код работает, однако я хочу, чтобы он повторял функцию "void doSomething();" до тех пор, пока не будет нажата другая кнопка. Когда я нажимаю кнопку дистанционного управления, она выполняет эту функцию только один раз., @Matthew Amisi


2

Я собираюсь предположить, что вы не хотите включать cm == 6, поэтому у вас есть оба случая. Я бы рассмотрел возможность использования цикла while вместо единичного оператора "если", чтобы постоянно проверять, нажимаются эти кнопки или нет (в то время как (cm<6){делайте это}). В противном случае он проверит один раз и больше никогда не проверит.

Вместо этого он перейдет к следующему оператору "если", он завершится ошибкой, а затем перейдет в верхнюю часть цикла, где он проверит код 0xFF807F. Дай мне знать, как все пройдет!

,

1
if (My_Decoder.value == 0xFF807F) {
if (cm<6)

Вы хотите, чтобы оба "если" произошли? Может быть, побитовый оператор типа логического И (&)?

,

& имеет смысл только в том случае, если биты связаны друг с другом-здесь будет использоваться *логический*&&; значение == 0xFF807F && cm < 6`., @Dave Newton


0

Это выглядит как хорошее применение для конечного автомата.

Это выглядело бы примерно так:

typedef enum State
{
  STATE_IDLE,
  STATE_THIS,
  STATE_THAT,
  STATE_OTHER
} State;

State state;

const int IR_BUTTON_1    = 0xFF807F;
const int IR_BUTTON_2    = 0x112233;
const int IR_BUTTON_3    = 0X445566;
const int IR_BUTTON_STOP = 0x778899;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("setup()"));
  state = STATE_IDLE;
}

void loop()
{
  Serial.println(F("loop()"));

  switch(my_decoder.value)
  {
    case IR_BUTTON_1:
      state = STATE_THIS;
      Serial.println(F("Entered STATE_THIS"));
      break;
    case IR_BUTTON_2:
      state = STATE_THAT;
      Serial.println(F("Entered STATE_THAT"));
      break;
    case IR_BUTTON_3:
      state = STATE_OTHER;
      Serial.println(F("Entered STATE_OTHER"));
      break;
    case IR_BUTTON_STOP:
      state = STATE_IDLE;
      Serial.println(F("Entered STATE_IDLE"));
      break;
  }

  switch(state)
  {
    case STATE_THIS:
      DoThis();
      break;
    case STATE_THAT:
      DoThat();
      break;
    case STATE_OTHER:
      DoOther();
      break;
  }
}

void DoThis()
{
  Serial.println(F("DoThis()"));
}

void DoThat()
{
  Serial.println(F("DoThat()"));
}

void DoOther()
{
  Serial.println(F("DoOther()"));
}

Это блокирует конечный автомат в активное состояние в соответствии с комментарием OP:

Я хочу, чтобы он повторял функцию "void doSomething();" до тех пор, пока не будет нажата другая кнопка.

Однако, как указал Дэйв Ньютон в комментариях, блокировка машины в определенное активное состояние может быть опасной, поэтому я отредактировал код, чтобы добавить кнопку остановки для перехода обратно в состояние простоя. Но это все еще зависит от оператора, нажимающего кнопку STOP, чтобы вернуться к холостому ходу; нет автоматического возврата к холостому ходу, который может быть опасен в зависимости от приложения.

,

Хм, может быть. Я думаю, что если бы это был "невырожденный" конечный автомат, у вас было бы состояние "полученный ввод", которое затем зацикливалось на значении "cm" до тех пор, пока не будет выполнено условие "сделано", а затем вернитесь в состояние "ожидание" или "обработка", в зависимости от фактического варианта использования операции. Как описано здесь, это просто разбиение проверки значения и вызова метода. Методы, все для этого. Обработка состояний-опасно, потому что нет примера выхода из состояния :), @Dave Newton