2.3 외부 인터럽트

c{mpy02p03}

 NodeMCU모듈의 16번 핀을 제외한 GPIO핀들에 외부 인터럽트 핸들러를 붙여줄 수 있다. 예를 들어서 GPIO4 핀에 택스위치를 GND와 직결한 다음 풀업레지스터를 연결하여 FALLING EDGE를 검출하는 예제는 다음과 같다.


from machine import Pin
p4 = Pin(4, Pin.IN, Pin.PULL_UP)

# 인터럽트핸들러
# 인터럽트가 발생한 Pin 객체가 넘어온다.
def callback(pin):
   print('falling ',pin)

p4.irq(trigger=Pin.IRQ_FALLING,handler=callback)

먼저 Pin 객체를 입력+풀업저항으로 설정한 후 그 객체의 irq 메서드를 이용하여 인터럽트의 종류와 핸들러를 설정할 수 있다. 그리고 irq()  함수의 trigger 인수는 다음과 같이 세 가지로 설정할 수 있다.


trigger 인수

동작

Pin.IRQ_FALLING

핀이 1에서 0올 떨어질때 handler 호출

Pin.IRQ_RISING

핀이 0에서 1로 올라갈때 handler 호출

Pin.IRQ_RISING | Pin.IRQ_FALLING

두 경우 모두 handler 호출


이렇게 지정하면 해당하는 경우에 handler 인수로 지정해둔 함수가 호출된다. hadler의 인수로는 Pin 객체가 넘어온다.


 주의할 점은 동일한 핀에 IRQ_RISING과 IRQ_FALLING에 각각 다른 handler를 붙여줄 수 없다는 점이다. 하지만 위 표에서와 같이 두 경우 중 하나가 발생했을 때 모두 동일한 handler를 붙여줄 수 있으므로 그 함수 안에서 pin.value() 함수값을 읽으면 어떤 인터럽트가 발생했는지 확인할 수 있으므로 각각을 다르게 처리할 수는 있을 것이다.


 만약 기계식 접점에서 발생하는 인터럽트라면 채터링(chattering)현상으로 인해서 누를 때마다 여러 번의 인터럽트가 발생할기 쉽다. 이러한 채터링 현상을 제거하는 것을 디바운싱(debouncing)이라고 하는데 다음과 같이 간단히 프로그램으로 해결할 수 있다.


from machine import Pin
import time
p4 = Pin(4, Pin.IN, Pin.PULL_UP)

def callback(pin):
   time.sleep_ms(150)
   if pin.value()==0:
       #아래에 실제 처리할 코드를 넣는다.
       print('falling ',pin)

p4.irq(trigger=Pin.IRQ_FALLING,handler=callback)

여기에서 사용하는 방법은 채터링이 사라질 때까지 기다린 다음 핀의 값을 읽어서 여전히 0이라면 FALLING 인터럽트가 실제로 일어났다고 판단하는 것이다. 만약 RISING 인터럽트의 경우는 기다린 후 pin.value()가 아직도 1인지를 검사하면 될 것이다. 채터링이 사라지는  시간은 대락 100~200ms 정도로 알려져 있으므로 기다리는 시간은 적당히 설정하면 된다.


 외부 인터럽트는 실행하고 있는 모든 일을 중단시키고 즉시 handler 함수를 호출하며 메모리 할당 등은 할 수 없다. 또한 handler 함수는 되도록 짧고 간결하게 작성하여야 한다.

(현 시점에서 RISING 인터럽트 동작은 문제가 있는 것 같다.)



Posted by 살레시오
,