First draft of a card terminal with keypad and

MFRC522 card reader together.
This commit is contained in:
Lars Hahn 2025-01-02 23:42:21 +01:00
parent d90781c0f8
commit 77565de933
3 changed files with 205 additions and 3 deletions

View File

@ -2,7 +2,7 @@ import machine
import utime
class membrane:
class Membrane:
"""Class for interpreting input from a membran-like keypad,
the default is a 4x4 matrix array membrane keypad.
The layout of key bindings and size (i.e. 4x3 alternative)
@ -244,7 +244,7 @@ class membrane:
if __name__ == "__main__":
membrane_keypad = membrane()
membrane_keypad = Membrane()
pin_size = 12
while len(membrane_keypad) < pin_size:

View File

@ -636,7 +636,7 @@ if __name__ == "__main__":
)
for sector_block in range(4)
)
print(f"Sector {sector: 02d}: {sector_text}")
print(f"Sector {sector:02d}: {sector_text}")
except TypeError:
break # When removing card, just skip
else:

202
src/systems/cardterm.py Normal file
View File

@ -0,0 +1,202 @@
import utime
from machine import Pin, Timer, PWM
from input.ukeypad import Membrane as KeyPad
from radiotech.rfid.umfrc522 import UMFRC522 as MFRC522
class CardTermRC522:
@classmethod
def led_pulse(cls, led_pwm, led_timer, period=1000, half=False):
led_pwm.freq(period)
def inputblink(t):
maxvalue = 2**17 if not half else 2**16
halfvalue = 2**16 if not half else 2**15
freq = (
(utime.ticks_ms() % period) * (maxvalue//period)
) % maxvalue
duty = freq if freq < halfvalue else (maxvalue - freq)
led_pwm.duty_u16(duty)
led_timer.init(freq=period, callback=inputblink)
@classmethod
def callback_ok(cls, cardid, data):
print("Status: OK")
print(f"Card ID: {cardid}")
print(f"Data: {data}")
@classmethod
def callback_nok(cls, cardid):
print("Status: NOT OK")
print(f"Card ID: {cardid}")
DEFAULT_KEY_PAD = (
('1', '2', '3', 'A'),
('4', '5', '6', 'B'),
('7', '8', '9', 'C'),
('F', '0', 'E', 'D')
)
def __init__(
self, key_length=12, key_pad=DEFAULT_KEY_PAD, led_period=1000,
led_inverted=False, pin_led_status=(16,15,14),
pins_keypad_row=(2, 3, 4, 5), pins_keypad_col=(6, 7, 8, 9),
pin_rc522_sck=10, pin_rc522_miso=11, pin_rc522_mosi=12,
pin_rc522_cs=13, pin_rc522_rst=22, spi_device=1,
time_wait_success=10, time_wait_failure=3):
self._key_length = key_length
self._key_pad = key_pad
self._led_period = led_period
self._led_inverted = led_inverted
self._pin_led_status = pin_led_status[0]
self._pin_led_ok = pin_led_status[1]
self._pin_led_nok = pin_led_status[2]
self._pins_keypad_row = pins_keypad_row
self._pins_keypad_col = pins_keypad_col
self._pin_rc522_sck = pin_rc522_sck
self._pin_rc522_miso = pin_rc522_mosi
self._pin_rc522_mosi = pin_rc522_miso
self._pin_rc522_cs = pin_rc522_cs
self._pin_rc522_rst = pin_rc522_rst
self._spi_dev = spi_device
self._time_wait_success = time_wait_success
self._time_wait_failure = time_wait_failure
self._setup()
@property
def callback_success(self):
return (self._callback_success, dict(self._callback_success_kwargs))
@callback_success.setter
def callback_success(self, callback, kwargs):
self._callback_success = callback
self._callback_success_kwargs = dict(kwargs)
@property
def callback_failure(self):
return (self._callback_failure, dict(self._callback_failure_kwargs))
@callback_failure.setter
def callback_failure(self, callback, kwargs):
self._callback_failure = callback
self._callback_failure_kwargs = dict(kwargs)
def _setup(self):
val = self._led_inverted
self._led_nok = Pin(self._pin_led_nok, Pin.OUT, value=val)
self._pwm_nok = PWM(self._led_nok)
self._timer_nok = Timer()
self._led_ok = Pin(self._pin_led_ok, Pin.OUT, value=val)
self._pwm_ok = PWM(self._led_ok)
self._timer_ok = Timer()
self._led_status = Pin(self._pin_led_status, Pin.OUT, value=val)
self._pwm_status = PWM(self._led_status)
self._timer_status = Timer()
self._reader = MFRC522(
spi_dev=self._spi_dev, sck=self._pin_rc522_sck,
mosi=self._pin_rc522_mosi, miso=self._pin_rc522_miso,
cs=self._pin_rc522_cs, rst=self._pin_rc522_rst
)
self._keypad = KeyPad(characters=self._key_pad)
self._led_init()
self.led_pulse(
led_pwm=self._pwm_status, led_timer=self._timer_status,
period=self._led_period*2, half=True
)
self._callback_success = self.callback_ok
self._callback_success_kwargs = {}
self._callback_failure = self.callback_nok
self._callback_failure_kwargs = {}
def _led_init(self):
self._timer_nok.deinit()
self._pwm_nok.freq(self._led_period)
self._pwm_nok.duty_u16(2**16 if self._led_inverted else 0)
self._timer_ok.deinit()
self._pwm_ok.freq(self._led_period)
self._pwm_ok.duty_u16(2**16 if self._led_inverted else 0)
self._timer_status.deinit()
self._pwm_status.freq(self._led_period)
self._pwm_status.duty_u16(2**16 if self._led_inverted else 0)
def read_card(self):
self._reader.clear_state()
status, token = self._reader.request(self._reader.REQUEST_IDLE)
if status == self._reader.STATUS_OK:
status, serial_number = self._reader.select_near_token()
if status == self._reader.STATUS_OK:
card_id = MFRC522.id_to_string(serial_number)
self._led_init()
self.led_pulse(
led_pwm=self._pwm_status, led_timer=self._timer_status,
period=self._led_period
)
self._keypad.clear()
while len(self._keypad) < self._key_length:
utime.sleep(self._keypad.DEFAULT_BUFFER_TIME)
key = self._keypad.pop_all()
key_bytes = [
int(f'{key[i]}{key[i+1]}',16)
for i in range(0,len(key),2)
]
data = []
for sector in range(16):
login_block = sector*4 + 3
status = self._reader.authenticate(
serial_number, login_block, key_bytes,
self._reader.AUTH_MODE_A
)
if status != self._reader.STATUS_OK:
continue
try:
sector_data = [
[
c
for c in self._reader.read(
sector*4 + sector_block
)
]
for sector_block in range(4)
]
data.append(sector_data)
except TypeError:
data.clear()
self._led_init()
self.led_pulse(
led_pwm=self._pwm_nok, led_timer=self._timer_nok,
period=self._led_period//2
)
self._callback_failure_kwargs["cardid"] = card_id
self._callback_failure(**self._callback_failure_kwargs)
utime.sleep(self._time_wait_failure)
self._led_init()
self.led_pulse(
led_pwm=self._pwm_status, period=self._led_period*2,
led_timer=self._timer_status, half=True
)
del self._callback_failure_kwargs["cardid"]
break
else:
self._led_init()
self.led_pulse(
led_pwm=self._pwm_ok, led_timer=self._timer_ok,
period=self._led_period
)
self._callback_success_kwargs["cardid"] = card_id
self._callback_success_kwargs["data"] = data
self._callback_success(**self._callback_success_kwargs)
utime.sleep(self._time_wait_success)
self._led_init()
self.led_pulse(
led_pwm=self._pwm_status, led_timer=self._timer_status,
period=self._led_period*2, half=True
)
del self._callback_success_kwargs["cardid"]
del self._callback_success_kwargs["data"]
def find_card_loop(self):
while True:
self.read_card()
utime.sleep(1)
cardterm = CardTermRC522(led_inverted=True)
cardterm.find_card_loop()