Push button press and led indicator

I have the following simulator code

What I'm trying to do is that when the button is first pressed the LED at A0 will be light on and will stay on and a the time of the button press will be store into a variable.

when the button is pressed once more the LED A0 will be turned off to indicate the button is pressed of the second time and the time of that second press will be store to another variable.

right now when I store a the time of millis when count is = 1 the time variable is keep update and stop only when count is 2 or != 1 (which make sense).
How can I store only the time when the button was first push? That it won't update it over and over

// Counts number of button presses
// output count to serial


byte switchPin = 13;                    // switch is connected to pin 2
byte ledPin = A0;                      // led on pin 13
byte buttonPresses = 0;                // how many times the button has been pressed 
byte lastPressCount = 0;                // to keep track of last press count

unsigned long firstPressMillis;
unsigned long SecondPressMillis;

void setup() {
  pinMode(switchPin, INPUT_PULLUP);          // Set the switch pin as input
  digitalWrite(switchPin, HIGH);      // set pullup resistor
  Serial.begin(9600);                 // Set up serial communication at 9600bps
}

void loop()
{
  if (digitalRead(switchPin) == LOW)  // check if button was pressed
  {
    buttonPresses++;                  // increment buttonPresses count
    delay(250);                       // debounce switch
  }
 
  if (lastPressCount != buttonPresses)              // only do output if the count has changed
  {
    Serial.print ("Button press count = ");          // out to serial
    Serial.println(buttonPresses, DEC);                   // wait again
    lastPressCount = buttonPresses;    // track last press count
  }
  if(lastPressCount == 1)
  {
    firstPressMillis = millis();
    Serial.println (firstPressMillis);
    
  }
}

Thanks

1 Like

What is that for ?

A state machine or leveraging a button library would be a solid approach to your need

(Mind button bouncing)

1 Like

If you use the button library, the counting is simple:

/*
 * This example reads the number of the pressed count of a button with debounce and print it to Serial Monitor.
 */

#include <ezButton.h>

ezButton button(7);  // create ezButton object that attach to pin 7;

void setup() {
  Serial.begin(9600);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
  button.setCountMode(COUNT_FALLING);
}

void loop() {
  button.loop(); // MUST call the loop() function first

  unsigned long count = button.getCount();
  Serial.println(count);
}

You can see more detailed in the Arduino button press count tutorial

A quarter of a second is an awfully long debounce and, in fact you are not using it to debounce you are using it to try and make the button press and release occur before the code loops and increments again. This doesn’t work because someone might hold the button down for > 250ms.

Look up standard button code which is called edge detection or state change detection. You want to know when the button becomes pressed not when it is pressed.

@hk_jh Here is some code to help answer your question. I left your debouncing delays in the code but added logic to track when the button was pressed down and logic for when the button is released. When the button is released we increment the button press count and then store the millis in one of the two variables depending on the press count. These variables will not update over and over like your existing code because we only update them when the button has been released...that was the part your code was missing.

In addition to the good suggestions about improving the button debouncing logic, I noticed you were using byte (8 bits) to save memory over the normal int (16 bits) that Arduino suggests for beginners. Because byte was used you ran into a situation where Serial.print didn't show you the expected result and you needed to include a DEC argument. Sometimes you can be more specific with your data types to allow functions to work as you would expect and in this case, an uint8_t is perfect since it lets the compiler know you'd like the 8 bits to represent an unsigned 8-bit integer. Being this specific will help the compiler do things as you expect and is a best practice. If you are too generic with data types you can create really hard to solve bugs. It's great you recognized the wasted space of int vs byte though, nice job!

uint8_t switchPin = 13;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t ledPin = A0;
uint8_t buttonPressCount = 0; // Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).

uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;

uint32_t firstPressMillis = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.
uint32_t secondPressMillis = 0;

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

    // Setup the button.
    pinMode(switchPin, INPUT_PULLUP);
    digitalWrite(switchPin, HIGH);

    // Setup the LED.
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
}

void loop()
{
    currentButtonState = digitalRead(switchPin);

    if (currentButtonState == LOW && lastButtonState == HIGH)
    {
        // The button was high and is now low, meaning the user pressed down
        // the button but they have not released it.

        delay(125); // debounce hack
        lastButtonState = LOW;
    }
    else if (currentButtonState == HIGH && lastButtonState == LOW)
    {
        // The user has released the button.  Since we now have a complete
        // button press down and release up cycle, count that as a button press.
        buttonPressCount++;

        if (buttonPressCount == 1)
        {
            firstPressMillis = millis();
            digitalWrite(ledPin, HIGH);   // Turn on the led after the first button press/release cycle.
        }
        else if (buttonPressCount == 2)
        {
            secondPressMillis = millis();
            digitalWrite(ledPin, LOW);    // Turn off the led after the second button press/release cycle.

        }

        Serial.print("Button press count = "); Serial.println(buttonPressCount); // No need for the DEC argument since we changed the data type to uint8_t...now the compiler knows it's an integer.
        Serial.print("  First press millis  = "); Serial.println(firstPressMillis);
        Serial.print("  Second press millis = "); Serial.println(secondPressMillis);

        delay(125); // debounce hack
        lastButtonState = HIGH;
    }
}
1 Like

What I'm actually try to do with the button is the following:

I have the following code:

For the moment the code is running when the program is start. Each LED is start to sequence at the time specify in is struct first index:

first led start to sequencr at 0ms , second led start after 0.5 minutes and the third led start after 0.75 minutes.

//leds structure//
struct leds
{
  unsigned long startTime;       // The time this led is first active after a buttun is first pressed
  unsigned long stopTime;        // The time this led becomes inactive after a buttun is second time pressed
  unsigned long minPulse;        // The minimum time the next pulse is generated
  unsigned long maxPulse;        // The maximum time the next pulse is generated
  unsigned long nextPulseStart;  // The time of the next pulse starts
  unsigned long nextPulseStop;   // The time of the next pulse  stops
  unsigned long pulseLength;     // The on time of the pulse
  uint8_t pin;                   // led GPIO pin number
};

leds myLeds[NUM_LED] = {0 min, 0.75 min, 1 sec,  2 sec, 0, 0, 100 ms, 2, //led num 0
                        0.5 min, 1 min, 1 sec, 2 sec, 0, 0, 100 ms, 3,//led num 1
                        0.75 min, 1.25 min, 1 sec, 2 sec, 0, 0, 100 ms, 4, //led num 2

                                      };

What I would like to do is:

the leds will start thier sequence only after a button is pressed. when that button is pressed another led will be light on to indicate the sequence is running.

When the button is pressed once again the indicator led will turned off and the LEDs will start to turn off.

Each one will turn off after the time specify at the second index of the array of the led struct. So the first led will stop after 0.75 min has passed since we press the button,

the second led will stop after 1 min has passed and the third led will stop after 1.25 min has passed.

How can I do the above?

full code I have is here:

#define NUM_LED 3

//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1

uint16_t millisOffset;
unsigned long currentMillis = millis();
unsigned long millisEnd;


//leds structure//
struct leds
{
  unsigned long startTime;       // The time this led is first active after a buttun is first pressed
  unsigned long stopTime;        // The time this led becomes inactive after a buttun is second time pressed
  unsigned long minPulse;        // The minimum time the next pulse is generated
  unsigned long maxPulse;        // The maximum time the next pulse is generated
  unsigned long nextPulseStart;  // The time of the next pulse starts
  unsigned long nextPulseStop;   // The time of the next pulse  stops
  unsigned long pulseLength;     // The on time of the pulse
  uint8_t pin;                   // led GPIO pin number
};

leds myLeds[NUM_LED] = {0 min, 0.75 min, 1 sec,  2 sec, 0, 0, 100 ms, 2, //led num 0
                        0.5 min, 1 min, 1 sec, 2 sec, 0, 0, 100 ms, 3,//led num 1
                        0.75 min, 1.25 min, 1 sec, 2 sec, 0, 0, 100 ms, 4, //led num 2

                                      };


void setup() {
  // put your setup code here, to run once:
 Serial.begin(115200);
  for (uint8_t i = 0; i < NUM_LED; i++)
  {
    pinMode(myLeds[i].pin, OUTPUT);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
startSequence();
}


void startSequence()
{  
 currentMillis = millis() - millisOffset;
for (uint8_t x = 0; x < NUM_LED; x++)
  {
   
    // Is this solenoid active
    if (myLeds[x].startTime < currentMillis)
    {
      // Do we need to calculate a next pulse time?
  

      if (myLeds[x].nextPulseStop < currentMillis)
      {
        // Turn off led
        digitalWrite(myLeds[x].pin, LOW);

        // Calculate nextPulseStart & nextPulseStop
        long  startOffset =random(myLeds[x].minPulse, myLeds[x].maxPulse);
        myLeds[x].nextPulseStart = startOffset + currentMillis;
        myLeds[x].nextPulseStop = myLeds[x].nextPulseStart + myLeds[x].pulseLength;
      }

      // Are we currently in the middle of a pulse?
      if (myLeds[x].nextPulseStart < currentMillis &&
          myLeds[x].nextPulseStop  > currentMillis)
      {
        //turn on led
        digitalWrite(myLeds[x].pin, HIGH);
      }
    }
  }
}

@hk_jh That simulator is really cool, haven't seen something like that before.

I updated the code in my previous post to turn on and off the pin A0 LED and it works as you originally described.

As for your additional question, here is a code snippet that should give you some ideas on how to go about calculating dynamic start and end times for the leds and how to control the leds based on those dynamic times:

void loop()
{
    // ... 

    else if (currentButtonState == HIGH && lastButtonState == LOW)
    {
        // Button press is complete
        delay(125); // debounce hack
        lastButtonState = HIGH;

        // Calculate the start and end times to control the leds...

        // Led 0
        myLeds[0].nextPulseStart = millis() + myLeds[0].startTime;
        myLeds[0].nextPulseStop = myLeds[0].nextPulseStart + myLeds[0].pulseLength;

        // Led 1
        // ...
    }

    // Control led 0.
    // We only want to control it when a button was pressed so we check to see if a start time was set.
    if (myLeds[0].nextPulseStart > 0)
    {
        if (led0IsActive == 0 && millis() > myLeds[0].nextPulseStart) // If the led is off and it's time to turn it on...
        {
            led0IsActive = 1;
            digitalWrite(myLeds[0].pin, HIGH);
        }
        else if (led0IsActive == 1 && millis() > myLeds[0].nextPulseStop) // If the led is on and it's time to turn it off...
        {
            led0IsActive = 0;
            digitalWrite(myLeds[0].pin, LOW);

            myLeds[0].nextPulseStart = 0; // Clear the start time so we don't control the led anymore.
        }
    }

    // Control led 1.
    // ...
}

consider

struct Led {
    byte          pin;
    unsigned long msecPeriod;
};

byte switchPin = A1;

Led leds [] = {
    { 10, 5000 },
    { 11, 3000 },
    { 12, 1000 },
    { 13,    0 },
};
#define N_LED       (sizeof(leds)/sizeof(Led))

byte butState;

enum { Off = HIGH, On = LOW };

unsigned long msecLst;

enum { Idle, Pressed, Run };
int state;

const char * stStr [] = {
    "Idle",
    "Pressed",
    "Run",
};

char s [80];

// -----------------------------------------------------------------------------
void loop()
{
    unsigned long msec = millis ();

    if (Run == state)  {
        state = Idle;
        for (unsigned n = 0; n < N_LED; n++)  {
            if (msec - msecLst < leds [n].msecPeriod)
                state = Run;
            else 
                digitalWrite (leds [n].pin, Off);
        }

        if (Idle == state)  {
            sprintf (s, " state %s", stStr [state]);
            Serial.println (s);
        }
    }

    byte but = digitalRead (switchPin);
    if (butState != but)  {
        butState = but;
        delay (10);         // debounce

        if (LOW == but)  {
            if (Idle == state)  {
                state = Pressed;
                for (unsigned n = 0; n < N_LED; n++)
                    digitalWrite (leds [n].pin, On);
            }
            else if (Pressed == state)  {
                msecLst = msec;
                state   = Run;
            }

            sprintf (s, " state %s", stStr [state]);
            Serial.println (s);
        }
    }
}

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

    // configure but and initialize state
    pinMode (switchPin, INPUT_PULLUP);
    butState = digitalRead (switchPin);

    for (unsigned n = 0; n < N_LED; n++)  {
        pinMode      (leds [n].pin, OUTPUT);
        digitalWrite (leds [n].pin, Off);
    }
}

what is all this code you share? is it only for the button?
where I should add my led code I shared at post #6 ?

There is no option to do for loop instead of repeating the code for each led?

like there is in the original code:

for (uint8_t x = 0; x < NUM_LED; x++)

i believe it does what you asked: pressing the buttons all the LEDs on and pressing it again causes all the LEDs to turn of after a specified delay,

@hk_jh
where I should add my led code I shared at post #6 ?

That is a really worrying question, it seems like you are not attempting to study the examples @gcjr and I are giving you.

@hk_jh
is no option to do for loop instead of repeating the code for each led?

It is straight forward for you to add that type of logic. You know about loops and iterators, use these examples to think through what needs to happen. Both @gcjr and I gave you examples of how you can see when a button is pressed and you already have examples of how to iterate through the myLeds array. I didn't want to write the exact code because this seems like a homework question and from your replies, it seems like you just want us to do your homework. So good luck, you should have more than you need at this point.

So I continued working on your function.

I made the following

I put the button code into a function and right now the sequence is starting only when the button in pressed for the first time which is great.

this is done at the void startSequence() function
were at the beginning I write: { if(buttonPressCount == 1) { currentMillis = millis() + firstPressMillis;

How can I now make it all stop only after the second button is pressed and only after the time of each led has come (as specify in the led struct second index(stop time)

full code :

uint8_t switchPin = 13;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t ledPin = A0;
uint8_t buttonPressCount = 0; // Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).

uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;

uint32_t firstPressMillis = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.
uint32_t secondPressMillis = 0;
uint32_t currentMillis;

/////


#define NUM_LED 3

//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1



//leds structure//
struct leds
{
  unsigned long startTime;       // The time this led is first active after a buttun is first pressed
  unsigned long stopTime;        // The time this led becomes inactive after a buttun is second time pressed
  unsigned long minPulse;        // The minimum time the next pulse is generated
  unsigned long maxPulse;        // The maximum time the next pulse is generated
  unsigned long nextPulseStart;  // The time of the next pulse starts
  unsigned long nextPulseStop;   // The time of the next pulse  stops
  unsigned long pulseLength;     // The on time of the pulse
  uint8_t pin;                   // led GPIO pin number
};

leds myLeds[NUM_LED] = {0 min, 0.75 min, 1 sec,  2 sec, 0, 0, 100 ms, 2, //led num 0
                        0.5 min, 1 min, 1 sec, 2 sec, 0, 0, 100 ms, 3,//led num 1
                        0.75 min, 1.25 min, 1 sec, 2 sec, 0, 0, 100 ms, 4, //led num 2

                                      };


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

    // Setup the button.
    pinMode(switchPin, INPUT_PULLUP);
    digitalWrite(switchPin, HIGH);

    // Setup the LED.
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  
  // leds
  for (uint8_t i = 0; i < NUM_LED; i++)
  {
    pinMode(myLeds[i].pin, OUTPUT);
  }
}

void loop()
{
  buttonPress();
  startSequence();
}



void buttonPress(){
  {
    currentButtonState = digitalRead(switchPin);

    if (currentButtonState == LOW && lastButtonState == HIGH)
    {
        // The button was high and is now low, meaning the user pressed down
        // the button but they have not released it.

        delay(125); // debounce hack
        lastButtonState = LOW;
    }
    else if (currentButtonState == HIGH && lastButtonState == LOW)
    {
        // The user has released the button.  Since we now have a complete
        // button press down and release up cycle, count that as a button press.
        buttonPressCount++;

        if (buttonPressCount == 1)
        {
            firstPressMillis = millis();
            digitalWrite(ledPin, HIGH);   // Turn on the led after the first button press/release cycle.
        }
        else if (buttonPressCount == 2)
        {
            secondPressMillis = millis();
            digitalWrite(ledPin, LOW);    // Turn off the led after the second button press/release cycle.

        }

        Serial.print("Button press count = "); Serial.println(buttonPressCount); // No need for the DEC argument since we changed the data type to uint8_t...now the compiler knows it's an integer.
        Serial.print("  First press millis  = "); Serial.println(firstPressMillis);
        Serial.print("  Second press millis = "); Serial.println(secondPressMillis);

        delay(125); // debounce hack
        lastButtonState = HIGH;
    }
  }
}



void startSequence()
{  
 if(buttonPressCount == 1)
 {
   currentMillis = millis() + firstPressMillis;
for (uint8_t x = 0; x < NUM_LED; x++)
  {
   
    // Is this solenoid active
    if (myLeds[x].startTime < currentMillis)
    {
      // Do we need to calculate a next pulse time?
  

      if (myLeds[x].nextPulseStop < currentMillis)
      {
        // Turn off led
        digitalWrite(myLeds[x].pin, LOW);

        // Calculate nextPulseStart & nextPulseStop
        long  startOffset =random(myLeds[x].minPulse, myLeds[x].maxPulse);
        myLeds[x].nextPulseStart = startOffset + currentMillis;
        myLeds[x].nextPulseStop = myLeds[x].nextPulseStart + myLeds[x].pulseLength;
      }

      // Are we currently in the middle of a pulse?
      if (myLeds[x].nextPulseStart < currentMillis &&
          myLeds[x].nextPulseStop  > currentMillis)
      {
        //turn on led
        digitalWrite(myLeds[x].pin, HIGH);
      }
    }
  }
}
}


I wrote a second function to end the sequence:

void endSequence()
{  
 if(buttonPressCount == 2)
 {
   //currentMillis = millis() + secondPressMillis;
	for (uint8_t x = 0; x < NUM_LED; x++)
  {
      if (myLeds[x].nextPulseStop < millis())
      {
        // Turn off led
        digitalWrite(myLeds[x].pin, LOW);

        // Calculate nextPulseStart & nextPulseStop
        long  startOffset =random(myLeds[x].minPulse, myLeds[x].maxPulse);
        myLeds[x].nextPulseStart = startOffset + millis();
        myLeds[x].nextPulseStop = myLeds[x].nextPulseStart + myLeds[x].pulseLength;
      }

      // Are we currently in the middle of a pulse?
      if (myLeds[x].nextPulseStart < millis() &&
          myLeds[x].nextPulseStop  > millis())
      {
        //turn on led
        digitalWrite(myLeds[x].pin, HIGH);
      }
   if (myLeds[x].stopTime + secondPressMillis < millis())
   {
     digitalWrite(myLeds[x].pin, LOW);
   }
}
 }
}

It seems to never get off
could someone spot my problem?

your code wouldn't respond to button presses until i commented out the write to an input pin

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

    pinMode(switchPin, INPUT_PULLUP);
 // digitalWrite(switchPin, HIGH);

why is your buttonPress() so complicated?
why not simply

void buttonPress ()
{
    byte but = digitalRead (switchPin);
    if (lastButtonState != but)  {
        lastButtonState = but;
        delay (10);             // debounce

        if (LOW == but)  {
            buttonPressCount++;
            firstPressMillis = millis();
            digitalWrite (ledPin, ! digitalRead (ledPin));
        }
    }
}

That button press function won't store into a variable the millis() when the button is pressed for the second time

edit: It work just fine. as it store the time for each press and update the firstPressMillis variable

yes, secondPressMillis is not used anywhere but in a print within buttonPress.

please try to understand the code being posted by others.

it's difficult to explain, but maintainable code is easy to read, understand, debug and enhance. newbies tend to overcomplicate

here is my full code with the updated buttonpress() function:

uint8_t switchPin = 13;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t ledPin = A0;
uint8_t buttonPressCount = 0; // Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).

uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;

uint32_t firstPressMillis = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.
uint32_t secondPressMillis = 0;
uint32_t currentMillis;

/////


#define NUM_LED 3

//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1



//leds structure//
struct leds
{
  unsigned long startTime;       // The time this led is first active after a buttun is first pressed
  unsigned long stopTime;        // The time this led becomes inactive after a buttun is second time pressed
  unsigned long minPulse;        // The minimum time the next pulse is generated
  unsigned long maxPulse;        // The maximum time the next pulse is generated
  unsigned long nextPulseStart;  // The time of the next pulse starts
  unsigned long nextPulseStop;   // The time of the next pulse  stops
  unsigned long pulseLength;     // The on time of the pulse
  uint8_t pin;                   // led GPIO pin number
};

leds myLeds[NUM_LED] = {3 sec, 1 min, 1 sec,  2 sec, 0, 0, 100 ms, 2, //led num 0
                        4 sec, 2 min, 1 sec, 2 sec, 0, 0, 100 ms, 3,//led num 1
                        1 min, 3 min, 1 sec, 2 sec, 0, 0, 100 ms, 4, //led num 2

                                      };


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

    // Setup the button.
    pinMode(switchPin, INPUT_PULLUP);
    

    // Setup the LED.
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  
  // leds
  for (uint8_t i = 0; i < NUM_LED; i++)
  {
    pinMode(myLeds[i].pin, OUTPUT);
  }
}

void loop()
{
  buttonPress();
  startSequence();
  endSequence();
}


void buttonPress ()
{
    byte currentButtonState = digitalRead (switchPin);
    if (lastButtonState != currentButtonState)  {
        lastButtonState = currentButtonState;
        delay (10);             // debounce

        if (LOW == currentButtonState)  {
            buttonPressCount++;
          Serial.print("Button press count: ");
          Serial.println(buttonPressCount);
            firstPressMillis = millis();
          Serial.print("button pressed time: ");
          Serial.println(firstPressMillis);
            digitalWrite (ledPin, ! digitalRead (ledPin));
        }
    }
}



void startSequence()
{  
 if(buttonPressCount == 1)
 {
   currentMillis = millis() - firstPressMillis;
for (uint8_t x = 0; x < NUM_LED; x++)
  {
   
    // Is this led active
    if (myLeds[x].startTime < currentMillis)
    {
      // Do we need to calculate a next pulse time?
  

      if (myLeds[x].nextPulseStop < currentMillis)
      {
        // Turn off led
        digitalWrite(myLeds[x].pin, LOW);

        // Calculate nextPulseStart & nextPulseStop
        long  startOffset =random(myLeds[x].minPulse, myLeds[x].maxPulse);
        myLeds[x].nextPulseStart = startOffset + currentMillis;
        myLeds[x].nextPulseStop = myLeds[x].nextPulseStart + myLeds[x].pulseLength;
      }

      // Are we currently in the middle of a pulse?
      if (myLeds[x].nextPulseStart < currentMillis &&
          myLeds[x].nextPulseStop  > currentMillis)
      {
        //turn on led
        digitalWrite(myLeds[x].pin, HIGH);
      }
    }
  }
}
}


void endSequence()
{  
 if(buttonPressCount == 2)
 {
   
	for (uint8_t x = 0; x < NUM_LED; x++)
  {
      if(myLeds[x].stopTime + firstPressMillis < currentMillis)
         {
      if (myLeds[x].nextPulseStop < currentMillis)
      {
        // Turn off led
        digitalWrite(myLeds[x].pin, LOW);

        // Calculate nextPulseStart & nextPulseStop
        long  startOffset =random(myLeds[x].minPulse, myLeds[x].maxPulse);
        myLeds[x].nextPulseStart = startOffset +currentMillis;
        myLeds[x].nextPulseStop = myLeds[x].nextPulseStart + myLeds[x].pulseLength;
      }

      // Are we currently in the middle of a pulse?
      if (myLeds[x].nextPulseStart < currentMillis &&
          myLeds[x].nextPulseStop  > currentMillis)
      {
        //turn on led
        digitalWrite(myLeds[x].pin, HIGH);
      }
      }
   if (myLeds[x].stopTime + firstPressMillis < millis())
   {
     digitalWrite(myLeds[x].pin, LOW);
   }
}
 }
}

when I first press the button the sequence is starting to run as it should and is continue to run as long I'm not pressing the button again.
When I press the button again - I'm expect that each led will stop is sequence when the time has passed since we press the button specify at the second index of the led array struct myLeds[x].stopTime

the above is not happening rather the leds stopped immediately when pressing.

I feel I'm so close but yet can't figure why is not working for the last 10 hours.

Does it make sense to write another function for the end of the sequence like I did void endSequence() ?

The mistake is somewhere there but I can't figure it out.

it's unclear what you're trying to do with pulses.

not sure what, if anything you have working. it's usually best to start simple and then add additional features.

consider the following which should turn the LEDs after the start time when the button is pressed once and then turn them off after the stop time when the button is pressed twice

#undef MyHW
#ifdef MyHW
uint8_t switchPin = A1;
uint8_t ledPin    = LED_BUILTIN;
#else
uint8_t switchPin = 13;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t ledPin = A0;
#endif

uint8_t buttonPressCount = 0; // Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;

uint32_t firstPressMillis = 0;
uint32_t currentMillis;

#define NUM_LED 3
//time translating//
#define Sec * 1000
#define Min * 60000
#define Ms * 1

struct leds
{
    unsigned long startTime;       // The time this led is first active after a buttun is first pressed
    unsigned long stopTime;        // The time this led becomes inactive after a buttun is second time pressed
    unsigned long minPulse;        // The minimum time the next pulse is generated
    unsigned long maxPulse;        // The maximum time the next pulse is generated
    unsigned long nextPulseStart;  // The time of the next pulse starts
    unsigned long nextPulseStop;   // The time of the next pulse  stops
    unsigned long pulseLength;     // The on time of the pulse
    uint8_t pin;                   // led GPIO pin number
};

leds myLeds[NUM_LED] = {
#ifdef MyHW
//    start   stop  MinPul maxPul nextStart  nextStop     len  pin
    { 1 Sec, 3 Sec,  0 Sec, 2 Sec,        0,        0, 100 Ms,  10,},
    { 2 Sec, 4 Sec,  1 Sec, 3 Sec,        0,        0, 100 Ms,  11, },
    { 3 Sec, 2 Sec,  1 Sec, 2 Sec,        0,        0, 100 Ms,  12, },
#else
    //    start   stop  MinPul maxPul nextStart  nextStop     len  pin
    { 3 Sec, 1 Min,  1 Sec, 2 Sec,        0,        0, 100 Ms,   2,},
    { 4 Sec, 2 Min,  1 Sec, 2 Sec,        0,        0, 100 Ms,   3, },
    { 1 Min, 3 Min,  1 Sec, 2 Sec,        0,        0, 100 Ms,   4, },
#endif

};

enum { Off = HIGH, On = LOW };

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

    pinMode(switchPin, INPUT_PULLUP);

    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, Off);

    for (uint8_t i = 0; i < NUM_LED; i++) {
        digitalWrite (myLeds [i].pin, Off);
        pinMode      (myLeds [i].pin, OUTPUT);
    }
}

// -----------------------------------------------------------------------------
void loop()
{
    buttonPress();
    startSequence();
}

// -----------------------------------------------------------------------------
void buttonPress ()
{
    byte currentButtonState = digitalRead (switchPin);
    if (lastButtonState != currentButtonState)  {
        lastButtonState = currentButtonState;
        delay (10);             // debounce
        if (LOW == currentButtonState)  {
            buttonPressCount++;
            Serial.print("Button press count: ");
            Serial.println(buttonPressCount);
            firstPressMillis = millis();
            Serial.print("button pressed time: ");
            Serial.println(firstPressMillis);
            digitalWrite (ledPin, ! digitalRead (ledPin));
        }
    }
}

// -----------------------------------------------------------------------------
void startSequence()
{
    currentMillis = millis () - firstPressMillis;
    leds          *p = myLeds;

    if (1 == buttonPressCount)  {
        for (uint8_t i = 0; i < NUM_LED; i++, p++) {
            if (Off == digitalRead (p->pin))  {
                if (currentMillis >= p->startTime)
                    digitalWrite (p->pin, On);
            }
        }
    }

    if (2 == buttonPressCount)  {
        for (uint8_t i = 0; i < NUM_LED; i++, p++) {
            if (On == digitalRead (p->pin)) {
                if (currentMillis >= p->stopTime)
                    digitalWrite (p->pin, Off);
            }
        }
    }
}

i tried doing you're pulse thing. the problem is without updating a timestamp, as soon as the timestamp exceeds stopTime + maxPulse, it probably exceeds startTime + minPulse and is turned on again