ATmega2560 인터럽트 디바운싱: 스위치 바운싱과 채터링 해결 방법
임베디드 시스템(아두이노, ATmega 등)을 이용한 작품에는 보통 버튼, 즉 스위치가 달려 있다. 이 스위치는 생각대로 동작하지 않는 경우가 많은데, 바운싱(Bouncing) 또는 채터링(Chattering) 현상 때문인 경우가 많다. 본 글에서는 실제 스위치의 바운싱 파형을 확인하고, 인터럽트를 이용해 오작동을 방지하는 소프트웨어 디바운싱 방법을 소개한다.
내가 만든 작품의 스위치가 이상한 이유?
아두이노나 AVR과 같은 임베디드 시스템에서 외부 스위치를 이용해 어떤 동작을 하도록 만들 때, 코드에는 전혀 문제가 없어도 스위치가 이상하게 동작하는 경우가 종종 있다. 대표적으로 아래와 같은 상황이다.
- 버튼이 동작했다가 안 했다가 한다: 어쩔 때는 불이 켜지고, 어쩔 때는 불이 안 들어온다. 내 손가락이 문제인가 싶어진다.
- 소리나 영상이 시작할 때 랙(Lag) 걸린 것처럼 버벅거린다: 동작이 부드럽게 시작하지 않고 시작 부분에서 멈칫하며 시작한다.
문제의 원인: 바운싱(Bouncing)과 채터링(Chattering)
스위치는 사용자의 물리적인 입력을 전기적 방식으로 아두이노나 AVR 같은 마이크로컨트롤러에게 전달해 주는 역할을 한다. 거창하게 썼지만, 그냥 떨어진 두 지점 사이를 붙였다가 떼었다가 하며 연결해 주는 막대기, 즉 접점이다. 때로는 눌러서(푸시 방식), 때로는 밀어서(슬라이드/토글 방식), 때로는 돌려서(로터리 방식), 아무튼 수단과 방법을 가리지 않고 떨어져 있던 두 지점을 연결해 준다.
문제는, 사람은 스위치를 한 번 꾸~욱 눌렀다고 생각하지만, 접점이 붙는 순간에는 기계적인 반동 때문에 여러 번 튀어 오르며(bounce) 붙었다 떨어지기를 반복한다는 것이다. 공을 바닥에 떨어뜨리면 여러 번 튀어 오르는 것과 같은 현상인데, 이는 스위치 구조상 피할 수 없는 물리적 특성이다. 이를 바운싱(Bouncing)이라 한다.
바운싱이 발생하면, 스위치의 출력은 그에 따라 빠르게 HIGH/LOW를 오르내리며 요동치게 된다. 이러한 전기적 신호의 불안정성을 채터링(Chattering)이라고 부른다. 즉, 바운싱은 기계적 원인이고 채터링은 그 결과로 나타나는 전기적 노이즈이다.
문제는 디지털 시스템이 이 불안정한 신호 변화를 모두 정상 입력으로 받아들인다는 점이다. 사용자는 버튼을 한 번 눌렀다고 생각하지만, 마이크로컨트롤러는 이 짧은 바운싱 구간 동안 발생한 변화를 수십 번의 입력 이벤트로 처리할 수 있을 만큼 빠르게 동작한다.
실제로 일어나는 현상
바운싱으로 인한 채터링은 마이크로컨트롤러에게 버튼을 짧은 시간에 수십 번 누른 것과 같은 상황을 만들어 준다. 아니, 마이크로컨트롤러 입장에서는 실제로 수십 번 스위치가 눌린 것이다. 그 결과, 아래와 같은 현상을 만들어 낸다.
- 버튼이 동작했다가 안 했다가 한다
실제로는 수십 번 동작한 상황인 것이다. 불을 켜고 끄는 스위치라면, 인간의 눈으로 감지하지 못할 만큼 빠른 속도로 꺼졌다 켜졌다를 반복한 것이다. 문제는 몇 번 눌렸는지 모른다는 점이다. 횟수가 맞으면 마지막 상태는 불이 켜진 상태가 될 것이고, 횟수가 맞지 않으면 불은 꺼진 상태가 될 것이다. 이 때문에 ‘어쩔 때는 버튼이 먹고, 어쩔 때는 안 먹는 것처럼‘ 느껴지게 된다.
- 소리나 영상이 시작할 때 랙(Lag) 걸린 것처럼 버벅거린다
실제로는 재생이 시작되는 그 짧은 찰나에 시작 명령이 수십 번 연속으로 실행된 것이다. 결과적으로 시작 부분이 수십 번 연속으로 겹치니, 영상 첫 장면이 랙이 걸린 것처럼 버벅거리거나, 효과음이 “다 했다!”가 아니라 “드드드다 했다!”처럼 재생된다.
도대체 얼마나 많은 바운싱이 발생하는가?
아래 그림은 본 필자가 방송신호 자동절체 제어기에 적용한 스위치인 NKK Switch사의 YB26WSKW01-2CF02-JB 토글식 푸시스위치를 이용해, 스위치 접점에서 실제로 어떤 일이 일어나는지 오실로스코프로 측정한 파형이다. 나름 꽤 비싼 스위치로, ‘딱 한 번’ 눌렀다.

- 노란색 파형 : 스위치의 물리적 출력 전압을 표시한다. 그래프가 위에 있을 때는 OFF 신호, 아래로 내려간 상태가 ON 신호를 출력하고 있는 것이다.
- 하늘색 파형 : 스위치가 ON 상태로 바뀌면 ATmega2560에서 프로그램이 실행된다. 그래프가 위로 올라가면 프로그램이 실행됐다는 의미다.
스위치 출력은 여러 번 요동치고 있으며, 하늘색 파형은 ATmega2560에서 인터럽트 루틴이 그만큼 반복 실행된 것을 보여준다. 몇 번 실행됐는지 세기도 싫다…
바운싱을 어떻게 막을 수 있을까?
아래와 같이 바운싱으로 인한 오작동 현상을 완화하기 위해 사용하는 여러 가지 방법이 있다.
- 고품질 스위치 사용: 물리적 구조가 정교한 스위치는 바운싱이 적게 발생한다.
- 콘덴서(Capacitor) 병렬 연결: 콘덴서는 순간적인 전압 변동을 완화하여 채터링을 줄여 준다.
- 래치(Latch) 회로 구성: SR 래치나 논리게이트를 이용해 바운싱 신호를 안정된 신호로 변환할 수 있다.
하지만 이들 방법은 결국 돈이 들어간다는 문제가 있다. 비싼 스위치를 선택하는 것은 당연하고, 콘덴서를 추가하거나 래치 회로를 구성하는 것은 추가적인 부품과 공간이 필요하다는 얘기다. 거기에 결정적으로, 이렇게 돈을 들여도 바운싱이라는 물리적 현상을 완전히 없애는 것은 불가능하다는 사실은 변하지 않는다. 스위치를 바꾸고 콘덴서를 달아도, 결국 바운싱은 형태와 횟수만 달라질 뿐 완전히 없어지지 않는다.
그렇기 때문에 대부분의 디지털 임베디드 시스템에서는 하드웨어 보완과 더불어, 소프트웨어적으로 바운싱을 처리하는 디바운싱(debouncing) 방법을 반드시 함께 사용한다. 그렇지 않으면 결국 내가 만든 시스템이 어떻게 동작할지 전혀 예상할 수 없는 랜덤박스가 되어 버린다.
바운싱이 끝날 때까지 기다린다.
소프트웨어적으로 바운싱을 처리하는 여러 가지 방법이 있지만 그중 가장 간단하고 추가 부품이 필요 없는, 즉 비용이 들지 않는 방식이 바로 지연시간(delay)을 이용한 디바운싱이다.
원리는 매우 단순하다. 스위치가 눌려서 입력값이 바뀌는 것을 감지하면 바운싱이 사라질 때까지 기다렸다가 입력을 확정하는 것이다. 즉, 스위치가 흔들리는 짧은 구간 동안의 입력 변화는 모두 무시하고, 안정된 상태가 되었을 때 한 번만 처리하도록 하는 방식이다. 별도의 하드웨어를 구성할 필요가 없기 때문에 임베디드 시스템에서 흔하게 사용되는 디바운싱 기법이다.
인터럽트 기반 지연시간 구현 예시
아래는 스위치의 변화를 감지하고 실행되는 인터럽트 루틴에 1ms의 지연시간을 추가한 코드이다. 인터럽트가 한 번 실행된 후 일정 시간 동안은 추가 입력을 무시하여 바운싱을 효과적으로 막는다.
ISR(PCINT0_vect)
{
PCICR = PCICR & 0xFE; // 실행하는 동안 다른 루틴이 실행되는 것을 막기 위해 인터럽트 비활성화
PORTA=0xff; // 불을 켜 보고
// 할거 하고
_delay_ms(1); // 스위치 입력을 1ms 동안 무시.
PCIFR = (1<<PCIF0); // 기다릴 만큼 기다렸으니, 인터럽트 플래그 해제
PCICR = PCICR | 0x01; // 인터럽트 다시 활성화
PORTA=0x00; // 불을 꺼 보자
}
실행 결과

노란색 파형을 보면 스위치의 출력 신호는 여전히 날뛰고 있는 것을 알 수 있다. 하지만 인터럽트 루틴이 실행된 것을 나타내는 하늘색 파형을 보면 인터럽트 루틴은 단 한 번만 실행되었다. 1ms의 지연시간으로 인해 입력 신호가 여러 차례 변화했음에도 불구하고, 모든 전기적 잡음(Chattering)이 무시되었기 때문이다. 스위치를 누른 횟수와 실제 동작한 횟수가 드디어 같아졌다!
장점과 단점
이 방식의 가장 큰 장점은 회로 변경 없이 소프트웨어만으로 바운싱 문제를 처리할 수 있다는 점이다. 콘덴서나 래치 회로 같은 추가 부품이 필요 없고, 코드만 수정하면 되기 때문에 비용도 들지 않는다. 일반적인 시스템에서 수 ms 정도의 지연은 스위치 사용이나 동작에 큰 문제가 되지 않는 경우가 대부분이기 때문에 매우 실용적이다.
하지만 분명한 단점도 있다. 지연시간을 추가하는 만큼 시스템의 반응 속도가 느려진다는 점이다. 즉각적인 입력 반응이 필요하거나 실시간 통신이 이루어지는 시스템 등에서는 사용하기 어렵다. 바운싱을 무시하는 동안 실제로 필요한 입력까지 함께 놓칠 수 있기 때문이다.
본 필자의 예는 지연 시간을 통해 바운싱을 회피하는 것을 보이기 위한 단순한 예시이다. 간단하고 시간에 대해 민감하지 않은 시스템이라면 훌륭한 회피 방법이지만, 마이크로컨트롤러 입장에서 1ms는 엄청나게 긴 시간이며, 그 시간 동안 다른 처리가 지연될 수 있다는 것을 항상 기억해야 한다.
그 외의 방법
인터럽트와 지연시간(Delay)을 사용하지 않고도 바운싱을 회피하는 여러 가지 방법들이 있다.
- 타이머(Timer) 방식
위의 인터럽트 지연 방식이 ‘일단 멈춤’이었다면, 타이머 방식은 ‘알람을 맞춘다’란 차이가 있다. 즉, 스위치 입력이 바뀌었을 때 그 자리에서 바로 1ms를 기다리는 것이 아니라, 1ms 뒤에 동작할 타이머를 실행해 둔다. 그리고 마이크로컨트롤러는 하던 일을 계속 하다가, 타이머 시간이 끝났을 때 다시 스위치 입력을 확인하고 필요한 동작을 수행한다.
- 상태 머신(State Machine) 방식
스위치의 현재 상태, 이전 상태, 안정화 시간을 변수로 관리하면서 입력이 일정 시간 이상 유지되었을 때만 최종 입력으로 인정하는 방식이다. 코드 구조는 조금 복잡해지지만, 버튼이 여러 개이거나 하나의 버튼으로 ‘짧게 누르기(클릭)’, ‘길게 누르기(롱프레스)’, ‘더블 클릭’ 같은 복잡한 인터랙션을 구현할 때 유리하다.
- 폴링(Polling) 방식
인터럽트를 사용하지 않고 일정한 주기로 스위치 상태를 읽는 방식이다. 구현이 단순하고 안정적이다. 다만 검사 주기가 너무 길면 반응이 늦어지고, 너무 짧으면 바운싱을 그대로 읽어 들일 수 있으므로 적절한 주기 설정이 필요하다.
- 하드웨어 디바운싱 병행
콘덴서, 저항, 슈미트 트리거, 래치 회로 등을 이용해 입력 신호를 먼저 안정화한 뒤 소프트웨어 디바운싱을 함께 적용하는 방식이다. 부품과 회로 공간이 추가로 필요하지만, 노이즈가 많은 환경이나 오동작이 치명적인 장치에서는 더 안정적인 방법이 될 수 있고 입력 신호가 하드웨어적으로 정돈되기 때문에, 소프트웨어 코드가 대기해야 하는 시간을 크게 줄일 수 있다.
FAQ
- 본문에 나온 인터럽트 지연 방식을 아두이노 우노(Uno)에도 적용할 수 있는가?
- 가능하다. 스위치 입력을 받는 모든 시스템에서 적용 가능하다. 단, 기본 원리는 같지만, 레지스터 설정 코드가 다르다. 본문의 예제는 ATmega2560(아두이노 메가)의 핀 변화 인터럽트(PCINT0)를 직접 제어하는 코드이다.
- 버튼을 한 번 눌렀는데 여러 번 입력되는 이유는?
- 스위치 접점이 바운싱을 일으키면 입력 신호가 짧은 시간 동안 HIGH와 LOW를 여러 번 오가게 된다. 마이크로컨트롤러는 이 변화를 각각의 입력 이벤트로 인식할 수 있기 때문에, 버튼을 한 번 눌러도 여러 번 누른 것처럼 동작할 수 있다.
- 고급 스위치를 사용하면 바운싱이 사라지는가?
- 고품질 스위치는 바운싱이 적게 발생할 수는 있지만, 바운싱이라는 물리적 현상을 완전히 없애기는 어렵다. 따라서 고급 스위치를 사용하더라도 하드웨어 또는 소프트웨어 디바운싱을 함께 고려하는 것이 좋다.
- 스위치 바운싱이란 무엇인가?
- 스위치 바운싱은 스위치 접점이 붙는 순간 기계적인 반동으로 인해 접점이 여러 번 붙었다 떨어지기를 반복하는 현상이다. 사람은 버튼을 한 번 눌렀다고 생각하지만, 실제 전기 신호는 짧은 시간 동안 여러 번 변화할 수 있다.
- 채터링과 바운싱은 같은 뜻인가?
- 엄밀히 말하면 바운싱은 스위치 접점에서 발생하는 기계적 현상이고, 채터링은 그 결과로 나타나는 전기적 신호의 불안정성이다. 다만 실제 현장에서는 두 표현을 거의 같은 의미로 혼용하는 경우가 많다.
- 1ms 지연시간이면 항상 충분한가?
- 항상 그렇지는 않다. 필요한 지연시간은 스위치의 종류와 상태에 따라 달라질 수 있다. 본 글의 예제에서는 1ms 지연으로 효과를 확인했지만, 실제 회로에서는 오실로스코프 측정이나 반복 테스트를 통해 적절한 값을 정하는 것이 좋다.
- 디바운싱은 하드웨어로 하는 것이 좋은가, 소프트웨어로 하는 것이 좋은가?
- 단순한 버튼 입력은 소프트웨어 디바운싱만으로도 충분한 경우가 많다. 하지만 노이즈가 많은 환경이거나 오동작이 치명적인 장치라면 콘덴서, 슈미트 트리거, 래치 회로 같은 하드웨어 디바운싱과 소프트웨어 디바운싱을 함께 사용하는 것이 더 안정적이다.
🔄 갱신 내역
- — 최초 게시
- — 주소 이전
- — 주소 이전 및 수정
- — 수정