from machine import Pin, PWM, SoftI2C
from time import sleep
from keypad import Keypad
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
# Display Setup
I2C_ADDR = 0x27
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16
i2c = SoftI2C(sda=Pin(1), scl=Pin(0), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
# Keypad Pins
row_pins = [Pin(9),Pin(8),Pin(7),Pin(6)]
column_pins = [Pin(5),Pin(4),Pin(3),Pin(2)]
# Keypad layout
keys = [
['1', '2', '3', 'A'],
['4', '5', '6', 'B'],
['7', '8', '9', 'C'],
['*', '0', '#', 'D']]
keypad = Keypad(row_pins, column_pins, keys)
keypad_debounce = 0.2
# Servo Setup
servo = PWM(Pin(27), freq=50)
def set_servo_angle(angle):
# Convert angle to duty cycle
min_duty = 1638 # 0.5ms = 0 degrees
max_duty = 8192 # 2.5ms = 180 degrees
duty = int(min_duty + (angle / 180) * (max_duty - min_duty))
servo.duty_u16(duty)
pin_code = ""
pin_length = 4
pin_pos = (I2C_NUM_COLS - pin_length) // 2
def lcd_put_center(string: str, row, clear = False):
align_center = (I2C_NUM_COLS - len(string)) // 2
if clear:
lcd.clear()
lcd.move_to(align_center, row)
lcd.putstr(string)
def get_pin_code(row: int):
global pin_length
pin_entered = ""
while len(pin_entered) < pin_length:
lcd_put_center("*" * len(pin_entered)
+ "_" * (pin_length - len(pin_entered)), 1)
key = keypad.read_keypad()
if key in ['1','2','3',
'4','5','6',
'7','8','9','0']:
pin_entered += key
sleep(keypad_debounce)
return pin_entered
def set_pin_code():
lcd_put_center("Enter a new PIN:", 0, True)
global pin_code
pin_code = get_pin_code(1)
lcd_put_center("Confirm new PIN:", 0, True)
if get_pin_code(1) != pin_code:
lcd_put_center("Did not match!", 0, True)
lcd_put_center("try again...", 1)
sleep(2)
set_pin_code()
locked()
def locked():
set_servo_angle(0)
global pin_code
lcd.clear()
lcd_put_center("Locked", 0)
if get_pin_code(1) == pin_code:
unlocked()
else:
lcd_put_center("Wrong PIN!", 0, True)
sleep(3)
locked()
def unlocked():
set_servo_angle(90)
lcd_put_center("Unlocked!", 0, True)
sleep(1)
lcd_put_center("Relocking in:", 0, True)
sleep(1)
for i in reversed(range(16)):
lcd.move_to(0,0)
lcd.putstr(f"{i:^16}")
lcd.move_to(0,1)
lcd.putstr(chr(255) * (I2C_NUM_COLS - i))
sleep(0.5)
locked()
set_pin_code()