from machine import Pin, PWM, SoftI2C, SPI
from mfrc522 import MFRC522
from i2c_lcd import I2cLcd
import time
# ===== I2C LCD =====
I2C_ADDR = 0x27
i2c = SoftI2C(sda=Pin(8), scl=Pin(9), freq=100000)
lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)
# ===== SERVO =====
servo = PWM(Pin(16), freq=50)
servo.duty(0) # safe initial position
def set_servo(angle):
angle = max(0, min(180, angle))
duty = int(26 + (angle / 180) * 102)
servo.duty(duty)
# ===== BUZZER =====
buzzer = PWM(Pin(17))
buzzer.duty(0) # off initially
def beep(duration=80, freq=3000):
buzzer.freq(freq)
buzzer.duty(512)
time.sleep_ms(duration)
buzzer.duty(0) # always turn off
# ===== LEDs =====
green = Pin(18, Pin.OUT)
red = Pin(19, Pin.OUT)
yellow = Pin(20, Pin.OUT)
green.off()
red.off()
yellow.off()
# ===== RFID =====
spi = SPI(1, baudrate=1000000, polarity=0, phase=0,
sck=Pin(12), mosi=Pin(11), miso=Pin(13))
rfid = MFRC522(spi, Pin(10), Pin(14))
authorized_uids = ["DEADBEEF", "12345678"]
failed_rfid = 0
max_fails = 3
# ===== KEYPAD =====
row_pins = [Pin(pin, Pin.OUT) for pin in [1,2,42,41]]
col_pins = [Pin(pin, Pin.IN, Pin.PULL_DOWN) for pin in [40,39,38,37]]
for r in row_pins:
r.value(0) # initialize rows low
keys = [
['1','2','3','A'],
['4','5','6','B'],
['7','8','9','C'],
['*','0','#','D']
]
correct_pin = "1234"
entered_pin = ""
people_count = 0
keypad_mode = False
# ===== DISPLAY =====
def display_main():
lcd.clear()
lcd.putstr("People: {}".format(people_count))
lcd.move_to(0,1)
lcd.putstr("Mode: RFID")
def display_message(l1, l2=""):
lcd.clear()
lcd.putstr(l1)
lcd.move_to(0,1)
lcd.putstr(l2)
# ===== ACCESS CONTROL =====
def grant_access():
global people_count, failed_rfid, keypad_mode
people_count += 1
failed_rfid = 0
keypad_mode = False
green.on()
red.off()
yellow.off()
# success tones
beep(120, 2000)
time.sleep_ms(100)
beep(120, 2600)
display_message("Access Granted", "Welcome!")
set_servo(90)
time.sleep(2)
set_servo(0)
green.off()
display_main()
def deny_access():
global failed_rfid
failed_rfid += 1
red.on()
for _ in range(3):
beep(120, 800)
time.sleep_ms(100)
display_message("Access Denied", "Try Again")
time.sleep(2)
red.off()
display_main()
# ===== KEYPAD SCAN =====
def scan_keypad():
for i, row in enumerate(row_pins):
row.value(1)
for j, col in enumerate(col_pins):
if col.value():
time.sleep_ms(180)
row.value(0)
return keys[i][j]
row.value(0)
return None
# ===== STARTUP =====
beep(100, 2500)
time.sleep_ms(100)
beep(100, 3000)
display_main()
# ===== MAIN LOOP =====
while True:
# RFID mode
if failed_rfid < max_fails:
if keypad_mode:
yellow.off()
display_main()
keypad_mode = False
(stat, tag_type) = rfid.request(rfid.REQIDL)
if stat == rfid.OK:
(stat, raw_uid) = rfid.anticoll()
if stat == rfid.OK:
uid = ''.join(['%02X' % b for b in raw_uid])
if uid in authorized_uids:
grant_access()
else:
deny_access()
time.sleep(1)
else: # keypad fallback
if not keypad_mode:
yellow.on()
display_message("Use Keypad", "Enter Code:")
entered_pin = ""
keypad_mode = True
key = scan_keypad()
if key:
if key.isdigit():
beep() # sharp beep
entered_pin += key
lcd.putstr("*")
elif key == "#":
entered_pin = ""
display_message("Use Keypad", "Enter Code:")
if len(entered_pin) == 4:
if entered_pin == correct_pin:
grant_access()
else:
deny_access()
entered_pin = ""
failed_rfid = 0
# safety idle state
set_servo(0)
buzzer.duty(0)
time.sleep(0.1)