diff --git a/orchestrateur/main.py b/orchestrateur/main.py index e7b4983..e9dea1b 100644 --- a/orchestrateur/main.py +++ b/orchestrateur/main.py @@ -113,7 +113,7 @@ def on_microwave_change(state: MicrowaveState, field: MicrowaveStateFields): if state.cooking_state in (CookingStates.DONE, CookingStates.STIRRING_REQUIRED, CookingStates.ALERT): # Trigger buzzer for user attention beats = 5 if state.cooking_state == CookingStates.ALERT else (1 if state.cooking_state == CookingStates.STIRRING_REQUIRED else 3) - buzzer.buzzer_siren(beatsNb=beats) + buzzer.buzzer_siren(beats_nb=beats) elif state.cooking_state == CookingStates.DONE and state.state == MicrowaveState.COOKING: state.set_state(MicrowaveState.DONE) print(f"[{state.microwave_id}] Cooking finished. Waiting for user to remove dish.") @@ -275,17 +275,17 @@ async def rfid_listener_task(): TECHNICIAN_MODE = True print(f"[RFID] Card {tag_id} VALIDATED! -> TECHNICIAN_MODE = TRUE") # Optional: Sound positive feedback beep - buzzer.buzzer_siren(beatsNb=1) + buzzer.buzzer_siren(beats_nb=2) else: print(f"[RFID] Card {tag_id} REJECTED / Invalid.") # Optional: Sound error feedback beep - buzzer.buzzer_siren(beatsNb=2) + buzzer.buzzer_siren(beats_nb=4) except Exception as e: print(f"[RFID Task] Error reading RFID tag: {e}") # Sleep 100ms between checks to keep CPU usage near zero - await asyncio.sleep(0.1) + await asyncio.sleep(0.2) async def display_broadcast_worker_task(): """ diff --git a/orchestrateur/sensors/buzzer.py b/orchestrateur/sensors/buzzer.py index 49f5d23..78770c8 100644 --- a/orchestrateur/sensors/buzzer.py +++ b/orchestrateur/sensors/buzzer.py @@ -1,33 +1,45 @@ import time +import threading import grovepi from sensors.lock import grove_lock from shared import config -# Pin definition -BUZZER_PIN = 8 +BUZZER_PIN = 8 # Must be a PWM pin on GrovePi (D3, D5, D6, D8 support analogWrite) -grovepi.pinMode(BUZZER_PIN, "OUTPUT") -buzzer_state = 0 +# Initialize pin mode +try: + with grove_lock: + grovepi.pinMode(BUZZER_PIN, "OUTPUT") +except Exception as e: + print(f"[BUZZER] Init error: {e}") -def set_buzzer(state: int): - global buzzer_state - buzzer_state = state +def _siren_worker(beats_nb: int, delay: float): if not config.BUZZER_ACTIVATED: return - try: - with grove_lock: - grovepi.digitalWrite(BUZZER_PIN, state) - except Exception as e: - print(f"[BUZZER] Error occurred while setting buzzer state: {e}") -def buzzer_toggle(): - global buzzer_state - new_state = 1 - buzzer_state - set_buzzer(new_state) - -def buzzer_siren(beatsNb: int = 3, delay: float = 0.3): - for _ in range(beatsNb): - set_buzzer(1) - time.sleep(delay) - set_buzzer(0) - time.sleep(delay) \ No newline at end of file + with grove_lock: + try: + for _ in range(beats_nb): + # 1. Send single PWM write to start sound (Duty cycle ~128/255) + grovepi.analogWrite(BUZZER_PIN, 128) + time.sleep(delay) + + # 2. Send single PWM write to kill sound + grovepi.analogWrite(BUZZER_PIN, 0) + time.sleep(delay) + except Exception as e: + print(f"[BUZZER] Error during siren execution: {e}") + finally: + # Absolute safety reset + try: + grovepi.analogWrite(BUZZER_PIN, 0) + grovepi.digitalWrite(BUZZER_PIN, 0) + except Exception: + pass + +def buzzer_siren(beats_nb: int = 3, delay: float = 0.2, async_run: bool = True): + if async_run: + thread = threading.Thread(target=_siren_worker, args=(beats_nb, delay), daemon=True) + thread.start() + else: + _siren_worker(beats_nb, delay) \ No newline at end of file diff --git a/orchestrateur/sensors/camera.py b/orchestrateur/sensors/camera.py index b38bcd1..52e7aef 100644 --- a/orchestrateur/sensors/camera.py +++ b/orchestrateur/sensors/camera.py @@ -1,6 +1,3 @@ -import grovepi -import math -from sensors.lock import grove_lock from picamera2 import Picamera2, Preview import time