1

我正在尝试在 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,关闭,但如果我再次按下按钮直到完成,我无法摆脱它。如何通过按一下按钮来逃避这个循环?

4

3 回答 3

1

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

要突破循环(){}?你试过打电话吗

返回;

无论您希望它在哪里退出该循环?像:

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

  continueOperationOtherwise();
  delay(loopDelay); 
}

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

于 2015-01-02T20:37:18.993 回答
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,则该按钮被禁用。

于 2013-06-30T16:14:54.113 回答
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 how long since last count to see if it is greater than 1 s (1000 ms), if so, it needs to count down.
    if(millis() - last_count >= 1000) {
      //Time to count down.
      timer_value--;
      last_count = last_count + 1000;
      Serial.println(timer_value);
    }
  }
}

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

于 2014-04-01T03:01:19.210 回答