from machine import Pin, I2C, PWM
from time import sleep, sleep_ms, ticks_ms
# -------------------------
# Pin setup
# -------------------------
green_led = Pin(16, Pin.OUT)
red_led = Pin(17, Pin.OUT)
button = Pin(18, Pin.IN, Pin.PULL_UP)
buzzer = PWM(Pin(15))
buzzer.duty_u16(0)
# -------------------------
# MPU6050 setup
# -------------------------
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
MPU_ADDR = 0x68
PWR_MGMT_1 = 0x6B
ACCEL_XOUT_H = 0x3B
def mpu_write(reg, val):
i2c.writeto_mem(MPU_ADDR, reg, bytes([val]))
def mpu_read(reg, nbytes):
return i2c.readfrom_mem(MPU_ADDR, reg, nbytes)
def to_signed(high, low):
value = (high << 8) | low
if value > 32767:
value -= 65536
return value
def init_mpu():
# Wake up MPU6050
mpu_write(PWR_MGMT_1, 0)
def read_accel():
data = mpu_read(ACCEL_XOUT_H, 6)
ax = to_signed(data[0], data[1])
ay = to_signed(data[2], data[3])
az = to_signed(data[4], data[5])
return ax, ay, az
# -------------------------
# Alarm helpers
# -------------------------
def buzzer_on(freq=1000, duty=30000):
buzzer.freq(freq)
buzzer.duty_u16(duty)
def buzzer_off():
buzzer.duty_u16(0)
def short_beep():
buzzer_on(1200, 25000)
sleep_ms(120)
buzzer_off()
def alarm_pattern():
for _ in range(3):
red_led.on()
buzzer_on(1400, 32000)
sleep_ms(180)
red_led.off()
buzzer_off()
sleep_ms(120)
# -------------------------
# Button edge detection
# -------------------------
last_button_state = 1
last_press_time = 0
def button_pressed():
global last_button_state, last_press_time
current = button.value()
pressed = False
# Detect HIGH -> LOW transition
if last_button_state == 1 and current == 0:
now = ticks_ms()
if now - last_press_time > 300: # debounce
pressed = True
last_press_time = now
last_button_state = current
return pressed
# -------------------------
# Main logic
# -------------------------
armed = False
alarm_active = False
baseline = (0, 0, 0)
# Thresholds for raw accelerometer values
WARNING_THRESHOLD = 2500
ALARM_THRESHOLD = 5000
def set_disarmed():
global armed, alarm_active
armed = False
alarm_active = False
green_led.on()
red_led.off()
buzzer_off()
print("System DISARMED")
def set_armed():
global armed, alarm_active, baseline
armed = True
alarm_active = False
baseline = read_accel()
green_led.off()
red_led.on()
short_beep()
sleep_ms(100)
short_beep()
print("System ARMED")
print("Baseline:", baseline)
def check_tamper():
global alarm_active
ax, ay, az = read_accel()
bx, by, bz = baseline
dx = abs(ax - bx)
dy = abs(ay - by)
dz = abs(az - bz)
max_delta = max(dx, dy, dz)
print("Accel:", (ax, ay, az), " Delta:", (dx, dy, dz))
if max_delta > ALARM_THRESHOLD:
alarm_active = True
return "ALARM"
elif max_delta > WARNING_THRESHOLD:
return "WARNING"
else:
return "SAFE"
# -------------------------
# Start
# -------------------------
init_mpu()
set_disarmed()
while True:
if button_pressed():
if armed:
set_disarmed()
else:
set_armed()
if not armed:
green_led.on()
red_led.off()
buzzer_off()
sleep_ms(100)
continue
status = check_tamper()
if status == "SAFE":
red_led.on()
buzzer_off()
sleep_ms(100)
elif status == "WARNING":
red_led.on()
buzzer_on(1000, 18000)
sleep_ms(100)
buzzer_off()
red_led.off()
sleep_ms(100)
elif status == "ALARM":
green_led.off()
for _ in range(2):
alarm_pattern()
# stay in alarm until disarmed
while armed:
if button_pressed():
set_disarmed()
break
red_led.toggle()
buzzer_on(1500, 32000)
sleep_ms(150)
buzzer_off()
sleep_ms(150)