from machine import Pin, I2C, PWM
import struct
import time
# =====================================================
# I2C Configuration
# =====================================================
# Initialize I2C communication using GPIO22 (SCL) and GPIO21 (SDA)
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
# MPU6050 I2C address
MPU_ADDR = 0x68
# Wake up the MPU6050 by clearing the sleep mode bit
i2c.writeto_mem(MPU_ADDR, 0x6B, b'\x00')
# =====================================================
# Output Devices
# =====================================================
# Green LED indicates normal operation
green_led = Pin(2, Pin.OUT)
# Red LED indicates a security alert
red_led = Pin(12, Pin.OUT)
# Configure the buzzer
buzzer = PWM(Pin(14))
buzzer.freq(2000) # Set buzzer frequency to 2 kHz
buzzer.duty(0) # Keep the buzzer OFF initially
# =====================================================
# Detection Thresholds
# =====================================================
# Minimum vibration level required to trigger detection (in g)
VIBRATION_THRESHOLD = 0.15
# Minimum rotation speed required to trigger detection (degrees/second)
ROTATION_THRESHOLD = 40
# =====================================================
# Variables for Previous Accelerometer Readings
# =====================================================
# Store previous acceleration values to calculate vibration
prev_ax = 0
prev_ay = 0
prev_az = 0
# =====================================================
# Function: Read MPU6050 Sensor
# =====================================================
def read_mpu():
"""
Reads accelerometer and gyroscope data from the MPU6050.
Returns:
ax, ay, az : Raw accelerometer values
gx, gy, gz : Raw gyroscope values
"""
# Read 14 bytes starting from the accelerometer register
data = i2c.readfrom_mem(MPU_ADDR, 0x3B, 14)
# Unpack the received bytes
# ax, ay, az, temperature, gx, gy, gz
ax, ay, az, temp, gx, gy, gz = struct.unpack(">hhhhhhh", data)
return ax, ay, az, gx, gy, gz
# =====================================================
# Main Program Loop
# =====================================================
while True:
# -----------------------------------------
# Read sensor measurements
# -----------------------------------------
ax, ay, az, gx, gy, gz = read_mpu()
# -----------------------------------------
# Convert accelerometer readings to g
# (Default sensitivity: ±2g)
# 16384 LSB = 1g
# -----------------------------------------
ax = ax / 16384
ay = ay / 16384
az = az / 16384
# Remove the Earth's gravity from the Z-axis
az = az - 1.0
# -----------------------------------------
# Calculate vibration
# -----------------------------------------
# Compare the current reading with the
# previous reading. A large difference
# indicates sudden movement or vibration.
# -----------------------------------------
delta_x = abs(ax - prev_ax)
delta_y = abs(ay - prev_ay)
delta_z = abs(az - prev_az)
# Use the largest vibration value
vibration = max(delta_x, delta_y, delta_z)
# Save the current readings for the next iteration
prev_ax = ax
prev_ay = ay
prev_az = az
# -----------------------------------------
# Convert gyroscope readings to degrees/second
# (Default sensitivity: ±250°/s)
# 131 LSB = 1°/s
# -----------------------------------------
gx = gx / 131
gy = gy / 131
gz = gz / 131
# Calculate the maximum rotation speed
rotation = max(abs(gx), abs(gy), abs(gz))
# -----------------------------------------
# Display sensor information
# -----------------------------------------
print("--------------------------------")
print("Acceleration (g)")
print("AX = {:.2f} AY = {:.2f} AZ = {:.2f}".format(ax, ay, az))
print("Gyroscope (deg/s)")
print("GX = {:.2f} GY = {:.2f} GZ = {:.2f}".format(gx, gy, gz))
print("Vibration = {:.2f} g".format(vibration))
print("Rotation = {:.2f} deg/s".format(rotation))
# -----------------------------------------
# Sensor Fusion Decision
# -----------------------------------------
# Trigger the alarm only if:
# 1. Strong vibration is detected
# AND
# 2. Fast rotation is detected
# -----------------------------------------
if vibration > VIBRATION_THRESHOLD or rotation > ROTATION_THRESHOLD:
# Turn ON the alarm indicators
red_led.on()
green_led.off()
buzzer.duty(512)
print("SAFE TAMPERING DETECTED")
print("ALARM ON")
else:
# Keep the safe in normal operating mode
green_led.on()
red_led.off()
buzzer.duty(0)
print("SAFE SECURE")
print("ALARM OFF")
# Wait before taking the next measurement
time.sleep(0.5)