Two button long press

Hi All.
Some help with my code would be greatly appreciated.
I'm sequencing 3 led's to turn on one at a time e.g 1,2,3 at a long button press (start) and stay on.
Then turn off in turn e.g 3,2,1 at a second button (stop), long press too and stay off.
There are also 3 additional led's,
2 to indicate either the start or stop states and 1 to confirm that a button has been pressed.

The part of the code above the ************ works exactly how I've described above, but can't get it to reverse. I think the trouble is below the **********.

a little help please



int start = 3;
int stopp = 2;
int led1 = 9;
int led8 = 8;
int led7 = 7;
int led12 = 12;
int led11 = 11;
int led10 = 10;

unsigned long resetTheClock;
int interval = 2000;
int buttonSt = 0;
int buttonStp = 0;
bool flagWithNoFancyName = false;

void setup()
{ pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode (2, INPUT);
  pinMode (3, INPUT);
}

void loop() {

  buttonSt = digitalRead(start);
  buttonStp = digitalRead (stopp);

  if (buttonSt == HIGH) // start button not pressed

  { resetTheClock = millis();
    flagWithNoFancyName = true;
  }

  if (buttonSt == LOW && flagWithNoFancyName) // start pressed for interval
  {
    digitalWrite(led1, HIGH);  // button pressed led on
  }
  else
  {
    digitalWrite(led1, LOW); // button released led off
  }

  if (millis() - resetTheClock >= interval)

  { digitalWrite(led1, HIGH);

    flagWithNoFancyName = false;
    resetTheClock = millis();
    delay (500);
    digitalWrite (led7, LOW); //stop status led
    digitalWrite (led8, HIGH); //start status led
    digitalWrite(led12, HIGH); // sequence 1 led
    delay (2000);
    digitalWrite(led11, HIGH); // sequence 2 led
    delay (2000);
    digitalWrite(led10, HIGH); // sequence 3 led
    delay (2000);
  }
  ****************************************************************
  // When I add this part in it all stops working
  if (buttonStp == HIGH)

  { resetTheClock = millis();
    flagWithNoFancyName = true;
  }

  if (buttonStp == LOW && flagWithNoFancyName)


  {
    digitalWrite(led1, HIGH);
  }
  else
  {
    digitalWrite(led1, LOW);
  }

  if (millis() - resetTheClock >= interval)

  { digitalWrite(led1, HIGH);

    flagWithNoFancyName = false;
    resetTheClock = millis();
    delay (500);
    digitalWrite (led8, LOW);
    delay (250);
    digitalWrite (led7, HIGH);
    digitalWrite(led10, LOW);
    delay (2000);
    digitalWrite(led11, LOW);
    delay (2000);
    digitalWrite(led12, LOW);
    delay (2000);


  }
}

The OneButton library from Matthias Hertel could come handy...

You are using a single "flagWithNoFancyName" for both the Start and Stop buttons. Your code needs to know WHICH button it is acting on.

You could use the MoToButtons class of the MobaTools Lib:

#define MAX8BUTTONS
#include <MobaTools.h>


int start = 3;
int stopp = 2;
int led1 = 9;
int led8 = 8;
int led7 = 7;
int led12 = 12;
int led11 = 11;
int led10 = 10;
int interval = 2000;

const byte buttonPins[] = { start, stopp };
enum :byte { START, STOP }; // Index of Buttons in buttonPins
MoToButtons myButtons( buttonPins, sizeof(buttonPins), 20, interval ); // array of buttonpins, nbr of active buttons, debouncetime, longpress time

void setup()
{ pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led10, OUTPUT);
  pinMode(led11, OUTPUT);
  pinMode(led12, OUTPUT);
}

void loop() {
  myButtons.processButtons();
  digitalWrite( led1, ( myButtons.state(START) || myButtons.state(STOP) ) ); // Led is lit as long as a button is pressed
  
  if ( myButtons.longPress(START) ) {
    delay (500);
    digitalWrite (led7, LOW); //stop status led
    digitalWrite (led8, HIGH); //start status led
    digitalWrite(led12, HIGH); // sequence 1 led
    delay (2000);
    digitalWrite(led11, HIGH); // sequence 2 led
    delay (2000);
    digitalWrite(led10, HIGH); // sequence 3 led
    delay (2000);
  }
  if ( myButtons.longPress(STOP) ) {
    delay (500);
    digitalWrite (led8, LOW);
    delay (250);
    digitalWrite (led7, HIGH);
    digitalWrite(led10, LOW);
    delay (2000);
    digitalWrite(led11, LOW);
    delay (2000);
    digitalWrite(led12, LOW);
    delay (2000);


  }
}

The next step would than be, to get rid of the delay. The MoToTimer class could help you a lot with that :wink:

Thank you all for your replies, I know its such a basic code but had me stumped for weeks. MobaTools worked a treat.
johnwasser it didn't even cross my mind that the start and stop needed their onw bools

Hello
Well, you need to avoid using the delay() function.
This function blocks the continuous execution of your sketch. Some tasks within your sketch need to be executed "in parallel".
For this you need a timer, a timer() function for debouncing the keys and a second timer() function for counting up and counting down the leds. A small FSM takes care of the count up and count down phases. All other later wanted function restrictions, e.g. interlocks, will be designed during the fine tuneing of sketch.

1 Like

The keys are already debounced by the MoToButtons class. Only a timer for the leds is needed. And MoToButtons will work better without delays, because processButtons should be called often to provide all its functionality.

1 Like

My tutorials on How to write Timers and Delays in Arduino and Multi-tasking in Arduino are worth a look, along with Debouncing Switches in Arduino

@toonoos : Here is a suggestion how to get rid of the delays. I used only simple arrays to define se sequences. If you will be familiar with structs and/or multidimensional arrays, the sketch could be further improved.

#define MAX8BUTTONS
#include <MobaTools.h>

int start = 3;
int stopp =2;
int led1 = 9;
int led8 = 8;
int led7 = 7;
int led12 = 12;
int led11 = 11;
int led10 = 10;
int interval = 2000;

// sequence for switching ON
// All arrays must have same size
const byte ledLineOn[] = { led7, led8, led12, led11, led10 };
const byte ledStatesOn[] = { ON,  OFF,  ON,    ON,    ON   };
const int ledTimesOn[]  = { 250, 1,   2000,  2000,  2000  };     // must be at least 1ms
// sequence for switching off
const byte ledLineOff[] = { led8, led7, led10, led11, led12 };
const byte ledStatesOff[] = { ON,  OFF,  OFF,    OFF,    OFF   };
const int ledTimesOff[]  = { 250, 1,   2000,  2000,  2000  };     // must be at least 1ms
const byte sequenceMAX = sizeof( ledLineOn );       // ledLineOn MUST be of type byte
bool sequenceDir = ON;                              // switching ON or OFF
byte sequenceIx = 0;                                // state of sequence

MoToTimer sequenceTimer;

const byte buttonPins[] = { start, stopp };
enum : byte { START, STOP }; // Index of Buttons in buttonPins
MoToButtons myButtons( buttonPins, sizeof(buttonPins), 20, interval ); // array of buttonpins, nbr of active buttons, debouncetime, longpress time

void setup()
{ pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led10, OUTPUT);
  pinMode(led11, OUTPUT);
  pinMode(led12, OUTPUT);
  delay(2000);
}

void loop() {
  myButtons.processButtons();
  digitalWrite( led1, ( myButtons.state(START) || myButtons.state(STOP) ) ); // Led is lit aslong abutton is pressed

  if ( myButtons.longPress(START) ) {
    // Start sequence switching ON
    sequenceDir = ON;
    sequenceIx = 0;
    sequenceTimer.setTime( 500 );        // start with a 500ms delay
  }
  if ( myButtons.longPress(STOP) ) {
    // start sequence seitching OFF
    sequenceDir = OFF;
    sequenceIx = 0;
    sequenceTimer.setTime( 500 );        // start with a 500ms delay
  }

  if ( sequenceTimer.expired() ) {
    // Timer expired, do activity according to the array values and switch to next state in sequence
    // if we are already at the end, do nothing ( timer will not expire again )
    if ( sequenceIx < sequenceMAX ) {
      if ( sequenceDir == ON ) {
        // switch led and set Time for next step going ON
        digitalWrite( ledLineOn[sequenceIx], ledStatesOn[sequenceIx] );
        sequenceTimer.setTime( ledTimesOn[sequenceIx] );
      } else {
        // switch led and set Time for next step going OFF
        digitalWrite( ledLineOff[sequenceIx], ledStatesOff[sequenceIx] );
        sequenceTimer.setTime( ledTimesOff[sequenceIx] );
      }
      sequenceIx++;  // switch to next state in sequence chain
    }
  }
}

You can play a little bit with the array values to see what happens.

1 Like

Thank you @MicroBahner, appreciate the help

You're welcome

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.