3.10. GPIO 입력¶
GPIO 핀에서 스위치(또는 임의의 디지털 신호)를 읽는 것은 다시 machine.Pin 을 거치는데, 이번에는 입력으로 구성됩니다. 인터페이스는 출력과 대칭적입니다: 모드를 구성한 다음, 메인 루프에서 핀의 값을 폴링하거나 값이 변할 때 발화하는 인터럽트 핸들러를 등록합니다.
3.10.1. 입력 구성하기¶
생성자에 Pin.IN 을 전달하고, 선택적으로 풀 저항을 전달합니다:
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
이는 P0 를 MCU의 내부 풀업 저항이 활성화된 입력으로 구성합니다. 핀에 아무것도 연결하지 않으면 풀업이 핀을 하이로 유지하고, 핀에서 접지로 가는 스위치를 닫으면 핀이 로우로 당겨집니다.
3.10.2. 값 읽기¶
인자 없이 value() 를 호출하면 현재 상태를 반환합니다 – 로우는 0, 하이는 1 입니다:
if button.value() == 0:
print("button pressed")
else:
print("button released")
메인 루프 패턴에서 폴링은 다음과 같습니다:
while True:
if button.value() == 0:
do_action()
time.sleep_ms(50)
50 ms의 슬립은 루프가 CPU를 최대로 사용하며 도는 것을 막아줍니다.
3.10.3. 인터럽트 기반 입력¶
폴링은 동작하지만, 메인 루프의 매 반복마다 CPU 시간이 듭니다. 드물게 변하는 입력 – 분당 한 번 누르는 버튼, 알람 신호 등 – 에 대해서는 irq() 가 핀이 변할 때만 실행되는 핸들러를 등록합니다.
핸들러는 인터럽트 컨텍스트 에서 실행되며, 이는 핸들러가 할 수 있는 일을 제약합니다:
메모리 할당 금지. 새 객체 – 리스트, 문자열, 예외, 포맷된 문자열 – 를 만드는 것은 힙이 잠겨 있기 때문에 ISR 내부에서 실패할 수 있습니다. 핸들러가 필요로 하는 버퍼는 모듈 범위에서 미리 할당하세요.
장시간 실행되는 작업 금지. 핸들러는 작업을 넘기고 반환해야 합니다. ISR 내부에서 실제 시간을 소비하면 다른 모든 것(다른 인터럽트, 메인 루프, USB 트래픽)이 지연됩니다.
촘촘한 ISR에서 출력 금지.
print()는 할당을 수행하고, UART에서 블록되며, 핸들러가 할 수 있는 가장 비싼 작업 중 하나입니다.
표준 패턴은 ISR이 micropython.schedule() 를 통해 실제 작업을 스케줄링 하는 것으로, 이는 다음 안전한 지점에 메인 컨텍스트로 돌아가 실행될 함수를 큐에 넣습니다:
import micropython
def handle_press(pin):
print("button pressed")
def on_press(pin):
micropython.schedule(handle_press, pin)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
ISR은 한 줄입니다: 콜백을 큐에 넣고 반환합니다. 그러면 handle_press 가 일반 컨텍스트에서 실행되며, 그곳에서는 할당, print(), 느린 I/O가 모두 다시 안전합니다.
trigger 인자는 어느 에지가 발화할지 선택합니다:
Pin.IRQ_FALLING– 1에서 0으로.Pin.IRQ_RISING– 0에서 1로.Pin.IRQ_FALLING|Pin.IRQ_RISING– 양쪽 에지 모두.