0

我正在做这个项目,它应该是一个车棚的灯。有两种方法可以打开灯,通过运动传感器或通过开关。LED灯条开始一个接一个地打开。它将保持亮起一段时间,然后开始反转动画并将所有 LED 变为黑色。我正在为这个动画使用一个 for 循环(它与 FastLed 在第一个灯光示例中使用的循环相同)。只有当运动传感器被激活并且 for 循环正在运行时,才会出现错误。我很抱歉整数名称不好,可能会造成混淆。非常感谢!

这是代码:(如果您不懂德语,- Bewegungsmelder = 运动传感器 - Schalter = Switch


// für die Leds
#define NUMfront_LEDS 150 //150 Leds
#define NUMinner_LEDS 35 //35 Leds
#define rightPIN 6 //Pin 6
#define leftPIN 5
#define innerrightPIN 8
#define innerleftPIN 7

#define CLOCK_PIN 13

// für die Schalter
#define schalter 2 //Pin 2
#define Bewegungsmelder 4 //Pin 4

int schalterval = 0;
int Bewegungsval = 0;
long Time = 0;
long Wait = 900000;
int On = 0;

CRGB leftLeds[NUMfront_LEDS];
CRGB rightLeds[NUMfront_LEDS];
CRGB innerleftLeds[NUMinner_LEDS];
CRGB innerrightLeds[NUMinner_LEDS];


void setup() {
  // sanity check delay - allows reprogramming if accidently blowing power w/leds
  Serial.begin(115200);
  delay(2000);
  FastLED.addLeds<WS2812B, rightPIN, RGB>(rightLeds, NUMfront_LEDS);  // GRB ordering is typical
  FastLED.addLeds<WS2812B, leftPIN, RGB>(leftLeds, NUMfront_LEDS);
  FastLED.addLeds<WS2812B, innerrightPIN, RGB>(innerrightLeds, NUMinner_LEDS);
  FastLED.addLeds<WS2812B, innerleftPIN, RGB>(innerleftLeds, NUMinner_LEDS);
Time = millis();
}

void loop() {
  Serial.println("----------------------------------------------");
  Serial.print(Wait);
  Serial.print("----");
  Serial.print(millis());
  Bewegungsval = digitalRead(Bewegungsmelder);
  schalterval = digitalRead(schalter);
  Serial.println(Bewegungsval);
  Serial.println(schalterval);
  Serial.println("Space");
Schalter:

  if (digitalRead(schalter) == 1) {
    On = 0;
for (int blackLed = NUMfront_LEDS; blackLed > -1; blackLed = blackLed - 1) {
      leftLeds[blackLed] = CRGB::White;
      rightLeds[blackLed] = CRGB::White;
      delay(19);
      FastLED.show();
    }
    // Carport innen
    fill_solid( innerrightLeds, NUMinner_LEDS, CRGB::White);
    fill_solid( innerleftLeds, NUMinner_LEDS, CRGB::White);
    //Leds aus
    //Carport aussen



    while (digitalRead(schalter) == 1) {
    }
    for (int whiteLed = 0; whiteLed < NUMfront_LEDS; whiteLed = whiteLed + 1) {
      leftLeds[whiteLed] = CRGB::Black;
      rightLeds[whiteLed] = CRGB::Black;
      delay(19);
      FastLED.show();
    }
    // Carport innen
    fill_solid( innerrightLeds, NUMinner_LEDS, CRGB::Black);
    fill_solid( innerleftLeds, NUMinner_LEDS, CRGB::Black);
    FastLED.show();
  }



  else if (Bewegungsval == 1) {
    //Carport aussen
    if (On == 1) {
      goto Skip;
    }
    for (int blackLed = NUMfront_LEDS; blackLed > -1; blackLed = blackLed - 1) {
      leftLeds[blackLed] = CRGB::White;
      rightLeds[blackLed] = CRGB::White;
      delay(19);
      FastLED.show();
    }
    // Carport innen
    fill_solid( innerrightLeds, NUMinner_LEDS, CRGB::White);
    fill_solid( innerleftLeds, NUMinner_LEDS, CRGB::White);
     FastLED.show();
    //Leds aus
    On = 1;
Skip:
    Time = millis();
    Wait = Time + 10000; // + 5min. 300000
    Bewegungsval = digitalRead(Bewegungsmelder);
    goto Schalter;
  }

   Time = millis();
  if (Time  >=  Wait) {

    On = 0;
    for (int whiteLed = 0; whiteLed < NUMfront_LEDS; whiteLed = whiteLed + 1) {
      leftLeds[whiteLed] = CRGB::Black;
      rightLeds[whiteLed] = CRGB::Black;
      delay(19);
      FastLED.show();
    }
    // Carport innen
    fill_solid( innerrightLeds, NUMinner_LEDS, CRGB::Black);
    fill_solid( innerleftLeds, NUMinner_LEDS, CRGB::Black);
  }

}```
4

1 回答 1

0

虽然德语流利,但程序结构有点混乱。因为我们在 C++

  • 你不应该使用 goto
  • 因为据我了解,开关和红外的光例程是相同的,所以这个代码应该只存在一次
  • 您测量时间的例程不是安全翻转的,请参阅 blinkwithoutdelay 示例如何操作

因此,使用以下结构清理代码:

 unsigned long startTime = 0;
 unsigned long myTimer = 10000;// 10 sec
 bool lightIsOn = false;

setup(){....}

loop(){
....
// We check wether switch or IR are triggerd AND we are not already in a light sequence
 if ((digitalRead(schalter) == 1 || Bewegungsval == 1) && lightIsOn == false) { 
    lightIsOn = true;   // change state so we know that a light sequence is running
    startTime = millis(); // reset the timer
 }
  // this part runs as long lighIsOn == true and time is not up
 if(millis() - startTime <= myTimer && lighIsOn == true){
// Carport aussen
your light sequence .....
}
// Here we run the time is up sequence 
if(millis() - startTime > myTimer && lighIsOn == true) {   // rollover safe
  light sequence for time is up
 ........
  lightIsOn = false;   // change state so we know that a light sequence is over
 }
}

这种技术被称为有限状态机,没有通过 goto 的“跳跃”。如果您需要更多状态,您只需扩展序列
- 没有别的,因为例如在最后两个组合的 if 语句中,我们检查 lightIsON == true ==> else 将意味着 lightIsON == false 在第二个这在这里没有意义我们只按时间将它们区分为状态。
请永远不要在面向对象编程中使用 goto,它会使您的代码不可读和不可追踪。重写程序,如果有“新”问题在此处编辑或打开一个新问题

于 2020-04-10T23:30:09.947 回答