Как переключаться между циклами while до завершения текущего цикла? ИК-пульт + светодиод

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

К сожалению, мой код ждет, пока после полного вращения (или полного цикла while/if) не переместится в цикл вращения ccw. Как я закодирую это, чтобы сразу переключаться между циклами?

Вот мой код:

#include <IRremote.h>

int RECV_PIN = 10;
int Switch = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;

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

  pinMode(2, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  irrecv.enableIRIn();         // Запуск приемника
}

void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value);
    irrecv.resume();           // Получить следующее значение
  }

  while (results.value == 16615543)     // кнопка 2: вращение по часовой стрелке
  {
    digitalWrite(2, HIGH);
    delay(500);                // Ожидание 500 миллисекунд(с)

    digitalWrite(9, LOW);
    delay(1000);               // Ожидание 1000 миллисекунд(с)

    digitalWrite(3, HIGH);
    delay(500);                // Ожидание 500 миллисекунд(с)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Ожидание 500 миллисекунд(с)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }

  while (results.value == 16580863)     //power button - break other loops and wait for next IR transmission
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
  }

  while (results.value == 16619623)     // button 8: ccw rotation
  {
    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(3, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }
}

, 👍-1

Обсуждение

Что касается вашего скобочного комментария в исходном редактировании, то вам не хватало форматирования последовательности из трех обратных ссылок, чтобы процитировать код. Во время редактирования в правом верхнем углу есть встроенная справка с помощью значка (вопросительный знак с кружком). Я прогнал ваш код через автоформат и вручную свернул большую часть двойного интервала., @timemage


2 ответа


0

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

А ты-нет. Вы снимаете петли. Вы не хотите их - они никогда не могут закончиться, так как нет никакого способа для изменения результатов между итерациями.

У вас есть фундаментальное непонимание того, как работают ИК-пульты. Не может быть никакого "в то время как", так как пульт дистанционного управления посылает сигнал либо один раз на нажатие кнопки, либо несколько раз, пока кнопка удерживается, в зависимости от функции, которую должна выполнять кнопка.

Вместо этого все, что вы можете сделать, это "Если кнопка нажата, то сделайте что-нибудь". Там нет "Он в настоящее время нажат" или "Он был выпущен", только "Я получил сигнал, что он нажат".

,

0

В дополнение к ответу Маенко, то, что вы должны использовать, - это так называемый State Engine.

Сначала вы определяете перечисление:

enum EState { Off, Clockwise, CounterClockwise };

EState _state;

В программе установки вы устанавливаете _state на некоторое значение по умолчанию.

В цикле вы проверяете наличие изменений кнопок и соответствующим образом устанавливаете их состояние.

Затем вы действуете на состояние:

switch (_state)
{
case EState::Off:
    {
        // Выключить все
        for (int n = 0; n < 9; n++)
        {
            digitalWrite(n, LOW);
        }
    }
    break;

case EState::Clockwise:
    ... See below

case EState::CounterClockwise:
    ... Similar as above
}

Для состояний по часовой стрелке и против часовой стрелки вы должны сохранить переменную, которая увеличивается каждые 100 мс, сбрасывается при переходе в новое состояние.

В зависимости от значения шага вы что-то делаете, например, для первых двух шагов по часовой стрелке:

digitalWrite(2, HIGH);
delay(500);                // Ожидание 500 миллисекунд

digitalWrite(9, LOW);
delay(1000);               // Ожидание 1000 миллисекунд

вы можете сделать такой переключатель внутри корпуса, который у вас уже есть (или лучше: создать новую функцию):

switch (_step)
{
case 0: // 0 ms
    digitalWrite(2, HIGH);
    break;

case 5: // 500 ms
    delay(1000);

...

Обратите внимание, что это немного более чисто для создания своего рода хэша/массива, но вышесказанное тоже должно работать. Вы можете увеличивать _step каждые 100 мс или только тогда, когда активны состояния (против)часовой стрелки.

,