Do Task once after status change; Then stay in command

Hey, im using a Arduino D1 Wemos atm. This is my first Code i made mostly by myself.
I want a rainbow effect after the IRSensors are changing low and high all the time BUT ONCE. After that it should stay with the order i have written in the code. Do you guys have any idea?

Even more...is there a more simple way to write my code?

#include <FastLED.h>
//-------------------------------------------------------------
#define NUM_LEDS 12                     //Number per LED Strip    
#define CHIPSET WS2812B   
#define COLOR_ORDER GRB
#define BRIGHTNESS 20
#define DATA_PIN1 2                     //LED Strip Data_Pin
#define DATA_PIN2 3                     //LED Strip Data_Pin
#define VOLTS 5
#define MAX_AMPS 500

const int Sensor2 = D12;                 //IRSensor DataPin
const int Sensor1 = D11;                  //IRSensor DataPin
int Sensor_State1 = 0;                  //IRSensor start Value
int Sensor_State2 = 0;                  //IRSensor start Value
//-----------------

CRGB ledsCup1[NUM_LEDS];                //Color index for LedsCup1
CRGB ledsCup2[NUM_LEDS];                //Color index for LedsCup2
//CRGB ledsCup3[NUM_LEDS];                //Color index for LedsCup3
//CRGB ledsCup4[NUM_LEDS];                //Color index for LedsCup4
//CRGB ledsCup5[NUM_LEDS];                //Color index for LedsCup5
//CRGB ledsCup6[NUM_LEDS];                //Color index for LedsCup6
//CRGB ledsCup7[NUM_LEDS];                //Color index for LedsCup7
//CRGB ledsCup8[NUM_LEDS];                //Color index for LedsCup8
//CRGB ledsCup9[NUM_LEDS];                //Color index for LedsCup9
//CRGB ledsCup10[NUM_LEDS];                //Color index for LedsCup10


//---------------------------------------------------------------------------------
void setup() {
  // put your setup code here, to run once:
  pinMode(D12, INPUT);
  pinMode(D11, INPUT);
//-------------------------------------------------------------------------------
  FastLED.addLeds<CHIPSET, DATA_PIN1, COLOR_ORDER>(ledsCup1, NUM_LEDS);           //Define Leds setup...
  FastLED.addLeds<CHIPSET, DATA_PIN2, COLOR_ORDER>(ledsCup2, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN3, COLOR_ORDER>(ledsCup3, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN4, COLOR_ORDER>(ledsCup4, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN5, COLOR_ORDER>(ledsCup5, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN6, COLOR_ORDER>(ledsCup6, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN7, COLOR_ORDER>(ledsCup7, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN8, COLOR_ORDER>(ledsCup8, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN9, COLOR_ORDER>(ledsCup9, NUM_LEDS);
  //FastLED.addLeds<CHIPSET, DATA_PIN10, COLOR_ORDER>(ledsCup10, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS);
  FastLED.clear();
  FastLED.show();
  Serial.begin(9600);
}
//---------------------------------------------------------------------------------
void loop() { 
   Sensor_State2 = digitalRead(D12);
   Sensor_State1 = digitalRead(D11);                        //Read out IRSensor HIGH or LOW
  
   if (Sensor_State1 == 1)                                //if IRSensor is HIGH
   {
     for (int i=0; i<=NUM_LEDS; i++) {                    //LED setup
     ledsCup1[i] =CRGB::Blue;                             //LED Index
     FastLED.show();}                                     //Show
   }
   else                                                   //if IRSensor is NOT HIGH
   {
     for (int i=0; i<=NUM_LEDS; i++) {                    //LED setup
     ledsCup1[i] =CRGB::Red;                              //LED Index
     FastLED.show();}                                     //Show
   }
//------------------------------------------------------------------------------------
   if (Sensor_State2 == 1){
     for (int i=0; i<=NUM_LEDS; i++) {
     ledsCup2[i] =CRGB::Blue;
     FastLED.show();}
   }
   else 
   {
     for (int i=0; i<=NUM_LEDS; i++) {
     ledsCup2[i] =CRGB::Red;
     FastLED.show();}
   }
  }

Welcome to the forum

Wrap the code that you want to run once in an if code block and control it with a boolean variable that you initially set to true

boolean okToRun = true;
if (okToRun)
{
//code here to run once
  okToRun = false;  //prevent it running again
}

Look up state machines as this will be a common problem if you don’t understand them. Be aware of where you put the Boolean above as you could set it to true every time through loop.

Can I include the FastLED Pride 2015 Example and run it once with boolean ?
Its written in a void pride(); Somehow like this ?

void pride() 
{
  static uint16_t sPseudotime = 0;
  static uint16_t sLastMillis = 0;
  static uint16_t sHue16 = 0;
 
  uint8_t sat8 = beatsin88( 87, 220, 250);
  uint8_t brightdepth = beatsin88( 341, 96, 224);
  uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  uint8_t msmultiplier = beatsin88(147, 23, 60);

  uint16_t hue16 = sHue16;//gHue * 256;
  uint16_t hueinc16 = beatsin88(113, 1, 3000);
  
  uint16_t ms = millis();
  uint16_t deltams = ms - sLastMillis ;
  sLastMillis  = ms;
  sPseudotime += deltams * msmultiplier;
  sHue16 += deltams * beatsin88( 400, 5,9);
  uint16_t brightnesstheta16 = sPseudotime;
  
  for( uint16_t i = 0 ; i < NUM_LEDS; i++) {
    hue16 += hueinc16;
    uint8_t hue8 = hue16 / 256;

    brightnesstheta16  += brightnessthetainc16;
    uint16_t b16 = sin16( brightnesstheta16  ) + 32768;

    uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
    uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
    bri8 += (255 - brightdepth);
    
    CRGB newcolor = CHSV( hue8, sat8, bri8);
    
    uint16_t pixelnumber = i;
    pixelnumber = (NUM_LEDS-1) - pixelnumber;
    
    nblend( ledsCup1[pixelnumber], newcolor, 64);
  }
}

Something like this ?

**boolean Pride2015 = true;**

void loop() { 
   Sensor_State2 = digitalRead(D12);
   Sensor_State1 = digitalRead(D11);                        //Read out IRSensor HIGH or LOW
  
   if (Sensor_State1 == 1)                                //if IRSensor is HIGH
   {
     if (Pride2015){
     Pride2015 = false;}
     for (int i=0; i<=NUM_LEDS; i++) {                    //LED setup
     ledsCup1[i] =CRGB::Blue;                             //LED Index
     FastLED.show();}                                     //Show
   }
   else                                                   //if IRSensor is NOT HIGH
   {
     for (int i=0; i<=NUM_LEDS; i++) {                    //LED setup
     ledsCup1[i] =CRGB::Red;                              //LED Index
     FastLED.show();}                                     //Show
   }

In my dummy code, where I put

//code here to run once

that could be any code that you want to run once or a call to a function that you want to run once

Where you call pride() in your code?

That's a complete if statement.

It is exactly equivalent to

Pride2015 = false;

What were you hoping it meant, or have you mismatched some braces in your code?

a7

Well... I have no clue what you all talking :smiling_face_with_tear:
As i said thats my first code.
I get the if Statement and how include commands in it. But if you are all telling me to put another if statement, i dont know wher to put it... :frowning:

In that case how are you going to write your sketches? :slight_smile:

If you defined the function pride() - is assumed that you are going to call it in your code, otherwise why you defined it? But in you code no that call, so the function is completely useless.

It is defindes :slight_smile: I just have to include it into the code

void pride() 
{
  static uint16_t sPseudotime = 0;
  static uint16_t sLastMillis = 0;
  static uint16_t sHue16 = 0;
 
  uint8_t sat8 = beatsin88( 87, 220, 250);
  uint8_t brightdepth = beatsin88( 341, 96, 224);
  uint16_t brightnessthetainc16 = beatsin88( 203, (25 * 256), (40 * 256));
  uint8_t msmultiplier = beatsin88(147, 23, 60);

  uint16_t hue16 = sHue16;//gHue * 256;
  uint16_t hueinc16 = beatsin88(113, 1, 3000);
  
  uint16_t ms = millis();
  uint16_t deltams = ms - sLastMillis ;
  sLastMillis  = ms;
  sPseudotime += deltams * msmultiplier;
  sHue16 += deltams * beatsin88( 400, 5,9);
  uint16_t brightnesstheta16 = sPseudotime;
  
  for( uint16_t i = 0 ; i < NUM_LEDS; i++) {
    hue16 += hueinc16;
    uint8_t hue8 = hue16 / 256;

    brightnesstheta16  += brightnessthetainc16;
    uint16_t b16 = sin16( brightnesstheta16  ) + 32768;

    uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
    uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
    bri8 += (255 - brightdepth);
    
    CRGB newcolor = CHSV( hue8, sat8, bri8);
    
    uint16_t pixelnumber = i;
    pixelnumber = (NUM_LEDS-1) - pixelnumber;
    
    nblend( ledsCup1[pixelnumber], newcolor, 64);
  }
}

Do yo understand the difference between "function definition" and "call the function" ?
if simplified, the first is creation the function and the second - using it.
What are you show above is definition. Where are you call this function?
Why do you create the function, if you don't use it?

     if  (Pride2015) {
       pride(); // call the pride function
       Pride2015 = false;  // but only once, never again.
     } 

If Pride2915 is a boolean variable that is initialised as true, this will do the trick.

Place thy code where you want the price() thing to happen once, but only once, as program flow passes
through.

Presumably at some point for some reason you'll want to set Pride2015 true again, or quite literally you will never see the pride() function do its thing again.

Unless you restart the program or power cycle it.

What conditions shoukd obtain for you to reset that variable? Like ten minutes without motion, or temperature above 37 degrees C?

It's just what @UKHeliBob propose straightaway, and is a correction and addition to your idea of it.

Does that make sense now, and do you get why you would need to have some reset of the mechanism employed?

a7