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

debouncing-keypad-2560

Switch debouncing and Keypad interfacing
Switch debouncing 과 Keypad Interfacing


  • Switch의 Bouncing 현상과 Debouncing 기술
    • Switch Interfacing
      • Switch Interfacing Circuit 예
        • PD0와 GND 사이에 Push Button Switch를 연결 한다.
        • PD0를 Input Port로 설정 한다.
        • Switch 가 Push 상태 일때 PD0는 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 예
      • uP의 실행 속도에 충분한 여유가 있는 경우, 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 예


        Time Delay를 이용한 Switch Debouncing 프로그램 예(cho_sw_count_debouncing_2560). 아래 Code에는 Time delay function은 생략 되었다.


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

        a) Gadfly loop와 Time Delay를 이용한 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 프로그램 예


    • Debouncing 프로그램 예:

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

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


    • Key Scanning
      • 출력 Port PC4 - PC7에 0111 패턴을 출력 하고 입력 Port PB0, PB1, PB2를 읽으면 1,2,3 Key가 눌린 경우에만(1,2,3 이외에 다른 Key가 눌린 경우에는 PB0 - PB2 값이 1이 됨) 해당 위치의 Input port(PB0 - PB2)의 값이 0이 된다.
      • 출력 Port PC4 - PC7에 1011 패턴을 출력 하고 입력 Port PB0 - PB2 읽으면 4,5,6 Key가 눌린 경우에만(4,5,6 이외 다른 Key가 눌린 경우에는 PB0 - PB2 값이 1이 됨) 해당 위치의 Input port(PB0 - PB2)의 값이 0이 된다.
      • 위와 같이 출력 Port PC4 - PC7에 1101 패턴을 출력 하고 입력 Port PB0 - PB2를 읽으면 7,8,9 Key가 눌린 경우에만 해당 위치의 Input port(PB0 - PB2)의 값이 0이 되고, PC4-PC7에 1110 패턴을 출력 하고 입력 Port PB0 - PB2를 읽으면 *,0,# Key가 눌린 경우에만 해당 위치의 Input port(PB0 - PB2)의 값이 0이 되기 때문에,
      • 순차적으로 출력 Port에 0111, 1011, 1101, 1110 패턴을 출력 하면서 해당 Row에 있는 Key Switch의 상태를 읽어 어느 Key가 Press 되었는지 판단 한다.

      • 그림 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 예:
      • Keypad로 부터 입력되는 문자를 UART 통신을 통하여 모니터(Console)에 출력 하는 실험 구성도

      • 4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예: cho_keypad_basic_soft_2560.zip
      • Keypad 초기화 와 Key scaning 함수, get_key() 함수 예: get_keypad_soft_c.txt

        • 실험을 위한 준비
          • Arduino Mega 2560를 사용하는 경우 2560 Pin name과 Mega board pin name mapping table을 참고하여 신호선을 연결한다.

            참고자료: Arduino Mega 2560 PIN mapping table

          • 실험 구성도를 참고하여 개발보드에 Keypad를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 RXD와 Mega board의 TXD1(PD3)를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 TXD와 Mega board의 RXD1(PD2)를 연결한다.
          • 컴퓨터(USB --> UART(RS232) 변환 모듈)의 GND와 Mega board의 GND를 연결한다.
          • 주: UART1은 "USB --> UART(RS232) 변환 모듈"를 사용(USB Port를 Serial Port로 변환)하여 연결한다. Mega board의 UART0는 개발 Tool에서 사용하기 때문에 이 예서는 UART 통신 실험에 UART1을 사용한다.

            참고자료: USB - Serial 변환 모듈

        • 실험 방법
          • cho_keypad_basic_soft_2560.zip 파일을 Download하여 압축을 해제한다.
          • cho_keypad_basic_soft_2560.hex를 개발 보드에 Upload 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "KeyPad Input Testing" 메세지가 출력된다.
            • Keypad에서 문자를 입력하면 입력된 문자는 UART 통신을 이용하여 모니터에 출력된다.

      • 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가 실행 되지 않도록 Interrupt routine 이 종료 되기 전에 이 Flag를 Clear 하여야 한다.

      • 4 by 3 Keypad로 부터 Key 값을 읽어(get_key() 함수: External Interrupt와 Timer Interrupt를 사용 한다.) 그 결과를 모니터에 출력 한다. 예: cho_keypad_ext_time_int_2560.zip
      • Keypad 초기화 와 Key scaning 함수, get_key() 함수 예: get_keypad_ext_timer_interrupt_c.txt

        Timer의 Output Compare Match Interrupt를 이용한 Debouncing 예: get_keypad_timer3_interrupt_c.txt

        • 실험을 위한 준비와 실험 방법은 위 "4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예"를 참고바람.

      • 4 by 3 Keypad로 부터 Key 값을 읽어(External Interrupt와 Timer Interrupt를 사용 한다.) 모니터에 출력하는 프로그램으로 circular Buffer를 사용하고 Buffer overflow Testing 기능을 포함 한다. 예: cho_keypad_ext_int_time_buf_2560_V1.zip
        • 실험을 위한 준비와 실험 방법은 위 "4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예"를 참고바람.

      • 4 by 3 Keypad를 입력으로 모니터를 출력으로 사용하여 가산을 실행하는 프로그램(Microchip Studio 개발 환경) 예: cho_keypad_calculator_pointer_2560.zip
        • 실험을 위한 준비
          • 실험을 위한 준비는 위 "4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예"를 참고바람.
        • 실험 방법
          • cho_keypad_calculator_pointer_2560.zip 파일을 Download하여 압축을 해제하고 Project를 Build 한다.
          • cho_keypad_calculator_pointer_2560.hex를 개발 보드에 Upload 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "Input Format 예 : 12 + 23 = " 메세지가 출력된다.
            • Keypad에서 윗 예와 같이 숫자 와 연산자( * Key는 + 연산자이고 # Key는 = 연산자로 사용함)를 입력하면 연산 결과가 모니터에 출력된다.

      • 4 by 3 Keypad를 입력으로 모니터를 출력으로 사용하여 4칙 연산을 실행하는 프로그램(Microchip Studio 개발 환경) 예: keypad_multi_calculator_pointer_2560.zip
        • 실험을 위한 준비
          • 실험을 위한 준비는 위 "4 by 3 Keypad로 부터 Key 값을 읽어 모니터에 출력하는 프로그램 예"를 참고바람.
        • 실험 방법
          • keypad_multi_calculator_pointer_2560.zip 파일을 Download하여 압축을 해제하고 Project를 Build 한다.
          • keypad_multi_calculator_pointer_2560.hex를 개발 보드에 Upload 한다.
          • 실험:
            • 개발 보드의 Reset SW를 누르면 모니터에 "Input Format 예 : 12 =+ 23 = " 메세지가 출력된다.
            • Keypad에서 윗 예와 같이 첫번째 숫자를 입력하고 숫자가 아닌 문자(* Key와 # Key를 = 연산자로 사용함)를 입력하면 자동으로 Keypad가 연산자 입력 모드로 변경된다.
            • 연산자 입력 모드에서 연산자(+, -, *, /)를 입력하면 Keypad가 숫자 입력 모드로 변경된다.
            • Keypad에서 두변째 숫자를 입력하고 연산자(* Key와 # Key를 = 연산자로 사용함)를 입력하면 연산 결과가 모니터에 출력된다.

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