How can I make LED blink until I press button?

Hi,

I have this project turning a projector on/off with one button and hide/show picture with another:

// Projektor model Acer H5380BD

#include <Bounce2.h>

#define powerButton 8
#define powerLED 9

#define hideButton 6
#define hideLED 7

int powerLEDState = LOW;
int hideLEDState = LOW;

// Instantiate a Bounce object :
Bounce powerDebouncer = Bounce();
Bounce hideDebouncer = Bounce();

boolean projectorState = false;
boolean hidePicture = false;

void setup() {
  Serial.begin(9600);

  // Setup the button with an internal pull-up
  pinMode(powerButton, INPUT_PULLUP);
  pinMode(hideButton, INPUT_PULLUP);

  // After setting up the button, setup the Bounce instance
  powerDebouncer.attach(powerButton);
  powerDebouncer.interval(5);

  hideDebouncer.attach(hideButton);
  hideDebouncer.interval(5);

  // Setup the LED :
  pinMode(powerLED, OUTPUT);
  digitalWrite(powerLED, powerLEDState);

  pinMode(hideLED, OUTPUT);
  digitalWrite(hideLED, hideLEDState);
}

void loop() {
  int onBlink = 0;          //integer to hold value of blinks during 'turning on' state
  projectorState = false;   //default projector state is off

  // Update the Bounce instance
  powerDebouncer.update();
  hideDebouncer.update();

  // Toggle POWER LED and serial output
  if (powerDebouncer.fell()) {
    powerLEDState = !powerLEDState;
    hideLEDState = powerLEDState;

    //digitalWrite(powerLED, powerLEDState);
    digitalWrite(hideLED, hideLEDState);

    projectorState = true;

    if (powerLEDState == 1) {
      Serial.write("* 0 IR 001\r\n");                 // Turn projector on
      while (projectorState == true)  {               //while projectorState is true, blink for 45 seconds while projector is turning on
        powerLEDState = false;                        //switch powerLEDState to off
        digitalWrite(powerLED, powerLEDState);        //write powerLEDState state to powerLED, turning off the ON LED
        delay (500);                                  //delay a half second
        powerLEDState = true;                         //switch powerLEDState to on
        digitalWrite(powerLED, powerLEDState);        //write powerLEDState state to powerLED, turning on the ON LED
        delay (500);                                  //delay a half second
        onBlink++;                                    //add 1 to onBlink integer (starting at 0)
        if (onBlink == 45)  {                          //if onBlink equals 45
          powerLEDState = true;                       //switch powerLEDState to on
          digitalWrite(powerLED, powerLEDState);      //write powerLEDState state to powerLED, turning on the ON LED
          onBlink = 0;                                //reset onBlink counter to 0
          projectorState = false;                     //turn off projectorState to end blink program
        }
      }
    }
    else {
      projectorState = true;
      Serial.write("* 0 IR 002\r\n");                 // Turn projector off
      while (projectorState == true)  {               //while projectorState is true, blink for 45 seconds while projector is turning on
        powerLEDState = false;                        //switch powerLEDState to off
        digitalWrite(powerLED, powerLEDState);        //write powerLEDState state to powerLED, turning off the ON LED
        delay (200);                                  //delay a half second
        powerLEDState = true;                         //switch powerLEDState to on
        digitalWrite(powerLED, powerLEDState);        //write powerLEDState state to powerLED, turning on the ON LED
        delay (500);                                  //delay a half second
        onBlink++;                                    //add 1 to onBlink integer (starting at 0)
        if (onBlink == 30)  {                          //if onBlink equals 30
          powerLEDState = false;                      //switch powerLEDState to off
          digitalWrite(powerLED, powerLEDState);      //write powerLEDState state to powerLED, turning LED OFF
          onBlink = 0;                                //reset onBlink counter to 0
          projectorState = false;                     //turn off projectorState to end blink program
        }
      }
    }
  }

  // Toggle PICTURE LED and serial output
  if (hideDebouncer.fell() && powerLEDState == 1) {
    hideLEDState = !hideLEDState;
    Serial.write("* 0 IR 030\r\n");                     // Send hide/mute command
    digitalWrite(hideLED, hideLEDState);
  }
}

I would like to have the hide LED blink while the image is off. How do I do this? I’ve tried to implement the same methos as the power on/off, but all I get is the LED blinking without the system respoding to anything else.

/Carl

I've tried to implement the same methos as the power on/off, but all I get is the LED blinking without the system respoding to anything else.

You tried something, in some code you didn't post. It did not do what you wanted, and you want us to tell you why. Don't you see the problem with that?

Some functions would certainly be useful. All the code for turning the projector on should be in a function. All the code for hiding/showing the picture should be in a function.

It is NOT necessary to comment every line of code, especially when the comment does nothing more than (incorrectly, in some cases) state the obvious. No one would assume that delay(500); does anything other than //delay a half second. You look especially dumb when you have that useless comment after a delay(200); call.

Ok. I’ll try again and hopefully the code now meets the standard. I got the hide LED blinking but it doesn’t turn off when I press the button again. I also would like to have the power button override the hide button so that the hide LED goes off when the power is off.

// Projektor model Acer H5380BD

#include <Bounce2.h>

#define powerButton 8
#define powerLED 9

#define hideButton 6
#define hideLED 7

// Instantiate a Bounce object :
Bounce powerDebouncer = Bounce();
Bounce hideDebouncer = Bounce();

// Declare variables
int powerLEDState = LOW;
int hideLEDState = LOW;
boolean projectorState = false;
boolean hideState = false;

void setup() {
  Serial.begin(9600);

  // Setup the button with an internal pull-up
  pinMode(powerButton, INPUT_PULLUP);
  pinMode(hideButton, INPUT_PULLUP);

  // After setting up the button, setup the Bounce instance
  powerDebouncer.attach(powerButton);
  powerDebouncer.interval(5);

  hideDebouncer.attach(hideButton);
  hideDebouncer.interval(5);

  // Setup the LED :
  pinMode(powerLED, OUTPUT);
  digitalWrite(powerLED, powerLEDState);

  pinMode(hideLED, OUTPUT);
  digitalWrite(hideLED, hideLEDState);
}

void loop() {
  // Update the Bounce instance
  powerDebouncer.update();
  hideDebouncer.update();

  // Power button pressed
  if (powerDebouncer.fell()) {
    powerLEDState = !powerLEDState;
    if (powerLEDState == 1) {
      powerToggle();
      powerBlink(45, 500, 500);             // Run 45 cycles, on 500ms, off 500ms
    }
    else {
      powerToggle();
      powerBlink(30, 200, 500);             // Run 30 cycles, on 200ms, off 500ms
    }
  }

  // Hide button pressed
  if (hideDebouncer.fell() && projectorState == true) {
    togglePicture();
    pictureBlink();
  }
}

void powerToggle() {
  projectorState = !projectorState;
  if (projectorState == true) {
    Serial.write("* 0 IR 001\r\n");           //Turn projector on
    hideLEDState = powerLEDState;
    digitalWrite(hideLED, hideLEDState);
  }
  else {
    Serial.write("* 0 IR 002\r\n");           //Turn projector off
    hideLEDState = powerLEDState;
    digitalWrite(hideLED, hideLEDState);
  }
}

void togglePicture() {
  hideLEDState = !hideLEDState;
  Serial.write("* 0 IR 030\r\n");           // Send hide/mute command
  digitalWrite(hideLED, hideLEDState);      // Toggle hide LED
}

void powerBlink(int duration, int onTime, int offTime) {
  int onBlink = 0;
  while (onBlink < duration) {
    powerLEDState = false;
    digitalWrite(powerLED, powerLEDState);
    delay (onTime);
    powerLEDState = true;
    digitalWrite(powerLED, powerLEDState);
    delay (offTime);
    onBlink++;
    if (onBlink == duration)  {
      powerLEDState = projectorState;
      digitalWrite(powerLED, powerLEDState);
    }
  }
}

void pictureBlink() {
  hideState = !hideState;
  while (hideState == true) {
    hideLEDState = false;
    digitalWrite(hideLED, hideLEDState);
    delay (1000);
    hideLEDState = true;
    digitalWrite(hideLED, hideLEDState);
    delay (150);
    if (hideState == false) {
      hideLEDState = true;
      digitalWrite(hideLED, hideLEDState);
    }
  }
}
  // Update the Bounce instance
  powerDebouncer.update();
  hideDebouncer.update();

If you are going to have useless comments, at least make them accurate. There are TWO instances.

 if (hideDebouncer.fell() && projectorState == true) {

The variable name projectorState may mean something to you. It doesn't mean anything to me. I can't imagine why it would be true.

It seems to me that the power might, or might not, be on. It seems to me that the picture may be showing, or it might not. So, names like poweredOn and pictureShowing make a lot more sense, to me. Then, a statement that includes "&& poweredOn)" implies that the block of code should be executed only if the projector is powered on.

The projectorState == true comparison will be true only if projectorState contains true. It will be false if projectorState contains false. Since the result of the comparison is the same as the value in projectorState, you should be able to see that the == true part is unnecessary. Real programmers would never include == true in an expression.

I really don't like compound if statements if a nested if statement makes the intent clearer. There is, for instance, no need to even read the state of the hide/show "bouncer" if the projector is not on.

  if(poweredOn)
   {
      // Now, we care about changes in the hide/show switch state
      if(hideDebouncer.fell())
      {
          // Hide or show the picture, as required
      }
   }

Notice how I put every { on a new line, and how the code lines up neatly. It's far easier, IMHO, to see where to insert code when the structure of the program is visible.

Notice, too, how I do NOT put comments at the end of statements. If there is a need for a comment (and there are always needs), put it before a block of code, to explain what the block does, not how it does it.

Now, it's time to focus on your issue. I really don't see how/where the hide LED is changing state.

It seems to me that toggling the power LED or the hide LED should be separate tasks that do not depend on the state of the power or hide/show switches. The state of the power LED should be a function of time and of the projector being powered on.

The state of the hide LED should be a function of time and something else. What that something else is is really not clear to me.

So, I think you need 4 blocks of code in loop(). Or, better yet, 4 function calls. One to determine if the power switch changed state; if so, the projector needs to be turned on or off. One to determine, if the projector is on, whether the hide/show switch changed stated; if so, the picture needs to be shown or hidden. One to determine, if the projector is on, if it is time to change the state of the power LED, based on time. One to determine, if the projector is on, if it is time to change the state of the hide LED, based on time.

So, loop() would look like:

void loop()
{
  checkPowerSwitch();
  if(poweredOn)
  {
     checkHideShowSwitch();

     togglePowerLED();
     if(someUndefinedCondition)
        toggleHideLED();
  }
}

All you need to do is rename some variables, move some code around, and define the condition under which the hide LED should be flashing, other than just time and the projector being on.

Thanks! I'll go through the code again and use your guidelines. Thanks for helping a noob like me. How's the weather in Seattle?

So I went back to the drawing board and found out that the issue probably is caused by the usage of delay(). This is the new code which works:

// Projektor model Acer H5380BD

#include <Bounce2.h>

#define powerButton 8
#define powerLED 9

#define hideButton 5
#define hideLED 6

int powerLEDState = LOW;
int hideLEDState = LOW;

boolean powerOn = false;
boolean pictureOn = false;

int powerLoop = 0;

int ledState = LOW;
unsigned long previousMillis = 0;

int powerOnDuration = 46;
const long powerInterval = 500;

int hledState = LOW;
unsigned long hpreviousMillis = 0;
const long hinterval = 1000;

Bounce powerDebouncer = Bounce();
Bounce hideDebouncer = Bounce();

void setup() {
  Serial.begin(9600);

  // Setup the buttons with an internal pull-up
  pinMode(powerButton, INPUT_PULLUP);
  pinMode(hideButton, INPUT_PULLUP);

  // After setting up the buttons, setup the Bounce instances
  powerDebouncer.attach(powerButton);
  powerDebouncer.interval(5);

  hideDebouncer.attach(hideButton);
  hideDebouncer.interval(5);

  // Setup the LED :
  pinMode(powerLED, OUTPUT);
  digitalWrite(powerLED, powerLEDState);

  pinMode(hideLED, OUTPUT);
  digitalWrite(hideLED, hideLEDState);
}

void loop() {
  // Update the Bounce instances
  powerDebouncer.update();
  hideDebouncer.update();

  // Power projector on / off
  if (powerDebouncer.fell()) {
    powerOn = !powerOn;
    powerControl();
  }

  // Hide/show picture
  if (powerOn) {
    if (hideDebouncer.fell()) {
      Serial.write("* 0 IR 030\r\n");
      pictureOn = !pictureOn;
    }
  }

  if (powerOn == true) {
    powerLedOn();
    pictureControl();
  }
}

void powerControl() {
  if (powerOn == true) {
    Serial.write("* 0 IR 001\r\n");
    digitalWrite(hideLED, HIGH);
    pictureOn = powerOn;
  }
  else {
    Serial.write("* 0 IR 002\r\n");
    digitalWrite(powerLED, LOW);
    digitalWrite(hideLED, LOW);
    pictureOn = powerOn;
    powerLoop = 0;
  }
}

void powerLedOn() {
  if (powerLoop <= powerOnDuration) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= powerInterval) {
      previousMillis = currentMillis;
      ledState = !ledState;
      digitalWrite(powerLED, ledState);
      powerLoop++;
    }
  }
}

void pictureControl() {
  if (pictureOn == true) {
    digitalWrite(hideLED, HIGH);
  }
  else {
    unsigned long hcurrentMillis = millis();
    if (hcurrentMillis - hpreviousMillis >= hinterval) {
      hpreviousMillis = hcurrentMillis;
      hledState = !hledState;
      digitalWrite(hideLED, hledState);
    }
  }
}