if/else statement not repeating with PWM controlled led strips

Hi,

I am having difficulty finding an answer to why my code is not repeating my if/else statement. I am currently trying to control 4 single color led strips with a simple timer so I can turn on my led strips for a given amount of time and then turn off for a given amount of time. My program has no compile errors, but will not perform the continuous on and off cycle. Currently, the leds will start in their programmed dimmed state, then turn off for 30secs, and then turn on but will not cycle back to off after the set 30sec time period.

I have no problem setting the leds to any analog input value from 0 to 255 and having them turn on, but when adding in the if/else statement with the millis timer and I cannot get the program to continue cycling the leds on and off.

I am also using NTE Logic Level MOSFET N-Channel for each led strip.

LED_Only_v1.ino (1.59 KB)

Instead of attached the code file, please paste the code in code tag. People do not like to download the file on local PC and open it. it makes us feel unsafe and takes a little time.

Variable ‘GreenLed’ is the pin number and is 3.
Variable ‘threshold’ is 10 and is never changed.
You are comparing 3 with 10. Why ?

Please add the word ‘pin’ to a variable that is a pin number.

const int GreenLedPin = 3;           // the PWM pin the LED is attached to

You have just one software-millis-timer. It is allowed to change the interval.
I have an example for that: millis_different_on_and_off_times.ino.

As you can see, I have an extra global variable: ‘ledState’. That variable remembers if the led was on or off. You need such a variable.

I have added the word in to variables that are associated with a pin and added a analogwrite ledState after my if/else statement. Below is my updated code, but do I need to add ledState throughout my code or just as a global variable and after the if/else statement?

// Definitions

const int GreenLedPin = 3;           // the PWM pin the LED is attached to
const int RedLedPin = 5;           // the PWM pin the LED is attached to
const int BlueLedPin = 6;           // the PWM pin the LED is attached to
const int YellowLedPin = 9;           // the PWM pin the LED is attached to
const int threshold = 10;          // Threshold value for leds in on position

int ledState = 0;

const unsigned long SECOND = 1000;
const unsigned long MIN = 60 * SECOND;
const unsigned long HOUR = 3600 * SECOND;
const unsigned long onDuration = 30 * SECOND; // ON time for LEDs
const unsigned long offDuration = 30 * SECOND; // OFF time for LEDs

unsigned long rememberTime = 0;// inital state

// the setup routine runs once when you press reset:
void setup() {

  // declare pins to be an output:
  pinMode(GreenLedPin, OUTPUT);
  pinMode(RedLedPin, OUTPUT);
  pinMode(BlueLedPin, OUTPUT);
  pinMode(YellowLedPin, OUTPUT);

  analogWrite(GreenLedPin, 20);
  analogWrite(RedLedPin, 20);
  analogWrite(BlueLedPin, 20);
  analogWrite(YellowLedPin, 20);

}

// the loop routine runs over and over again forever:
void loop() {


  if (GreenLedPin > threshold)
  {
    if ( (millis() - rememberTime) >= onDuration) {
      analogWrite(GreenLedPin, 0);
      analogWrite(RedLedPin, 0);
      analogWrite(BlueLedPin, 0);
      analogWrite(YellowLedPin, 0);
      rememberTime = millis();
    }
  }
  else

    if (GreenLedPin < threshold)

    {
      if ( (millis() - rememberTime) >= offDuration) {
        analogWrite(GreenLedPin, 250);
        analogWrite(RedLedPin, 250);
        analogWrite(BlueLedPin, 250);
        analogWrite(YellowLedPin, 250);
        rememberTime = millis();
      }

      analogWrite(GreenLedPin, ledState);
      analogWrite(RedLedPin, ledState);
      analogWrite(BlueLedPin, ledState);
      analogWrite(YellowLedPin, ledState);
    }
}

Also, the intent for the threshold is to provide a reference PWM value for when the leds are at a lower dimmed state but still need to cycle on and off. Do I need to define my threshold to associate it with an ledState?

in your code: "if (GreenLedPin > threshold)" is always false because GreenLedPin is 3 and threshold is 10.

I believe I have added some additional code that should help with my threshold issue, see below, not sure though.

// the loop routine runs over and over again forever:
void loop() {

  int GreenAnalogValue = analogRead(GreenLedPin);
  Serial.println(GreenAnalogValue);

  if (GreenAnalogValue > threshold) {
    if ( (millis() - rememberTime) >= onDuration) {
      analogWrite(GreenLedPin, 0);
      analogWrite(RedLedPin, 0);
      analogWrite(BlueLedPin, 0);
      analogWrite(YellowLedPin, 0);
      rememberTime = millis();
    }
  }
  else

I am still having difficulty as to how to get the new led values to update so the loop can continue and repeat. Below is my current code with my attempt at resolving the issue with global led state values and analogwrite after the if/else statement, but I am still having difficulties where the leds run for the first duration and then turn off, but never cycle back to the on state.

// Definitions

const int GreenLedPin = 3;           // the PWM pin the LED is attached to
const int RedLedPin = 5;           // the PWM pin the LED is attached to
const int BlueLedPin = 6;           // the PWM pin the LED is attached to
const int YellowLedPin = 9;           // the PWM pin the LED is attached to
const int threshold = 10;          // Threshold value for leds in on position

int GreenAnalogValue = 0;
int RedAnalogValue = 0;
int BlueAnalogValue = 0;
int YellowAnalogValue = 0;

const unsigned long SECOND = 1000;
const unsigned long MIN = 60 * SECOND;
const unsigned long HOUR = 3600 * SECOND;
const unsigned long onDuration = 30 * SECOND; // ON time for LEDs
const unsigned long offDuration = 30 * SECOND; // OFF time for LEDs

unsigned long rememberTime = 0;// inital state

// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(115200);

  // declare pins to be an output:
  pinMode(GreenLedPin, OUTPUT);
  pinMode(RedLedPin, OUTPUT);
  pinMode(BlueLedPin, OUTPUT);
  pinMode(YellowLedPin, OUTPUT);

  analogWrite(GreenLedPin, 20);
  analogWrite(RedLedPin, 20);
  analogWrite(BlueLedPin, 20);
  analogWrite(YellowLedPin, 20);

}

// the loop routine runs over and over again forever:
void loop() {

  int GreenAnalogValue = analogRead(GreenLedPin);
  Serial.println(GreenAnalogValue);

  if (GreenAnalogValue > threshold) {
    if ( (millis() - rememberTime) >= onDuration) {
      analogWrite(GreenLedPin, 0);
      analogWrite(RedLedPin, 0);
      analogWrite(BlueLedPin, 0);
      analogWrite(YellowLedPin, 0);
      rememberTime = millis();
    }
  }
  else
  {
    if (GreenAnalogValue < threshold) {
      if ( (millis() - rememberTime) >= offDuration) {
        analogWrite(GreenLedPin, 250);
        analogWrite(RedLedPin, 250);
        analogWrite(BlueLedPin, 250);
        analogWrite(YellowLedPin, 250);
        rememberTime = millis();
      }

      analogWrite(GreenLedPin, GreenAnalogValue);
      analogWrite(RedLedPin, RedAnalogValue);
      analogWrite(BlueLedPin, BlueAnalogValue);
      analogWrite(YellowLedPin, YellowAnalogValue);
    }

    Serial.println(GreenAnalogValue);
  }
}

You have put the software-millis-timers inside the if-statement. Therefor the millis-timers can not do their thing, they depend on that if-statement. Let's get the millis-timer out of there.

First, you need to describe what you want. I'm sorry, but I don't get it. This is a serious problem. Many bail out when I ask to describe what they want. Take your time, and try to explain it. Describe for every situation what is going on.

Is it this:
Suppose the leds are off, and the green sensor is below the threshold, then turn the leds on. Keep the leds on for at least a certain time.
Suppose the leds are on, and the green sensor is above the threshold then turn the leds off. Keep them off for a at least a certain time.

That is not the same as what you describe or what your sketch is supposed to do.

Whatever you want to make, I think the solution is this:
You have to know if the timer is running and if the leds are on or off. In your sketch, you made the analog value and the threshold are the most important things, but they are of little importance. They are only used to make a decision.

One way to do this, is using two variables: 'enableTimerLedsOnRunning' and 'enableTimerLedsOffRunning'.
Then split the loop() into three parts. Let the millis-timers run on their own.

bool enableTimerLedsOnRunning = false;
bool enableTimerLedsOffRunning = false;


void loop()
{
  // read sensors


  // make decisions
  // turn on or off the leds immediately
  // start millis-timers


  // millis-timer to keep them on
  if( enableTimerLedsOnRunning)
  {
    if( millis() - ... >= ...
 

  // millis-timer to keep them off
  if( enableTimerLedsOffRunning)
  {
    if( millis() - ... >= ...
}

You have to find better names for the 'enableTimerLedsOnRunning' variables.
I call it 'enabled' in my millis_single_delay.ino. Since you have two of those, perhaps 'onTimer' and 'offTimer' will do.

Hi Koepel, What I am trying to design is a photobioreactor (PBR) using 4 different color wavelengths, along with natural daylight, to determine optimal growth parameters for a phototrophic microorganism by adjusting the amount of light on time and intensity in a closed volume/container. The PBR will also have a lux sensor to measure the overall light intensity along with a spectrometer, in the future, to measure the intensity of specific wavelengths. Where I am currently at is trying to get just the leds to cycle on and off for a given time so I can have them repeat a particular schedule and measure the changes in growth rate. From there I will then add in my lux sensor, Overview | Adafruit VEML7700 Ambient Light Sensor | Adafruit Learning System, so I can control the leds intensity to be able to combine the daylight with the leds to match an overall lux value/setting; that is also the reason why I thought a threshold value would be useful in my code to allow for the leds to cycle even if there is a small amount of natural daylight present.

Thank you for your help.

steve1817:
Where I am currently at is trying to get just the leds to cycle on and off for a given time so I can have them repeat a particular schedule

When you write down a good description, then half of the sketch is already written.
I'm really trying very hard to understand, but I have no clue at all. What you want seems to change every time you try to describe it.
Do you want the leds to blink with different 'on' and 'off' duration ? I have an example for that as well: millis_different_on_and_off_times.ino.

Hi, Sorry for not providing any clarification. What I want to do is turn my leds on for a certain time and then off for a different amount of time. I have modified my code below to be similar to the example you provided but right now the leds turn on and off for the same amount of time where I need them to be on and off for different amounts of time.

I see in your example that you have a predetermined interval and then have the led turn on and off for different amounts of time. Is there a way to modify your example or my code so that the leds can turn on and off for different amounts of time without the need for a predetermined interval.

Your example with the predetermined interval.

if( currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    
    if( ledState == HIGH) // led was on ?
    {
      interval = 3000;    // new interval is a few seconds
      ledState = LOW;     // new led state is off
    }
    else                  // led was off
    {
      interval = 400;     // new interval is a short time
      ledState = HIGH;    // new led state is on
    }

My current code where the leds turn on and off for the same amount of time.

// Definitions

const int GreenLedPin = 3;           // the PWM pin the LED is attached to
const int RedLedPin = 5;           // the PWM pin the LED is attached to
const int BlueLedPin = 6;           // the PWM pin the LED is attached to
const int YellowLedPin = 9;           // the PWM pin the LED is attached to
const int threshold = 10;          // Threshold value for leds in on position

int GreenAnalogValue = 0;
int RedAnalogValue = 0;
int BlueAnalogValue = 0;
int YellowAnalogValue = 0;

const unsigned long SECOND = 1000;
const unsigned long MIN = 60 * SECOND;
const unsigned long HOUR = 3600 * SECOND;
const unsigned long onDuration = 60 * SECOND; // ON time for LEDs
const unsigned long offDuration = 5 * SECOND; // OFF time for LEDs

unsigned long previousMillis;// inital state

// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(115200);

  // declare pins to be an output:
  pinMode(GreenLedPin, OUTPUT);
  pinMode(RedLedPin, OUTPUT);
  pinMode(BlueLedPin, OUTPUT);
  pinMode(YellowLedPin, OUTPUT);

}

// the loop routine runs over and over again forever:
void loop()
{
  unsigned long currentMillis = millis();
  
  Serial.println(GreenAnalogValue);

  if (currentMillis - previousMillis >= onDuration)
  {
    previousMillis = currentMillis;

    if (GreenAnalogValue > threshold)
    {
      GreenAnalogValue = 0;
      RedAnalogValue = 0;
      BlueAnalogValue = 0;
      YellowAnalogValue = 0;
    }

    else

      if (GreenAnalogValue < threshold)
      {
        GreenAnalogValue = 250;
        RedAnalogValue = 250;
        BlueAnalogValue = 250;
        YellowAnalogValue = 250;

      }

    digitalWrite(GreenLedPin, GreenAnalogValue);
    digitalWrite(RedLedPin, RedAnalogValue);
    digitalWrite(BlueLedPin, BlueAnalogValue);
    digitalWrite(YellowLedPin, YellowAnalogValue);
  }

}

Hi, Sorry for the multiple posts, but I think I understand how your example works and after modifying my code I can now have the leds cycle on and off for different times!

I did not understand that the Duration in the initial if statement below gets updated to either set duration within the if/else loop. I have seen code for turning on and off leds with two different if(currentMillis - previousMillis >= Duration and I think that was giving me some confusion as I thought it had to be written like that instead of the way you showed me.

 if (currentMillis - previousMillis >= Duration)

Here is my working code and thank you very much for your help!

// Definitions

const int GreenLedPin = 3;           // the PWM pin the LED is attached to
const int RedLedPin = 5;           // the PWM pin the LED is attached to
const int BlueLedPin = 6;           // the PWM pin the LED is attached to
const int YellowLedPin = 9;           // the PWM pin the LED is attached to
const int threshold = 10;          // Threshold value for leds in on position

int GreenAnalogValue = 0;
int RedAnalogValue = 0;
int BlueAnalogValue = 0;
int YellowAnalogValue = 0;

const unsigned long SECOND = 1000;
const unsigned long MIN = 60 * SECOND;
const unsigned long HOUR = 3600 * SECOND;
unsigned long Duration = 5 * SECOND; //initial start value of 5 seconds

unsigned long previousMillis;// inital state

// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(115200);

  // declare pins to be an output:
  pinMode(GreenLedPin, OUTPUT);
  pinMode(RedLedPin, OUTPUT);
  pinMode(BlueLedPin, OUTPUT);
  pinMode(YellowLedPin, OUTPUT);

}

// the loop routine runs over and over again forever:
void loop()
{
  unsigned long currentMillis = millis();

  Serial.println(GreenAnalogValue);

  if (currentMillis - previousMillis >= Duration)
  {
    previousMillis = currentMillis;

    if (GreenAnalogValue > threshold)
    {
      GreenAnalogValue = 0;
      RedAnalogValue = 0;
      BlueAnalogValue = 0;
      YellowAnalogValue = 0;
      Duration = 1*MIN;
    }

    else

      if (GreenAnalogValue < threshold)
      {
        GreenAnalogValue = 250;
        RedAnalogValue = 250;
        BlueAnalogValue = 250;
        YellowAnalogValue = 250;        
        Duration = 2*MIN;

      }


    digitalWrite(GreenLedPin, GreenAnalogValue);
    digitalWrite(RedLedPin, RedAnalogValue);
    digitalWrite(BlueLedPin, BlueAnalogValue);
    digitalWrite(YellowLedPin, YellowAnalogValue);
  }
}

You can set a new interval to any value. It is even allowed to change the interval all the time. Sooner or later the millis-timer will become active.

// code that changes the interval all the time
interval = random( 1000, 5000);  // random number between 1 and 5 seconds

if( currentMillis - previousMillis >= interval)
{
  previousMillis = currentMillis;
  ...
}

The millis() timer can be written in a different way:

unsigned long elapsedMillis = currentMillis - previousMillis;
if( elapsedMillis >= interval)
{
  previousMillis = currentMillis;
  
  ...
}

Now to your sketch.

There is only one software millis-timer. Just one. It has the onDuration and offDuration in itself. We are going to set the interval to whatever we want.

When you do this:

if (currentMillis - previousMillis >= onDuration)
{

then you are stuck to that 'onDuration'.

// global variables
unsigned long interval = onDuration;   // or offDuration

void loop()
{
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;

    if (GreenAnalogValue > threshold)
    {
      // New interval with new values for leds turned off
      interval = offDuration;
      GreenAnalogValue = 0;
      RedAnalogValue = 0;
      BlueAnalogValue = 0;
      YellowAnalogValue = 0;
    }
    else
    {
      // New interval with new values for leds turned on
      interval = onDuration;
      GreenAnalogValue = 250;
      RedAnalogValue = 250;
      BlueAnalogValue = 250;
      YellowAnalogValue = 250;
    }

    // Update the outputs
    digitalWrite(GreenLedPin, GreenAnalogValue);
    digitalWrite(RedLedPin, RedAnalogValue);
    digitalWrite(BlueLedPin, BlueAnalogValue);
    digitalWrite(YellowLedPin, YellowAnalogValue);
  }
  
  ...
}

When the value is not above the threshold, then it is below the threshold. You probably have to add hysteresis later.

You were very close :wink: Do you see that using millis() can be fun ?
When this is working, then you can alter it, or add new things. You can even use extra millis-timers to make the three leds blink, each led with its own sequence :stuck_out_tongue:

[Update] You found it already yourself, that is very good :smiley: I will show the post that I had written anyway for some extra background information.

Yes, using the millis function is now fun! Thank you again for your help and explanations!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.