Arduino在使用FastLED时忽略串行中断

时间:2018-07-10 16:03:12

标签: arduino irq neopixel

我尝试了几种在互联网上发现的不同方法,但是它们似乎都不起作用。该代码适用于情况0-2,但当它进入情况3(即彩虹追逐循环)时,按此按钮不会中断该循环并使计数器向前移动。像往常一样,我想我先想念一些愚蠢的东西。

#define FASTLED_ALLOW_INTERRUPTS 1
#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>

#define AnalogIn A0
#define SwIn 2
#define LED_Out 12
#define NUM_LEDS 5
int pushCounterz = 0;
volatile int buttonState;  // Set volatile for interrupt DO NOT SHAKE!
int lastButtonState;

CRGB leds[NUM_LEDS];

void setup() {
  // put your setup code here, to run once:
  FastLED.setMaxRefreshRate(250);
  FastLED.addLeds<WS2812, LED_Out, GRB>(leds, NUM_LEDS);
  pinMode(SwIn, INPUT);
  pinMode(LED_Out, OUTPUT);

  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB ( 255, 0, 255 );  
  }
  FastLED.show();
  delay(120);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB ( 0, 0, 0 );  
  }

  FastLED.show();
  Serial.begin(115200);
  Serial.println(pushCounterz);
  lastButtonState = digitalRead(SwIn); // Set the button state to the startup state 

  attachInterrupt((SwIn-2), button_ISR, CHANGE);  // Set SwIn button as an interrupt pin  // Change to Low???

}

void loop() {
  if (pushCounterz != 3) {
    FastLED.show();
  }
Serial.println(pushCounterz);
delay(120);
}

void button_ISR () {
    buttonState = digitalRead(SwIn);
    digitalWrite(13, buttonState);
  if (buttonState == LOW && buttonState != lastButtonState) {
    if (pushCounterz > 3) {
      //Serial.println("Reset to 0: ");
      pushCounterz = 0;
    } else {
      pushCounterz = pushCounterz + 1;
      //Serial.println("Incerment");
    }
    //Serial.println(pushCounterz);

      switch (pushCounterz) {
      case 0:
        for (int i = 0; i < NUM_LEDS; i++) {
          leds[i] = CRGB (255, 0, 0);
        }
        break;
      case 1:
        for (int i = 0; i < NUM_LEDS; i++) {
          leds[i] = CRGB ( 0, 255, 0);
         }
         break;
      case 2:
        for (int i = 0; i < NUM_LEDS; i++) {
           leds[i] = CRGB ( 0, 0, 255);
         }
        break;
      case 3:
        theaterChaseRainbow(1,50);
        break;
      default:
       for (int i = 0; i < NUM_LEDS; i++) {
         leds[i] = CRGB ( 0, 0, 0);
       }
       break;
      }
  }

lastButtonState = buttonState;
}

// Theater-style crawling lights with rainbow effect
void theaterChaseRainbow(int cycles, int speed) { // TODO direction, duration
  for (int j = 0; j < 256 * cycles; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        int pos = i + q;
        leds[pos] = Wheel( (i + j) % 255);  //turn every third pixel on
      }
      FastLED.show();

      delay(speed);

      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        leds[i + q] = CRGB::Black; //turn every third pixel off
      }
    }
  }
}

CRGB Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return CRGB(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
  else if (WheelPos < 170) {
    WheelPos -= 85;
    return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  else {
    WheelPos -= 170;
    return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

3 个答案:

答案 0 :(得分:2)

您的问题不是按钮没有更改值,而是您的代码没有退出点;该按钮将更改该值,但是theaterChaseRainbow中的任何内容都不指示它停止。

只需在该方法中添加一个检查,以在按钮状态更改时返回:

// Theater-style crawling lights with rainbow effect
void theaterChaseRainbow(int cycles, int speed) { // TODO direction, duration
  for (int j = 0; j < 256 * cycles; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        int pos = i + q;
        leds[pos] = Wheel( (i + j) % 255);  //turn every third pixel on
      }
      FastLED.show();
      if (pushCounterz != 3) return; //ADDED THIS HERE*****    

      delay(speed);

      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        leds[i + q] = CRGB::Black; //turn every third pixel off
      }
    }
  }
}

此外,我建议简化您的ISR,使其仅增加按钮,而不使其也处理程序的逻辑。该参数应包含在loop方法中,或从loop方法中调用。这应该使代码更简洁,更容易混淆,因为ISR的工作只是调整按钮计数器的值,而循环工作是处理程序当前所在的状态。

答案 1 :(得分:1)

也-您不能在AVR上允许中断,或者我应该说它什么也不做。发生这种情况时,我应该发出警告消息-AVR / arduino的ISR处理非常缓慢,以至于时钟滴答ISR都足以破坏WS2812数据的写入(导致FastLED切断帧),因此我将代码从中剔除AWS WS2812 ASM实现。 FastLED支持的大多数arm和esp平台的确允许在写出每个led的数据之间的小窗口中进行中断处理-这要归功于其更高的时钟速度。

如果您使用的是基于ARM或ESP的平台,则可以忽略此评论(主要是将其放在此处,以便在良好搜索中偶然发现此问题的人都知道这是怎么回事)。

答案 2 :(得分:0)

具有ISR清理功能的工作代码作为参考。 (请注意,由于我还有更多关于亮度等方面的工作,其中仍然有一些串行调试代码)

#define FASTLED_ALLOW_INTERRUPTS 1
#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>

#define AnalogIn A0
#define SwIn 2
#define LED_Out 12
#define NUM_LEDS 5
int pushCounterz = 4; // 4 = off
volatile int buttonState;  // Set volatile for interrupt DO NOT SHAKE!
int lastButtonState;

CRGB leds[NUM_LEDS];

void setup() {
  // put your setup code here, to run once:
  FastLED.setMaxRefreshRate(250);
  FastLED.addLeds<WS2812, LED_Out, GRB>(leds, NUM_LEDS);
  pinMode(SwIn, INPUT);
  pinMode(LED_Out, OUTPUT);

  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB ( 255, 0, 255 );  
  }
  FastLED.show();
  delay(120);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB ( 0, 0, 0 );  
  }

  FastLED.show();
  Serial.begin(19200);
  Serial.println(pushCounterz);
  lastButtonState = digitalRead(SwIn); // Set the button state to the startup state 

  attachInterrupt((SwIn-2), button_ISR, LOW);  // Set SwIn button as an interrupt pin  // Change to Low???

}

void loop() {
//  if (pushCounterz != 3) {
    //FastLED.show();
    //Serial.println(pushCounterz);
//  }

//delay(20);
switch (pushCounterz) {
  case 0:
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB (255, 0, 0);
    }
    FastLED.show();
    break;
  case 1:
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB ( 0, 255, 0);
    }
    FastLED.show();
    break;
  case 2:
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB ( 0, 0, 255);
    }
    FastLED.show();
    break;
  case 3:
    theaterChaseRainbow(1,50);
    break;
  default:
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB ( 0, 0, 0);
    }
    FastLED.show();
    break;
    }
}

void button_ISR () {
    buttonState = digitalRead(SwIn);
    //digitalWrite(13, buttonState);
  if (buttonState == LOW && buttonState != lastButtonState) {
    if (pushCounterz > 3 || pushCounterz < 0) {
      Serial.println("Reset to 0: ");
      pushCounterz = 0;
    } else {
      pushCounterz = pushCounterz + 1;
      Serial.println("Incerment");
    }
    Serial.println(pushCounterz);
  }
lastButtonState = buttonState;
}

// Theater-style crawling lights with rainbow effect
void theaterChaseRainbow(int cycles, int speed) { // TODO direction, duration
  for (int j = 0; j < 256 * cycles; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        int pos = i + q;
        leds[pos] = Wheel( (i + j) % 255);  //turn every third pixel on
      }
      FastLED.show();
      if (pushCounterz != 3) return;

      delay(speed);

      for (int i = 0; i < NUM_LEDS; i = i + 3) {
        leds[i + q] = CRGB::Black; //turn every third pixel off
      }
    }
  }
}

CRGB Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return CRGB(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
  else if (WheelPos < 170) {
    WheelPos -= 85;
    return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  else {
    WheelPos -= 170;
    return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}