from machine import Pin, PWM, I2C
from lcd1602 import LCD
import time
# --- 測定対象の距離範囲(cm) ---
MIN_DIST = 1
MAX_DIST = 50
# --- 白鍵15音(C4〜C6) ---
white_keys = [
("C4", 261), ("D4", 294), ("E4", 330), ("F4", 349), ("G4", 392),
("A4", 440), ("B4", 494), ("C5", 523), ("D5", 587), ("E5", 659),
("F5", 698), ("G5", 784), ("A5", 880), ("B5", 988), ("C6", 1047)
]
# --- 超音波センサー設定 ---
trig = Pin(17, Pin.OUT)
echo = Pin(16, Pin.IN)
# --- スピーカーPWM設定 ---
speaker = PWM(Pin(15))
speaker.duty_u16(0)
# --- LCD設定 ---
i2c = I2C(1, sda=Pin(18), scl=Pin(19), freq=400000)
lcd = LCD(i2c)
lcd.message("Distance Piano\n Loading...")
time.sleep(2)
lcd.clear()
# --- 距離を測る関数 ---
def measure_distance():
trig.low()
time.sleep_us(2)
trig.high()
time.sleep_us(10)
trig.low()
while echo.value() == 0:
pass
start = time.ticks_us()
while echo.value() == 1:
pass
end = time.ticks_us()
duration = time.ticks_diff(end, start)
dist_cm = duration * 0.0343 / 2
return max(MIN_DIST, min(MAX_DIST, dist_cm))
# --- 距離 → 音階変換 ---
def distance_to_note(cm):
step = (MAX_DIST - MIN_DIST) / (len(white_keys) - 1)
index = int((cm - MIN_DIST) / step)
index = max(0, min(len(white_keys) - 1, index))
return white_keys[index]
# --- メインループ ---
try:
last_lcd_update = time.ticks_ms()
while True:
dist = measure_distance()
note_name, freq = distance_to_note(dist)
# 音を更新(リアルタイム)
speaker.freq(freq)
# LCDの表示は0.5秒おきに更新
now = time.ticks_ms()
if time.ticks_diff(now, last_lcd_update) >= 500:
lcd.clear()
lcd.message("Dist:{:.1f}cm\nNote:{} ({}Hz)".format(dist, note_name, freq))
last_lcd_update = now
time.sleep(0.1)
# --- 停止処理 ---
finally:
speaker.duty_u16(0)
lcd.clear()
lcd.message("Stopped")
time.sleep(1)
lcd.closelight()