Wow this is deep checking it out thanks
I plugged it into my script and there is one bug
My low beam fog lights are always on by default and they do not turn off in the blink sequence consistently. I think it is because of button 4 may be stuck on low at times, here is my script. Sometimes it blinks normally and sometimes it doesn't. You have to do a double-click on button 5 to run your script
if you uncomment run_police_lights(); you will see my original blink does fine but not with the fancy blink I like in your script that I edited
//call the function
//run_police_lights();
run_police_lights_2();
//Arduino forum 02_21_2022 blh64 Faraday https://forum.arduino.cc/t/onebutton-library-doubleclick/959465/30
//My_Working_OneButton_Harley_Fog_Lights_With_Police_Fine_Tuneup_1.uno
//button 4 blinks the fog lights
//Button 5 has 3 jobs short click, long press, double click
//Button 5 will have 3 jobs, a short press will toggle on or off the high beam fog lights, as you have coded.
//Button 5 the first long press will turn off all the fog lights, and a second long press will turn on just the low beam fog lights, as you have coded.
//while all the fog lights are off , no other button presses will work
//Button 5 a first double click, will turn on the police lights, and a second double click will turn off the police lights and just light the low beam fog lights, the high beams will be off.
//The low beam fog lights are always on as default.
//Declarations
#include "OneButton.h"
//===================================================================================================================================================
//=======================================================================================================================================================
//BEGIN run_police_lights_2 code
//=======================================================================================================================================================
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
// CONSTANT DEFINITION
constexpr byte LedPinsStages[] {6,7,8,9}; // portPin o---|220|---|LED|---GND
//LED pins
constexpr byte LedPinsStage1[] {6,7}; // portPin o---|220|---|LED|---GND
constexpr byte LedPinsStage3[] {8,9};
// portPin o---|220|---|LED|---GND
//How many flashes
constexpr int numberOfFlashs1 {6};
constexpr int numberOfFlashs3 {6};
//set the times
constexpr unsigned long delayTimeStage1 {50};
constexpr unsigned long delayTimeStage2 {100};
constexpr unsigned long delayTimeStage3 {50};
#define OutPutTest
unsigned long OutPutTestTime {500};
// VARIABLE DECLARATION AND DEFINITION
unsigned long currentTime;
struct TIMER { // has the following members
unsigned long duration; // memory for interval time
unsigned long stamp; // memory for actual time
bool onOff; // control for start/stop
};
TIMER stage1 {delayTimeStage1, 0, false};
TIMER stage2 {delayTimeStage2, 0, false};
TIMER stage3 {delayTimeStage3, 0, false};
bool timerEvent (TIMER &timer) {
return (currentTime - timer.stamp >= timer.duration && timer.onOff);
}
void startTimer(TIMER &timer) {
timer.stamp = currentTime;
timer.onOff = true;
}
void resetTimer(TIMER &timer) {
timer.stamp = currentTime;
}
void stoppTimer(TIMER &timer) {
timer.onOff = false;
}
void toogleLedPin(int pin) {
digitalWrite(pin, !digitalRead(pin));
}
//=======================================================================================================================================================
//END run_police_lights_2 code
//=======================================================================================================================================================
// Setup a new OneButton push buttons on pin 4 and 5
/*
Button 4 - toggle blinking on/off
Button 5 - toggle HIGH fog ligts on, long click - toggle all lights on/off
*/
//OneButton blink_button(4, true); //original
//OneButton on_off_button(5, true); //original
OneButton button_blink_the_fog_lights(4, true);
OneButton switch_turn_on_the_high_beam_fog_lights(5, true);
//define
#define DISABLED false
#define ENABLED true
#define LEDon HIGH
#define LEDoff LOW
unsigned long currentMillis;
unsigned long previousMillis;
unsigned long on_off_long_press_start_time;
const unsigned long blinkInterval = 100;
//this is not needed on a long press because of switch_turn_on_the_high_beam_fog_lights.setPressTicks(2500); // a long press will be detected after 2500 ms
const unsigned long longPressInterval = 2500;
//LED's
const int fog_light_low_beam = 6;
const int fog_light_low_beam_indicator = 7;
const int fog_light_high_beam = 8;
const int fog_light_high_beam_indicator = 9;
//bool
bool blinking = DISABLED;
bool inLongPress = false;
bool all_the_fog_lights_are_off = DISABLED;
//enum
//enum { LIGHTS_OFF, LIGHTS_LOW_BEAM, LIGHTS_BOTH };//original
enum { LIGHTS_OFF, LIGHTS_LOW_BEAM, LIGHTS_BOTH, POLICE_LIGHTS };
int lightState;
//Police lights
bool start_police_lights_now = DISABLED;
bool Short_Button_Press_Allowed = ENABLED;
const long onDuration_1 = 250;// OFF time for LED//orig 100
const long offDuration_1 = 200;// ON time for LED //orig 500 lower this number for a faster blink
const long onDuration_2 = 250;// OFF time for LED// orig 100
const long offDuration_2 = 200;// ON time for LED//orig 500 lower this number for a faster blink
int LEDState_1 = HIGH;// initial state of LED
int LEDState_2 = LOW;// initial state of LED
long rememberTime_1 = 0;// this is used by the code
long rememberTime_2 = 0;
//end Police
//END Declarations
void setup()
{
//=======================================================================================================================================================
//BEGIN run_police_lights_2 code
//=======================================================================================================================================================
// https://www.learncpp.com/cpp-tutorial/for-each-loops/
for (auto Output_ : LedPinsStages) pinMode(Output_, OUTPUT);
#ifdef OutPutTest
// check outputs
//for (auto Output_ : LedPinsStages) digitalWrite(Output_, HIGH), delay(OutPutTestTime);//original
//BEGIN my add edit
////this does NOT light the 4 LED's, on startup, when Output is set to LOW, uncomment it if you wish, and then "comment out" for (auto Output_ : LedPinsStages) digitalWrite(Output_, HIGH), delay(OutPutTestTime);
//for (auto Output_ : LedPinsStages) digitalWrite(Output_, LOW), delay(OutPutTestTime);
//this lights the 4 LED's, on startup, when Output is set to HIGH, comment it out is you wish and then "uncomment" /for (auto Output_ : LedPinsStages) digitalWrite(Output_, LOW), delay(OutPutTestTime);
for (auto Output_ : LedPinsStages) digitalWrite(Output_, HIGH), delay(OutPutTestTime);
//END my add edit
for (auto Output_ : LedPinsStages) digitalWrite(Output_, LOW), delay(OutPutTestTime);
#endif
startTimer(stage1);
//=======================================================================================================================================================
//END run_police_lights_2 code
//=======================================================================================================================================================
pinMode(fog_light_low_beam, OUTPUT);
pinMode(fog_light_low_beam_indicator, OUTPUT);
pinMode(fog_light_high_beam, OUTPUT);
pinMode(fog_light_high_beam_indicator, OUTPUT);
digitalWrite(fog_light_high_beam, LEDoff);
digitalWrite(fog_light_high_beam_indicator, LEDoff);
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
//turns on the low beeams default
lightState = LIGHTS_LOW_BEAM;
// Setup the Serial port. see http://arduino.cc/en/Serial/IfSerial
Serial.begin(115200);
while (!Serial)
{
; // wait for serial port to connect. Needed for Leonardo only
}
//link your buttos here
button_blink_the_fog_lights.attachClick(blink_click);//original this is for a "latched switch" if you want one
//begin my add or edit
button_blink_the_fog_lights.attachLongPressStart(blink_click);//this is for a momentary-on switch the "blinking" variable gets switched on and off in the blink_click function, blinking = !blinking;
button_blink_the_fog_lights.attachLongPressStop(blink_click);//this is for a momentary-on switch the "blinking" variable gets switched on and off in the blink_click function, blinking = !blinking;
//
button_blink_the_fog_lights.setDebounceTicks(50);
button_blink_the_fog_lights.setPressTicks(10);//set faster click response
//end my add or edit
//original
switch_turn_on_the_high_beam_fog_lights.attachClick(on_off_click);//original
switch_turn_on_the_high_beam_fog_lights.attachLongPressStart(on_off_long_press_start);//original
switch_turn_on_the_high_beam_fog_lights.attachDuringLongPress(on_off_long_press);//original
switch_turn_on_the_high_beam_fog_lights.attachLongPressStop(on_off_long_press_stop);//original
//begin my add or edit
switch_turn_on_the_high_beam_fog_lights.setDebounceTicks(50);
switch_turn_on_the_high_beam_fog_lights.setClickTicks(150);//this 150ms will allow the doubleclick to work, any "lower" and doubleclick will not be detected
switch_turn_on_the_high_beam_fog_lights.setPressTicks(2500); // a long press will be detected after 2500 ms
switch_turn_on_the_high_beam_fog_lights.attachDoubleClick(doubleclick); //will use this for police lights
//end my add or edit
} //setup
void loop()
{
//don't forget to set start time with millis()
currentMillis = millis();
//currentTime = millis(); used for run_police_lights_2
currentTime = millis();
// keep watching the push buttons:
button_blink_the_fog_lights.tick();
switch_turn_on_the_high_beam_fog_lights.tick();
if (blinking)
{
//call the function
blink_the_fog_lights();
}
if(start_police_lights_now)//toggled in doubleclick
{
lightState = POLICE_LIGHTS;//set lightState to POLICE_LIGHTS
blinking = DISABLED;
Short_Button_Press_Allowed = DISABLED;//don't allow short clicks
//call the function
//run_police_lights();
run_police_lights_2();
}
else//police lights are off
{
Short_Button_Press_Allowed = ENABLED;// allow short clicks
}
}//loop
//SHORT PRESS BUTTON 4 toggle on and off the high beam fog lights
void on_off_click()//button 5 short press hereh "LIGHTS_BOTH" is doing 1 job here for a "short press" high beams are OFF low beams are ON
{
// if the high beam fog lights are off, turn them on
// if the high beam fog lights are on, turn them off
if(Short_Button_Press_Allowed)
{
Serial.println("switch_turn_on_the_high_beam_fog_lights click.");
switch ( lightState )
{
case POLICE_LIGHTS:// short press do noting
break;
case LIGHTS_OFF: // all lights are off so ignore
break;
//this is called initally from void setup() lightState = LIGHTS_LOW_BEAM;
case LIGHTS_LOW_BEAM: // low beam fog lights are on so switch to just high beam fog lights
digitalWrite(fog_light_high_beam, LEDon);
digitalWrite(fog_light_high_beam_indicator, LEDon);
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
lightState = LIGHTS_BOTH;
Serial.println("high ON");
break;
case LIGHTS_BOTH: // both low and high beam fog lights are on so switch high off, "LIGHTS_BOTH" is doing 1 job here for the second "short press" high beams are OFF low beams are ON
digitalWrite(fog_light_high_beam, LEDoff);
digitalWrite(fog_light_high_beam_indicator, LEDoff);
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
lightState = LIGHTS_LOW_BEAM;
Serial.println("high OFF");
break;
}//switch case
}//if
}// end on_off_click()
//LONG PRESS BUTTON 5 on the first long press turn off all the fog lights then on the second long press turn back on just the low beam fog lights
void on_off_long_press()//button 5 long press here or doubleclick
{
// this gets called while a long press is in progress
// if enough time has elapsed, toggle the state
//using millis() here
unsigned long duration = millis() - on_off_long_press_start_time;
if ( duration >= longPressInterval && inLongPress == true )
{
// if the high beam fog lights are off, turn them on
// if the high beam fog lights are on, turn them off
Serial.println("Button 5 on_off_longPress.");
//lightState can be used in other functions
switch (lightState)
{
case LIGHTS_OFF: // all lights are off so turn on low beam fog lights
Serial.println("long press button 5 High Beam Fog Lights Off will call LIGHTS_BOTH on the next press");
digitalWrite(fog_light_high_beam, LEDoff);
digitalWrite(fog_light_high_beam_indicator, LEDoff);
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
all_the_fog_lights_are_off = DISABLED;
lightState = LIGHTS_LOW_BEAM;
Serial.println("low ON");
break;
case LIGHTS_LOW_BEAM: // low beam fog lights are on so switch everything off
case LIGHTS_BOTH: // "LIGHTS_BOTH" is doing another job here for a "long press", both low and high beam fog lights are off
Serial.println("long press button 5 ALL Fog Lights Off will call LIGHTS_OFF on the next press");
digitalWrite(fog_light_high_beam, LEDoff);
digitalWrite(fog_light_high_beam_indicator, LEDoff);
digitalWrite(fog_light_low_beam, LEDoff);
digitalWrite(fog_light_low_beam_indicator, LEDoff);
all_the_fog_lights_are_off = ENABLED;
lightState = LIGHTS_OFF;
Serial.println("all OFF");
break;
case POLICE_LIGHTS:
lightState = POLICE_LIGHTS;
break;
}//switch case
inLongPress = false;//this was set true in void on_off_long_press_start(), and set false also in void on_off_long_press_stop()
}//if
}//on_off_long_press_stop()
void on_off_long_press_start()
{
// record time of the long press
//begin my add edit
//on_off_long_press_start_time = millis();//don't need millis here because of switch_turn_on_the_high_beam_fog_lights.setPressTicks(2500); // a long press will be detected after 2500 ms
//end my add edit
inLongPress = true;
} //on_off_long_press_start
void on_off_long_press_stop()
{
inLongPress = false;
}
void blink_click()
{
//this blinking bool variable, toggles "blinking" back and forth on each run of the blink_click() function
blinking = !blinking;
// if we are done blinking, make sure we leave the lights on
if ( blinking == DISABLED )//if blinking is DISABLED do nothing
{
Serial.println("blinking");
Serial.println(blinking);
if ( lightState == LIGHTS_BOTH )
{
Serial.println("blinking");
Serial.println(blinking);
digitalWrite(fog_light_high_beam, LEDon);
digitalWrite(fog_light_high_beam_indicator, LEDon);
}//if
//if the value of "lightState" equals the value of "LIGHTS_HIGH_BEAM" "OR" the value of "lightState" equals the value of "LIGHTS_BOTH"
if ( lightState == LIGHTS_LOW_BEAM || lightState == LIGHTS_BOTH )
{
// toggle low beams
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
}//if
}//blinking DISABLED
}//blink_click()
void blink_the_fog_lights()
{
//if lighrState = LIGHTS_OFF bail out, do not blink
if ( lightState == LIGHTS_OFF )
{
// lights are off so nothing to do
return;
}//if
//using millis() here
if (currentMillis - previousMillis >= blinkInterval)
{
// enough time passed yet?
previousMillis = currentMillis; // sets the time we wait "from"
if ( lightState == LIGHTS_BOTH )
{
// toggle high beams
digitalWrite(fog_light_high_beam, !digitalRead(fog_light_high_beam)); // shortcut to toggle the LED
digitalWrite(fog_light_high_beam_indicator, !digitalRead(fog_light_high_beam_indicator)); // shortcut to toggle the LED
}//if
//if the value of "lightState" equals the value of "LIGHTS_LOW_BEAM" "OR" the value of "lightState" equals the value of "LIGHTS_BOTH"
if ( lightState == LIGHTS_LOW_BEAM || lightState == LIGHTS_BOTH )
{
// toggle low beams
digitalWrite(fog_light_low_beam, !digitalRead(fog_light_low_beam)); // shortcut to toggle the LED
digitalWrite(fog_light_low_beam_indicator, !digitalRead(fog_light_low_beam_indicator)); // shortcut to toggle the LED
}//if
}//if
}//blink_the_fog_lights()
// this function will be called when the button was pressed 2 times in a short timeframe.
void doubleclick()
{
if (!all_the_fog_lights_are_off)//all the fog lights are NOT off, so continue to run the police lights
{
if (!start_police_lights_now)//police lights are on
{
start_police_lights_now = ENABLED;
Short_Button_Press_Allowed = DISABLED;
}
else//police lights are off
{
start_police_lights_now = DISABLED;
Short_Button_Press_Allowed = ENABLED;
if (lightState = POLICE_LIGHTS)
{
digitalWrite(fog_light_high_beam, LEDoff);
digitalWrite(fog_light_high_beam_indicator, LEDoff);
digitalWrite(fog_light_low_beam, LEDon);
digitalWrite(fog_light_low_beam_indicator, LEDon);
lightState = LIGHTS_LOW_BEAM;//go back to short press LIGHTS_LOW_BEAM
} //if
}//else
} //all_the_fog_lights_are_off
} //end doubleclick
//Police
void run_police_lights()
{
if(start_police_lights_now)
{
Serial.println("the police lights are on");
// LED blink with millis()
if( LEDState_1 == HIGH )
{
if( (millis() - rememberTime_1) >= onDuration_1)
{
LEDState_1 = LOW;// change the state of LED
rememberTime_1 = millis();// remember Current millis() time
}//if
}
else
{
if( (millis()- rememberTime_1) >= offDuration_1)
{
LEDState_1 = HIGH;// change the state of LED
rememberTime_1 = millis();// remember Current millis() time
}//if else
}//if
// LED blink with millis()
digitalWrite(fog_light_low_beam,LEDState_1);// turn the LED ON or OFF
digitalWrite(fog_light_low_beam_indicator,LEDState_1);// turn the LED ON or OFF
if( LEDState_2 ==LOW )
{
if( (millis() - rememberTime_2) >= onDuration_2)
{
LEDState_2 = HIGH;// change the state of LED
rememberTime_2 = millis();// remember Current millis() time
}
}
else
{
if( (millis()- rememberTime_2) >= offDuration_2)
{
LEDState_2 = LOW;// change the state of LED
rememberTime_2 = millis();// remember Current millis() time
}//if
}//if else
// LED blink with millis()
digitalWrite(fog_light_high_beam,LEDState_2);// turn the LED ON or OFF
digitalWrite(fog_light_high_beam_indicator,LEDState_2);// turn the LED ON or OFF
}
else
{
if (!start_police_lights_now)
{
digitalWrite(fog_light_high_beam,LEDoff);
digitalWrite(fog_light_high_beam_indicator,LEDoff);
Short_Button_Press_Allowed = ENABLED;
}//if
}//if else
} //end void
void run_police_lights_2()
{
if(start_police_lights_now)
{
if (timerEvent(stage1))
{
for (auto LedPinStage1 : LedPinsStage1) toogleLedPin(LedPinStage1);
resetTimer(stage1);
static int counter=0;
if(!(++counter%=numberOfFlashs1<<1)) startTimer(stage2),stoppTimer(stage1);
}
if (timerEvent(stage2))
{
startTimer(stage3),stoppTimer(stage2);
}
if (timerEvent(stage3))
{
for (auto LedPinStage3 : LedPinsStage3) toogleLedPin(LedPinStage3);
resetTimer(stage3);
static int counter=0;
if(!(++counter%=numberOfFlashs3<<1)) startTimer(stage1),stoppTimer(stage3);
}
}
else
{
if (!start_police_lights_now)
{
digitalWrite(fog_light_high_beam,LEDoff);
digitalWrite(fog_light_high_beam_indicator,LEDoff);
Short_Button_Press_Allowed = ENABLED;
}//if
}//else
}//run_police_lights_2