Using millis with multiple switches and one output... help please!

Hi everyone,
I'm trying to figure this out but am starting to get frustrated. I'm making a control panel for an led driver using the dim function and a transistor and an arduino nano. Basically I have one output pin controlled by three switches. The first is a momentary button that should turn the light on (put the output pin in LOW) for a desired amount of time eg 55000 ms. The second is a momentary switch with a different preset timer, and the third is an on/off switch used to manually control the light. I got the thing working great with delay but of course I need to also be able to cancel the operation and turn it off with any button press, and delay won't allow for that, so I've been trying to examine and edit BlinkWithoutDelay and use millis to create the timers, but I'm stuck for a few days with that. I deleted most of what I did and started over about a dozen times and have googled enough to be crosseyed so I'm hoping someone here is kind enough to point me in the right direction. Here's my code:

const int buttonA = 5; 
const int buttonB = 4;
const int buttonC = 3;
const int luxOut =  LED_BUILTIN;   
const long intervalA = 5000;
const long intervalB = 2000;
int buttonStateA = 1;  
int buttonStateB = 1;   
int buttonStateC = 1;
int ledState = 0;
static unsigned long previousMillis = 0;
unsigned long currentMillis = millis();

void setup() {
  // initialize the LED pin as an output:
  pinMode(luxOut, OUTPUT);
  // initialize the pushbutton pin as an input:
 pinMode(buttonA, INPUT_PULLUP);
 pinMode(buttonB, INPUT_PULLUP);
 pinMode(buttonC, INPUT_PULLUP);
  
}

void loop() {
digitalWrite(luxOut, HIGH);

  buttonStateA = digitalRead(buttonA);
  buttonStateB = digitalRead(buttonB);
  buttonStateC = digitalRead(buttonC);
  ledState = digitalRead(luxOut);
  
if (buttonStateA == LOW) {
    previousMillis = currentMillis;
    digitalWrite(luxOut, LOW); 
  }
if (currentMillis - previousMillis >= intervalA) // this stops the timer
{
 digitalWrite (luxOut, HIGH); 
}

if (buttonStateB == LOW) {
    previousMillis = currentMillis;
    digitalWrite(luxOut, LOW); 
  }
if (currentMillis - previousMillis >= intervalB) // this stops the timer
{
 digitalWrite (luxOut, HIGH); 
}


  if (buttonStateC == LOW) {
    digitalWrite(luxOut, LOW);
    delay(10);
  } else {
    digitalWrite(luxOut, HIGH);
  }


}

My problem is the code stopping the timers don't seem to know which button was pressed to start with, so how do I make this work? Any help is greatly appreciated.

What do you think happens when this code is executed?

  if (buttonStateC == LOW) {
    digitalWrite(luxOut, LOW);
    delay(10);
  } else {
    digitalWrite(luxOut, HIGH);
  }

BTW
currentMillis is never updated.

That part works fine. It's my on/off switch. There's no need to interrupt that part because as soon as the switch goes high the light turns off. My issue is the momentary timers

“That part works fine.”
It may work fine but it overwrites things previously done :frowning:

Also
currentMillis is never updated.

You should be using “state change detection” with your switches.

As it is now, you are looping through ‘all’ your code rather than on specific switch code.

Here is my code which works like this. when you press a bottun you need to unpress it before delay(pauza) is over. If you continue to hold it it will automaticly go to last if statment.
I declared pauza as int pauza=500;

with this code you can trigger some function and stop it when you want with same bottun.

        if(digitalRead(buttondown1) == HIGH && c==0){
  delay(pauza);
timer1=millis();
c=1;
  }

if(millis()-timer1<=interval && c==1){

  digitalWrite(down1,LOW);
}

if(millis()-timer1>interval && c==1){
  digitalWrite(down1,HIGH);
 c=0;

}

if(digitalRead(buttondown1) == HIGH && c==1){
 digitalWrite(down1,HIGH);
 c=0;
 delay(pauza);  
}

delay(pauza);

You should never use delay() when creating non blocking code :wink:

Scan your switches ≈50ms.
Look for a change in state in your switch.
If there is a change, initialize a timer, set a variable or cancel an operation as needed.
Repeat for remaining switches.

In loop(), examine timers to see if they are enabled and finished, operate on things accordingly.

larryd:
delay(pauza);

You should never use delay() when creating non blocking code :wink:

that delay is just 500ms so you can remove your finger from bottun

500ms is 1/2 a second!

This is an eternity!

Imagine what effect a delay of 1/2 a second has on system when you are scanning switches, timing LEDs etc.

Depends on application of the code. This delay will happen only when you press a bottun and it will start doing something and scanning switches just after 500 ms.

When you scan switches for state changes there is no need to use delay().

Suggest you avoid delay() in all your sketches.

Okay you can use delay(1) now and then :wink:

Can you please edit my code or create new one so I can see how you do that.

so program will be triggered by bottun and it will do something for some time but it can stop if you press again bottun.

also there is problem if you press bottun again it can again enter the loop (active timer again).

Thanks im sure that will help. :slight_smile:

fibra59:
Can you please edit my code or create new one so I can see how you do that.

so program will be triggered by bottun and it will do something for some time but it can stop if you press again bottun.

also there is problem if you press bottun again it can again enter the loop (active timer again).

#define PUSHED HIGH
#define LEDon LOW
#define LEDoff !LEDon

const byte buttonA = 5;
const byte buttonB = 4;
const byte buttonC = 3;
const byte luxOut =  13;

const unsigned long intervalA = 6000;
const unsigned long intervalB = 3000;

byte switchAstate;
byte lastStateA;

byte switchBstate;
byte lastStateB;

byte switchCstate;
byte lastStateC;

bool A_flag = false;
bool B_flag = false;

unsigned long A_millis;
unsigned long B_millis;
unsigned long switchMillis;

//*****************************************************************************
void setup()
{
  pinMode(luxOut, OUTPUT);
  digitalWrite(luxOut, LEDoff);      

  pinMode(buttonA, INPUT_PULLUP);
  lastStateA = digitalRead(buttonA);

  pinMode(buttonB, INPUT_PULLUP);
  lastStateB = digitalRead(buttonB);

  pinMode(buttonC, INPUT_PULLUP);
  lastStateC = digitalRead(buttonB);
}

//*****************************************************************************
void loop()
{
  //***************************
  //time to check the switches?
  if ( millis() - switchMillis >= 50)
  {
    //re-initialize timer
    switchMillis = millis();

    checkSwitches();
  }

  //***************************
  //if enabled, has the timer finished?
  if (A_flag == true && millis() - A_millis >= intervalA)
  {
    //disable timer
    A_flag = false;

    //Turn LED OFF
    digitalWrite (luxOut, LEDoff); 
  }

  //***************************
  //if enabled, has the timer finished?
  if (B_flag == true && millis() - B_millis >= intervalB)
  {
    //disable timer
    B_flag = false;

    //Turn LED OFF
    digitalWrite (luxOut, LEDoff); 
  }

  //***************************


} //END of loop()


//*****************************************************************************
void checkSwitches()
{
  //***************************
  switchAstate = digitalRead(buttonA);

  //has the switch changed state?
  if (lastStateA != switchAstate)
  {
    lastStateA = switchAstate;

    //is it now pushed?
    if (switchAstate == PUSHED)
    {
      //disable B timer
      B_flag = false;

      //enable A timer
      A_flag = true;

      //initialize timer
      A_millis = millis();

      //Turn LED ON
      digitalWrite (luxOut, LEDon); 
    }
  }

  //***************************
  switchBstate = digitalRead(buttonB);

  //has the switch changed state?
  if (lastStateB != switchBstate)
  {
    lastStateB = switchBstate;

    //is it now pushed?
    if (switchBstate == PUSHED)
    {
      //disable A timer
      A_flag = false;

      //enable B timer
      B_flag = true;

      //initialize timer
      B_millis = millis();

      //Turn LED ON
      digitalWrite (luxOut, LEDon); 
    }
  }

  //***************************
  switchCstate = digitalRead(buttonC);

  //has the switch changed state?
  if (lastStateC != switchCstate)
  {
    lastStateC = switchCstate;

    //is it now pushed?
    if (switchCstate == PUSHED)
    {
      //disable A timer
      A_flag = false;

      //disable B timer
      B_flag = false;

      digitalWrite (luxOut, !digitalRead(luxOut)); //toggle LED
    }
  }

} //END of checkSwitches()

Thank you for your time for writing this code!
Now I understand what you wanted to say.

“what you wanted to say”

It’s what I said :wink:

larryd:
“what you wanted to say”

It’s what I said :wink:

hahahh

larryd, that was awesome, thank you! The code you posted works for the timers and buttons pretty much perfectly, but the thing I need to add now is the ability to cancel any of the timers (turn off the light or interrupt the timed lit period) by pressing any button. Should I start a new void section or try to add a new button function to the existing code? I know it's a stupid question to you but I don't want to break your awesome sketch. Thanks again!!

forgetfuljones:
I don't want to break your awesome sketch.

That's why they invented Save As :wink:

Oh believe me I'm breaking it. Hints? I'm learning a lot reading what you did, and I really appreciate the help. If I figure it out I'll post here. Thanks