print("\n\tWelcome to IPD Evidence Locker Security System Program!")
print("\n\tSDG 16: Peace, Justice & Strong Institutions")
print("\n\tCreated by: SHAHRIL FAHMIERUL, AHMAD DANIEL, MUHAMMAD SYAFIQ")
print("\n\tGroup: L05 No ID: 51220225100, 51220225XXX, 51220225XXX")
print("\n---------------------------------------------------------------------")
#Import Libraries
from machine import Pin, I2C, PWM, ADC
from utime import sleep, ticks_ms, sleep_ms
import neopixel
import ssd1306
import dht
from hcsr04 import HCSR04
# ==========================================
# HARDWARE PIN DECLARATION (30-Pin Safe Map)
# ==========================================
i2c = I2C(0, scl=Pin(22), sda=Pin(21)) # I2C Native Hardware Pins
door_sensor = Pin(14, Pin.IN, Pin.PULL_UP)
# PWM Controls
buzzer = PWM(Pin(27))
buzzer.duty_u16(0)
servo = PWM(Pin(23), Pin.OUT)
servo.freq(50)
# NeoPixel Data Line
led_ring = neopixel.NeoPixel(Pin(25), 16)
# Standalone Discrete Status LEDs
led_red = Pin(2, Pin.OUT)
led_yellow = Pin(0, Pin.OUT) # NOTE: Keep ungrounded during system power-on
led_green = Pin(4, Pin.OUT)
# Sensor Signal Interfacing
dht_sensor = dht.DHT22(Pin(15))
ldr_sensor = ADC(Pin(34)) # Input-Only Pin (Perfect for Analog Reading)
ldr_sensor.atten(ADC.ATTN_11DB)
# 4x4 Matrix Keypad Arrays
row_pins = [
Pin(13, Pin.OUT),
Pin(12, Pin.OUT),
Pin(19, Pin.OUT),
Pin(18, Pin.OUT),
]
col_pins = [
Pin(5, Pin.IN, Pin.PULL_DOWN),
Pin(17, Pin.IN, Pin.PULL_DOWN),
Pin(16, Pin.IN, Pin.PULL_DOWN),
Pin(26, Pin.IN, Pin.PULL_DOWN),
]
#Object Declaration
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
keys = [
['1','2','3','A'],
['4','5','6','B'],
['7','8','9','C'],
['*','0','#','D']
]
PASSWORD = "1234"
entered = ""
locked = True
wrong_attempts = 0
unlock_time = 0
unlock_duration = 10000
last_dht_read = 0
last_ultra_read = 0
# State Trackers
light_was_on = False
object_was_near = False
# Ultrasonic config (Optimized Timeout to prevent Keypad latency)
ultra_sensor = HCSR04(trigger_pin=33, echo_pin=32, echo_timeout_us=6000)
#Functions
def oled_display(line1, line2="", line3=""):
oled.fill(0)
oled.text(line1, 0, 0)
oled.text(line2, 0, 20)
oled.text(line3, 0, 40)
oled.show()
def set_ring_color(r, g, b):
for i in range(16):
led_ring[i] = (r, g, b)
led_ring.write()
def update_hardware_leds(red_val, yellow_val, green_val):
led_red.value(red_val)
led_yellow.value(yellow_val)
led_green.value(green_val)
def beep(times=1):
for i in range(times):
buzzer.freq(2000)
buzzer.duty_u16(30000)
sleep(0.1)
buzzer.duty_u16(0)
sleep(0.1)
def servo_angle(angle):
duty = int(1638 + (angle / 180) * (8192 - 1638))
servo.duty_u16(duty)
def log_event(event):
print("[LOG] -", event)
def keypad_read():
for i in range(4):
row_pins[i].value(1)
for j in range(4):
if col_pins[j].value() == 1:
row_pins[i].value(0)
return keys[i][j]
row_pins[i].value(0)
return None
def lock_system():
global locked, entered
locked = True
entered = ""
servo_angle(0)
set_ring_color(255, 150, 0) # NeoPixel Yellow
update_hardware_leds(0, 1, 0) # Physical Yellow LED On
oled_display("EVIDENCE LOCKER", "STATUS: LOCKED", "Enter PIN")
log_event("System Locked")
def unlock_system():
global locked, unlock_time
locked = False
unlock_time = ticks_ms()
servo_angle(90)
set_ring_color(0, 255, 0)
update_hardware_leds(0, 0, 1) # Green LED On
oled_display("EVIDENCE LOCKER", "ACCESS GRANTED", "Unlocked")
log_event("Access Granted - Locker Unlocked")
beep(2)
def alarm_system(reason):
oled_display("!!! ALARM !!!", reason, "SECURITY ALERT")
set_ring_color(255, 0, 0)
update_hardware_leds(1, 0, 0)
log_event("ALARM TRIGGERED: " + reason)
for i in range(4):
buzzer.freq(2000)
buzzer.duty_u16(30000)
update_hardware_leds(1, 0, 0)
sleep(0.15)
buzzer.duty_u16(0)
update_hardware_leds(0, 0, 0)
sleep(0.15)
lock_system()
#Main Program Initialization
oled_display("EVIDENCE LOCKER", "System Starting", "Please Wait...")
set_ring_color(0, 0, 255)
update_hardware_leds(0, 1, 0)
servo_angle(0)
sleep(1)
lock_system()
while True:
current_time = ticks_ms()
# 1. Keypad Logic Priority
key = keypad_read()
if key:
if key == '*':
entered = ""
oled_display("EVIDENCE LOCKER", "PIN CLEARED", "Enter PIN")
elif key == '#':
if entered == PASSWORD:
wrong_attempts = 0
unlock_system()
else:
wrong_attempts += 1
set_ring_color(255, 0, 0)
update_hardware_leds(1, 0, 0)
oled_display("ACCESS DENIED", "Wrong PIN", "Try Again")
log_event("Wrong PIN Attempt: " + entered)
beep(1)
if wrong_attempts >= 3:
wrong_attempts = 0
alarm_system("3 Wrong PIN!")
else:
if light_was_on:
set_ring_color(255, 0, 0)
update_hardware_leds(1, 0, 0)
else:
lock_system()
entered = ""
else:
entered += key
oled_display("EVIDENCE LOCKER", "Enter PIN:", "*" * len(entered))
sleep(0.25)
# 2. Ultrasonic Sensor Logic
if locked and (current_time - last_ultra_read > 300):
try:
distance = ultra_sensor.distance_cm()
if distance > 0 and distance < 30:
if not object_was_near:
beep(1)
print(f"[EVENT TRIGGERED] Proximity Alert! User detected at: {int(distance)}cm")
object_was_near = True
else:
if object_was_near:
object_was_near = False
last_ultra_read = current_time
except OSError:
pass
# 3. Door Sensor Logic
if locked and door_sensor.value() == 0:
alarm_system("Door Opened!")
# 4. DHT22 & LDR Environment Check (Executes cleanly every 2.5s)
if current_time - last_dht_read > 2500:
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
light_intensity = ldr_sensor.read()
if temp > 40.0:
alarm_system("High Temp Blast!")
# Event-Driven LDR Logic
if locked:
if light_intensity < 600:
if not light_was_on:
set_ring_color(255, 0, 0)
update_hardware_leds(1, 0, 0)
beep(1)
print(f"[EVENT TRIGGERED] Room Light ON! Temp: {temp}C | Light Raw: {light_intensity}")
light_was_on = True
else:
if light_was_on:
set_ring_color(255, 150, 0)
update_hardware_leds(0, 1, 0)
light_was_on = False
last_dht_read = current_time
except Exception as error:
pass
# 5. Auto-relock Timer Logic
if not locked:
if current_time - unlock_time > unlock_duration:
lock_system()
sleep_ms(10)