Files
dollcontrol/main_single.py
T
2026-03-25 10:40:43 +01:00

139 lines
3.3 KiB
Python

from machine import Pin, UART
import time
# ============================================================
# PIN-EMPFEHLUNGEN (Pico 2 W)
# ============================================================
# UART für DFPlayer-kompatibles MP3-Modul
UART_ID = 1
UART_TX_GPIO = 8 # Pico TX -> MP3 RX
UART_RX_GPIO = 9 # Pico RX <- MP3 TX
# Buttons (jeweils gegen GND, interner Pull-Up)
GPIO_CRY = 2
GPIO_WHIM = 3
GPIO_GIG = 4
GPIO_STOP = 5
GPIO_POOP = 10
# Pumpen-Ausgang (später Treiber/ULN2003 etc.)
GPIO_PUMP_OUT = 7
# ============================================================
# DFPLAYER / MP3-MODUL SETUP (laut Datenblatt 9600 baud, 3.3V TTL)
# ============================================================
uart = UART(
UART_ID,
baudrate=9600,
bits=8,
parity=None,
stop=1,
tx=Pin(UART_TX_GPIO),
rx=Pin(UART_RX_GPIO),
)
def dfplayer_cmd(cmd, param=0, feedback=False):
"""
DFPlayer Serial Protocol:
0x7E 0xFF 0x06 CMD FB PAR_H PAR_L CHK_H CHK_L 0xEF
"""
start = 0x7E
ver = 0xFF
ln = 0x06
fb = 0x01 if feedback else 0x00
ph = (param >> 8) & 0xFF
pl = param & 0xFF
checksum = -(ver + ln + cmd + fb + ph + pl) & 0xFFFF
ch = (checksum >> 8) & 0xFF
cl = checksum & 0xFF
packet = bytes([start, ver, ln, cmd, fb, ph, pl, ch, cl, 0xEF])
uart.write(packet)
def df_set_volume(vol):
"""Volume 0..30"""
vol = max(0, min(30, vol))
dfplayer_cmd(0x06, vol)
def df_play_mp3(track_no):
"""
Play track from /mp3 folder:
/mp3/0001.mp3 -> track_no=1
/mp3/0002.mp3 -> track_no=2
...
"""
dfplayer_cmd(0x12, track_no)
def df_stop():
"""Stop playback"""
dfplayer_cmd(0x16, 0)
def df_pause():
"""Pause (optional)"""
dfplayer_cmd(0x0E, 0)
def df_resume():
"""Resume (optional)"""
dfplayer_cmd(0x0D, 0)
# Kurze Boot-Wartezeit, damit Modul initialisieren kann
time.sleep_ms(800)
df_set_volume(30) # 0..30, ggf. anpassen
# ============================================================
# BUTTONS SETUP
# ============================================================
btn_cry = Pin(GPIO_CRY, Pin.IN, Pin.PULL_UP)
btn_whim = Pin(GPIO_WHIM, Pin.IN, Pin.PULL_UP)
btn_gig = Pin(GPIO_GIG, Pin.IN, Pin.PULL_UP)
btn_stop = Pin(GPIO_STOP, Pin.IN, Pin.PULL_UP)
btn_poop = Pin(GPIO_POOP, Pin.IN, Pin.PULL_UP)
# Entprellung
DEBOUNCE_MS = 80
last_ms = {
"cry": 0,
"whim": 0,
"gig": 0,
"stop": 0,
"pee": 0,
"poop": 0,
}
def is_pressed(pin: Pin) -> bool:
"""Active-low button"""
return pin.value() == 0
def allow(key: str) -> bool:
now = time.ticks_ms()
if time.ticks_diff(now, last_ms[key]) > DEBOUNCE_MS:
last_ms[key] = now
return True
return False
# ============================================================
# MAIN LOOP
# ============================================================
while True:
# STOP hat Priorität (soll sofort alles beenden)
if is_pressed(btn_stop) and allow("stop"):
df_stop()
# Sounds
if is_pressed(btn_cry) and allow("cry"):
df_play_mp3(1) # /mp3/0001.mp3
if is_pressed(btn_whim) and allow("whim"):
df_play_mp3(2) # /mp3/0002.mp3
if is_pressed(btn_gig) and allow("gig"):
df_play_mp3(4) # /mp3/0004.mp3
if is_pressed(btn_poop) and allow("poop"):
df_play_mp3(3) # /mp3/0003.mp3
time.sleep_ms(10)