Chapter 5. 공간 인지 센서 제어 (초음파 센서, PIR 모션 센서)

주변 환경을 인식하는 두 가지 핵심 센서를 제어합니다. 거리를 재는 초음파 센서와 인간의 움직임을 잡아내는 인체 감지 센서입니다.

초음파 (HC-SR04) 물체 거리 = (시간 × 음속) / 2

5.1 HC-SR04 초음파 센서 거리 측정

Trig 핀으로 초음파를 쏘고 Echo 핀으로 되돌아오는 시간을 마이크로초(us) 단위로 정밀 측정하여 물체와의 거리를 cm 단위로 계산해 냅니다.

Pico 2 3V3 GP17 GP16 GND HC-SR04 T R Trig Echo VCC Trig Echo GND → 발사 트리거(OUT) ← 반사음 수신(IN)

HC-SR04: VCC→3V3, Trig→GP17(출력), Echo→GP16(입력), GND→GND. 안정적인 측정을 위해 VCC를 VSYS(5V) 핀에 연결하는 것을 권장합니다.

from machine import Pin
import time

# 핀 설정
trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)

def get_distance():
    # 1. Trig 핀을 깨끗하게 비운 뒤 10us 동안 초음파 발사 신호를 줍니다.
    trig.value(0)
    time.sleep_us(2)
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)

    # 2. Echo 핀이 High(1)로 올라가는 순간(시작 시간)을 기록합니다.
    while echo.value() == 0:
        signaloff = time.ticks_us()

    # 3. Echo 핀이 다시 Low(0)로 떨어지는 순간(도착 시간)을 기록합니다.
    while echo.value() == 1:
        signalon = time.ticks_us()

    # 4. 시간 차이를 계산하여 거리(cm)로 환산합니다. (음속 340m/s 반영)
    time_passed = signalon - signaloff
    distance = (time_passed * 0.0343) / 2
    return distance

while True:
    dist = get_distance()
    print(f"물체와의 거리: {dist:.1f} cm")
    time.sleep(0.5)

💡 왜 time_pulse_us() 대신 while문으로 시간을 직접 재나요?

MicroPython의 machine.time_pulse_us(echo, 1) 함수를 사용하면 위 코드의 2·3단계(Echo 핀의 상태 변화 감지)를 한 줄로 대체할 수 있습니다. 다만 원리를 이해하는 첫 학습 단계에서는 while 문으로 신호 시작·종료 시각을 직접 기록하는 방식이 "왜 초음파 센서가 시간을 측정하는지" 감을 잡기에 좋습니다. 아래는 time_pulse_us()를 사용한 더 안전한 버전입니다.

from machine import Pin
import machine
import time

trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)

def get_distance():
    trig.value(0)
    time.sleep_us(2)
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)

    # timeout(30000us)을 지정하면 물체가 없어 반사파가 오지 않을 때도
    # 프로그램이 멈추지 않고 -2(timeout) 등의 값을 반환합니다.
    duration = machine.time_pulse_us(echo, 1, 30000)
    if duration < 0:
        return None  # 측정 실패(범위 밖 또는 timeout)

    distance = (duration * 0.0343) / 2
    return distance

while True:
    dist = get_distance()
    if dist is None:
        print("측정 실패: 범위를 벗어났거나 물체가 없습니다.")
    else:
        print(f"물체와의 거리: {dist:.1f} cm")
    time.sleep(0.5)

time_pulse_us(pin, pulse_level, timeout_us)는 지정한 레벨(여기서는 1=High)이 유지되는 시간을 마이크로초 단위로 반환하며, while문과 달리 반사파가 아예 오지 않아도 무한정 멈추지 않고 timeout 후 음수를 반환합니다. 실전 프로젝트에서는 이 방식을 권장합니다.

거리 값이 이상하게 튀거나 측정되지 않는다면?
  • Trig와 Echo 핀이 서로 바뀌어 연결되지 않았는지 확인하기
  • 측정 대상 물체가 센서 정면 2cm~400cm 범위 안에 있는지 확인하기 (HC-SR04 공식 측정 범위)
  • 물체 표면이 소리를 잘 흡수하는 스펀지·천 등이면 반사파가 약해 오류가 날 수 있음
  • VCC를 3V3이 아닌 VSYS(5V)에 연결하면 더 안정적으로 동작하는 경우가 많음
  • 배선이 길거나 느슨하면 노이즈로 인해 값이 튈 수 있으니 점퍼선 연결 상태 점검하기

5.2 PIR 적외선 인체 감지 센서

사람이나 동물의 움직임으로 발생하는 적외선의 변화량을 측정하여 움직임 유무를 디지털 값(0 또는 1)으로 반환합니다.

Pico 2 3V3 GP18 GND PIR 센서 VCC OUT GND ← 감지 신호(IN)

PIR 센서: VCC→3V3, OUT→GP18(입력), GND→GND. 전원 인가 후 약 2초 안정화 시간이 필요하며, 3핀 모듈의 경우 왼쪽부터 VCC·GND·OUT 순서가 일반적입니다 (구매 제품의 핀 배열 확인 필수).

from machine import Pin
import time

# GPIO 18번에 PIR 센서의 Out 핀 연결
pir = Pin(18, Pin.IN)

print("침입 감지 시스템 가동중...")
time.sleep(2) # 센서 안정화를 위한 초기 대기

while True:
    if pir.value() == 1:
        print("🚨 경고: 구역 내 움직임이 감지되었습니다!")
        time.sleep(2) # 중복 경고 방지 대기
    else:
        print("안전 - 움직임 없음")
    time.sleep(0.5)

💡 PIR 센서의 원리 이해하기

PIR(Passive Infrared, 수동형 적외선)은 모든 물체가 방출하는 적외선 열복사량을 감지합니다. 사람이나 동물처럼 체온을 가진 물체가 센서 앞을 지나가면 감지 영역 내 적외선 양이 급격히 변하고, 이 변화를 센서 내부 회로가 감지해 OUT 핀을 HIGH(1)로 바꿉니다. 움직임이 없으면 OUT 핀은 LOW(0) 상태를 유지합니다. 카메라처럼 이미지를 분석하는 것이 아니라 "변화량"만 보기 때문에 매우 저렴하고 소비전력도 적습니다.

🏆 과제 해결해보기!

과제 1. 초음파 센서로 자동문 흉내내기

HC-SR04로 거리를 측정하여, 물체가 20cm 이내로 가까이 오면 "문이 열립니다!"를 출력하고, 그렇지 않으면 "문이 닫혀 있습니다."를 출력하는 코드를 작성해 보세요.

💻 정답 코드 보기
from machine import Pin
import machine
import time

trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)

def get_distance():
    trig.value(0)
    time.sleep_us(2)
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)
    duration = machine.time_pulse_us(echo, 1, 30000)
    if duration < 0:
        return None
    return (duration * 0.0343) / 2

while True:
    dist = get_distance()
    if dist is not None and dist <= 20:
        print("🚪 문이 열립니다! (거리: %.1f cm)" % dist)
    else:
        print("문이 닫혀 있습니다.")
    time.sleep(0.5)

과제 2. 초음파 + PIR 이중 보안 시스템

PIR 센서로 움직임이 감지되었을 때만 HC-SR04로 거리를 측정하여, 움직임이 있고 동시에 거리가 50cm 이내일 경우에만 "🚨 침입 경고!"를 출력하는 코드를 작성해 보세요. (두 센서를 함께 써서 오작동을 줄이는 실무 아이디어입니다.)

💻 정답 코드 보기
from machine import Pin
import machine
import time

trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)
pir  = Pin(18, Pin.IN)

def get_distance():
    trig.value(0)
    time.sleep_us(2)
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)
    duration = machine.time_pulse_us(echo, 1, 30000)
    if duration < 0:
        return None
    return (duration * 0.0343) / 2

print("이중 보안 시스템 가동중...")
time.sleep(2)  # PIR 안정화 대기

while True:
    if pir.value() == 1:
        dist = get_distance()
        if dist is not None and dist <= 50:
            print(f"🚨 침입 경고! (거리: {dist:.1f} cm)")
        else:
            print("움직임 감지됨 (거리 범위 밖)")
    else:
        print("안전 - 움직임 없음")
    time.sleep(0.5)

5.3 Wokwi 시뮬레이션으로 실습하기

Chapter 1의 1.8 실물 없이도 실습! Wokwi 온라인 시뮬레이터에서 소개한 대로, Wokwi를 사용하면 실제 HC-SR04나 PIR 센서가 아직 없어도 브라우저에서 바로 회로 동작을 확인할 수 있습니다.

📄 diagram.json 예시 (HC-SR04 + PIR)

Wokwi 프로젝트의 diagram.json 탭에 아래 내용을 붙여넣으면 Pico 2, 초음파 센서, PIR 센서가 자동으로 배치됩니다.

{
  "version": 1,
  "author": "picostudy",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-pi-pico", "id": "pico", "top": 0, "left": 0, "attrs": {} },
    { "type": "wokwi-hc-sr04", "id": "sr04", "top": -60, "left": 220, "attrs": {} },
    { "type": "wokwi-pir-motion-sensor", "id": "pir1", "top": 120, "left": 220, "attrs": {} }
  ],
  "connections": [
    [ "pico:GP17", "sr04:TRIG", "yellow", [] ],
    [ "pico:GP16", "sr04:ECHO", "cyan", [] ],
    [ "pico:3V3",  "sr04:VCC",  "red", [] ],
    [ "pico:GND",  "sr04:GND",  "black", [] ],
    [ "pico:GP18", "pir1:OUT",  "cyan", [] ],
    [ "pico:3V3",  "pir1:VCC",  "red", [] ],
    [ "pico:GND",  "pir1:GND",  "black", [] ]
  ]
}

회로를 구성한 뒤 main.py 탭을 열어 이 챕터에서 작성한 코드(5.1 또는 5.2의 코드)를 붙여넣고, 화면 상단의 ▶️ (초록색 재생) 버튼을 누르면 시뮬레이션이 시작됩니다. PIR 센서는 Wokwi 화면에서 클릭하면 움직임 감지를 흉내내는 체크박스가 나타나고, HC-SR04는 슬라이더로 가상의 물체 거리를 조절할 수 있습니다.

시뮬레이터 사용 시 주의사항

Wokwi 라이브러리의 부품 이름은 버전에 따라 조금씩 바뀔 수 있으므로, 부품 검색창에서 "HC-SR04", "PIR Motion Sensor" 등으로 직접 검색해 정확한 type 값을 확인하세요. 시뮬레이션은 실제 하드웨어의 미세한 오차(노이즈, 반사각 등)까지 완벽히 재현하지는 않으므로, 코드 로직 검증용으로 활용하고 최종 확인은 실제 부품으로 진행하는 것을 권장합니다.