# main.py
from machine import Pin, I2C, PWM, time_pulse_us
from time import sleep, sleep_us
from pico_i2c_lcd import I2cLcd
# ---------- 설정 ----------
TRIG_PIN = 17
ECHO_PIN = 16
I2C_SDA = 0
I2C_SCL = 1
BUZZER_PIN = 13
THRESH_CM = 30.0 # 경고 기준 거리 (cm)
MEASURE_INTERVAL = 0.8 # 초 단위 측정 간격
BUZZER_FREQ = 2000 # 경고음 기본 주파수(Hz)
BUZZER_DUTY = 32768 # 50% duty (0..65535)
# --------------------------
# 하드웨어 초기화
trigger = Pin(TRIG_PIN, Pin.OUT)
echo = Pin(ECHO_PIN, Pin.IN)
i2c = I2C(0, sda=Pin(I2C_SDA), scl=Pin(I2C_SCL), freq=100000)
# I2C 장치가 붙어있지 않으면 에러가 나므로 간단 체크
addrs = i2c.scan()
if not addrs:
raise RuntimeError("I2C 장치(예: LCD)를 찾을 수 없습니다. 배선 확인하세요.")
I2C_ADDR = addrs[0]
lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.duty_u16(0) # 초기 무음
# 보조: 내장 LED (선택)
led_onboard = Pin("LED", Pin.OUT)
led_onboard.value(0)
def measure_distance_cm():
# 초음파 트리거 신호
trigger.low()
sleep_us(2)
trigger.high()
sleep_us(10)
trigger.low()
try:
# echo가 HIGH로 머문 시간(마이크로초)
pulse = time_pulse_us(echo, 1, 300000) # 타임아웃 0.3s
# 음속 약 343 m/s -> 0.0343 cm/us, 왕복이므로 /2
distance = (pulse * 0.0343) / 2
return distance
except OSError:
# 타임아웃 등 에러 발생시 아주 먼 거리로 처리
return None
def alarm_on():
# 부저 켜기 (연속음)
buzzer.freq(BUZZER_FREQ)
buzzer.duty_u16(BUZZER_DUTY)
led_onboard.value(1)
def alarm_off():
buzzer.duty_u16(0)
led_onboard.value(0)
# 메인 루프
lcd.clear()
lcd.move_to(0,0)
lcd.putstr("Distance Monitor")
sleep(1)
while True:
dist = measure_distance_cm()
lcd.clear()
lcd.move_to(0,0)
if dist is None:
lcd.putstr("Distance: --.- cm")
lcd.move_to(0,1)
lcd.putstr("Status: no echo")
alarm_off()
else:
lcd.putstr("Distance:")
lcd.move_to(11,0)
lcd.putstr("{:5.1f}cm".format(dist))
lcd.move_to(0,1)
if dist <= THRESH_CM:
lcd.putstr("Status: ALERT! ")
alarm_on()
else:
lcd.putstr("Status: Normal ")
alarm_off()
# 시리얼에도 출력 (디버그용)
if dist is None:
print("거리 측정 실패(타임아웃)")
else:
print("Distance: {:.1f} cm".format(dist))
sleep(MEASURE_INTERVAL)