import M5
from M5 import *
import _thread
from hardware import Rotary
from machine import PWM,Pin,I2C
from utime import sleep
from random import choice
# A constant that specifies the duty of the SG90 (lock, unlock).
deg = [2676, 5788]
# A constant that specifies the lock level.
LPRM = [range(0,10), range(-9,10), range(0,30), range(-15,16)]
# A constant that specifies the segment pattern
DI = {'0':0,'1':1,'2':2,'3':3,'4':4,
'5':5,'6':6,'7':7,'8':8,'9':9,
'a':10,'b':11,'c':12,'d':13,'e':14,'f':15,
'-':16,' ':17}
# Defining Global Variables
bsw = 0 # Previous sw status
bro = 0 # Previous rotary status
d = [17 for i in range(16)] # LED display characters
b = [1 for i in range(16)] # LED blinking setting
# Initialization
M5.begin()
sw = Pin(1, Pin.IN, Pin.PULL_UP)
ro = Rotary()
Widgets.setBrightness(0)
sleep(0.1)
sv = PWM(Pin(2), freq=50, duty_u16=deg[0])
sleep(0.3)
Widgets.setBrightness(150)
Speaker.setVolume(200)
# LED display processing (multi-threaded)
def led_change():
i2c = I2C(0, scl=Pin(15), sda=Pin(13), freq=400000)
addr = i2c.scan()
i2c.writeto(addr[0], bytes([0x21])) # SYSTEM on
i2c.writeto(addr[0], bytes([0x81])) # LED power on
i2c.writeto(addr[0], bytes([0xE8])) # LED brightness setting
for i in range(16): i2c.writeto_mem(addr[0], i, bytes([0x00])) #LED initialization
p = [0xee, 0x48, 0xba, 0xda, 0x5c, 0xd6, 0xf6, 0x4e, 0xfe, 0xde, # LED lighting bit data
0x7e, 0xf4, 0xa6, 0xf8, 0xb6, 0x36, 0x10, 0x00]
bf = 0 # Blinking Flag
while True:
for i in range(8):
i2c.writeto_mem(addr[0], i*2, bytes([p[d[i]] * (b[i]|bf)]))
i2c.writeto_mem(addr[0], i*2+1, bytes([p[d[i+8]] * (b[i+8]|bf)]))
bf = (bf+1)%2
sleep(0.1)
# LCD display processing
def disp_change(n, val):
if n==0 or n==1:
Widgets.fillScreen(0xffffff)
else:
Widgets.fillScreen(0x000000)
if n==0:
l0 = Widgets.Label(" LOCK ",50,105,1.0,0x000000,0xffffff,Widgets.FONTS.DejaVu40)
if n==1:
l0 = Widgets.Label("UNLOCK",30,105,1.0,0x000000,0xffffff,Widgets.FONTS.DejaVu40)
if n>=2:
c0 = Widgets.Circle(120, 120, 100, 0xffffff, 0xffffff)
c1 = Widgets.Circle(120, 120, 90, 0x000000, 0x000000)
r0 = Widgets.Rectangle(110, 12, 20, 20, 0x000000, 0x000000)
r1 = Widgets.Rectangle(0, 120, 240, 120, 0x000000, 0x000000)
t0 = Widgets.Triangle(10, 114, 40, 114, 25, 130, 0xffffff, 0xffffff)
t1 = Widgets.Triangle(200, 115, 230, 115, 215, 130, 0xffffff, 0xffffff)
if n==2:
r0 = Widgets.Rectangle(0, 0,120,240, 0x000000, 0x000000)
lr = Widgets.Label("LOCK", 130, 71, 1.0, 0xffff00, 0x000000, Widgets.FONTS.DejaVu18)
if n==3:
lr = Widgets.Label("- SELECT +", 60, 90, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
if n==2 or n==3:
l1 = Widgets.Label("LOCK LEVEL", 60, 148, 1.0, 0x000000, 0xffffff, Widgets.FONTS.DejaVu18)
l2 = Widgets.Label(str(val+1),110, 180, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu40)
if n==4:
r2 = Widgets.Rectangle(0, 140, 240, 100, 0xffffff, 0xffffff)
l1 = Widgets.Label("UNLOCK PASS", 50, 148, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
l2 = Widgets.Label("yQ = yA", 64, 175, 1.0, 0x000000, 0xffffff, Widgets.FONTS.DejaVu24)
l3 = Widgets.Label("(x=1~5)", 75, 208, 1.0, 0x000000, 0xffffff, Widgets.FONTS.DejaVu18)
if n==4 and val==0:
lr = Widgets.Label("X + ", 140, 90, 1.0, 0xffff00, 0x000000, Widgets.FONTS.DejaVu18)
ll = Widgets.Label("NEXT", 50, 90, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
if n==4 and val==1:
lr = Widgets.Label("NEXT", 140, 90, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
ll = Widgets.Label("a - ", 50, 90, 1.0, 0xffff00, 00000000, Widgets.FONTS.DejaVu18)
if n==4 and val==2:
lr = Widgets.Label("b + ", 140, 90, 1.0, 0xffff00, 0x000000, Widgets.FONTS.DejaVu18)
ll = Widgets.Label("NEXT", 50, 90, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
if n==4 and val==3:
lr = Widgets.Label("NEXT", 140, 90, 1.0, 0xffffff, 0x000000, Widgets.FONTS.DejaVu18)
ll = Widgets.Label("c - ", 50, 90, 1.0, 0xffff00, 0x000000, Widgets.FONTS.DejaVu18)
M5.update()
# Key Scan Processing
def key_serch():
global bsw, bro
nsw = sw.value()
nro = ro.get_rotary_value()
k = 0
if bsw != nsw and nsw == 0: k=2 # key2:sw on
if bsw != nsw and nsw == 1: k=3 # key3:sw off
if bro != nro and nro - bro > 0: k=1 # key1:rotary+
if bro != nro and nro - bro < 0: k=-1 # key-1:rotary-
bsw = nsw
bro = nro
return k
# Multi-threading Start
_thread.start_new_thread(led_change, ())
# Main loop start
while True:
# Initialization before unlocking
dp = 3
lv = 0
d = [17 for i in range(16)]
disp_change(3, lv)
Speaker.tone(2400, 200)
sleep(0.5)
#Processing during unlock
while dp != 0:
key = 0
while key == 0: key = key_serch()
if sw.value() == 1 and key == 1: lv = (lv+1)%len(LPRM) # Lv select +
if sw.value() == 1 and key == -1: lv = (lv-1)%len(LPRM) # Lv select -
if key == 2: dp = 2 # Screen switching(Lock display)
if key == 3: dp = 3 # Screen switching(Unlock display)
if sw.value() == 0 and key== 1: dp=0 # Door locking conditions
disp_change(dp, lv)
if abs(key) == 1: Speaker.tone(1600, 50)
else: Speaker.tone(1200, 300)
#Unlocking Process
Widgets.setBrightness(0)
sleep(0.1)
sv.duty_u16(deg[1])
sleep(0.3)
Widgets.setBrightness(150)
d = [17,17,17,17,17,17,17,17,0,0,0,0,0,0,0,0]
b = [ 1, 1, 1, 1, 1, 1, 1, 1,0,0,0,0,0,0,0,0]
disp_change(0, 0)
Speaker.tone(3000, 1000)
sleep(3)
sel = 0
x = 0
ka = [0, 0, 0]
kq = [0, 0, 0]
while 0 in kq: kq = [choice(LPRM[lv]) for i in range(3)]
dp = 4
disp_change(dp, sel)
# Processing during lock
while True:
asum = 0
for i in range(5):
q = kq[0]*(i+1)*(i+1) + kq[1]*(i+1) + kq[2]
a = ka[0]*(i+1)*(i+1) + ka[1]*(i+1) + ka[2]
if x==i:
nyq = q
nya = a
if q==a: asum += 1
sx = str(x+1)
if lv != 3: # Display numbers as decimal numbers
syq = f'{nyq:04}'
sya = f'{nya:04}'
sk0 = f'{ka[0]:02}'
sk1 = f'{ka[1]:02}'
sk2 = f'{ka[2]:02}'
if lv == 3: # Display numbers in hexadecimal
syq = f'{nyq:04x}'
sya = f'{nya:04x}'
sk0 = f'{ka[0]:02x}'
sk1 = f'{ka[1]:02x}'
sk2 = f'{ka[2]:02x}'
d = [DI[' '] ,DI[ sx[0]],DI[sk0[1]],DI[sk0[0]],
DI[sk1[1]],DI[sk1[0]],DI[sk2[1]],DI[sk2[0]],
DI[syq[3]],DI[syq[2]],DI[syq[1]],DI[syq[0]],
DI[sya[3]],DI[sya[2]],DI[sya[1]],DI[sya[0]]]
if asum==5: break # Unlocked when all conditions are met
b = [1 for i in range(16)] # Initialize the blinking state
b[sel*2] = 0
b[sel*2+1] = 0
nsel = sel
key = 0
while key==0: key = key_serch()
if key == 1 and sel == 0:
x = (x+1)%5 # x +
elif key == -1 and sel == 1:
ka[0] = ka[0]-1 if ka[0]>min(LPRM[lv]) else max(LPRM[lv]) # ka -
elif key == 1 and sel == 2:
ka[1] = ka[1]+1 if ka[1]<max(LPRM[lv]) else min(LPRM[lv]) # kb +
elif key == -1 and sel == 3:
ka[2] = ka[2]-1 if ka[2]>min(LPRM[lv]) else max(LPRM[lv]) # kc -
elif key != 2 and key != 3:
sel = (sel+1)%4 # Change your selection
disp_change(dp, sel)
if abs(key) == 1 and sel == nsel:Speaker.tone(1600, 50)
if abs(key) == 1 and sel != nsel:Speaker.tone(2400, 200)
# Unlocking Process
Widgets.setBrightness(0)
sleep(0.1)
sv.duty_u16(deg[0])
sleep(0.3)
Widgets.setBrightness(150)
b=[0 for i in range(16)]
disp_change(1, 0)
Speaker.tone(3000, 1000)
sleep(2)
key = 0
while key != 3: key = key_serch()
Comments