아두이노 - 버튼 - 긴 누름 단 누름 | Arduino - Button - Long Press Short Press
우리는 배울 것입니다:
처음 세 부분에서, 우리는 원칙적으로 감지하는 방법을 배웁니다.
마지막 부분에서는 디바운스를 적용하여 실제 사용 시 감지하는 방법을 배웁니다. 버튼을 위해 디바운스가 필요한 이유를 확인하려면 왜 버튼에 디바운스가 필요한가를 참고하세요. 디바운스 처리를 하지 않으면 버튼의 짧은 누름을 잘못 감지할 수 있습니다.
1 | × | Arduino Uno | Amazon | |
1 | × | USB 2.0 cable type A/B | 쿠팡 | Amazon | |
1 | × | Push Button | 쿠팡 | Amazon | |
1 | × | (Optional) Panel-mount Push Button | Amazon | |
1 | × | Breadboard | 쿠팡 | Amazon | |
1 | × | Jumper Wires | Amazon | |
1 | × | (Optional) 9V Power Adapter for Arduino | Amazon | |
1 | × | (Recommended) Screw Terminal Block Shield for Arduino Uno | 쿠팡 | Amazon | |
1 | × | (Recommended) Breadboard Shield For Arduino Uno | 쿠팡 | Amazon | |
1 | × | (Recommended) Enclosure For Arduino Uno | Amazon | |
공개: 이 섹션에서 제공된 링크 중 일부는 제휴 링크입니다. 이 링크를 통해 구매한 경우 추가 비용없이 수수료를 받을 수 있습니다. 지원해 주셔서 감사합니다.
버튼(핀아웃, 작동 방식, 프로그래밍 방법 등)에 대해 잘 모르시다면, 다음 튜토리얼에서 배워보세요:
아두이노 - 버튼 튜토리얼
이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
이 튜토리얼에서는 내부 풀업 저항을 사용할 것입니다. 그러므로 버튼의 상태는 정상일 때 HIGH이고 눌렸을 때는 LOW입니다.
누른 상태에서 릴리스된 상태까지의 시간 간격을 측정합니다. 이 기간이 정의된 시간보다 짧으면 짧은 누름 이벤트가 감지됩니다.
한 단계씩 살펴봅시다:
const int SHORT_PRESS_TIME = 500;
if(lastState == HIGH && currentState == LOW)
pressedTime = millis();
if(lastState == LOW && currentState == HIGH)
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지되었습니다");
const int BUTTON_PIN = 7;
const int SHORT_PRESS_TIME = 500;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
currentState = digitalRead(BUTTON_PIN);
if(lastState == HIGH && currentState == LOW)
pressedTime = millis();
else if(lastState == LOW && currentState == HIGH) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지되었습니다");
}
lastState = currentState;
}
A short press is detected
※ NOTE THAT:
시리얼 모니터는 한 번의 누름에 대해 여러 번의 짧은 누름 감지를 보여줄 수 있습니다. 이것은 버튼의 정상적인 동작입니다. 이 현상을 "채터링 현상"이라고 합니다. 이 문제는 이 튜토리얼의 마지막 부분에서 해결될 것입니다.
롱 프레스를 감지하기 위한 두 가지 사용 사례가 있습니다.
첫 번째 사용 사례에서, 우리는 눌린 이벤트와 릴리스된 이벤트 사이의 시간 지속을 측정합니다. 지속 시간이 정의된 시간보다 길면, 롱-프레스 이벤트가 감지됩니다.
두 번째 사용 사례에서, 버튼이 눌린 후, 우리는 버튼이 놓일 때까지 지속적으로 누르는 시간을 측정하고 롱 프레스 이벤트를 확인합니다. 버튼이 눌려지는 동안, 지속 시간이 정의된 시간보다 길 경우, 롱 프레스 이벤트가 감지됩니다.
const int BUTTON_PIN = 7;
const int LONG_PRESS_TIME = 1000;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
currentState = digitalRead(BUTTON_PIN);
if(lastState == HIGH && currentState == LOW)
pressedTime = millis();
else if(lastState == LOW && currentState == HIGH) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration > LONG_PRESS_TIME )
Serial.println("A long press is detected");
}
lastState = currentState;
}
버튼이 놓인 직후에만 롱 프레스 이벤트가 감지됩니다.
const int BUTTON_PIN = 7;
const int LONG_PRESS_TIME = 1000;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
bool isPressing = false;
bool isLongDetected = false;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
currentState = digitalRead(BUTTON_PIN);
if(lastState == HIGH && currentState == LOW) {
pressedTime = millis();
isPressing = true;
isLongDetected = false;
} else if(lastState == LOW && currentState == HIGH) {
isPressing = false;
}
if(isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;
if( pressDuration > LONG_PRESS_TIME ) {
Serial.println("긴 누름이 감지됨");
isLongDetected = true;
}
}
lastState = currentState;
}
버튼이 아직 릴리스되지 않았을 때만 롱-프레스 이벤트가 감지됩니다.
const int BUTTON_PIN = 7;
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
currentState = digitalRead(BUTTON_PIN);
if(lastState == HIGH && currentState == LOW)
pressedTime = millis();
else if(lastState == LOW && currentState == HIGH) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지됨");
if( pressDuration > LONG_PRESS_TIME )
Serial.println("긴 누름이 감지됨");
}
lastState = currentState;
}
※ NOTE THAT:
시리얼 모니터는 길게 누르는 동안 여러 번의 짧은 누름 감지를 표시할 수 있습니다. 이것은 버튼의 정상적인 동작입니다. 이러한 현상을 "채터링 현상"이라고 합니다. 이 문제는 이 튜토리얼의 마지막 부분에서 해결될 것입니다.
const int BUTTON_PIN = 7;
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
currentState = digitalRead(BUTTON_PIN);
if(lastState == HIGH && currentState == LOW) {
pressedTime = millis();
isPressing = true;
isLongDetected = false;
} else if(lastState == LOW && currentState == HIGH) {
isPressing = false;
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지됨");
}
if(isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;
if( pressDuration > LONG_PRESS_TIME ) {
Serial.println("긴 누름이 감지됨");
isLongDetected = true;
}
}
lastState = currentState;
}
※ NOTE THAT:
시리얼 모니터는 길게 누를 때 여러 번의 짧은 누름 감지를 보여줄 수 있습니다. 이것은 버튼의 정상적인 동작입니다. 이 현상을 "차터링 현상"이라고 합니다. 이 문제는 이 튜토리얼의 마지막 부분에서 해결될 것입니다.
많은 애플리케이션에서 버튼을 디바운스 하는 것이 매우 중요합니다.
디바운싱은 특히 여러 버튼을 사용할 때 조금 복잡합니다. 초보자들이 훨씬 쉽게 다룰 수 있도록, 저희는 ezButton 이라는 라이브러리를 만들었습니다.
우리는 아래 코드에서 이 라이브러리를 사용할 것입니다.
#include <ezButton.h>
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
ezButton button(7);
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(9600);
button.setDebounceTime(50);
}
void loop() {
button.loop();
if(button.isPressed())
pressedTime = millis();
if(button.isReleased()) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지됨");
if( pressDuration > LONG_PRESS_TIME )
Serial.println("긴 누름이 감지됨");
}
}
#include <ezButton.h>
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
ezButton button(7);
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;
void setup() {
Serial.begin(9600);
button.setDebounceTime(50);
}
void loop() {
button.loop();
if(button.isPressed()){
pressedTime = millis();
isPressing = true;
isLongDetected = false;
}
if(button.isReleased()) {
isPressing = false;
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < SHORT_PRESS_TIME )
Serial.println("A short press is detected");
}
if(isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;
if( pressDuration > LONG_PRESS_TIME ) {
Serial.println("A long press is detected");
isLongDetected = true;
}
}
}
비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.
버튼의 수를 줄이기 위해 하나의 버튼으로 두 가지 이상의 기능을 할 수 있습니다. 예를 들어, 짧게 누르면 작동 모드 변경, 길게 누르면 장치를 끕니다.
실수로 짧게 누르는 것을 줄이기 위해 길게 누르기 기능을 사용합니다. 예를 들어, 일부 기기는 공장 초기화를 위해 버튼을 사용합니다. 버튼이 실수로 눌리면 위험합니다. 이를 방지하기 위해, 장치는 버튼을 길게 누를 때만 (예: 5초 이상) 공장 초기화가 실행되도록 구현되었습니다.