Trying to blink 4 LEDs with two buttons

Hello all,
I have this script working however there is 1 problem

PROBLEM:
LED pin 10 & led pin 11 seem to be blinking faster than LED pin 6 & led pin 7.
I can't figure out why. Please read on.

Here is what I have:

I have 2 buttons and 4 LEDs

Here is what I am trying to do:

I want to simulate fog lights that I can make blink with a "temporary on button" for my Harley Davidson, with either the low beam blinking or both the high beam and the low beam blinking.

The low beam fog lights are "always-on" LED pin 6 & led pin 7

Button 8 "temporary on" will blink LED pin 6 & led pin 7, the "low beam fog lights", when held down and stop blinking LED pin 6 & led pin 7 when released.

Button 5 a "toggle switch" will turn on LED pin 10 & led pin 11 the "high beam fog lights" when pushed and keep them on until it is pushed again.

Then when LED pin 10 & led pin 11, are ON and you press button 8, the "temporary on" all 4 led's 6 -7 10 -11 will blink.

When LED pin 10 & led pin 11, are "OFF" and you press button 8 the temporary on just LED pin 6 & led pin 7 will blink.

LED pin 6 & led pin 7 are blinking at 100ms this is what I want 100ms on all 4 LEDs

Please see if you can help me.

Thanks

//============================================================================================
//BEGIN:Declarations
//============================================================================================
//
#define LEDon                         HIGH
#define LEDoff                        LOW

#define PUSHED                        LOW

bool blink_the_high_bem_fog_lights = false;

int current_buttonState;
int current_button_press_reading = 0;
int Val = 0;
int previous_button_state_reading = LOW;  // the previous reading from the input pin
int ledState = LOW;





unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 25;    // the debounce time; increase if the output flickers




//
const unsigned long led_blink_speed  = 100;
const unsigned long led_blink_speed_2  = 100;

byte button_blink_all_fog_lights         = 8;  //+5V----[Internal Pullup Resistor]----Input Pin ----[switch]----GND
byte button_turn_on_high_beam_fog_lights = 5;
bool onAndOff = false;


byte fog_light_halo_low_beam_indicator        = 6;
byte fog_light_halo_low_beam        = 7;  //Pin Number----[>|]----[220 ohm]----GND
////
byte fog_light_high_beam_indicator        = 10;
byte fog_light_high_beam        = 11;  //Pin Number----[>|]----[220 ohm]----GND


byte lastButton;

boolean LEDflag = false;


unsigned long blinkMillis;
unsigned long switchMillis;
unsigned long currentMillis;

///////
byte lastButton_2;

boolean LEDflag_2 = false;

unsigned long blinkMillis_2;
unsigned long switchMillis_2;
unsigned long currentMillis_2;

int lastButtonState;
int currentButtonState; // the current state of button

int trythis = 0;
//============================================================================================
//END:Declarations
//============================================================================================



//============================================================================================
//BEGIN:setup ()
//============================================================================================


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

  digitalWrite(fog_light_halo_low_beam, LOW );

  pinMode(fog_light_halo_low_beam_indicator , OUTPUT);
  pinMode(fog_light_halo_low_beam, OUTPUT);
  //
  pinMode(fog_light_high_beam_indicator , OUTPUT);
  pinMode(fog_light_high_beam, OUTPUT);

  //
  pinMode(button_blink_all_fog_lights, INPUT_PULLUP);
  pinMode(button_turn_on_high_beam_fog_lights, INPUT_PULLUP);


  lastButton  = digitalRead (button_blink_all_fog_lights);
  digitalWrite(fog_light_halo_low_beam, LEDon);
  digitalWrite(fog_light_halo_low_beam_indicator, LEDon);
  //
  lastButton_2  = digitalRead (button_turn_on_high_beam_fog_lights);
  digitalWrite(fog_light_high_beam, LEDoff);
  digitalWrite(fog_light_high_beam_indicator, LEDoff);
  Serial.begin(9600);

} //END of setup()
//===========================================================================================
//END:setup ()
//===========================================================================================


//============================================================================================
//BEGIN:void loop ()
//===========================================================================================

void loop ()
{
  currentMillis = millis();
  currentMillis_2 = millis();




  //===========================================================================================
  //BEGIN:Do the work here
  //===========================================================================================
  //this is where you do the work of the temporary on button press
  //************************
  checkSwitches_1();
  //************************
  if (LEDflag == true && currentMillis - blinkMillis >= led_blink_speed)
  {

    //start the TIMER
    blinkMillis = currentMillis;
    //put your code here
    //toggle LED

    //Serial.println(Val);
    //Serial.println(current_button_press_reading);

    Serial.println("this is trythis");
    Serial.println(trythis);
    Serial.println("this is onAndoff");
    Serial.println(onAndOff);


    //trythis = digitalRead(fog_light_high_beam_indicator);

    if (onAndOff == 0)
      //if (trythis == 0)
    {

      //Serial.println(onAndOff);

      //Serial.println("button pressed");
      //trythis = digitalRead(fog_light_high_beam_indicator);
      //Serial.println(trythis);
      //Serial.println("the High beam fog light indicator is OFF");
      // turn LED on:
      //digitalWrite(ledPin, HIGH);
      digitalWrite (fog_light_halo_low_beam, ! digitalRead (fog_light_halo_low_beam));
      digitalWrite (fog_light_halo_low_beam_indicator, ! digitalRead (fog_light_halo_low_beam_indicator));
      Serial.println("I am just blinking the low beams now");
    }

    if (onAndOff == 1)
      //if (trythis == 1)
    {

      //Serial.println(onAndOff);

      //Serial.println("button pressed");
      //trythis = digitalRead(fog_light_high_beam_indicator);
      //Serial.println(trythis);
      //Serial.println("the High beam fog light indicator is OFF");
      // turn LED on:
      //digitalWrite(ledPin, HIGH);
      digitalWrite (fog_light_halo_low_beam, ! digitalRead (fog_light_halo_low_beam));
      digitalWrite (fog_light_halo_low_beam_indicator, ! digitalRead (fog_light_halo_low_beam_indicator));
      digitalWrite (fog_light_high_beam, ! digitalRead (fog_light_high_beam));
      digitalWrite (fog_light_high_beam_indicator, ! digitalRead (fog_light_high_beam_indicator));
      Serial.println("I am  blinking the low beam and high beams too");
    }
    //===========================================================================================
    //END:Do the work here
    //===========================================================================================

  }  //end void loop
  //============================================================================================
  //END:void loop ()
  //===========================================================================================


  //this is where you do the work of the led stays on utill button pressed again button press
  checkSwitches_2();
  if (LEDflag_2 == true && currentMillis_2 - blinkMillis_2 >= led_blink_speed_2)
  {
    //start the TIMER
    blinkMillis_2 = currentMillis_2;
    //put your code here
    //toggle LED
  }


} //END of void loop()

//============================================================================================
//BEGIN:checkSwitches_1()
//============================================================================================
void checkSwitches_1()
{
  if (currentMillis - switchMillis < 50) //debounce
  {
    //it is not time to check the switches
    return;
  }

  //start the TIMER
  switchMillis = currentMillis;


  byte button = digitalRead (button_blink_all_fog_lights);

  if (lastButton != button)
  {
    //save the new state of the switch
    lastButton = button;

    if (button == PUSHED)       // button pressed
    {
      //enable flashing
      LEDflag = true;
      //digitalWrite(fog_light_high_beam, LEDon);
      //digitalWrite(fog_light_high_beam_indicator, LEDon);
    }

    else //not pushed
    {
      //disable flashing
      LEDflag = false;
      digitalWrite(fog_light_halo_low_beam, LEDon);
      digitalWrite(fog_light_halo_low_beam_indicator, LEDon);

    }

  }


} //END of checkSwitches_1()

//============================================================================================
//END:checkSwitches_1()
//============================================================================================



//============================================================================================
//BEGIN:checkSwitches_2()
//============================================================================================
void checkSwitches_2()
{


  // put your main code here, to run repeatedly:
  //get the value of current_button_press_reading
  current_button_press_reading = digitalRead(button_turn_on_high_beam_fog_lights);

  // If the switch changed, due to noise or pressing:
  if (current_button_press_reading != previous_button_state_reading) {
    // reset the debouncing timer


    //NOTE the "+=" in - "lastDebounceTime += millis();"
    //The reason for this is that millis() may accumulate "jitter", and the clock then drifts.
    //Fine if you use only timer, not so great if you have other timers running
    //and you want them all to remain in lock step.

    lastDebounceTime += millis();

  }//end Debounce
  if ((millis() - lastDebounceTime) > debounceDelay)

  {
    lastButtonState    = currentButtonState;      // save the last state
    currentButtonState = digitalRead(button_turn_on_high_beam_fog_lights); // read new state

    if (lastButtonState == HIGH && currentButtonState == LOW)
    {
      if (onAndOff == true)
        onAndOff = false;
      //Serial.println("The button is pressed");

      //Serial.println(ledState );
      onAndOff = ledState;
      LEDflag = false;
      //Serial.println(onAndOff);
      // toggle state of LED
      ledState = !ledState;
    }
    else
    { //button not pushed
      onAndOff = false;
      //LEDflag = true;
      //Serial.println(lastButtonState);
      //Serial.println(ledState );
      onAndOff = ledState;
      //Serial.println(onAndOff);
      //delay(2000);
      // control LED arccoding to the toggled state
      digitalWrite(fog_light_high_beam, ledState);
      digitalWrite(fog_light_high_beam_indicator, ledState);

    }
  }//end if millis

}   //END of checkSwitches_2()


//============================================================================================
//END:checkSwitches_2()
//============================================================================================

Just a friendly hint.
Myself and many others won’t go to third party sites to collect code.

Read the guidelines, and post your code directly here (in code tags)
You’ll get responses within a few minutes.

Good luck.

Code Tags? was that supposed to be a link?
thanks

Read the How to use the forum topic.

Thank you
I read it but not clear how to enter my explanation of my problem can anyone hit the edit button to see my explanation?

Never mind I got it. Thank you much for your help

Does this somewhat simplified version do what you want?

#define LEDon       HIGH
#define LEDoff      LOW
#define PUSHED      LOW
 
const uint8_t pinLB = 7; 
const uint8_t pinLBInd = 6; 
const uint8_t pinHB = 11;
const uint8_t pinHBInd = 10;

const uint8_t pinDebugLED = LED_BUILTIN;

const uint8_t pinHighbeam = 5;      //high-beam buttoninput
const uint8_t pinMomentary = 8;     //momentary blink input

bool
    bBlink = false,
    bMomBlinkEn = false,
    bHBEn = false;
uint8_t
    lastHB,
    lastMom;

void setup( void )
{
    Serial.begin(115200);
    pinMode( pinHighbeam, INPUT_PULLUP );
    pinMode( pinMomentary, INPUT_PULLUP );
    lastHB = digitalRead( pinHighbeam );
    bHBEn = (lastHB == PUSHED) ? true : false;
    lastMom = digitalRead( pinMomentary );
    bMomBlinkEn = (lastMom == PUSHED) ? true : false;            
    
    //
    pinMode( pinLB, OUTPUT );    
    pinMode( pinLBInd, OUTPUT );
    digitalWrite( pinLB, LEDoff );
    digitalWrite( pinLBInd, LEDoff );
    //
    pinMode( pinHB, OUTPUT );
    pinMode( pinHBInd, OUTPUT );
    digitalWrite( pinHB, LEDoff );
    digitalWrite( pinHBInd, LEDoff );
    //
    pinMode( pinDebugLED, OUTPUT );
    digitalWrite( pinDebugLED, LEDoff );
                
}//setup

void loop( void )
{
    bool
        bEn;
    
    doBlink();          //toggles main "blink" flag every 100mS
    checkMomentary();   //checks the momentary blink switch
    checkHighBeams();   //checks the highbeam switch

    //for the low beams
    //  if the momentary button is not pressed, they're on (true)
    //  if the momentary button is pressed, they follow the bBlink variable
    bEn = (bMomBlinkEn == false) ? true : bBlink; 
    digitalWrite( pinLB, bEn ? LEDon : LEDoff );
    digitalWrite( pinLBInd, bEn ? LEDon : LEDoff );
    //digitalWrite( pinDebugLED, bEn ? LEDon : LEDoff );

    //for the highbeams
    //  if the highbeam switch is off, they're off
    //  if the highbeam switch is pressed, then they follow the same logic the low-beam do:
    //      if the momentary button not pressed, they're on
    //      if the momentary button is pressed, they follow the bBlink variable
    bEn = bHBEn & ( (bMomBlinkEn == false) ? true : bBlink );
    Serial.print( bEn ); Serial.print( bHBEn ); Serial.println( bMomBlinkEn );
    digitalWrite( pinHB, bEn ? LEDon : LEDoff );
    digitalWrite( pinHBInd, bEn ? LEDon : LEDoff );
    //digitalWrite( pinDebugLED, bEn ? LEDon : LEDoff );
     
} //END of void loop()

void doBlink( void )
{
    static uint32_t
        tBlink = 0ul;
    uint32_t
        tNow = micros();

    //every 100,000uS (100mS) we toggle the state of the boolean bBlink
    if( (tNow - tBlink) >= 100000ul )
    {
        tBlink = tNow;    
        bBlink ^= true;
        
    }//if
    
}//doBlink

void checkMomentary( void )
{
    static uint32_t
        tMom = 0ul;
    uint32_t
        tNow = millis();

    //read the momentary switch every 50mS
    if( (tNow - tMom) >= 50ul )
    {
        tMom = tNow;
        //read the momentary switch
        uint8_t nowMom = digitalRead( pinMomentary );
        //if not the same as last read...
        if( nowMom != lastMom )
        {            
            //save now as last
            lastMom = nowMom;
            //if now is pushed, enable momentary blink flag
            //else disable it
            bMomBlinkEn = (nowMom == PUSHED) ? true : false;            
            
        }//if
        
    }//if
    
}//checkMomentary

void checkHighBeams( void )
{
    static uint32_t
        tHB = 0ul;
    uint32_t
        tNow = millis();

    //check HB switch every 50mS
    if( (tNow - tHB) >= 50ul )
    {
        tHB = tNow;
        //read the highbeam switch
        uint8_t nowHB = digitalRead( pinHighbeam );
        //if not the same as last check...
        if( nowHB != lastHB )
        {
            lastHB = nowHB;
            //if highbeam button is pressed, enable the highbeams
            //else, disable them
            bHBEn = (nowHB == PUSHED) ? true : false;
            
        }//if
        
    }//if
    
}//checkHighBeams

Yes, except the pins 10 & led pin 11 the high beams, don't stay on, they are to stay on when button 5 toggle switch is pressed, button 5 is a toggle switch, else you got it. Thank you can you fix that for me? Beautiful code!

Thank You

I want to understand the problem: When you say "toggle", what do you mean?

The conventional usage might be a SPDT switch; three contacts, 1-2-3. With the switch in one position, contacts 1-2 are connected. In the other position, contacts 2-3 are connected. In your case, in my head I'm picturing contact 1 (e.g.) being not-connected, contact 2 going to the Arduino pin 5 and contact 3 being ground.

When I tested here I just used a jumper lead; I would leave pin 5 "open" to simulate toggle position 1-2 and would stick the jumper into pin 5 and GND to simulate the toggle in position 2-3. It worked for me.

So can you describe what your definition of toggle is in this context and how it's wired?

A toggle to my thinking is a SPST switch, on and stays on till toggled off.

Sorry if I wasn't clear. When button 5 is pressed the led 10 and 11 "high Beams" should come on and stay on, until button 5 is pressed again.

Currently, in your script, if I press button 5 the high beams come on, but turn off when I release button 5, they should stay on until I press button 5 again.

Hope this is clear. Thank you much.

OK, so the two buttons are both momentary (SPST-NO MOM), correct?

If so, try changing the line:

bHBEn = (nowHB == PUSHED) ? true : false;

to

bHBEn ^= (nowHB == PUSHED) ? true : false;

No Sir, one button is momentary, the button 8 is momentary. You have that correct.

The button 5 is like a house wall switch, the light stays on when the switch is turned on, and stays on until the wall switch is turned off. Thank you so much

I am looking at your code and a lot of what I see is new to me, I am hoping you could send me code for the high beam section to leave the high beams on until button 5 is pressed again. Please help I will study your code and google what is not clear to me. Thank You

Here's the whole thing with the HB fix:

#define LEDon       HIGH
#define LEDoff      LOW
#define PUSHED      LOW
 
const uint8_t pinLB = 7; 
const uint8_t pinLBInd = 6; 
const uint8_t pinHB = 11;
const uint8_t pinHBInd = 10;

const uint8_t pinDebugLED = LED_BUILTIN;

const uint8_t pinHighbeam = 5;      //high-beam buttoninput
const uint8_t pinMomentary = 8;     //momentary blink input

bool
    bBlink = false,
    bMomBlinkEn = false,
    bHBEn = false;
uint8_t
    lastHB,
    lastMom;

void setup( void )
{
    Serial.begin(115200);
    pinMode( pinHighbeam, INPUT_PULLUP );
    pinMode( pinMomentary, INPUT_PULLUP );
    lastHB = digitalRead( pinHighbeam );
    bHBEn = (lastHB == PUSHED) ? true : false;
    lastMom = digitalRead( pinMomentary );
    bMomBlinkEn = (lastMom == PUSHED) ? true : false;            
    
    //
    pinMode( pinLB, OUTPUT );    
    pinMode( pinLBInd, OUTPUT );
    digitalWrite( pinLB, LEDoff );
    digitalWrite( pinLBInd, LEDoff );
    //
    pinMode( pinHB, OUTPUT );
    pinMode( pinHBInd, OUTPUT );
    digitalWrite( pinHB, LEDoff );
    digitalWrite( pinHBInd, LEDoff );
    //
    pinMode( pinDebugLED, OUTPUT );
    digitalWrite( pinDebugLED, LEDoff );
                
}//setup

void loop( void )
{
    bool
        bEn;
    
    doBlink();          //toggles main "blink" flag every 100mS
    checkMomentary();   //checks the momentary blink switch
    checkHighBeams();   //checks the highbeam switch

    //for the low beams
    //  if the momentary button is not pressed, they're on (true)
    //  if the momentary button is pressed, they follow the bBlink variable
    bEn = (bMomBlinkEn == false) ? true : bBlink; 
    digitalWrite( pinLB, bEn ? LEDon : LEDoff );
    digitalWrite( pinLBInd, bEn ? LEDon : LEDoff );
    //digitalWrite( pinDebugLED, bEn ? LEDon : LEDoff );

    //for the highbeams
    //  if the highbeam switch is off, they're off
    //  if the highbeam switch is pressed, then they follow the same logic the low-beam do:
    //      if the momentary button not pressed, they're on
    //      if the momentary button is pressed, they follow the bBlink variable
    bEn = bHBEn & ( (bMomBlinkEn == false) ? true : bBlink );
    Serial.print( bEn ); Serial.print( bHBEn ); Serial.println( bMomBlinkEn );
    digitalWrite( pinHB, bEn ? LEDon : LEDoff );
    digitalWrite( pinHBInd, bEn ? LEDon : LEDoff );
    digitalWrite( pinDebugLED, bEn ? LEDon : LEDoff );
     
} //END of void loop()

void doBlink( void )
{
    static uint32_t
        tBlink = 0ul;
    uint32_t
        tNow = micros();

    //every 100,000uS (100mS) we toggle the state of the boolean bBlink
    if( (tNow - tBlink) >= 100000ul )
    {
        tBlink = tNow;    
        bBlink ^= true;
        
    }//if
    
}//doBlink

void checkMomentary( void )
{
    static uint32_t
        tMom = 0ul;
    uint32_t
        tNow = millis();

    //read the momentary switch every 50mS
    if( (tNow - tMom) >= 50ul )
    {
        tMom = tNow;
        //read the momentary switch
        uint8_t nowMom = digitalRead( pinMomentary );
        //if not the same as last read...
        if( nowMom != lastMom )
        {            
            //save now as last
            lastMom = nowMom;
            //if now is pushed, enable momentary blink flag
            //else disable it
            bMomBlinkEn = (nowMom == PUSHED) ? true : false;            
            
        }//if
        
    }//if
    
}//checkMomentary

void checkHighBeams( void )
{
    static uint32_t
        tHB = 0ul;
    uint32_t
        tNow = millis();

    //check HB switch every 50mS
    if( (tNow - tHB) >= 50ul )
    {
        tHB = tNow;
        //read the highbeam switch
        uint8_t nowHB = digitalRead( pinHighbeam );
        //if not the same as last check...
        if( nowHB != lastHB )
        {
            lastHB = nowHB;
            //if highbeam button is pressed, toggle the highbeams
            bHBEn ^= (nowHB == PUSHED) ? true : false;
            
        }//if
        
    }//if
    
}//checkHighBeams

Blackfin you are a saint!

Thank you so much it works perfectly. Your code is scary to me, lots of google stuff for me to do. I am sure you are a professional coder. Any links you can give me, to help me understand your code?

Thanks again, Sir.

Oh no...no no. Anything but. Lots of folks here will tell you that :slight_smile:

I suspect the part of the code giving the most head-scratches would be the operations like:

bHBEn = (lastHB == PUSHED) ? true : false;

This is called a "ternary" (google it.) It basically evaluates the part to the left of the '?' (so lastHB == PUSHED) and, if true, it selects the part to the left of the ':'. If false, it selects the part to the right of the ':'.

This would be equivalent to:

if( lastHB == TRUE )
    bHBEn = true;
else
    bHBEn = false;

It's just written in a more compact way here.

Can you tell me where in the code you make the button 5 work as a house wall switch? I looked at void checkHighBeams( void ) and it looks identical to the first script you sent where button 5 acted like a mom on switch. Thanks

Go back to post 11. The two statements there superficially look alike but there's a subtle difference:

bHBEn ^= (nowHB == PUSHED) ? true : false;

Notice the '^' operator performs the logic operation "exclusive OR" or "XOR". If you look up XOR truth table:

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

You'll see that if you XOR a 0 with a 1, you get a 1 and if you XOR a 1 with a 1 you get a 0. In that line, if the HB button is seen to have been pressed (nowHB == PUSHED), then bHBEn = bHBEn ^ true, which means bHBEn toggles; if it was true it's now false and if it's false it's now true.

If button change was not from UNPUSHED to PUSHED but instead was PUSHED to UNPUSHED, the statement nowHB == PUSHED is false and so the equation is bHBEn = bHBEn ^ false which does not change bHBEn.

Wow, that is deep, I will study this. Thanks again Blackfin

Hello, Blackfin I hope you don't mind a question or two, why do you use Serial.begin(115200); instead of Serial.begin(9600); Could I use Serial.begin(9600); in your script?

Serial.begin(115200); looks like garbage in my monitor