Invert LED blink and millis()

I'm trying to get the red LED to blink at the opposite times of the green LED. Note that I have void toggleRedLED () opposite of the green. But they both still blink on and off together. How do I make one off while the other is on and vice versa?

//sourced from blink_2_leds_and_motor_independent_-_gannon
// http://gammon.com.au/blink


// Which pins are connected to which LED
const byte greenLED = 9;
const byte redLED = 13;

const unsigned long greenLEDinterval = 1000;
const unsigned long redLEDinterval = 2000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup ()
{
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  greenLEDtimer = millis ();
  redLEDtimer = millis ();

}  // end of setup

void toggleGreenLED ()
{
  if (digitalRead (greenLED) == LOW)
    digitalWrite (greenLED, HIGH);
  else
    digitalWrite (greenLED, LOW);

  // remember when we toggled it
  greenLEDtimer = millis ();
}  // end of toggleGreenLED

void toggleRedLED ()
{
  if (digitalRead (redLED) == HIGH)
    digitalWrite (redLED, LOW);
  else
    digitalWrite (redLED, HIGH);

  // remember when we toggled it
  redLEDtimer = millis ();
}  // end of toggleRedLED

void loop ()
{

  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
    toggleGreenLED ();

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval)
    toggleRedLED ();


}  // end of loop

Use setup() to turn one on and the other off. Then they will blink alternately.

Why not just check the state of one, then set the state of both based on that result? Then they will stay out of phase permanently, even if some other function changes one of them in a future version of your program.

Why not just check the state of one, then set the state of both based on that result?

Because they have different intervals.

unsigned long greenLEDtimer;
unsigned long redLEDtimer;

millis() returns a time, not a timer.

OP: Why don't you keep track of the state of the LED pins? That is faster than asking the pin what state it is in, AND makes toggling the pin simpler:

void toggleGreenLED ()
{
  greenLEDState = !greenLEDState;
  digitalWrite (greenLED, greenLEDState);

  // remember when we toggled it
  greenLEDtimer = millis ();
}

I don't see anything in your code that would cause the behavior that you describe. So, comment out the call to toggleGreenLED() in loop(), and see if just the red LED toggles at the desired interval.

Then, uncomment that call, and comment out the call to toggleRedLED() and see if just the green LED toggles at the desired (different) interval.

callmebob:
Note that I have void toggleRedLED () opposite of the green.

Note that there is no opposite of toggle, no matter which way you implement it.

MorganS:
Use setup() to turn one on and the other off. Then they will blink alternately.

I'm trying to get the red LED to blink at the opposite times of the green LED.

Then why do the 2 LEDs have different periods in your program ?

Thanks guys for all your great input! I initially was doing it with the same interval for both. They don't alternate in that case.

I changed the interval of one of them from 2000 to 1000 as a test and that's the code I posted here. (I should have posted the code with both intervals the same -- DOH! -- But I learned a lot anyway.)

With the different intervals they do light on and off at different intervals and opposite eachother at times in the loop. But in going through all this, I do want them opposite at the same interval so they're more (easily) predictable. So I'll try all your suggestions with both intervals at 2000 and see how it goes...

const byte redLedPin = 10;
const byte greenLedPin = 11;

void setup()
{
  pinMode(redLedPin, OUTPUT);
  pinMode(greenLedPin, OUTPUT);
}

void loop()
{
  digitalWrite(redLedPin, !digitalRead(redLedPin));
  digitalWrite(greenLedPin, !digitalRead(redLedPin));
  delay(500);
}

I will leave it to you to convert it to non blocking timing.

Thanks again all! I think I'm good on this one.

MorganS:
Use setup() to turn one on and the other off. Then they will blink alternately.

Perfect!

MorganS:
Why not just check the state of one, then set the state of both based on that result? Then they will stay out of phase permanently, even if some other function changes one of them in a future version of your program.

Don't know how to do that, but am fine with your first idea.

MorganS:
Why not just check the state of one, then set the state of both based on that result? Then they will stay out of phase permanently, even if some other function changes one of them in a future version of your program.

PaulS:
Because they have different intervals.

That's resolved

PaulS:

unsigned long greenLEDtimer;

unsigned long redLEDtimer;



millis() returns a time, not a timer.

Got it!

PaulS:
OP: Why don't you keep track of the state of the LED pins? That is faster than asking the pin what state it is in, AND makes toggling the pin simpler:

void toggleGreenLED ()

{
  greenLEDState = !greenLEDState;
  digitalWrite (greenLED, greenLEDState);

// remember when we toggled it
  greenLEDtimer = millis ();
}

Because I'm not that educated :slight_smile: -- But used yours and it works - thanks!

Whandall:
Note that there is no opposite of toggle, no matter which way you implement it.

Aha!

UKHeliBob:
Then why do the 2 LEDs have different periods in your program ?

Good point - resolved

UKHeliBob:

const byte redLedPin = 10;

const byte greenLedPin = 11;

void setup()
{
 pinMode(redLedPin, OUTPUT);
 pinMode(greenLedPin, OUTPUT);
}

void loop()
{
 digitalWrite(redLedPin, !digitalRead(redLedPin));
 digitalWrite(greenLedPin, !digitalRead(redLedPin));
 delay(500);
}



I will leave it to you to convert it to non blocking timing.

Thanks! I'll look at this as well!