如何检测Arduino中按下按钮的时间?

时间:2015-09-06 19:49:12

标签: c arduino atmega

如何检测Arduino中按下/释放按钮的时间长度,然后再打印一些自定义输出?

2 个答案:

答案 0 :(得分:11)

Arduino只能检测按钮的状态(按下或未按下)。

您可以使用计时器变量(基于其文档中的this example)来保存按下释放按钮的确切时间,这样您就可以了可以检查两个变量之间的差异,以计算它被按下和释放的时间。

代码看起来像这样:

const int buttonPin = 2;  

int buttonState = 0;     // current state of the button
int lastButtonState = 0; // previous state of the button
int startPressed = 0;    // the time button was pressed
int endPressed = 0;      // the time button was released
int timeHold = 0;        // the time button was hold
int timeReleased = 0;    // the time button was released

void setup() {
  pinMode(buttonPin, INPUT); // initialize the button pin as a input
  Serial.begin(9600);        // initialize serial communication
}

void loop() {
  buttonState = digitalRead(buttonPin); // read the button input

  if (buttonState != lastButtonState) { // button state changed
     updateState();
  }

  lastButtonState = buttonState;        // save state for next loop
}

void updateState() {
  // the button was just pressed
  if (buttonState == HIGH) {
      startPressed = millis();
      timeReleased = startPressed - endPressed;

      if (timeReleased >= 500 && timeReleased < 1000) {
          Serial.println("Button was idle for half a second");
      }

      if (timeReleased >= 1000) {
          Serial.println("Button was idle for one second or more"); 
      }

  // the button was just released
  } else {
      endPressed = millis();
      timeHold = endPressed - startPressed;

      if (timeHold >= 500 && timeHold < 1000) {
          Serial.println("Button was hold for half a second"); 
      }

      if (timeHold >= 1000) {
          Serial.println("Button was hold for one second or more"); 
      }

  }
}

但是,如果你想触发一个事件按下按钮(或者你想在某个显示中增加一个计数器),你仍然可以做同样的数学运算。

将循环函数中的条件更改为:

  if (buttonState != lastButtonState) { 
     updateState(); // button state changed. It runs only once.
  } else {
     updateCounter(); // button state not changed. It runs in a loop.
  }

然后实现你的新功能:

void updateCounter() {
  // the button is still pressed
  if (buttonState == HIGH) {
      timeHold = milis() - startPressed;

      if (timeHold >= 1000) {
          Serial.println("Button is hold for more than a second"); 
      }

  // the button is still released
  } else {
      timeReleased = milis() - endPressed;

      if (timeReleased >= 1000) {
          Serial.println("Button is released for more than a second");  
      }
  }
}

答案 1 :(得分:0)

为了您的兴趣,这里有一个代码示例,它使用 2 个数组来存储分配给相应输入按钮的 arduino 引脚的按钮状态。在循环期间,您可以对想要的重复进行简单的检查:

  if(button_down(But1_pin, BTN_LOOP_DELAY_MS))
  {
    // code here repeated if the button is either clicked or maintained
  }

button_down() 还将第一次重复推迟 DELAY_WAIT_BEFORE_REPEAT 毫秒。

这里是完整的测试示例:

#define BTN_LOOP_DELAY_MS   100
#define DELAY_WAIT_BEFORE_REPEAT  500
#define NB_MAX_PIN_INPUT    13

#define But1_pin    7
#define But2_pin    6

// array to check status change
bool prev_button[NB_MAX_PIN_INPUT];
unsigned long button_last_down[NB_MAX_PIN_INPUT];

// macro : our read init with prev_button storage
#define READ_INIT_BUTTON(pin)  \
  do{ \
    pinMode(pin, INPUT); \
    prev_button[pin] = digitalRead(pin); \
   } while(false)

// function at the end of the code
bool button_down(byte pin_num, unsigned int delay_repeated);

void setup() {
  READ_INIT_BUTTON(But1_pin);
  READ_INIT_BUTTON(But2_pin);
  Serial.begin(115200);
}

void loop() {
  if(button_down(But1_pin, BTN_LOOP_DELAY_MS))
  {
    Serial.print("new inpulse");
    Serial.print(millis());
    Serial.println();
  }

  if(button_down(But2_pin, BTN_LOOP_DELAY_MS))
  {
    Serial.println("button2");
  }

}

bool button_down(byte pin_num, unsigned int delay_repeated)
{
  bool b = digitalRead(pin_num);
  bool r = false;

  unsigned long currentMillis = millis();

  if(prev_button[pin_num] != HIGH && b == HIGH)
  {
    r = true;
    button_last_down[pin_num] = currentMillis + DELAY_WAIT_BEFORE_REPEAT;
  }
  else if(b == HIGH 
      && prev_button[pin_num] == HIGH
      && currentMillis > button_last_down[pin_num] 
      && currentMillis - button_last_down[pin_num] > delay_repeated
    )
  {
    // save the last time we give a button impusle at true
    button_last_down[pin_num] = currentMillis;
    r = true;
  }

  // store button state, if changed
  if(prev_button[pin_num] != b)
  {
    prev_button[pin_num] = b;
  }
    
  return r;
}
相关问题