버튼과 디바운싱
한 줄 요약 — 기계 접점은 붙었다 떨어졌다를 수 ms 동안 반복합니다. 하드웨어나 소프트웨어로 걸러야 합니다.
채터링 (chattering)
기계식 스위치는 접점이 닿는 순간 튀면서 수 µs~수십 ms 동안 여러 번 ON/OFF를 반복합니다.
| 스위치 종류 | 채터링 시간 |
|---|---|
| 택트 스위치 | 1~10 ms |
| 토글 스위치 | 5~20 ms |
| 릴레이 접점 | 1~5 ms |
| 마이크로 스위치 | 1~5 ms |
결과: 한 번 눌렀는데 여러 번 눌린 것으로 인식됩니다.
하드웨어 디바운싱
1. RC 필터 + 슈미트 트리거
| 부품 | 어디에 붙나 | 하는 일 |
|---|---|---|
| (10 kΩ) | VCC ↔ 버튼 노드 | 버튼을 안 눌렀을 때 노드를 High로 올린다 |
| 버튼 | 그 노드 ↔ GND | 누르면 노드를 GND로 끌어내린다. 접점이 튀면서 여러 번 붙었다 떨어진다 |
| R (10 kΩ) | 버튼 노드 ↔ 출력 | C와 함께 시정수시정수 time constantRC 회로가 목표값까지 63%를 가는 데 걸리는 시간으로, 회로의 빠르기를 한 숫자로 나타냅니다.자세히 보기 →를 만든다 |
| C (100 nF) | 출력 ↔ GND | 빠른 채터링을 못 따라오게 한다. 출력은 완만하게만 움직인다 |
| 슈미트 입력 | 출력 ↔ MCU | 완만해진 파형을 다시 깔끔한 디지털 에지로 바꾼다 |
tau시정수time constantsC정전용량capacitanceFR저항resistanceΩ설계 기준: 채터링 시간 / 3 정도. 10 ms 채터링이면 = 3~10 ms.
⚠️ 슈미트 트리거(Schmitt trigger) 입력이 필수입니다. 일반 CMOS 입력에 느린 에지를 넣으면 문턱 근처에서 발진합니다. 대부분의 MCU GPIO는 슈미트 입력이지만 데이터시트로 확인하세요.
2. RS 래치 (SPDT 스위치)
3단자 스위치와 NAND 래치로 완벽하게 디바운스합니다. 접점이 어느 한쪽에 처음 닿는 순간 래치가 걸려 이후 튐을 무시합니다.
장점: 지연 없음, 완벽 단점: SPDT 스위치 필요, 부품 증가
소프트웨어 디바운싱
1. 지연 후 재확인
if (읽기() == 눌림) {
delay(20ms);
if (읽기() == 눌림) {
// 확정
}
}간단하지만 blocking이라 실시간 시스템에 부적합합니다.
2. 주기적 샘플링 + 카운터 (권장)
// 1 ms 타이머 인터럽트에서
if (읽기() == 눌림) {
if (count < THRESHOLD) count++;
} else {
if (count > 0) count--;
}
state = (count >= THRESHOLD);비블로킹이고 노이즈에도 강합니다. THRESHOLD를 20으로 잡으면 20 ms 디바운싱입니다.
3. 시프트 레지스터 방식
history = (history << 1) | 읽기();
if ((history & 0xFF) == 0xFF) 눌림_확정();
if ((history & 0xFF) == 0x00) 뗌_확정();연속 8회 같은 값일 때만 인정합니다.
⚖️ 부품 트레이드오프
| 방식 | ✅ 좋아지는 것 | ⚠️ 나빠지는 것 |
|---|---|---|
| RC + 슈미트 | 하드웨어에서 해결, CPU 부담 0, 노이즈도 함께 제거 | 부품 2개, 지연, 커패시터 방전 전류 |
| RS 래치 | 지연 없음, 완벽 | SPDT 스위치 + 게이트 필요 |
| 소프트웨어 (카운터) | 부품 0, 유연(임계값 조정) | CPU 자원, 노이즈 펄스가 GPIO에 그대로 들어옴 |
| 소프트웨어 (지연) | 가장 간단 | 블로킹, 실시간성 저하 |
💡 측정 시스템에서는 하드웨어 RC를 권장합니다. 이유는 디바운싱보다 노이즈 필터링 때문입니다. 긴 배선(trace)의 버튼은 안테나가 되어 노이즈를 주워오는데, RC 필터가 그것도 함께 막아줍니다.
🔌 실제 쓰임새
| 상황 | 권장 |
|---|---|
| 일반 UI 버튼 | 소프트웨어 (카운터) |
| 긴 배선의 버튼 | RC 필터 필수 (노이즈) |
| 인터럽트로 받는 버튼 | RC 필수 (인터럽트가 여러 번 걸림) |
| 안전 정지 스위치 | 하드웨어 + 소프트웨어 이중 |
| 로터리 엔코더 | RC + 상태 머신 |
| 릴레이 접점 입력 | RC + 광절연 고려 |
⚠️ 인터럽트로 버튼을 받을 때는 반드시 하드웨어 디바운싱을 하세요. 채터링이 인터럽트를 수십 번 발생시켜 시스템이 마비될 수 있습니다.
시뮬레이션으로 확인
# examples/10-mcu-interfacing/debounce-rc.yaml
meta:
name: RC 디바운싱 필터
lesson: docs/10-mcu-interfacing/02-debouncing.md
note: 채터링을 펄스열로 모사하고 RC가 걸러내는지 본다
components:
- {ref: VDD, type: vdc, value: 3.3}
- {ref: RP, type: r, value: 10k, label: 풀업}
- {ref: RF, type: r, value: 10k, label: 필터 저항}
- {ref: CF, type: c, value: 100n, label: 필터 커패시터}
- {ref: SW, type: sw, model: SW_IDEAL}
- {ref: VC, type: vpulse, params: {v1: 0, v2: 5, td: 1m, tr: 1u, tf: 1u, pw: 0.2m, per: 0.5m}}
nets:
VP: [VDD.p, RP.1]
BTN: [RP.2, SW.1, RF.1]
OUT: [RF.2, CF.1]
CTL: [VC.p, SW.cp]
GND: [VDD.n, SW.2, SW.cn, CF.2, VC.n]
analyses:
- {type: tran, tstep: 10u, tstop: 10m}BTN은 빠르게 튀지만 OUT은 완만하게 변하는 것을 확인하세요.
⚠️ 이상과 실제의 차이
| 이상 | 실제 |
|---|---|
| 접점이 즉시 붙음 | 수 ms 채터링 |
| 채터링 시간이 일정 | 스위치 개체·마모·온도에 따라 변동 |
| RC만으로 충분 | 슈미트 입력이 없으면 발진 |
| 버튼은 노이즈원이 아님 | 긴 배선은 안테나, ESD 유입 경로 |
연습문제
문제 1. 채터링 15 ms인 스위치에 RC 디바운싱을 설계하세요. = 10 kΩ이면 는?
풀이
ms 정도로 잡으면:
mu이동도mobilitym²/V·stau시정수time constantsC정전용량capacitanceFR저항resistanceΩ470 nF 또는 1 µF 선택.
⚠️ 너무 크게 하면 버튼 반응이 느껴질 정도로 느려집니다. 50 ms를 넘지 않게 하세요.
문제 2. 1 ms 타이머로 소프트웨어 디바운싱을 합니다. 20 ms 디바운싱을 원하면 카운터 임계값은? 그리고 이 방식의 장점은?
exercises/10-02-debounce-20ms.yaml풀이
임계값 = 20 (1 ms × 20 = 20 ms)
장점:
- 비블로킹 — CPU가 다른 일을 할 수 있음
- 노이즈 내성 — 단발 노이즈 펄스는 카운터를 조금 올릴 뿐 임계값에 도달하지 못함
- 히스테리시스(hysteresis)히스테리시스 hysteresis켜지는 문턱과 꺼지는 문턱을 일부러 벌려 두어, 경계에서 덜덜 떠는 것을 막는 장치입니다.자세히 보기 → 효과 — 올릴 때와 내릴 때 임계값을 다르게 하면 더 안정
- 임계값을 런타임에 조정 가능
개선: 상승/하강 임계값을 다르게 (예: 눌림 20, 뗌 5) 하면 반응이 빠르면서도 안정적입니다.
이전 ← 01 GPIO 입출력 | 다음 → 03 ADC 입력 설계