0

I'am working on this project, it should be a light for a carport. There are two ways to turn the light on, via motion sensor or via a switch. The Led strip starts to turn on one led after another. It will stay on for a period of time and then a reversed animation starts and turns all LEDs to black. I'am using a for loop for this animation (it's the same one FastLed uses in the first light example). The error is only when the motion sensor is activate and while the for loop is running. I'am sorry for the bad integer names, could be confusing. Thanks a lot!

Here is the Code: (If you can't understand German, - Bewegungsmelder = Motion sensor - 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);
  }

}```
marvinm
  • 11
  • 3

1 Answers1

0

Although fluent in German the program structure is alittle chaotic. Since we are in C++

  • you should not use goto
  • Since to my understanding the light routines for switch and IR are the same this code should only exist once
  • Your routine for measuring time is not rollover safe see blinkwithoutdelay example how todo

So clean the code up by using the following structure:

 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
 }
}

This technique is called finite state machine there is no "jumping around" via goto. If you need more states you just expand the sequence
- there is no else because eg in the last two combined if statements we check for lightIsON == true ==> else would mean lightIsON == false in the second which makes no sense here as we only differentiate these to states by time.
Please never use goto in object oriented programming it makes your code unreadable and untraceable. Rewrite the program and if there are "new" problems edit here or open a new question

Codebreaker007
  • 2,911
  • 1
  • 10
  • 22