아두이노 나노 - 버튼 - 길게 누르기 짧게 누르기 | Arduino Nano - Button - Long Press Short Press
이 튜토리얼은 아두이노 나노를 사용하여 버튼의 긴 누름과 짧은 누름을 감지하는 방법을 지시합니다. 구체적으로, 다음 예제들을 살펴볼 것입니다:
아두이노 나노는 버튼의 짧은 누름을 감지합니다.
아두이노 나노는 버튼의 긴 누름을 감지합니다.
아두이노 나노는 버튼의 긴 누름과 짧은 누름을 모두 감지합니다.
아두이노 나노는 긴 누름과 짧은 누름에 대해 디바운싱을 합니다.
마지막 섹션에서는 실용적인 애플리케이션에서 버튼 누름을 감지하기 위해 디바운스(debounce)를 어떻게 사용하는지 배울 것입니다. 버튼에 디바운싱이 왜 필요한지 더 알아보려면, 이 글을 참조하세요. 그것 없이는, 우리는 버튼의 짧은 누름을 잘못 감지할 수 있습니다.
1 | × | Arduino Nano | Amazon | |
1 | × | USB A to Mini-B USB cable | 쿠팡 | 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 Nano | Amazon | |
1 | × | (Recommended) Screw Terminal Expansion Board for Arduino Nano | 쿠팡 | Amazon | |
공개: 이 섹션에서 제공된 링크 중 일부는 제휴 링크입니다. 이 링크를 통해 구매한 경우 추가 비용없이 수수료를 받을 수 있습니다. 지원해 주셔서 감사합니다.
버튼(핀 배치, 기능성 및 프로그래밍 포함)에 익숙하지 않다면, 다음 튜토리얼이 도움이 될 수 있습니다:
이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
이 튜토리얼에서는 내부 풀업 저항을 사용할 것입니다. 따라서 버튼의 정상 조건에서는 상태가 HIGH이며, 눌렸을 때는 LOW입니다.
우리는 눌린 이벤트와 떼어진 이벤트 사이의 간격을 계산합니다. 만약 그 시간이 사전에 정의된 시간보다 짧으면, 단시간 누름 이벤트로 식별됩니다.
짧은 누름의 지속 시간을 지정하세요.
const int SHORT_PRESS_TIME = 500;
버튼이 눌렸을 때를 확인하고 눌린 시간을 기록하세요.
if(prev_button_state == HIGH && button_state == LOW)
time_pressed = millis();
버튼이 놓여졌을 때를 감지하고 놓인 시간을 기록하십시오.
if(prev_button_state == LOW && button_state == HIGH)
time_released = millis();
long press_duration = time_released - time_pressed;
지정된 짧은 누름 시간과 누름 지속 시간을 비교하여 짧은 누름을 식별합니다.
if( press_duration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지되었습니다");
const int BUTTON_PIN = 2;
const int SHORT_PRESS_TIME = 500;
int prev_button_state = LOW;
int button_state;
unsigned long time_pressed = 0;
unsigned long time_released = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
button_state = digitalRead(BUTTON_PIN);
if(prev_button_state == HIGH && button_state == LOW)
time_pressed = millis();
else if(prev_button_state == LOW && button_state == HIGH) {
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지되었습니다");
}
prev_button_state = button_state;
}
A short press is detected
※ NOTE THAT:
시리얼 모니터는 단일 누름에 대해 여러 번의 짧은 누름 감지를 표시할 수 있습니다. 이것은 “차터링 현상”으로 알려진 버튼의 예상된 동작입니다. 이 문제는 이 튜토리얼의 마지막 부분에서 다룰 것입니다.
긴 누름을 탐지하는 데는 두 가지 시나리오가 있습니다:
버튼이 릴리스된 후에 롱-프레스 이벤트가 확인됩니다.
버튼이 릴리스되기 전에도, 버튼을 계속 누르고 있을 때 롱-프레스 이벤트가 확인됩니다.
1. 초기 애플리케이션에서는 눌린 상태와 릴리스된 상태 사이의 시간을 계산할 것입니다. 2. 만약 지속 시간이 사전에 정해진 시간 이상이라면, 그때 롱-프레스 이벤트가 확인됩니다.
두 번째 사용 사례에서 버튼이 눌릴 때, 버튼이 놓일 때까지 연속적으로 누르는 시간이 측정되고 길게 누르기 이벤트가 확인됩니다. 버튼이 눌리고 있는 동안, 지속 시간이 사전에 정의된 시간을 초과하면 길게 누르기 이벤트가 감지됩니다.
const int BUTTON_PIN = 2;
const int LONG_PRESS_TIME = 1000;
int prev_button_state = LOW;
int button_state;
unsigned long time_pressed = 0;
unsigned long time_released = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
button_state = digitalRead(BUTTON_PIN);
if(prev_button_state == HIGH && button_state == LOW)
time_pressed = millis();
else if(prev_button_state == LOW && button_state == HIGH) {
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration > LONG_PRESS_TIME )
Serial.println("A long press is detected");
}
prev_button_state = button_state;
}
버튼을 놓았을 때만 길게 누르는 이벤트가 감지됩니다.
const int BUTTON_PIN = 2;
const int LONG_PRESS_TIME = 1000;
int prev_button_state = LOW;
int button_state;
unsigned long time_pressed = 0;
bool is_pressing = false;
bool is_long_detected = false;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
button_state = digitalRead(BUTTON_PIN);
if(prev_button_state == HIGH && button_state == LOW) {
time_pressed = millis();
is_pressing = true;
is_long_detected = false;
} else if(prev_button_state == LOW && button_state == HIGH) {
is_pressing = false;
}
if(is_pressing == true && is_long_detected == false) {
long press_duration = millis() - time_pressed;
if( press_duration > LONG_PRESS_TIME ) {
Serial.println("A long press is detected");
is_long_detected = true;
}
}
prev_button_state = button_state;
}
버튼이 떼어지지 않았을 때만 길게 누르는 이벤트가 등록됩니다.
const int BUTTON_PIN = 2;
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
int prev_button_state = LOW;
int button_state;
unsigned long time_pressed = 0;
unsigned long time_released = 0;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
button_state = digitalRead(BUTTON_PIN);
if(prev_button_state == HIGH && button_state == LOW)
time_pressed = millis();
else if(prev_button_state == LOW && button_state == HIGH) {
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지됨");
if( press_duration > LONG_PRESS_TIME )
Serial.println("긴 누름이 감지됨");
}
prev_button_state = button_state;
}
※ NOTE THAT:
시리얼 모니터는 긴 누름이 있을 때 여러 번의 짧은 누름 감지를 표시할 수 있습니다. 이것은 버튼의 예상되는 동작이며 "차터링 현상"으로 언급됩니다. 이 문제에 대한 해결책은 이 튜토리얼의 마지막 부분에서 제공될 것입니다.
const int BUTTON_PIN = 2;
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
int prev_button_state = LOW;
int button_state;
unsigned long time_pressed = 0;
unsigned long time_released = 0;
bool is_pressing = false;
bool is_long_detected = false;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
button_state = digitalRead(BUTTON_PIN);
if(prev_button_state == HIGH && button_state == LOW) {
time_pressed = millis();
is_pressing = true;
is_long_detected = false;
} else if(prev_button_state == LOW && button_state == HIGH) {
is_pressing = false;
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration < SHORT_PRESS_TIME )
Serial.println("짧은 누름이 감지됨");
}
if(is_pressing == true && is_long_detected == false) {
long press_duration = millis() - time_pressed;
if( press_duration > LONG_PRESS_TIME ) {
Serial.println("긴 누름이 감지됨");
is_long_detected = true;
}
}
prev_button_state = button_state;
}
※ NOTE THAT:
시리얼 모니터에서 긴 입력을 했을 때 여러 번의 짧은 입력이 감지되는 것이 표시될 수 있습니다. 이는 버튼의 예상되는 동작이며 “차터링 현상”이라고 합니다. 이 문제는 이 튜토리얼의 마지막 부분에서 다루게 될 것입니다.
버튼에서 디바운싱을 구현하는 것은 여러 애플리케이션에서 필수적입니다.
디바운싱은 여러 버튼이 관련되어 있을 때 특히 복잡할 수 있습니다. 초보자를 위해 간단하게 만들기 위해, 저희는 ezButton이라는 라이브러리를 개발했습니다.
아래 코드에서 이 라이브러리를 사용할 것입니다.
#include <ezButton.h>
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
ezButton button(2);
unsigned long time_pressed = 0;
unsigned long time_released = 0;
void setup() {
Serial.begin(9600);
button.setDebounceTime(50);
}
void loop() {
button.loop();
if(button.isPressed())
time_pressed = millis();
if(button.isReleased()) {
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration < SHORT_PRESS_TIME )
Serial.println("A short press is detected");
if( press_duration > LONG_PRESS_TIME )
Serial.println("A long press is detected");
}
}
#include <ezButton.h>
const int SHORT_PRESS_TIME = 1000;
const int LONG_PRESS_TIME = 1000;
ezButton button(2);
unsigned long time_pressed = 0;
unsigned long time_released = 0;
bool is_pressing = false;
bool is_long_detected = false;
void setup() {
Serial.begin(9600);
button.setDebounceTime(50);
}
void loop() {
button.loop();
if(button.isPressed()){
time_pressed = millis();
is_pressing = true;
is_long_detected = false;
}
if(button.isReleased()) {
is_pressing = false;
time_released = millis();
long press_duration = time_released - time_pressed;
if( press_duration < SHORT_PRESS_TIME )
Serial.println("A short press is detected");
}
if(is_pressing == true && is_long_detected == false) {
long press_duration = millis() - time_pressed;
if( press_duration > LONG_PRESS_TIME ) {
Serial.println("A long press is detected");
is_long_detected = true;
}
}
}
비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.
버튼의 수를 최소화하기 위해 하나의 버튼에 여러 기능을 할당할 수 있습니다. 예를 들어, 짧게 누르는 것은 작동 모드를 전환하는 데 사용되며, 길게 누르는 것은 장치를 끄는 데 사용될 수 있습니다.
길게 누르기는 우발적인 활성화를 방지하기 위해 사용됩니다. 예를 들어, 일부 장치는 공장 초기화를 위한 버튼을 사용합니다. 만약 의도치 않게 눌러지면 위험할 수 있습니다. 이를 방지하기 위해, 장치는 버튼을 일정 시간(예: 5초) 동안 누르고 있어야만 공장 초기화가 실행되도록 설계되었습니다.