이 블로그는 임베디드 컴퓨터를 이용한 장치(시스템) 개발과 원격제어에 필요한 지식을 공유 하기 위한 블로그 입니다.
실제 개발과 프로그램 예를 위하여 Microchip 사의 ATmega128를 사용한 보드와 Arduino Mega 보드(ATmega2560), Raspberry Pi Pico, Raspberry Pi, WiFi 모듈을 사용 합니다.

debouncing-keypad

Switch debouncing and Keypad
Switch debouncing 과 Keypad


  • Switch의 Bouncing 현상과 Debouncing 기술
    • Switch Interfacing
      • Switch Interfacing Circuit 예
        • Input Port(예: GP22)와 GND 사이에 Push Button Switch를 연결 한다.
        • GP22를 Input Port로 설정 한다.
        • Switch 가 Push 상태 일때 GP22는 0(Low) 상태가 되고,
        • Switch 가 Release 상태 일때 1(High) 상태가 된다.

        a) 외부 Pull Up 저항을 사용한 경우의 예.                       b) 프로세서 내부 Pull Up 저항을 사용한 경우의 예.


    • Switch를 닫(Closed)거나 개방(Open) 할 때 발생하는 Bouncing 현상
    • Switch의 금속 접점은 이상적이지 않기 때문에 Switch를 Closed 하거나 Open 하는 순간에 아래 그림과 같이 Bouncing 현상이 발생 한다.

      Bouncing은 Switch의 상태에 따라 대략 5mSec - 10mSec 사이에 발생 한다.

      Bouncing 신호는 장치 오동작의 중요한 요인 이다.


    • Hardware Debouncing
      • Hardware Debouncing circuits
      • 아래 그림a)와 같이 R-C Low Pass Filter 회로(Bouncing 신호는 Switch의 동작 속도에 비교 하면 높은 주파수 신호 이기 때문에 Low Pass Filter를 사용 하면 Bouncing 신호의 진폭만 크게 감소 한다.)를 사용 하면 Bouncing 신호의 진폭을 크게 감소 시킬 수 있다.

        그러나 a) 회로에서는 Switch가 닫이는 순간 Switch가 Open 상태에서 C에 충전되었던 전하가 아주 짧은 시간에 Switch를 통하여 방전되면서 Switch에 큰 순간 전류(회로를 손상 시키는 원인이 됨)가 흐르게 된다.

        Switch가 닫이는 순간 Switch에 흐르는 큰 전류에 의한 손상을 방지 하기 위하여 그림 b)와 같이 Switch와 직렬로 22옴 정도를 연결 한다.


        a) R-C Low Pass Filter와 Schmitt Trigger 회로를 사용한 Debouncing circuit


        b) 위 Debouncing circuit에서 발생하는 Switch 과도 전류 문제를 개선한 회로

      • Schmitt Trigger 회로에 의한 Debouncing
      • 아래 그림 b)와 같이 Bouncing 신호의 진폭을 R-C 회로를 사용하여 낮게 할 수 있다.

        그러나 R-C 회로를 통과한 Bouncing 신호의 진폭이 입력 Port의 Vt(Gate 입력의 Low(0) High(1)을 구분 하는 경계 전압) 보다 높을 수 있기 때문에 아래 그림 a)와 같은 전달 특성을 같는 Schmitt Trigger 회로를 사용 하여 Noise Margin을 크게 한다.

        그 결과 그림 b)에서와 같이 Switch 에서 발생한 Bouncing 신호를 R-C 회로와 Schmitt Trigger 회로를 사용 하여 그림 c)와 같이 제거 할 수 있게 된다.

        a) Schmitt Trigger 회로의 전달 특성


        b) Hardware Debouncing circuit의 입력 파형


        c) Hardware Debouncing circuit의 출력 파형


    • Software Debouncing
      • Time Delay를 이용한 Debouncing 예
      • MCU(MicroController Unit)의 실행 속도에 충분한 여유가 있는 경우, Switch가 동작(Closed or Open)한 순간으로 부터 Bouncing 현상이 없어지는 시간 만큼 Delay 한 후에 Switch의 상태를 읽는 방법(Software적인 방법)으로 Bouncing 현상을 제거 할 수 있다.

        아래 그림 a)는 Switch를 닫을 때(Press) 발생 하는 Bouncing 문제를 해결 하기 위한 예(Block diagram) 이고,

        그림 b)는 Switch를 개방(Release) 할 때 발생 하는 Bouncing 문제를 해결 하기 위한 예(Block diagram) 이다.

        a) Switch를 닫을 때(Press) Debouncing 예                       b) Switch를 개방 할 때(Release) Debouncing 예


      • Gadfly loop와 Time Delay를 이용한 Debouncing 예
      • 아래 Gadfly loop를 이용한 Debouncing 예는 위에서 설명한 Software debouncing 알고리즘을 개선한 방법 이다.

        a) Gadfly loop와 Time Delay를 이용한 Debouncing 예


        Time Delay를 이용한 Switch Debouncing 프로그램 예


      • External interrupt와 Timer interrupt를 이용한 Debouncing 예
      • External interrupt 입력 단자와 Timer interrupt를 사용 할 수 있는 Timer 가 있는 경우 아래와 같이 보다 효과 적으로 Bouncing 문제를 해결 할 수 있다. 이 방법을 이해 하기 위하여는 External interrupt와 Timer interrupt에 대한 이해가 필요 하다.

      • External interrupt service routine
        • External interrupt 입력 단자에 연결된 Switch를 동작(Press or Release) 시키면 External interrupt service routine이 실행 된다.
        • 원하지 않는 Bouncing 신호에 의하여 Interrupt Service Routine이 다시 실행 되지 않도록 External interrupt를 Disable 상태로 한다.
        • Timer interrupt에 사용 할 Timer의 Delay Time를 설정 한다. Timer의 Interrupt Service Routine은 여기서 설정한 Delay Time(약 10 - 16mSec) 후에 실행 된다.
        • External interrupt service routine의 실행을 종료 한다.
      • Timer interrupt service routine
        • External interrupt service routine에서 설정한 Delay Time 후에 Timer interrupt Service routine이 실행 된다.
        • Timer interrupt를 Disable 한다. Timer interrupt Routine은 다음 Switch 동작에 의하여 Switch External interrupt에서 Timer interrupt를 Enable 할 때 까지 실행 되지 않는다.
        • 새로운 Switch 동작에 의하여 External interrupt routine이 실행 될 수 있도록 External interrupt를 Enable 한다.
        • Switch의 상태(Pressed or Released)에 따른 동작을 실행 한다.
        • Timer interrupt service routine의 실행을 종료 한다.

        a) External interrupt이 발생 하였을 때의 처리                   b) Timer interrupt이 발생 하였을 때의 처리


        External interrupt와 Timer interrupt를 이용한 Switch Debouncing 프로그램 예


  • Keypad Interfacing
    • 4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예
      • 아래 그림의 예에서는 GP6 - GP9을 Output Port로 사용하고 GP2 - GP4를 Input Port로 사용 한다.
      • GP6 - GP9을 Output Port로 설정 한다.
      • GP2 - GP4를 Input Port로 설정 한다.
      • Key Scanning 방식을 이용하여 Keypad의 상태(어느 Key가 Push 되었는지 확인 하고 해당 Key의 Code를 Return 하는 getkey() 함수를 작성 한다.
      • Keypad 동작의 신뢰도를 높이기 위하여 Key 동작시 발생하는 Bouncing 문제를 고려 하여 프로그램을 작성 하여야 한다.(아래 프로그램 예를 참고 할 것.)

      a) Keypad와 Raspberry Pi Pico I/O Port Interfacing 회로도.           b) 4 by 3 Keypad Pin.


    • Key Scanning
      • 출력 Port GP6 - GP9에 0111 Code을 출력 하고 입력 Port GP2, GP3, GP4를 읽으면 1,2,3 Key가 눌린 경우에만(1,2,3 이외에 다른 Key가 눌린 경우에는 GP2, GP3, GP4 값이 1이 됨) 해당 위치의 Input port(GP2, GP3, GP4)의 값이 0이 된다.
      • 출력 Port GP6 - GP9에 1011 Code을 출력 하고 입력 Port GP2, GP3, GP4를 읽으면 4,5,6 Key가 눌린 경우에만(4,5,6 이외 다른 Key가 눌린 경우에는 GP2, GP3, GP4 값이 1이 됨) 해당 위치의 Input port(GP2, GP3, GP4)의 값이 0이 된다.
      • 위와 같이 출력 Port GP6 - GP9에 1101 Code을 출력 하고 입력 Port GP2, GP3, GP4를 읽으면 7,8,9 Key가 눌린 경우에만 해당 위치의 Input port(GP2, GP3, GP4)의 값이 0이 되고, GP6 - GP9에 1110 Code을 출력 하고 입력 Port PE4 - PE6 읽으면 *,0,# Key가 눌린 경우에만 해당 위치의 Input port(GP2, GP3, GP4)의 값이 0이 되기 때문에,
      • 순차적으로 출력 Port에 0111, 1011, 1101, 1110 Code을 출력 하면서 해당 Row에 있는 Key Switch의 상태를 읽어 어느 Key가 Press 되었는지 판단 한다.
      • Key input disable code: 출력 Port GP6 - GP9에 1111 Code을 출력하면 어떤 Key를 눌러도 입력 Port GP2, GP3, GP4의 값은 1이 된다. 이 기능은 어떤 Key를 눌러도 입력 신호가 발생하지 않도록(Key input interrupt가 발생하지 않도록)하는 목적으로 사용한다.
      • Key input detection code: 출력 Port GP6 - GP9에 0000 Code을 출력하면 전체 Key 중 어느 하나의 Key만 눌러도 입력 Port GP2, GP3, GP4 중 하나의 값이 0이 된다. 이 기능은 전체 Key 중 어느 하나의 Key만 눌려도 Key input interrupt가 발생(Key input detection)하도록 하기 위하여 사용한다.

      • 그림 a) 4 By 3 Keypad Interface 회로와 Scanning Code 예


    • key Switch를 press와 release 시 발생 하는 Bouncing 문제
    • Key Switch를 Press 하거나 Release 할 때 입력 Port에 발생 하는 파형 예(Bouncing 문제).


    • Key Switch를 Press 하거나 Release 할 때 입력 Port에 발생 하는 Bouncing 문제의 해결
      • Key Switch 접점의 불안정한 접속으로 Switch를 Press 하거나 Release 할 때 윗 그림과 같이 Bouncing 현상이 발생 한다.
      • Bouncing 문제를 해결하기 위하여는 전자회로 적인 접근(RC Low Pass Filter 이용한 Hardware Debouncing)과,
      • Bouncing 현상은 보통 16mSec 이내 에서 발생 하기 때문에 첫 Press 또는 Release 신호 발생 후 일정 시간(16mSec 정도) 후에 다시 Switch의 상태를 읽어 Press 또는 Release 상태를 판단 하는 기술(Software Debouncing)을 사용 한다.
  • Keypad programming 예:
    • Software debouncing을 사용하는 예
      • Keyoad 제어 프로그램과 테스트 프로그램을 하나의 파일로 작성한 예
        • 프로그램 예: get-keypad-soft.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
        • 실험 방법
          • "get-keypad-soft.py"를 다운로드하여 저장 한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 get-keypad-soft.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key를 누르면 Key code 문자가 Thonny IDE의 Python shell 창에 출력된다.
      • Keyoad 제어 프로그램을 library(별도 파일)로 작성한 예
        • Keyoad 제어 library 프로그램 예: keypadSoft.py



        • 실험을 위한 main 프로그램 예: keypad-soft-main.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
        • 실험 방법
          • Keyoad 제어 library 프로그램 "keypadSoft.py"를 다운로드하여 저장 한다.
          • 실험을 위한 main 프로그램 "keypad-soft-main.py"를 다운로드하여 저장 한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keypadSoft.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keypadSoft.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 keypad-soft-main.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key를 누르면 Key code 문자가 Thonny IDE의 Python shell 창에 출력된다.

    • External Interrupt와 Timer Interrupt를 사용하는 예
      • External Interrupt와 Timer Interrupt를 이용한 Key debouncing과 key scan 과정에서 발생 하는 문제
      • External Interrupt와 Timer Interrupt를 이용한 Keypad 제어 시 아래 그림과 같이 Scan enable, disable control 과정(Key를 누르고 있는 상태가 계속되는 상태에서 Key scanning 프로그램 이 실행 되는 경우)에서 원 하지 않는 펄스(S4)가 발생 할 수 있다. 이 신호의 Falling edge(p5)에서 External Interrupt Flag 가 Set 된다. 이 External Interrupt Flag에 의하여 External Interrupt가 실행 되지 않도록 Key scan을 진행하는 동안 External Interrupt를 Disable하고, Interrupt routine 이 종료 되기 전에 이 Flag를 Clear 하여야 한다.

      • Keyoad 제어 프로그램과 테스트 프로그램을 하나의 파일로 작성한 예
        • 프로그램 예: get-keypad-interrupt.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
        • 실험 방법
          • get-keypad-interrupt.py를 다운로드하여 저장 한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 get-keypad-interrupt.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key를 누르면 Key code 문자가 Thonny IDE의 Python shell 창에 출력된다.
      • Keyoad 제어 프로그램을 library(별도 파일)로 작성한 예
        • Keyoad 제어 library 프로그램 예: keypadInterrupt.py



        • 실험을 위한 main 프로그램 예: keypad-interrupt-main.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
        • 실험 방법
          • Keyoad 제어 library 프로그램 "keypadInterrupt.py"를 다운로드하여 저장 한다.
          • 실험을 위한 main 프로그램 "keypad-interrupt-main.py"를 다운로드하여 저장 한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keypadInterrupt.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keypadInterrupt.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 keypad-interrupt-main.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key를 누르면 Key code 문자가 Thonny IDE의 Python shell 창에 출력된다.

    • Keypad를 사용하여 실시간으로 장치를 제어하기 위한 예
      • Key를 누르는 순간 Key 값을 제어 프로그램에 전달하기 위하여 External Interrupt를 사용하고 Key debouncing은 Timer Interrupt(ONE_SHOT)를 사용하였다.

      • Keyoad 제어 프로그램을 library(별도 파일)로 작성한 예: keypad-command-main.zip
        • Keyoad 제어 library 프로그램 예: keypadCommand.py



        • Interrupt routine과 main 프로그램의 Data 공유를 위한 파일(Global variables sharing file) 예: keyDataGlobal.py



        • 실험을 위한 main 프로그램 예: keypad-command-main.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
        • 실험 방법
          • keypad-command-main.zip(keypadCommand.py, keyDataGlobal.py, keypad-command-main.py)을 다운로드하여 압축을 해제한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keypadCommand.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keypadCommand.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keyDataGlobal.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keyDataGlobal.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 keypad-command-main.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key를 누르면 Key code 문자가 Thonny IDE의 Python shell 창에 출력된다.

    • Keypad를 사용하여 실시간으로 LED를 제어하는 예
      • Key를 누르는 순간 Key 값을 제어 프로그램에 전달하여 LED를 제어(Key 값(0 - 9)에 해당되는 수 만큼 LED를 1초 간격으로 점멸)한다. '*'은 LED를 Turn off 하고 '#'은 LED를 Turn on 하는 Key로 사용한다.

      • Keyoad 제어 프로그램을 library(별도 파일)로 작성한 예: keypad-command-led-main.zip
        • Keyoad 제어 library 프로그램은 윗 예의 keypadCommand.py를 사용한다.
        • Interrupt routine과 main 프로그램의 Data 공유를 위한 파일(Global variables sharing file)은 윗 예의 keyDataGlobal.py를 사용한다.
        • 실험을 위한 main 프로그램 예: keypad-command-led-main.py



        • 실험을 위한 준비
          • 위 "4 by 3 Keypad와 Raspberry Pi Pico의 Interfacing 예"를 참고하여 Raspberry Pi Pico에 Keypad를 연결 한다.
          • 주: Raspberry Pi Pico는 GPIO25를 On-board LED 제어에 사용하고, Raspberry Pi Pico W는 WL_GPIO0(Infineon CYW43439의 GPIO0)를 On-board LED 제어에 사용한다.

        • 실험 방법
          • keypad-command-led-main.zip(keypadCommand.py, keyDataGlobal.py, keypad-command-led-main)을 다운로드하여 압축을 해제한다.
          • Thonny IDE를 실행하고 Thonny IDE의 사용 환경(Thonny 실행에 사용할 장치와 COM Port 선택)이 바르게 되어 있는지 확인한다.
          • Thonny IDE의 Python shell 창에 prompt( >>> )가 출력되었는 확인한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keypadCommand.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keypadCommand.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE의 "파일 -> 열기"를 실행하여 keyDataGlobal.py 파일을 Open 한다.
          • Thonny IDE의 "...(으)로 저장" 기능을 사용하여 keyDataGlobal.py 파일을 "MicroPython 장치"에 저장(Upload)한다.
          • Thonny IDE에서 "파일 -> 열기... -> 이 컴퓨터"를 실행하여 keypad-command-led-main.py를 Open 한다.
          • 실험
            • "실행 -> 현재 스크립트 실행"을 실행하거나 Toolbar의 "실행" Icon을 클릭하면 스크립트가 개발보드에 전송되고 프로그램이 실행된다.
            • 프로그램 전송이 종료된 다음 Python shell 창에 prompt( >>> )가 출력된 상태에서도 Pi Pico 보드의 프로그램은 실행되고 있는 상태이다.
            • Keypad의 Key('0' - '9')를 누르면 해당 Key의 숫자 만큼 LED가 점멸한다. '*' Key는 LED를 Turn off 하고 '#' Key는 LED를 Turn on 한다.


  • Switch debouncing 과 Keypad 관련 페이지 보기