如何在按下按钮时打破此循环?

时间:2013-06-30 15:00:15

标签: loops arduino break

我正在尝试在Arduino中创建一个倒数计时器,它将在按下按钮时启动,并且在按下相同按钮时也会中止。该值介于0-60之间,由电位计设定。到目前为止我遇到的问题是我无法在启动后退出循环。我知道可以使用'break'来完成它,但是我无法弄清楚将结果放在哪里,结果将是所希望的。这就是我到目前为止所做的:

const int  buttonPin = 2;    // The pin that the pushbutton is attached to
int buttonState = 0;         // Current state of the button
int lastButtonState = 0;     // Previous state of the button

void setup() {
    // initialize serial communication:
    Serial.begin(9600);
}

void timer(){
    int pot_value = analogRead(A0); //read potentiometer value
    if (pot_value > 17) { //i set it so, that it doesn't start before the value
                          //isn't greater than the 60th part of 1023
        int timer_value = map(pot_value, 0, 1023, 0, 60); //Mapping pot values to timer
        for (int i = timer_value; i >= 0; i--){ //Begin the loop
            Serial.println(i);
            delay(1000);
        }
    }
}

void loop() {
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // If the current state is HIGH then the button
      // went from off to on:
      timer(); //run timer
    }
    else {
      // If the current state is LOW then the button
      // went from on to off:
      Serial.println("off");
    }
  }
  // Save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;
}

例如,如果我将电位计设置为5并按下按钮,我会看到5,4,3,2,1,0,关闭,但如果我再次按下按钮直到完成,我就无法突破它。如何通过按下按钮来摆脱这个循环?

3 个答案:

答案 0 :(得分:1)

我注意到这个帖子已经在这里待了一年了,但万一有人还在寻找答案......

突破loop(){}?你试过打电话吗

  

返回;

您希望它何时退出该循环?像:

void loop(){
  buttonState = digitalRead(buttonPin);
  if (buttonState == quitLoopState) {   
      delay(loopDelay); 
      return; 
  }

  continueOperationOtherwise();
  delay(loopDelay); 
}

您始终可以将延迟代码放在方法的顶部以避免代码重复,并避免因早期中断循环而意外跳过代码。

答案 1 :(得分:0)

  

到目前为止我遇到的问题是我无法在启动后退出循环。

在您的代码中,您创建以下循环:

for (int i = timer_value; i >= 0; i--){ //Begin the loop
    Serial.println(i);
    delay(1000);
}

它是在按下按钮时调用的函数内部。打破循环, 你只需要在该循环中添加一个break;语句。但问题是如何 检查可以帮助你摆脱循环的条件?

您需要再次检查循环内的输入引脚(使用digitalRead)。但 为什么在一个简单的算法中检查两次单个按钮的状态?

这就是为什么我建议您使用单个loop来解决您的问题, loop()函数,使用一组三个状态变量:

  • last_button_state用于检测按钮的过渡状态
  • count_down了解我们是否处于倒计时
  • count_down_value倒计时的实际价值

最后两个值可以合并为一个(例如,将count_down设置为-1以告知 我们没有处于倒计时状态,但为了清楚起见,我将这两个状态变量留下了。

#define BUTTON_PIN 42

void setup() {
    Serial.begin(9600);
    pinMode(BUTTON_PIN, INPUT);
}

// State variables
uint8_t last_button_state = LOW;
bool count_down;
uint8_t count_down_value;

void loop() {
    int pot_value;

    // Read the pushbutton input pin:
    uint8_t button_state = digitalRead(buttonPin);

    if (button_state != last_button_state) {
        Serial.println("BUTTON STATE CHANGED");
        // On button press
        if (button_state == HIGH) {
            Serial.println("BUTTON PRESS");
            // Starts the count down if the value of potentiometer is high enough
            pot_value = analogRead(A0);
            if (pot_value > 17) {
                Serial.println("POT IS HIGH ENOUGH");
                if (count_down == false) {
                    Serial.println("ENABLING THE COUNT DOWN");
                    count_down = true;
                    count_down_value = map(pot_value, 0, 1023, 0, 60);
                } else {
                    Serial.println("DISABLING THE COUNT DOWN");
                    count_down = false;
                }
            }
        } else {
            Serial.println("BUTTON RELEASE");
        }
    }
    Serial.println("STORING BUTTON STATE");
    // Save button state for next iteration
    last_button_state = button_state;

    // If the countdown is running
    if (count_down == true) {
        Serial.println("RUNNING COUNTDOWN");
        // If the last value has been shown, show last value and stop the countdown
        if (count_down_value == 0) {
            Serial.println("BOOM!");
            count_down = false;
        // Otherwise decrements the value
        } else {
            // Prints out the value
            Serial.println(count_down_value);
            // Wait
            delay(1000);
            --count_down_value;
        }
    }
    delay(500); // Not to flood output
}

我希望得到以下输出:

<Press button>
BUTTON STATE CHANGED
BUTTON PRESS
POT IS HIGH ENOUGH
ENABLING THE COUNT DOWN
STORING BUTTON STATE
RUNNING COUNTDOWN
142
STORING BUTTON STATE
RUNNING COUNTDOWN
141
<Release button>
BUTTON STATE CHANGED
BUTTON RELEASE
STORING BUTTON STATE
RUNNING COUNTDOWN
140
<Press button>
BUTTON STATE CHANGED
BUTTON PRESS
POT IS HIGH ENOUGH
DISABLING THE COUNT DOWN
STORING BUTTON STATE
STORING BUTTON STATE
<Release button>
BUTTON STATE CHANGED
BUTTON RELEASE
STORING BUTTON STATE
...

现在,只有两种可能的情况:

  • 按下按钮,倒计时开始,倒计时重复,倒计时结束并停止
  • 按下按钮,倒计时开始,倒计时重复,按下按钮,倒计时停止

如果电位计为0,则按钮被禁用。

答案 2 :(得分:0)

我知道它已经有一段时间了,因为这是活跃的,但我可以看到前一个答案的一个大问题是使用延迟,如果我正确读取它会给出1.5秒计数,而不是1秒。

更好的答案将计算自上次倒计时以来的时间,然后如果是1秒或更长时间倒计时。它可能有点偏,但它更接近1秒。

它还解决了另一个问题,即按钮只能在这些延迟之间存在,每1.5秒左右给出一个短时间,因此您可能需要按住按钮1.5秒才能停止它,而不是仅仅按下按钮停止它。

我会做更像这样的事情:

const int  buttonPin = 2;   // The pin that the pushbutton is attached to
int buttonState = 0;        // Current state of the button
int lastButtonState = 0;    // Previous state of the button
int timer_value = 0;        // The timer that you want.
int last_count = 0;         // The time the counter last counted down.

void setup() {
    // initialize serial communication:
    Serial.begin(9600);
}

void loop() {
  // Read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // Compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // If the current state is HIGH then the button
      // went from off to on:
      if(timer_value) {
        //checks to see if countdown is in progress, if 0, there is no count down.
        timer_value=0;
      }
      else {
        //The timer is not running, therefore start it.
        int pot_value = analogRead(A0); //read potentiometer value
        if (pot_value > 17) { //i set it so, that it doesn't start before the value
                              //isn't greater than the 60th part of 1023
            int timer_value = map(pot_value, 0, 1023, 0, 60); //Mapping pot values to timer.
            last_count = millis();  //sets up the timer to start counting.
            Serial.println(timer_value);  //Outputs the start of the timer.
        }
      }
    }
    else {
      // If the current state is LOW then the button
      // went from on to off:
      Serial.println("off");
    }
  }
  // Save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;

  //Check to see if counting down
  if(timer_value){
    //The timer is runing.
    //Check to see if it is time to count
    //Calculate what time it was 1000ms (1 second a go) and see if it is the same time or later than the last count, if so, it needs to count down.
    if(millis() - 1000 >= last_count) {
      //Time to count down.
      timer_value--;
      Serial.println(timer_value);
    }
  }
}

这样每个循环都会检查按钮,并且循环连续运行,而不是暂停第二个等待它倒计时,并且它将每秒计数。