from machine import Pin, PWM
import time
# =========================
# PIN SETUP
# =========================
# Servo
servo = PWM(Pin(15))
servo.freq(50)
# LEDs
red_led = Pin(13, Pin.OUT)
green_led = Pin(14, Pin.OUT)
# Buzzer
buzzer = PWM(Pin(12))
# Buttons
door_sensor = Pin(10, Pin.IN, Pin.PULL_UP)
emergency = Pin(11, Pin.IN, Pin.PULL_UP)
# Keypad
ROWS = [2, 3, 4, 5]
COLS = [6, 7, 8, 9]
rows = [Pin(pin, Pin.OUT) for pin in ROWS]
# IMPORTANT: 4 column pins
cols = [Pin(pin, Pin.IN, Pin.PULL_DOWN) for pin in COLS]
keys = [
['1', '2', '3', 'A'],
['4', '5', '6', 'B'],
['7', '8', '9', 'C'],
['*', '0', '#', 'D']
]
# =========================
# SETTINGS
# =========================
USER_PIN = "1234"
VISITOR_PIN = "5678"
ADMIN_PIN = "9999"
MAX_ATTEMPTS = 3
LOCKOUT_SECONDS = 15
attempts = 0
# =========================
# SERVO
# =========================
def lock_door():
servo.duty_u16(1638)
red_led.on()
green_led.off()
print("DOOR LOCKED")
def unlock_door():
servo.duty_u16(4915)
red_led.off()
green_led.on()
print("DOOR UNLOCKED")
# =========================
# BUZZER
# =========================
def beep(frequency, duration):
buzzer.freq(frequency)
buzzer.duty_u16(30000)
time.sleep_ms(duration)
buzzer.duty_u16(0)
def success_sound():
beep(1000, 150)
time.sleep_ms(50)
beep(1500, 150)
def error_sound():
beep(300, 300)
# =========================
# KEYPAD
# =========================
def get_key():
for r in range(4):
# Turn all rows OFF
for row in rows:
row.off()
# Turn current row ON
rows[r].on()
# Check columns
for c in range(4):
if cols[c].value():
key = keys[r][c]
# Wait until key is released
while cols[c].value():
time.sleep_ms(10)
return key
return None
# =========================
# ENTER PIN
# =========================
def enter_pin(first_key=None):
pin = ""
# Use the first key that started authentication
key = first_key
print("ENTER PIN:")
while True:
# Get a new key if there isn't one
if key is None:
key = get_key()
if key is not None:
# Number key
if key.isdigit():
pin += key
print("*", end="")
beep(800, 80)
# # means ENTER
elif key == "#":
print()
if len(pin) == 4:
return pin
print("PIN MUST BE 4 DIGITS")
error_sound()
pin = ""
# * means CLEAR
elif key == "*":
pin = ""
print("\nCLEARED")
beep(500, 100)
# Reset key
key = None
time.sleep_ms(50)
# =========================
# LOCKOUT
# =========================
def lockout():
global attempts
print("TOO MANY WRONG ATTEMPTS")
print("SYSTEM LOCKED")
red_led.on()
green_led.off()
for i in range(LOCKOUT_SECONDS):
beep(400, 100)
time.sleep_ms(900)
attempts = 0
print("SYSTEM READY")
# =========================
# AUTHENTICATION
# =========================
# =========================
# USER KEY
# =========================
def user_key():
attempts = 0
print("USER ACCESS")
success_sound()
unlock_door()
time.sleep(8)
lock_door()
def authenticate(first_key):
global attempts
pin = enter_pin(first_key)
# USER
if pin == USER_PIN:
user_key()
# VISITOR
elif pin == VISITOR_PIN:
attempts = 0
print("VISITOR ACCESS")
success_sound()
unlock_door()
time.sleep(5)
lock_door()
# ADMIN
elif pin == ADMIN_PIN:
attempts = 0
print("ADMIN ACCESS")
success_sound()
unlock_door()
time.sleep(9)
lock_door()
# WRONG PIN
else:
attempts += 1
print("WRONG PIN")
print("ATTEMPTS:", attempts)
error_sound()
if attempts >= MAX_ATTEMPTS:
lockout()
# =========================
# EMERGENCY MODE
# =========================
def emergency_mode():
print("!!! EMERGENCY !!!")
print("DOOR UNLOCKED")
unlock_door()
# Alarm
for i in range(5):
beep(1000, 200)
time.sleep_ms(100)
time.sleep(5)
lock_door()
print("EMERGENCY MODE ENDED")
# =========================
# START SYSTEM
# =========================
print("==============================")
print(" FUTURE SMART HOUSE LOCK")
print("==============================")
print("SYSTEM READY")
lock_door()
# =========================
# MAIN LOOP
# =========================
while True:
# Emergency button
if emergency.value() == 0:
emergency_mode()
time.sleep_ms(500)
continue
# Check keypad
key = get_key()
if key is not None:
authenticate(key)
# Door sensor
if door_sensor.value() == 0:
print("DOOR OPEN")
time.sleep_ms(100)