简体   繁体   中英

Arduino - stopping loop via button

So i have been experimenting with TinkerCad, waiting for my arduino to arrive. Currently I have a loop of ledlights and i want to start and stop the loop by pressing a button.

Currently i am able to start my loop via the button, but not able to stop the loop with the same button press. Does this have something to do with the debouncing?

const int button = 10;
const int led1 = 8;
const int led2 = 4;
const int led3 = 3;
const int timedelay = 250;

boolean buttonstate = false;  

void setup()
  {

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(button, INPUT);
}

void loop() {

if(digitalRead(button)==HIGH)  // check if button is pushed
   buttonstate = !buttonstate;    //reverse buttonstate value

   if(buttonstate==true)
  {  
    digitalWrite(led1, HIGH);
    delay(timedelay); 
    digitalWrite(led1, LOW);
    delay(timedelay); 
    digitalWrite(led2, HIGH);
    delay(timedelay);
    digitalWrite(led2, LOW);
    delay(timedelay);
    digitalWrite(led3, HIGH);
    delay(timedelay);
    digitalWrite(led2, HIGH);
    delay(timedelay);
    digitalWrite(led1, HIGH); 
    delay(timedelay);
    digitalWrite(led3, LOW);
    delay(timedelay);
    digitalWrite(led2, LOW);
    delay(timedelay);
    digitalWrite(led1, LOW); 
    delay(timedelay);
    digitalWrite(led1, HIGH); }
   else {
        digitalWrite(led1, HIGH);
  }     
}

My circuit setup:

你好世界项目

EDIT:

I have adjusted my code, replaced the delay with millis and looking for a change in button state. Still looking for a way to adjust interval_led1 at the end of the loop to make sick ledlight sequences.

const int led1 = 13;
const int led2 = 8;
const int led3 = 5;
const int button = 10;
int ledState_led1 = LOW;             // ledState used to set the LED
int ledState_led2 = LOW;
int ledState_led3 = LOW;


// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_led1 = 0;        // will store last time LED was updated
unsigned long previousMillis_led2 = 0;
unsigned long previousMillis_led3 = 0;

long interval_led1 = 500;           // interval at which to blink (milliseconds)
long interval_led2 = 600;
long interval_led3 = 700;

boolean buttonstate = false;


void setup() {

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);

}





void loop() {
   // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis_led1 = millis();
  unsigned long currentMillis_led2 = millis();
  unsigned long currentMillis_led3 = millis();

  bool current_state = digitalRead(button);
  bool prev_buttonstate= false;

if(current_state==HIGH && current_state != prev_buttonstate)
{  
   buttonstate = !buttonstate;    //reverse buttonstate value
}
prev_buttonstate = current_state;



if(buttonstate==true)
    if (currentMillis_led1 - previousMillis_led1 >= interval_led1) {
    previousMillis_led1 = currentMillis_led1;
    if (ledState_led1 == LOW) {
      ledState_led1 = HIGH;
    } else {
      ledState_led1 = LOW;
    }
    digitalWrite(led1, ledState_led1);
    }

if(buttonstate==true)    
    if (currentMillis_led2 - previousMillis_led2 >= interval_led2) {
    previousMillis_led2 = currentMillis_led2;
    if (ledState_led2 == LOW) {
      ledState_led2 = HIGH;
    } else {
      ledState_led2 = LOW;
    }
    digitalWrite(led2, ledState_led2);
    }

if(buttonstate==true)
    if (currentMillis_led3 - previousMillis_led3 >= interval_led3) {
    previousMillis_led3 = currentMillis_led3;
    if (ledState_led3 == LOW) {
      ledState_led3 = HIGH;
    } else {
      ledState_led3 = LOW;
    }
    digitalWrite(led3, ledState_led3);
    }
}

Here your two cases are very different in terms of delay: if(buttonstate==true) is very long to execute because of the multiple delay instructions in it, else is very fast because there is no delay in it.

When buttonstate==True and you press the button (as Delta_G said, the delay() prevent the test to happen most of the time and you should use millis() for instance to do the timing, but let say you are lucky and you pass your first if statement), so buttonstate will flip to false .

As there is no delay in your else instruction, the board will come back in no time to your initial if , which, unfortunately will still be true as you are not fast enough to press this button for only a few microseconds. So buttonstate will flip again and your code will fall in your if(buttonstate==true) which is very long, allowing you to release the button in time before the if(digitalRead(button)==HIGH) is reevaluated.

The solution (apart from timing issues raised by @Delta_G, and hardware issues raised by @TomServo) is to seek for changes of the button state. You thus have to compare to the previous value it had. You can declare another boolean boolean prev_buttonstate = false; and could do something like:

bool current_state = digitalRead(button);
if(current_state==HIGH && current_state != prev_buttonstate)
{  
   buttonstate = !buttonstate;    //reverse buttonstate value
}
prev_buttonstate = current_state;

Hope it helps!

Your circuit is correct. If you keep pressing the button little longer, the condition will continue to hold good and the state falsely resets again.

To simulate the toggling effect, use a bool variable like so:. You reset the variable when the signal goes low.

  void loop() {
       static bool ready = true;
       if(digitalRead(button)==HIGH && ready)
       {
           ready = false;
            buttonstate = !buttonstate; //reverse buttonstate value
            if(buttonstate){
                  digitalWrite(led1, HIGH);
                  delay(timedelay); 
                  digitalWrite(led1, LOW);
                  delay(timedelay); 
                  /* Etc*/ }
             else {
                  digitalWrite(led1, HIGH);
            }
     }
     else 
     if(digitalRead(button)==LOW && !ready)
     {
         ready = true;
     }     
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM