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

How to detect how long a button was pressed in Arduino?

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

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 moment the button was pressed
int endPressed = 0;      // the moment the button was released
int holdTime = 0;        // how long the button was hold
int idleTime = 0;        // how long the button was idle

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 has been just pressed
  if (buttonState == HIGH) {
      startPressed = millis();
      idleTime = startPressed - endPressed;

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

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

  // the button has been just released
  } else {
      endPressed = millis();
      holdTime = endPressed - startPressed;

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

      if (holdTime >= 1000) {
          Serial.println("Button was held 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) {
      holdTime = millis() - startPressed;

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

  // the button is still released
  } else {
      idleTime = millis() - endPressed;

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

出于您的兴趣,这里有一个代码示例,它使用 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;
}