Change Preset Delay of a sketch using external button

Hey guys, Hope you all will be fine. I am working on a project regarding traffic signal. I have prepared all the sketch and its running successfully. I wanted to know that "can i change the delay time without changing/disturbing the sketch with the help of any external push button? Any help will be highly appreciated....

Your description is a bit vague as you don't say what delay(s) you want to change. To do this without changing the sketch will be difficult as you would need to vary the MCU oscillator frequency on the fly and I'm not to sure how successful that would be and if it would do what you wanted.

Hi,

Yes you can (or at least I think so - as Riva says, your description of the project is very short and you have not posted a schamatic diagram and your sketch).

I imagine that at the moment your sketch contains fixed delays like

delay(3000);

To vary these delays, you need to change these to use a variable, for example:

delay(myDelay);

Then you can change the value of myDelay when you detect a button press.

Paul

I am extremely sorry for really a short description. I am extremely new to Arduino like one weak user.

I have just learnt only two commands pinMode and digitalWrita my sketch is given below.

void setup() {
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(4, OUTPUT);
 pinMode(5, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);

}

void loop() {
 digitalWrite(2, HIGH);
 digitalWrite(7, HIGH);
 digitalWrite(8, HIGH);
 digitalWrite(11, HIGH);
 delay(2000);
 digitalWrite(2, LOW);
 digitalWrite(3, HIGH);
 delay(2000);
 digitalWrite(3, LOW);
 digitalWrite(4, HIGH);
 delay(5000);
 digitalWrite(4, LOW);
 digitalWrite(3, HIGH);
 delay(2000);
 digitalWrite(3, LOW);
 digitalWrite(2, HIGH);
 delay(2000);
 digitalWrite(8, LOW);
 digitalWrite(9, HIGH);
 delay(2000);
 digitalWrite(9, LOW);
 digitalWrite(10, HIGH);
 delay(5000);
 digitalWrite(10, LOW);
 digitalWrite(9, HIGH);
 delay(2000);
 digitalWrite(9, LOW);
 digitalWrite(8, HIGH);
 delay(2000);
 digitalWrite(11, LOW);
 digitalWrite(12, HIGH);
 delay(2000);
 digitalWrite(12, LOW);
 digitalWrite(13, HIGH);
 delay(5000);
 digitalWrite(13, LOW);
 digitalWrite(12, HIGH);
 delay(2000);
 digitalWrite(12, LOW);
 digitalWrite(11, HIGH);
 delay(2000);
 digitalWrite(7, LOW);
 digitalWrite(6, HIGH);
 delay(2000);
 digitalWrite(6, LOW);
 digitalWrite(5, HIGH);
 delay(5000);
 digitalWrite(5, LOW);
 digitalWrite(6, HIGH);
 delay(2000);
 digitalWrite(6, LOW);
 digitalWrite(7, HIGH);
   
}

In this sketch I have used fix delays several times. and the requirement is to change these delay with the help of an external push button.

Help needed in regard plz.

Always use code tags when you post a sketch. Please modify your last post and put them in so that the sketch lookslike this.

Explain more about how you want the delays to be changed when the button is pressed, or released, or pressed more than once etc.

Add: pinMode (14, INPUT_PULLUP); // wire button to connect pin to Gnd when pressed

Every you have delay, replace with this: if (digitalRead(14) == LOW){ delay(2000); } else { delay(5000); }

And this, since you seem to have alternating times. if (digitalRead(14) == LOW){ delay(5000); } else { delay(2000); }

Or, at the start of loop: void loop(){ if (digitalRead(14)== LOW){ delay1 = 2000; delay2 = 5000; } else { delay1 = 5000; delay2 = 2000; } and put delay1 and delay2 thruout your code. You have to be pressing the button when the code reads the button. Perhaps a toggle switch, or rocker switch, would be good so change the switch direction and leave it.

and add to the top of the sketch, before setup() : int delay1; int delay2;

Thanks a lot CrossRoad.... I tried it and its working fine..

Now the question is , if I want to put multiple delays then what should i do? means if I press push button once it should go to 5 seconds from 2 sec. and if I press it again it should to 7 sec. if it is pushed again it should go to 9sec.

void setup() {
  pinMode(A0, INPUT);
  pinMode(13, OUTPUT);

}

void loop() {
  digitalWrite(13, HIGH);
  if(digitalRead(A0) == LOW){
    delay(2000);
  }
  else{
    delay(5000);
  }
  digitalWrite(13, LOW);
  if(digitalRead(A0) == LOW){
    delay(2000);
  }
  else{
    delay(5000);
}}

naashi: if I press push button once it should go to 5 seconds from 2 sec. and if I press it again it should to 7 sec. if it is pushed again it should go to 9sec.

Your code now is very simple. It detects if the button is pressed or not pressed. One delay is chosen if it pressed and a different delay if it is not pressed.

To do what you want to do next is a more difficult. Your sketch must be changed to perform two more functions:

  • Detect when the button changes from not-pressed to pressed
  • "Debounce" the button. When a button is pressed once by your finger, what actually happens is that the contacts inside the button touch, then bounce away, then touch again, then bounce away and so on for several times. It is like dropping a ball onto the ground, but it happens in a few milliseconds. To Debounce, your sketch must detect the first change from not-pressed to pressed, but then ignore any more changes for a few milliseconds after.

To do the first thing, you need to make a new variable that holds the previous state of the button (HIGH or LOW) so that it can be compared to the current value of the button:

int previousButtonState = LOW;

Then you can detect the button changing from LOW to HIGH like this:

int currentButtonState = digitalRead(A0);
if (previousButtonState == LOW && currentButtonState == HIGH) {
  // change the delay to the new delay
}
previousButtonState = currentButtonState;

PaulRB: Your code now is very simple. It detects if the button is pressed or not pressed. One delay is chosen if it pressed and a different delay if it is not pressed.

To do what you want to do next is a more difficult. Your sketch must be changed to perform two more functions:

  • Detect when the button changes from not-pressed to pressed
  • "Debounce" the button. When a button is pressed once by your finger, what actually happens is that the contacts inside the button touch, then bounce away, then touch again, then bounce away and so on for several times. It is like dropping a ball onto the ground, but it happens in a few milliseconds. To Debounce, your sketch must detect the first change from not-pressed to pressed, but then ignore any more changes for a few milliseconds after.

To do the first thing, you need to make a new variable that holds the previous state of the button (HIGH or LOW) so that it can be compared to the current value of the button:

int previousButtonState = LOW;

Then you can detect the button changing from LOW to HIGH like this:

int currentButtonState = digitalRead(A0);
if (previousButtonState == LOW && currentButtonState == HIGH) {
  // change the delay to the new delay
}
previousButtonState = currentButtonState;

Will you please elaborate it I am not understanding the thing coz i am a newbie. anyone here can please prepare a sketch (sample) for the said purpose?

Hi naashi,

I have made the next step for you:

int previousButtonState = LOW;
unsigned long delayLength = 5000;

int ledState = LOW;
unsigned long lastBlink = 0;


void setup() {
  pinMode(A0, INPUT);
  pinMode(13, OUTPUT);
}

void loop() {

  //Read the button
  int currentButtonState = digitalRead(A0);

  //Is the button pressed, and was not pressed the last time we read it?
  if (previousButtonState == LOW && currentButtonState == HIGH) {
    
    // change the delay to the new delay
    if (delayLength == 5000) delayLength = 2000;
    else if (delayLength == 2000) delayLength = 7000;
    else if (delayLength == 7000) delayLength = 9000;
    else if (delayLength == 9000) delayLength = 5000;
  }
  
  //Update the record of the button status to compare with next time we read the button
  previousButtonState = currentButtonState;

  //What is the time now?
  unsigned long timeNow = millis();

  //Is it time to update the led?
  if (timeNow - lastBlink > delayLength) {
    //Blink the led
    if (ledState == LOW) ledState = HIGH; else ledState = LOW;
    digitalWrite(13, ledState);

    //Update the record of the last time the led was blinked
    lastBlink = timeNow;
  }

}

Before you make any changes to the sketch, you must make sure first of all that you understand every line of code. So ask any questions you want.

Paul

PaulRB:
Hi naashi,

I have made the next step for you:

int previousButtonState = LOW;

unsigned long delayLength = 5000;

int ledState = LOW;
unsigned long lastBlink = 0;

void setup() {
 pinMode(A0, INPUT);
 pinMode(13, OUTPUT);
}

void loop() {

//Read the button
 int currentButtonState = digitalRead(A0);

//Is the button pressed, and was not pressed the last time we read it?
 if (previousButtonState == LOW && currentButtonState == HIGH) {
   
   // change the delay to the new delay
   if (delayLength == 5000) delayLength = 2000;
   else if (delayLength == 2000) delayLength = 7000;
   else if (delayLength == 7000) delayLength = 9000;
   else if (delayLength == 9000) delayLength = 5000;
 }
 
 //Update the record of the button status to compare with next time we read the button
 previousButtonState = currentButtonState;

//What is the time now?
 unsigned long timeNow = millis();

//Is it time to update the led?
 if (timeNow - lastBlink > delayLength) {
   //Blink the led
   if (ledState == LOW) ledState = HIGH; else ledState = LOW;
   digitalWrite(13, ledState);

//Update the record of the last time the led was blinked
   lastBlink = timeNow;
 }

}




Before you make any changes to the sketch, you must make sure first of all that you understand every line of code. So ask any questions you want.

Paul

Hey paul sir.
I tried above sketch but its not working properly. Means sometimes it works But sometimes not.
And it changes its only one condition from 5000 to 2000 and not more then that. Then I made some changes in time and still in the position to change its form once not more.

int previousButtonState = LOW;
unsigned long delayLength = 500;

int ledState = LOW;
unsigned long lastBlink = 0;


void setup() {
  pinMode(A0, INPUT);
  pinMode(9, OUTPUT);
}

void loop() {

  //Read the button
  int currentButtonState = digitalRead(A0);
 
  //Is the button pressed, and was not pressed the last time we read it?
  if (previousButtonState == LOW && currentButtonState == HIGH) {
    
    // change the delay to the new delay
    if (delayLength == 500) delayLength = 100;
    else if (delayLength == 100) delayLength = 2000;
    else if (delayLength == 2000) delayLength = 4000;
    else if (delayLength == 4000) delayLength = 500;
  }
  
  //Update the record of the button status to compare with next time we read the button
  previousButtonState = currentButtonState;

  //What is the time now?
  unsigned long timeNow = millis();

  //Is it time to update the led?
  if (timeNow - lastBlink > delayLength) {
    //Blink the led
    if (ledState == LOW) ledState = HIGH; else ledState = LOW;
    digitalWrite(9, ledState);

    //Update the record of the last time the led was blinked
    lastBlink = timeNow;
  }

}

Naashi, describe how your pushbutton is wired to the Arduino.

PaulRB: Naashi, describe how your pushbutton is wired to the Arduino.

Two terminals of push buttons are connected to arduino. 1 with A0 and other with 5V.

Ok, i thought that might be the problem.

What you have done is ok when the button is pressed. The A0 pin is connected to 5V and digitalRead() returns HIGH.

But when the button is not pressed, A0 is not connected to anything. Because of this, digitalRead() could return randomly either HIGH or LOW. This is called a "floating input".

There are two simple ways to stop this.

One is to connect a resistor like 10K between A0 and GND. This way is called a "pull-down" resistor and it makes sure that digitalRead() returns LOW when the button is not pressed.

The second way is to connect the button between A0 and GND. Then tell the Arduino to use it's internal pull-up resistor with pinMode( A0, INPUT_PULLUP). This will mean that digitalRead() will return LOW when the button is pressed and HIGH when it is not pressed.

Why not try both ways, to learn? The first way will not need any code changes. See if you can change the code to make the second way work.

I just tried the second method to connect the A0 to ground before you tell me sir but result was same just because Pull up or Pull down resistor was not used. Now it is working fine sir.

You are great…
Now I will try myself to expand the sketch as per requirements and will let you know soon.

Hats off…

Thnx alot again

I just tried both ways and both are working fine sir. Now I am going to expand the sketch for Four(4) Number of crossings. will let you the results and will provide the sketch to cross check.

Hey Paul sir.
Hope you will be fine.

I tried some changing in code last day to expand it for single crossing of traffic signal.
code was changed to given values.

//for Green
int previousButtonState = LOW;
unsigned long delayLength = 500;

//for Green
int ledState = LOW;
unsigned long lastBlink = 0;

void setup() {
  pinMode(9, OUTPUT);            //Green
  pinMode(47, OUTPUT);          //Yellow
  pinMode(49, OUTPUT);          //Red

  pinMode(A0, INPUT);    //For Green
  
  }

void loop() {
  {
    digitalWrite(49, HIGH);  //Red goes ON
    delay(1000);
    digitalWrite(49, LOW);   //Red goes Off
    digitalWrite(47, HIGH);  //Yellow goes On 
    delay(1000);
    digitalWrite(47, LOW);  //Yellow Goes Off
  }
  
  //Read the button for Green
  { int currentButtonState = digitalRead(A0);

    //Is the button pressed, and was not pressed the last time we read it?
    if (previousButtonState == LOW && currentButtonState == HIGH) {

      // change the delay to the new delay
      if (delayLength == 500) delayLength = 100;
      else if (delayLength == 100) delayLength = 2000;
      else if (delayLength == 2000) delayLength = 4000;
      else if (delayLength == 4000) delayLength = 500;
    }

    //Update the record of the button status to compare with next time we read the button
    previousButtonState = currentButtonState;

    //What is the time now?
    unsigned long timeNow = millis();

    //Is it time to update the led?
    if (timeNow - lastBlink > delayLength) {
      //Blink the led
      if (ledState == LOW) ledState = HIGH;
      digitalWrite(9, ledState);
      delay(timeNow);      
      //Update the record of the last time the led was blinked
      lastBlink = timeNow;
      digitalWrite(9, LOW);
    }

    {
      digitalWrite(47, HIGH);
      delay(1000);
      digitalWrite(47, LOW);
      digitalWrite(49, HIGH);
    }
  }
}

But result are not achieved as per requirment.
When I turns the circuit ON. In first loop Red and Green goes ON and OFF as per directions but when comes to green it remains on for 2 second, in second loop it remains ON for 7 seconds and in third loop it Turns ON for 17 seconds and vise versa.

And the second problem is that the Push button is also not working.

Any instruction please.

naashi: But result are not achieved as per requirment. When I turns the circuit ON. In first loop Red and Green goes ON and OFF as per directions but when comes to green it remains on for 2 second, in second loop it remains ON for 7 seconds and in third loop it Turns ON for 17 seconds and vise versa.

Naashi, I don't understand what it is that is not as per requirement.

naashi: And the second problem is that the Push button is also not working.

Using delay() will prevent the pushbutton from working. You must remove all delay() commands and use the technique I showed you with millis()