Change function on buttonpress during a delay

Hi there!

I’m working on a project where I have multiple functions, where I’m using a “menu” with help of two buttons (sw3 and sw4 in code) to change a value, and a start button (sw1) to change to another function. So far I have 6 functions that has different delays, before it goes to another function and back to the menu.

The main components is a Arduino pro, 2004 lcd display from ebay, 2x2 button pad from sparkfun and different leds and relays.

What I would like to do, is use another switch (sw2 in code) to abort the delay, and take it back to the menu.

I have found out that the arduino can’t do anything else during a delay. I have tried a for(); loop, just to test it out, with no luck. Tried millis(); too, but no matter how mutch I read about millis();, I still don’t understand how I can inplant that to my code.

In the code below, it is in void program1(); to program6(); I need help with.

Anyone on the forum that can explain the millis(); function for me and maybe help me out with inplant it in my code? Or do I have to find something else than millis();?

I’ll post the code in the next reply, due to max characters in one message…

Here is almost my entire code. Had to remove program 2-5 due to max lenght on reply… The only difference on function 1 to 6 is the delay and display text

/* 
  * All LEDs has common anode.
  * All relays has common anode +
  * The LEDs on the controll box is connected directly
  * to the relays, simulating the "Traffic light"
  * (Connected on the spole on the relay)
  */

#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(14,15,16,17,18,19);
// (RS, EN, DB4, DB5, DB6, DB7)

//Defining pins for switches
const int sw1 = 2; //Start button
const int sw2 = 3; //Stop button
const int sw3 = 4; //Prog - button
const int sw4 = 5; //Prog + button

//Defining pins for LEDs in switches
const int led1 = 6; //Start button LED
const int led2 = 7; //Stop button LED
const int led3 = 8; //Prog - button LED
const int led4 = 9; //Prog + button LED

//Defining pins for output LEDs
const int relayG = 10; //Relay for green light
const int relayY = 11; //Relay for yellow light
const int relayR = 12; //Relay for red light

//Defining value for program selection
int value;

void setup() {
  //Defining pinMode's
  pinMode(sw1, INPUT);
  pinMode(sw2, INPUT);
  pinMode(sw3, INPUT);
  pinMode(sw4, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(relayG, OUTPUT);
  pinMode(relayY, OUTPUT);
  pinMode(relayR, OUTPUT);

  //Starting a lamp test
  lcd.begin(20, 4);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Lamp test");
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW);
  digitalWrite(relayG, LOW);
  digitalWrite(relayY, LOW);
  digitalWrite(relayR, LOW);
  delay(10000);
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  digitalWrite(relayG, HIGH);
  digitalWrite(relayY, HIGH);
  digitalWrite(relayR, HIGH);
  lcd.setCursor(0,1);
  lcd.print("complete!");
  delay(2000);
  lcd.clear();
  //Lamp test complete

  //Setting value for program selection
  value = 1;

  //Turning red light on
  digitalWrite(relayR, LOW);
}

//Is the people ready to open FIRE?!? This part is NOT complete yet
void er_skytter_klar() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Er skytterene klare?");
  lcd.setCursor(0,1);
  lcd.print("Hvis nei, trykk rød");
  lcd.setCursor(0,2);
  lcd.print("knapp innen 15");
  lcd.setCursor(0,3);
  lcd.print("sekunder");
  if (digitalRead(sw2) == HIGH) {
    avbryt();
  } else if (digitalRead(sw2) == LOW ) {
    
  }
  
}

//Program 1, 6 sec
void program1() {
    delay(100);
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(relayR, HIGH);
    digitalWrite(relayY, HIGH);
    digitalWrite(relayG, LOW);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Program 1 kjorer");
    lcd.setCursor(0,1);
    lcd.print("6 sekunder");
    lcd.setCursor(0,2);
    lcd.print("skyting");
    delay(4000);
    stans();
}
 
...snip...


//Program 6 300 sec
void program6() {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(relayR, HIGH);
    digitalWrite(relayY, HIGH);
    digitalWrite(relayG, LOW);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Program 6 kjorer");
    lcd.setCursor(0,1);
    lcd.print("300 sekunder");
    lcd.setCursor(0,2);
    lcd.print("skyting");
    delay(298000);
    stans();
}

//Program 7, ∞ sec
void program7() {
  if (digitalRead(sw2) == HIGH) { 
    stans();
  } else {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(relayR, HIGH);
    digitalWrite(relayY, HIGH);
    digitalWrite(relayG, LOW);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Program 7 kjorer");
    lcd.setCursor(0,1);
    lcd.print("Friskyting");
    delay(200);
    program7();
  } 
}

//Stop sequense
void stans() {
  digitalWrite(relayG, LOW);
  digitalWrite(relayY, LOW);
  digitalWrite(relayR, HIGH);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Staaaaaaaaaaaaaaaans");
  delay(2000);
  performCommand();
}

//Abort sequense
void avbryt() {
  digitalWrite(relayG, HIGH);
  digitalWrite(relayY, HIGH);
  digitalWrite(relayR, LOW);
  digitalWrite(led1, HIGH);
  digitalWrite(led2, LOW);
  performCommand();
}

//Lamp test
void lamptest() {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Lampe test");
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, LOW);
    digitalWrite(relayG, LOW);
    digitalWrite(relayY, LOW);
    digitalWrite(relayR, LOW);
    delay(10000);
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    digitalWrite(led4, HIGH);
    digitalWrite(relayG, HIGH);
    digitalWrite(relayY, HIGH);
    digitalWrite(relayR, HIGH);
    lcd.setCursor(0,1);
    lcd.print("complete!");
    delay(2000);
    performCommand();
}

//Program selector
void performCommand() {
  lcd.clear();
  digitalWrite(led1, HIGH);
  digitalWrite(led2, LOW);
  digitalWrite(relayG, HIGH);
  digitalWrite(relayY, HIGH);
  digitalWrite(relayR, LOW);
  lcd.setCursor(0,0);
  lcd.print("Lismarken pk");
  lcd.setCursor(0,1);
  lcd.print("Velg program:");
  lcd.setCursor(0,2);
  lcd.print("Program:");
  lcd.setCursor(10,2);
  lcd.print(value);
 
//Magic that changes value with buttons!
  if (digitalRead(sw3) == HIGH) {
    value--;
    digitalWrite(led3, LOW);
    delay(350);
    digitalWrite(led3, HIGH);
    if (value == 0) value = 8;
  }
  if (digitalRead(sw4) == HIGH) {
    value++;
    digitalWrite(led4, LOW);
    delay(350);
    digitalWrite(led4, HIGH);
    if (value == 9) value = 1;
  }

//Showing text on line 4 on lcd, according to withc program to be selected
  if (value == 1) {
    lcd.setCursor(0,3);
    lcd.print("6 sekunder skyting");
  } else if (value == 2) {
    lcd.setCursor(0,3);
    lcd.print("8 sekunder skyting");
  } else if (value == 3) {
    lcd.setCursor(0,3);
    lcd.print("10 sekunder skyting");
  } else if (value == 4) {
    lcd.setCursor(0,3);
    lcd.print("20 sekunder skyting");
  } else if (value == 5) {
    lcd.setCursor(0,3);
    lcd.print("120 sekunder skyting");
  } else if (value == 6) {
    lcd.setCursor(0,3);
    lcd.print("300 sekunder skyting");
  } else if (value == 7) {
    lcd.setCursor(0,3);
    lcd.print("Friskyting");
  } else if (value == 8) {
    lcd.setCursor(0,3);
    lcd.print("Lampe test");
  }

//This makes the hole shit go in a loop, untill start button is pressed
  if (value == 1 && digitalRead(sw1) == HIGH) {
    program1();
  } else if (value == 2 && digitalRead(sw1) == HIGH) {
    program2();
  } else if (value == 3 && digitalRead(sw1) == HIGH) {
    program3();
  } else if (value == 4 && digitalRead(sw1) == HIGH) {
    program4();
  } else if (value == 5 && digitalRead(sw1) == HIGH) {
    program5();
  } else if (value == 6 && digitalRead(sw1) == HIGH) {
    program6();
  } else if (value == 7 && digitalRead(sw1) == HIGH) {
    program7 ();
  } else if (value == 8 && digitalRead(sw1) == HIGH) {
    lamptest ();
  }
  delay(200);
}

void loop() {
  performCommand();
}

What is a multiple void?

The millis function has been and is being explained hundreds of times on the forum. It may be the single most beat to death topic in history.

TKall:
What is a multiple void?

What I ment was that I have one line in void loop() witch goes to void performCommand(). performCommand switches to another void after it gets a value from button presses. Thats what I call multiple void, it might have a other name.

TKall:
The millis function has been and is being explained hundreds of times on the forum. It may be the single most beat to death topic in history.

And I have searched and found alot of them, but still can't understand it. Have tested it before (and I don't have my test code anymore) and it did not do a "delay", just jumped back to performcommand();. it did stop when I hold down sw1 and sw2

You don't need to understand it...just use it. The understanding comes later.

Have you read any books on c++, or did you just dive in?

Do you know what "void" means? That was rhetorical.

Have not read any books on c++. Most of my previous arduino programming is self learned and with help from friends, but last time is several years ago. So I guess id dive into it.

Tried with this above setup
unsigned long prevMillisprog4;
unsigned long currentMillis;
const unsigned intervalprog4 = 18000;

and this in one of the voids;

void program4() {
  if (digitalRead(sw2) == HIGH) {
    stans();
  } else {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(relayR, HIGH);
    digitalWrite(relayY, HIGH);
    digitalWrite(relayG, LOW);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Program 4 kjorer");
    lcd.setCursor(0,1);
    lcd.print("20 sekunder");
    lcd.setCursor(0,2);
    lcd.print("skyting");
    currentMillis = millis();
    if (currentMillis - prevMillisprog4 >= intervalprog4) {
      stans();
      prevMillisprog4 = currentMillis;
    }
  }
}

Now I have to hold down the sw1 button, and it goes back and fourt from performCommand() to program4(), but if I hold down sw1 and sw2, it actually goes to stans()

Someone who knows how to learn, knows to not start in the middle.

Maybe you could point me to the start, since I obviosly have started in the middle instead of insulting me?

You shouldn't take good advice as an insult. If something is worth doing, it's worth doing right.

Did you answer the question what does void mean yet?

Ill guess you asked me that question because I wrote multiple voids. And what I ment was that I hade more than just setup and loop. Sorry for getting that wrong.

A void is used to declear functions, isnt it? Correct me if im wrong

Correct me if im wrong

You should learn to ask yourself the question then find the answer. That's how you learn. Asking others is a poor substitute for learning how to ask yourself.

When I search a forum for answers to my questions, I've already tried for several days, maybe weeks to solve the problem myself. That includes asking myself how I can solve it, and what I have to learn.

I was expecting getting some help here, maybe a link, a little peace of code, comment to my own code, not just some wise words

Have you learned what void means yet? You have to put in the effort man. If you have been searching for weeks for answers to simple questions then you are doing something wrong. Starting in the middle maybe. Why not get yourself a good beginners book on arduino. Jack Pardum wrote a good one. There is one called arduino for teens and the one by Jeremy blum is good also.

It's the whole teach a boy to fish thing

I don't know what it means yet, but I know how to use it in the arduino programming...

The millis(); function is what stops me here. I can get my code fully working with a delay, but without the function to abort the function. And thats why I wrote this post. And yes, I have read several threads on the forum about it, mostly controlling leds. I have tried to understand it, and include it in my code. Using millis(); to controll a led and brightness is no problem, the countdown part is what I dont get.

What I don't get to work, is how I can use millis(); to make a countdown. When my code switches to for example void program4();, the leds and relays does it job when I'm using a delay, and then returns to void performCommand();. The only thing I don't get to work, is the function to abort the countdown, and go back to void performCommand();

How is a countdown different from any other timing? Blinking LED's are just countdowns to on and off.