Press and hold button to operate, releasing button stops function

Hi Guys im struggling here as this is my first ever Arduino project.

here is what i want to do.

i want to control a relay with progressive pulses starting from small pulses going to bigger ones and eventually a constant supply.

it must only operate while holding the button.

letting go of the push button should cancel the process entirely until you press and hold again.

process should only run while the button is being held otherwise it should not.

i manage it perfectly until i insert some pulses, as soon as i start doing pulses it runs through the entire code before it stops where as i want to interrupt it whenever i release the push button.

here is my current code:

*const int buttonPin = 2;     // the number of the pushbutton pin*
*const int ledPin =  13;      // the number of the LED pin*

*// variables will change:*
*int buttonState = 0;         // variable for reading the pushbutton status*

*void setup() {*
*  // initialize the LED pin as an output:*
*  pinMode(ledPin, OUTPUT);*
*  // initialize the pushbutton pin as an input:*
*  pinMode(buttonPin, INPUT);*
*}*

*void loop() {*
*  // read the state of the pushbutton value:*
*  buttonState = digitalRead(buttonPin);*



*  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:*
*  if (buttonState == HIGH) {*
*   int buttonState = 0; *
*    digitalWrite(ledPin, HIGH);*
*    delay(25)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(75)*
*    ;digitalWrite(ledPin, HIGH);*
*delay(25)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(75)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(25)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(75)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(50)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(50)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(50)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(50)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(50)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(50)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(75)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(25)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(75)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(25)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(75)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(25)*
*    ;digitalWrite(ledPin, HIGH);*
*    delay(10000)*
*    ;digitalWrite(ledPin, LOW);*
*    delay(25)*
*    ;digitalWrite(ledPin, HIGH);*
*  } else {*
*    // turn LED off:*
*    digitalWrite(ledPin, LOW);*

*  }*
*}*

any help will be appreciated

why are there so many "*" in your listing? you should clean this up. it's obviously not listing you compiled

[quote="nicolaas111, post:1, topic:966742"]
i manage it perfectly until i insert some pulses, as soon as i start doing pulses it runs through the entire code before it stops where as i want to interrupt it whenever i release the push button.[/quote]

once you execute the condition to generate the pulses, it must complete before checking a button press again.

using millis() to time the pulses would allow the code to monitor the button for a release and to terminate generating pulse as well as making sure the relay is deenergized

why do you redefine buttonState?
shoud it be

 if (buttonState == HIGH) {
      buttonState = 0; 

give more explaination of what you are attempting to do
e.g. while button is pressed loop
pulse for 50mSec
then pulse for 100mSec
then pluse for 200mSec
then pulse for 400mSec
etc etc

Try to work on a subset of the problem first. For example: pressing the button actuates a relay (or lights up an LED) for a given amount of time or until the button is released, whichever event comes first. Can you do that?

Hint: a blocking delay won't work here.

You will have to get rid of the delays. Use millis() to time the delays by checking whether the time between LED changes has expired. Since your delays vary you could put the delays in an array and use a counter to keep up with which delay is timing currently.

Yeah i don't know why it posted all the *.

Sorry for sounding stupid but it's my first project.

How do i use Millis?

I tried replacing delay with Millis and it gives me errors.

Can you help me with an example of what i should do please. I have been at this code for 2 days now.
Im clueless :man_facepalming:.

I have tried Millis but couldn't get it to work

There are a lot of tutorials if you just look for them. Here is a very basic one on how time a delay using millis():

BlinkWithoutDelay

Great thanks. Let me check it out and play with my code

are you attempting to do something along the lines of

pulseWidth=25
loop
  if buttonPressed
     digital write HIGH 
     delay for pulseWidth milliseconds
     digital write LOW
     delay for pulseWidth milliseconds
     pulseWidth = pulseWidth*2
  else
     pulseWidth=25

when you press the button you get a pulse of 25mSec, then 50, then 100etc
when button is released the pulses stop and reset to start again at 25mSec
problem: if you release button in middle of pulse it will not reset until the end if pulse

consider

#undef MyHW
#ifdef MyHW
const int buttonPin = A1;
#else
const int buttonPin = 2;     // the number of the pushbutton pin
#endif

const int ledPin =  13;      // the number of the LED pin

int buttonState = 0;         // variable for reading the pushbutton status

enum { Off = HIGH, On = LOW };

struct Pulse {
    int           state;
    unsigned long delay;
} pulse [] = {
    { On,   25 },
    { Off,  75 },
    { On,   25 },
    { Off,  75 },
    { On,   25 },
    { Off,  75 },
    { On,   50 },
    { Off,  50 },
    { On,   50 },
    { Off,  50 },
    { On,   50 },
    { Off,  50 },
    { On,   75 },
    { Off,  25 },
    { On,   75 },
    { Off,  25 },
    { On,   75 },
    { Off,  25 },
    { On,   1000 },     // too long to test 10000 },
    { Off,  25 },
};

#define N_PULSE (sizeof (pulse)/sizeof (Pulse))

unsigned idx;
unsigned long msecLst;

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

    if (LOW == buttonState)  {
        if ( (msec - msecLst) > pulse [idx].delay)  {
            idx++;
            if (N_PULSE <= idx)
                idx = 0;

            digitalWrite (ledPin, pulse [idx].state);
            msecLst = msec;
        }
    }

    byte but = digitalRead (buttonPin);
    if (buttonState != but)  {
        buttonState = but;

        if (LOW == but)  {
            idx     = 0;
            msecLst = msec;
            digitalWrite (ledPin, pulse [idx].state);
        }
        else
            digitalWrite (ledPin, Off);
    }
}

void
setup ()  {
    pinMode (ledPin, OUTPUT);
    pinMode (buttonPin, INPUT_PULLUP);
    buttonState = digitalRead (buttonPin);
}

Thats the problem im experiencing. If i let go of the button it must stop immediately

Will definitely try this when i have time and see how i can manage it.

The big idea is to start with pulses and progressively work towards a normal on function for as long as i hold the button.

Example

**press button
25ms pulses
50ms pulses
75ms pulses
100ms pulses
Continuous actuation until i let go of the button

sounds like you want a "fade", the LED gradually turns on.

one way to do that is gradually increase the PWM value using analogWrite() on a PWM pin

1 Like

something along the lines of

period=1000
pulseWidth=25
loop
  if buttonPressed
     digital write HIGH 
     loop for pulseWidth milliseconds
        if button not pressed break
     digital write LOW
     loop for period-pulseWidth milliseconds
        if button not pressed break
     pulseWidth = pulseWidth*2
  else
     pulseWidth=25

while you hold the button pulses increase in width - 25mSec, 50, 100 upto the period which is 1 second
in the above the delay is a loop which exits if the button is released (use millis())
you need to think about what happens when the pulseWidth >= 1000mSec

i want nothing to happen until i press the button.
when i press the sequence must start pulsing quick intervals and gradually make its way to a constant on beam.
when i let go of the button the whole operation should be aborted, it is going to pulse a solenoid to control a gas

here is exactly what is should do.

Button state LOW = nothing happens

Button state HIGH should have the following effect:
25ms HIGH
75ms LOW
25msHIGH
75msLOW
50msHIGH
50msLOW
50msHIGH
50msLOW
75msHIGH
25msLOW
75msHIGH
25msLOW
100msHIGH
25msLOW
100msHIGH
25msLOW
Then continuous illumination until button is released.

Functions should only run while button is being held.
releasing button should abort it immediately.

something like

period=1000
pulseWidth=25
while button not pressed
   wait
while button pressed and pulseWidth < period
  if buttonPressed
     digital write HIGH 
     loop for pulseWidth milliseconds
        if button not pressed break
     digital write LOW
     loop for period-pulseWidth milliseconds
        if button not pressed break
     pulseWidth = pulseWidth*2
while button  pressed
   wait
pulse solenoid

Here is exactly what i want to achieve.

ButtonState LOW nothing happens.

ButtonState HIGH = ledPin: (process should only run while button is being held down)

25ms HIGH
75ms LOW
25ms HIGH
75ms LOW
50ms HIGH
50ms LOW
50ms HIGH
50ms LOW
75ms HIGH
25ms LOW
75ms HIGH
25ms LOW
100ms HIGH
25ms LOW
100ms HIGH
25ms LOW
Continuous HIGH while button is being held and keep a constant on with no pulses until i let go of the button.

Releasing Button at any given time should abort the entire process immediately.

SORRY if i sound clueless

So it should start with pulses and work towards a constant on where it stays on.
it should run pulses when held and eventually stay on after the pulses are done.

leaving the button at any time should switch off the LED regardless.

I want to control a progressive gas system to start with a slow release working to constant on release