我尝试了几种在互联网上发现的不同方法,但是它们似乎都不起作用。该代码适用于情况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);
}
}
答案 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);
}
}