Прерывая петли - PullRequest
       4

Прерывая петли

1 голос
/ 27 июня 2019

Я работаю над проектом освещения Arduino, использующим светодиоды RGB для создания настраиваемых цветов. Я использую библиотеку IRremote для изменения «режимов» с помощью светодиодов.

Вот моя программа:

#include <IRremote.h>

const int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;
int redpin = 9;
int greenpin = 10;
int bluepin = 5;

void setup(){
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  pinMode(redpin, OUTPUT);
  pinMode(greenpin, OUTPUT);
  pinMode(bluepin, OUTPUT);
}

void loop(){
  if (irrecv.decode(&results)){
    Serial.println("Before it checks for signal");

    if (results.value == 0xFFE21D) { //'TITLE' button
      Serial.println("'TITLE' signal detected, before fade starts");

      //Fades through colors

      int i;

      //green to red
      for (i = 0; i < 255; i++) {
        analogWrite(redpin, i);
        analogWrite(greenpin, 255 - i);
        analogWrite(bluepin, 0);
        delay(1);
        Serial.println("Green to red");
      }

      //red to blue
      for (i = 0; i < 255; i++) {
        analogWrite(redpin, 255 - i);
        analogWrite(greenpin, 0);
        analogWrite(bluepin, i);
        delay(1);
        Serial.println("Red to blue");
      }

      //blue to green
      for (i = 0; i < 255; i++) {
        analogWrite(redpin, 0);
        analogWrite(greenpin, i);
        analogWrite(bluepin, 255 - i);
        delay(1);
        Serial.println("Blue to green");
      }
    }

    if (results.value == 0xFFD22D) { //'MENU' button
      Serial.println("'MENU' button detected");

      //LED red
      analogWrite(redpin, 255);
      analogWrite(greenpin, 0);
      analogWrite(bluepin, 0);
    }

    if (results.value == 0xFF52AD) { //'ON/OFF' button
      Serial.println("'STOP' button detected");

      //Stops
      analogWrite(redpin, 0);
      analogWrite(greenpin, 0);
      analogWrite(bluepin, 0);

      Serial.println("After LED stops");
    }

    Serial.println("After program");
    irrecv.resume();
  }
}

Внутри void loop() у меня есть три if() заявления. Первый проверяет, нажата ли определенная кнопка на пульте дистанционного управления, и индикатор гаснет с зеленого на красный, с синего на зеленый (это выполняется только один раз, но это проблема для другого потока).

Второй оператор if() проверяет, не нажата ли другая кнопка, и светодиод горит красным. Я планирую иметь несколько из них для разных цветов.

Третий оператор if() проверяет наличие кнопки ON / OFF и выключает светодиод.

Я могу переключаться между ними. Проблема в том, что как только первый оператор if() выполняется и светодиод гаснет, я не могу переключиться ни на один из других операторов, пока он не закончится.

Я знаю, что после выполнения первого оператора он не проверяет сигналы, пока не выполнит его, но я не могу придумать, как это сделать. Любая помощь приветствуется!

Ответы [ 3 ]

3 голосов
/ 27 июня 2019

Конечный автомат Штеннера - один из способов.Я опишу еще один ниже, но основная идея заключается в том, что вам нужно, чтобы цикл продолжался, так как вы гасите светодиоды за один шаг.Вот мой совместный подход:

int pins[3] = { redpin, greenpin, bluepin };
int current[3] = { 0, 0, 0 };
int target[3] = { 0, 0, 0 };

led_tick() {
  for (int i = 0; i < 3; i += 1) {
    if (current[i] == target[i]) continue;
    if (current[i] < target[i]) {
      current[i] += 1;
    } else {
      current[i] -= 1;
    }
    analogWrite(pins[i], current[i]);
  }
}

loop() {
  // handle buttons, change target values
  led_tick();
  delay(1);  // making this non-blocking would be even better

}
3 голосов
/ 27 июня 2019

Похоже, вы пытаетесь реализовать простой конечный автомат. Для этого вам нужно переключить ваш цикл / if. В псевдокоде:

int mode; // 0: green, 1: red and so on
while(true) {
    // check button presses
    if(buttonpress) {
        mode = mode+1;
    }
    if(mode==1)
        make_leds_more_green();
    else if(mode==2)
        make_leds_more_red();
    //...
    delay(1);
}
1 голос
/ 27 июня 2019

Вы можете попробовать ручной неблокирующий

  1. Удалить for
  2. Удалить delay
  3. Использовать millis() с периодом
#define DELAY  5000

int step;

void greenToRed() {
    // Non blocking, only check if the waiting period passed
    if(changeToRed && millis() > time_1 + DELAY){
        // Update the time
        time_1 = millis();
        // Update the step
        step -= 1;

        analogWrite(redpin, 255 - step);
        analogWrite(greenpin, step);
        analogWrite(bluepin, 0);
        Serial.println("Green to red");

        // Finish condition
        if(step =< 0) {
            changeToRed = 0;
        }
    }
}

void loop() {
    if (results.value == 0xFFE21D) {
        changeToRed = 1;
        step = 255;
    }
    greenToRed();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...