import board, digitalio, time, pwmio
# ====================== PIN SETUP ======================
def init_io(pin, direction, pull=None):
io = digitalio.DigitalInOut(pin)
io.direction = direction
if pull is not None: io.pull = pull
return io
# Buttons: Arm (GP18-3v3), Reset (GP19-GND), Tilt Proxy (GP20-GND)
btn_arm = init_io(board.GP18, digitalio.Direction.INPUT, digitalio.Pull.DOWN)
btn_reset = init_io(board.GP19, digitalio.Direction.INPUT, digitalio.Pull.UP)
btn_tilt = init_io(board.GP20, digitalio.Direction.INPUT, digitalio.Pull.UP)
# LEDs
led_g = init_io(board.GP2, digitalio.Direction.OUTPUT)
led_r = init_io(board.GP3, digitalio.Direction.OUTPUT)
led_y = init_io(board.GP4, digitalio.Direction.OUTPUT)
# Buzzer (GP6) & Servo (GP15)
bz_pwm = pwmio.PWMOut(board.GP6, frequency=1000, duty_cycle=0, variable_frequency=True)
sv_pwm = pwmio.PWMOut(board.GP15, frequency=50)
# Ultrasonic
trig = init_io(board.GP16, digitalio.Direction.OUTPUT)
echo = init_io(board.GP17, digitalio.Direction.INPUT)
# ====================== FUNCTIONS ======================
def get_dist():
trig.value = True
time.sleep(0.00001)
trig.value = False
t1 = time.monotonic()
while not echo.value:
if time.monotonic() - t1 > 0.02: return 999
t2 = time.monotonic()
while echo.value:
if time.monotonic() - t2 > 0.02: return 999
return (time.monotonic() - t2) * 17150
def set_servo_angle(angle):
# Duty cycle calculation for Wokwi SG90 Servo
# 0 deg = ~1638, 180 deg = ~8192
duty = int(((angle / 180) * 6554) + 1638)
sv_pwm.duty_cycle = duty
# ====================== INITIAL STATE ======================
system_armed = False
alarm_active = False
print("--- INITIALIZING SERVO (CLOSE WINDOW) ---")
set_servo_angle(0)
time.sleep(1)
print("--- SYSTEM READY ---")
# ====================== MAIN LOGIC ======================
while True:
# --- PART 3: TILT OVERRIDE ---
if not btn_tilt.value:
print("[DEBUG] TILT DETECTED")
led_y.value = True
print("[DEBUG] ACTION: OPENING WINDOW")
set_servo_angle(180)
# Emergency Siren
for i in range(4):
bz_pwm.frequency, bz_pwm.duty_cycle = 3500, 32768
time.sleep(0.15)
bz_pwm.frequency, bz_pwm.duty_cycle = 2500, 32768
time.sleep(0.15)
bz_pwm.duty_cycle = 0
led_y.value = False
while not btn_tilt.value: pass
continue
# --- PART 1: ARMING ---
if not system_armed and btn_arm.value:
print("[DEBUG] ARMING SYSTEM")
system_armed = True
led_g.value = True
bz_pwm.frequency, bz_pwm.duty_cycle = 1200, 32768
time.sleep(0.2)
bz_pwm.duty_cycle = 0
while btn_arm.value: pass
# --- PART 2: INTRUSION ---
if system_armed:
dist = get_dist()
if dist < 50:
if not alarm_active:
print(f"[DEBUG] INTRUDER AT {dist:.1f} cm")
alarm_active = True
if alarm_active:
led_r.value = True
bz_pwm.frequency, bz_pwm.duty_cycle = 800, 32768
if not btn_reset.value:
print("[DEBUG] RESET PRESSED")
alarm_active = system_armed = False
led_r.value = led_g.value = bz_pwm.duty_cycle = 0
print("[DEBUG] ACTION: CLOSING WINDOW")
set_servo_angle(0)
time.sleep(0.5)
time.sleep(0.05)