2017년 5월 9일 화요일

아두이노 실습] 푸쉬버튼 long press, short press 판단하기

아두이노에서 푸쉬버튼 스위치의 long press와 short press를 구분하기 위해서는 스위치가 눌린 시간을 기록해 놓은 다음 눌린 스위치가 떨어질 때 스위치가 눌려있던 기간을 계산해 특정 시간보다 짧으면 short press, 길면 long press로 판단 해 주면 된다.



이번 실험을 위해 연결한 회로이다. 13번 핀에 시스템이 동작하는지 확인하기 위한  heartbeat LED를 연결 해 주고 4번 핀에 푸쉬버튼 스위치를 연결해 주었다. 4번 핀의 pinMode로 INPUT_PULLUP을 사용할 것이기 때문에 추가로 저항을 연결할 필요는 없다.

#define SW 4
#define RELEASED 0
#define SHORT_PRESS 1
#define LONG_PRESS  2
#define SW_THRESHOLD  500

#define HB_LED 13

void setup() {
  pinMode(HB_LED, OUTPUT);
  pinMode(SW, INPUT_PULLUP);
  Serial.begin(115200);
}

void loop() {
  static boolean hbLedStat = LOW;
  static unsigned long last;
  int swState = readSw();
 
  if (SHORT_PRESS == swState) {
    Serial.println("SWITCH SHORT PRESSED");
  } else if (LONG_PRESS == swState) {
    Serial.println("SWITCH LONG PRESSED");
  }
  if ((millis()-last) >= 500) {
    digitalWrite(HB_LED, hbLedStat);
    hbLedStat = !hbLedStat;
    last = millis();
  }
}

int readSw()
{
  static boolean prev = HIGH;
  static unsigned long last, pressed;
  boolean curr;

  if ((millis()-last) >= 10) {
    curr = digitalRead(SW);
    if ((HIGH==prev)&&(LOW==curr)) {
      pressed = millis();
      prev = LOW;
    } else if ((LOW==prev)&&(HIGH==curr)) {
      prev = HIGH;
      if ((millis()-pressed) > SW_THRESHOLD) {
        return LONG_PRESS;
      } else {
        return SHORT_PRESS;
      }
    }
    last = millis();
  }
  return RELEASED;
}


코드는 위와 같다. 프로그램이 실행되면 heartbeat LED는 1초 간격으로 계속 깜빡이고 스위치를 눌렀다 떼면 누르고 있던 시간 길이에 따라 short press, long press를 판정해 시리얼 포트로 결과를 출력해 준다.



댓글 5개:

  1. 여기서 숏스위치는 스위치를 땔때 감지하고 롱스위치는 버튼을 누르고 있을때 감지하게 하려면 어떡게 하나요?

    답글삭제
    답글
    1. 질문 자체가 이해가 잘 안되는군요. 버튼을 떼야만 얼마동안 눌려 있는가를 알 수 있으니까 short/long을 판단할 수 있죠.
      만일 원하시는게 짧게 눌렀다 떼면 short으로 판단하고, 일정시간 이상 누르고 있으면 떼지 않더라도 long으로 바로 판단하게 하고 싶은거라면 readSW 함수 내에 별도의 플래그를 하나 더 추가해줘야 하고 코드가 좀 더 지저분해집니다. LONG_PRESS를 리턴하는 부분을 현재 위치가 아니고 prev, curr이 둘 다 LOW일 때 판단하도록 옮겨줘야겠죠. 그리고 버튼을 한번 누르면 LONG_PRESS가 한번만 리턴되어야 하니까 그걸 위한 별도의 플래그 변수가 있어야 할테구요.

      삭제
  2. 위 코드에서 SHORT_PRESS는 버튼을 땔때 감지하고, LONG_PRESS는 버튼을 누르고 있을때 감지하게 하려면 어떡게 하나요?

    답글삭제
  3. HIGH==prev && LOW==curr 이 버튼에서 떼었을 때 인가요?
    그렇다면 왜 버튼을 눌렀을 순간까지의 시간경과에서 버튼을 뗀 순간의 시간경과를 빼주는건지 모르겠습니다ㅠㅠㅠ
    버튼을 뗀 순간의 시간경과에서 버튼을 눌렀을 때의 millis()를 빼줘야 얼마동안 눌려있는지 알수있는것아닌가요

    답글삭제
    답글
    1. HIGH==prev && LOW==curr 버튼이 눌러진 순간, LOW==prev && HIGH==curr 버튼이 떨어진 순간입니다.
      회로도를 보시면 알겠지만 버튼이 떨어져 있으면 HIGH, 눌려 있으면 LOW입니다. 그래서 버튼이 눌러졌을 때 시간을 pressed 변수에 기록 해 놓고, 버튼이 떨어진 순간에 millis()-pressed 로 눌려져 있던 시간을 계산합니다.

      삭제