import board
import digitalio
import analogio
import pwmio
import time
# ================================================================
# PIN SETUP
# ================================================================
# --- Inputs ---
btn_arm = digitalio.DigitalInOut(board.GP0)
btn_arm.switch_to_input(pull=digitalio.Pull.UP)
btn_stop = digitalio.DigitalInOut(board.GP5)
btn_stop.switch_to_input(pull=digitalio.Pull.UP)
pir = digitalio.DigitalInOut(board.GP4)
pir.switch_to_input()
ldr_adc = analogio.AnalogIn(board.GP26)
ldr_dig = digitalio.DigitalInOut(board.GP16)
ldr_dig.switch_to_input()
# --- Outputs ---
buzzer = pwmio.PWMOut(board.GP2, frequency=2000, duty_cycle=0, variable_frequency=True)
led_green = digitalio.DigitalInOut(board.GP3)
led_green.direction = digitalio.Direction.OUTPUT
led_red = digitalio.DigitalInOut(board.GP6)
led_red.direction = digitalio.Direction.OUTPUT
led_yel = digitalio.DigitalInOut(board.GP17)
led_yel.direction = digitalio.Direction.OUTPUT
# --- Stepper Motor Coil Pins ---
coil_Am = digitalio.DigitalInOut(board.GP18)
coil_Am.direction = digitalio.Direction.OUTPUT
coil_Ap = digitalio.DigitalInOut(board.GP19)
coil_Ap.direction = digitalio.Direction.OUTPUT
coil_Bp = digitalio.DigitalInOut(board.GP20)
coil_Bp.direction = digitalio.Direction.OUTPUT
coil_Bm = digitalio.DigitalInOut(board.GP21)
coil_Bm.direction = digitalio.Direction.OUTPUT
# ================================================================
# SETTINGS
# ================================================================
STEPS_PER_REV = 200
STEP_DELAY = 0.002 # 2ms in seconds
LUX_THRESHOLD = 100
PIR_SETTLE = 0.3 # 300ms in seconds
DEBOUNCE_ARM = 0.05 # 50ms
DEBOUNCE_STP = 0.02 # 20ms
# Full-step sequence: [A-, A+, B+, B-]
STEP_SEQUENCE = [
[True, False, True, False], # Step 1
[False, True, True, False], # Step 2
[False, True, False, True ], # Step 3
[True, False, False, True ], # Step 4
]
# ================================================================
# SYSTEM STATE
# ================================================================
armed = False
# ================================================================
# STARTUP — all outputs off
# ================================================================
led_green.value = False
led_red.value = False
led_yel.value = False
buzzer.duty_cycle = 0
coil_Am.value = False
coil_Ap.value = False
coil_Bp.value = False
coil_Bm.value = False
print("Security system starting... System is DISARMED.")
# ================================================================
# MAIN LOOP
# ================================================================
while True:
# ============================================================
# SECTION: ARM / DISARM BUTTON CHECK (GPIO 0)
# ============================================================
if btn_arm.value == False: # Button pressed (LOW)
time.sleep(DEBOUNCE_ARM) # Wait 50ms debounce
if btn_arm.value == False: # Confirm still pressed
while btn_arm.value == False: # Wait for release
pass
if armed == False:
# --- ARM THE SYSTEM ---
armed = True
# Turn off all LEDs then turn on green
led_green.value = False
led_red.value = False
led_yel.value = False
led_green.value = True
# --- CHIRP: 1000Hz → 1500Hz → 2000Hz ---
buzzer.frequency = 1000
buzzer.duty_cycle = 32768
time.sleep(0.05)
buzzer.frequency = 1500
time.sleep(0.05)
buzzer.frequency = 2000
time.sleep(0.05)
buzzer.duty_cycle = 0 # Buzzer OFF
print("System ARMED.")
else:
# --- DISARM THE SYSTEM ---
armed = False
# Turn off all LEDs
led_green.value = False
led_red.value = False
led_yel.value = False
# --- CHIRP: 1000Hz → 1500Hz → 2000Hz ---
buzzer.frequency = 1000
buzzer.duty_cycle = 32768
time.sleep(0.05)
buzzer.frequency = 1500
time.sleep(0.05)
buzzer.frequency = 2000
time.sleep(0.05)
buzzer.duty_cycle = 0 # Buzzer OFF
print("System DISARMED.")
# ============================================================
# SECTION: SENSOR CHECKS (only when armed)
# ============================================================
if armed == True:
# --------------------------------------------------------
# PIR MOTION SENSOR CHECK (GPIO 4)
# --------------------------------------------------------
if pir.value == True: # Motion detected
print("PIR: Motion detected! Alarm triggered.")
# a. Turn off all LEDs
led_green.value = False
led_red.value = False
led_yel.value = False
# b. Turn on red LED
led_red.value = True
# c. Wait for PIR and button state to settle
time.sleep(PIR_SETTLE)
# d. Turn on buzzer at 2000 Hz continuously
buzzer.frequency = 2000
buzzer.duty_cycle = 32768
# e. Wait until reset button (GPIO 5) is pressed
print("PIR: Waiting for alarm reset...")
while True:
if btn_stop.value == False: # Button pressed (LOW)
time.sleep(DEBOUNCE_STP) # Wait 20ms debounce
if btn_stop.value == False: # Confirm still pressed
while btn_stop.value == False: # Wait for release
pass
break # Exit wait loop
time.sleep(0.01)
# f. Turn off buzzer
buzzer.duty_cycle = 0
# g. Turn on green LED
led_green.value = False
led_red.value = False
led_yel.value = False
led_green.value = True
print("PIR: Alarm cleared.")
# --------------------------------------------------------
# LDR LIGHT SENSOR CHECK (GPIO 26 / GPIO 16)
# Only runs if PIR did NOT detect motion
# --------------------------------------------------------
else:
# --- Read lux from ADC ---
raw = ldr_adc.value # 0–65535
voltage = (raw / 65535) * 3.3
if voltage == 0:
lux = 0.0
else:
r_ldr = 10000 * (3.3 - voltage) / voltage
if r_ldr == 0:
lux = 9999.0
else:
lux = 500 / (r_ldr / 1000)
# --- Check if light is detected ---
if ldr_dig.value == True or lux >= LUX_THRESHOLD:
print("LDR: Light detected! Alarm triggered.")
# a. Turn off all LEDs
led_green.value = False
led_red.value = False
led_yel.value = False
# b. Turn on yellow LED
led_yel.value = True
# c. Move stepper motor 90 degrees CLOCKWISE
print("LDR: Moving stepper 90 degrees CW.")
steps_to_move = int((90 / 360) * STEPS_PER_REV) # = 50 steps
step_count = 0
while step_count < steps_to_move:
# Step 1: A-=1, A+=0, B+=1, B-=0
coil_Am.value = STEP_SEQUENCE[0][0]
coil_Ap.value = STEP_SEQUENCE[0][1]
coil_Bp.value = STEP_SEQUENCE[0][2]
coil_Bm.value = STEP_SEQUENCE[0][3]
time.sleep(STEP_DELAY)
# Step 2: A-=0, A+=1, B+=1, B-=0
coil_Am.value = STEP_SEQUENCE[1][0]
coil_Ap.value = STEP_SEQUENCE[1][1]
coil_Bp.value = STEP_SEQUENCE[1][2]
coil_Bm.value = STEP_SEQUENCE[1][3]
time.sleep(STEP_DELAY)
# Step 3: A-=0, A+=1, B+=0, B-=1
coil_Am.value = STEP_SEQUENCE[2][0]
coil_Ap.value = STEP_SEQUENCE[2][1]
coil_Bp.value = STEP_SEQUENCE[2][2]
coil_Bm.value = STEP_SEQUENCE[2][3]
time.sleep(STEP_DELAY)
# Step 4: A-=1, A+=0, B+=0, B-=1
coil_Am.value = STEP_SEQUENCE[3][0]
coil_Ap.value = STEP_SEQUENCE[3][1]
coil_Bp.value = STEP_SEQUENCE[3][2]
coil_Bm.value = STEP_SEQUENCE[3][3]
time.sleep(STEP_DELAY)
step_count = step_count + 1
# Release all coils after CW move
coil_Am.value = False
coil_Ap.value = False
coil_Bp.value = False
coil_Bm.value = False
# d. Turn on buzzer at 2000 Hz continuously
buzzer.frequency = 2000
buzzer.duty_cycle = 32768
# e. Wait until reset button (GPIO 5) is pressed
print("LDR: Waiting for alarm reset...")
while True:
if btn_stop.value == False: # Button pressed (LOW)
time.sleep(DEBOUNCE_STP) # Wait 20ms debounce
if btn_stop.value == False: # Confirm still pressed
while btn_stop.value == False: # Wait for release
pass
break # Exit wait loop
time.sleep(0.01)
# f. Turn off buzzer
buzzer.duty_cycle = 0
# g. Turn on green LED
led_green.value = False
led_red.value = False
led_yel.value = False
led_green.value = True
# h. Move stepper 90 degrees COUNTER-CLOCKWISE (reset position)
print("LDR: Moving stepper 90 degrees CCW (reset).")
step_count = 0
while step_count < steps_to_move:
# Step 4 first (reverse order): A-=1, A+=0, B+=0, B-=1
coil_Am.value = STEP_SEQUENCE[3][0]
coil_Ap.value = STEP_SEQUENCE[3][1]
coil_Bp.value = STEP_SEQUENCE[3][2]
coil_Bm.value = STEP_SEQUENCE[3][3]
time.sleep(STEP_DELAY)
# Step 3: A-=0, A+=1, B+=0, B-=1
coil_Am.value = STEP_SEQUENCE[2][0]
coil_Ap.value = STEP_SEQUENCE[2][1]
coil_Bp.value = STEP_SEQUENCE[2][2]
coil_Bm.value = STEP_SEQUENCE[2][3]
time.sleep(STEP_DELAY)
# Step 2: A-=0, A+=1, B+=1, B-=0
coil_Am.value = STEP_SEQUENCE[1][0]
coil_Ap.value = STEP_SEQUENCE[1][1]
coil_Bp.value = STEP_SEQUENCE[1][2]
coil_Bm.value = STEP_SEQUENCE[1][3]
time.sleep(STEP_DELAY)
# Step 1: A-=1, A+=0, B+=1, B-=0
coil_Am.value = STEP_SEQUENCE[0][0]
coil_Ap.value = STEP_SEQUENCE[0][1]
coil_Bp.value = STEP_SEQUENCE[0][2]
coil_Bm.value = STEP_SEQUENCE[0][3]
time.sleep(STEP_DELAY)
step_count = step_count + 1
# Release all coils after CCW move
coil_Am.value = False
coil_Ap.value = False
coil_Bp.value = False
coil_Bm.value = False
# i. Log event
print("LDR: Alarm cleared.")
# Short pause before next loop iteration
time.sleep(0.01)