basic UID reading works
This commit is contained in:
parent
d5ca98fbaa
commit
faaf7fad4d
2 changed files with 107 additions and 74 deletions
|
@ -30,61 +30,61 @@ import adafruit_bus_device.spi_device as spi_device
|
||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
|
|
||||||
PN532_PREAMBLE = const(0x00)
|
_PREAMBLE = const(0x00)
|
||||||
PN532_STARTCODE1 = const(0x00)
|
_STARTCODE1 = const(0x00)
|
||||||
PN532_STARTCODE2 = const(0xFF)
|
_STARTCODE2 = const(0xFF)
|
||||||
PN532_POSTAMBLE = const(0x00)
|
_POSTAMBLE = const(0x00)
|
||||||
|
|
||||||
PN532_HOSTTOPN532 = const(0xD4)
|
_HOSTTOPN532 = const(0xD4)
|
||||||
PN532_PN532TOHOST = const(0xD5)
|
_PN532TOHOST = const(0xD5)
|
||||||
|
|
||||||
# PN532 Commands
|
# PN532 Commands
|
||||||
PN532_COMMAND_DIAGNOSE = const(0x00)
|
_COMMAND_DIAGNOSE = const(0x00)
|
||||||
PN532_COMMAND_GETFIRMWAREVERSION = const(0x02)
|
_COMMAND_GETFIRMWAREVERSION = const(0x02)
|
||||||
PN532_COMMAND_GETGENERALSTATUS = const(0x04)
|
_COMMAND_GETGENERALSTATUS = const(0x04)
|
||||||
PN532_COMMAND_READREGISTER = const(0x06)
|
_COMMAND_READREGISTER = const(0x06)
|
||||||
PN532_COMMAND_WRITEREGISTER = const(0x08)
|
_COMMAND_WRITEREGISTER = const(0x08)
|
||||||
PN532_COMMAND_READGPIO = const(0x0C)
|
_COMMAND_READGPIO = const(0x0C)
|
||||||
PN532_COMMAND_WRITEGPIO = const(0x0E)
|
_COMMAND_WRITEGPIO = const(0x0E)
|
||||||
PN532_COMMAND_SETSERIALBAUDRATE = const(0x10)
|
_COMMAND_SETSERIALBAUDRATE = const(0x10)
|
||||||
PN532_COMMAND_SETPARAMETERS = const(0x12)
|
_COMMAND_SETPARAMETERS = const(0x12)
|
||||||
PN532_COMMAND_SAMCONFIGURATION = const(0x14)
|
_COMMAND_SAMCONFIGURATION = const(0x14)
|
||||||
PN532_COMMAND_POWERDOWN = const(0x16)
|
_COMMAND_POWERDOWN = const(0x16)
|
||||||
PN532_COMMAND_RFCONFIGURATION = const(0x32)
|
_COMMAND_RFCONFIGURATION = const(0x32)
|
||||||
PN532_COMMAND_RFREGULATIONTEST = const(0x58)
|
_COMMAND_RFREGULATIONTEST = const(0x58)
|
||||||
PN532_COMMAND_INJUMPFORDEP = const(0x56)
|
_COMMAND_INJUMPFORDEP = const(0x56)
|
||||||
PN532_COMMAND_INJUMPFORPSL = const(0x46)
|
_COMMAND_INJUMPFORPSL = const(0x46)
|
||||||
PN532_COMMAND_INLISTPASSIVETARGET = const(0x4A)
|
_COMMAND_INLISTPASSIVETARGET = const(0x4A)
|
||||||
PN532_COMMAND_INATR = const(0x50)
|
_COMMAND_INATR = const(0x50)
|
||||||
PN532_COMMAND_INPSL = const(0x4E)
|
_COMMAND_INPSL = const(0x4E)
|
||||||
PN532_COMMAND_INDATAEXCHANGE = const(0x40)
|
_COMMAND_INDATAEXCHANGE = const(0x40)
|
||||||
PN532_COMMAND_INCOMMUNICATETHRU = const(0x42)
|
_COMMAND_INCOMMUNICATETHRU = const(0x42)
|
||||||
PN532_COMMAND_INDESELECT = const(0x44)
|
_COMMAND_INDESELECT = const(0x44)
|
||||||
PN532_COMMAND_INRELEASE = const(0x52)
|
_COMMAND_INRELEASE = const(0x52)
|
||||||
PN532_COMMAND_INSELECT = const(0x54)
|
_COMMAND_INSELECT = const(0x54)
|
||||||
PN532_COMMAND_INAUTOPOLL = const(0x60)
|
_COMMAND_INAUTOPOLL = const(0x60)
|
||||||
PN532_COMMAND_TGINITASTARGET = const(0x8C)
|
_COMMAND_TGINITASTARGET = const(0x8C)
|
||||||
PN532_COMMAND_TGSETGENERALBYTES = const(0x92)
|
_COMMAND_TGSETGENERALBYTES = const(0x92)
|
||||||
PN532_COMMAND_TGGETDATA = const(0x86)
|
_COMMAND_TGGETDATA = const(0x86)
|
||||||
PN532_COMMAND_TGSETDATA = const(0x8E)
|
_COMMAND_TGSETDATA = const(0x8E)
|
||||||
PN532_COMMAND_TGSETMETADATA = const(0x94)
|
_COMMAND_TGSETMETADATA = const(0x94)
|
||||||
PN532_COMMAND_TGGETINITIATORCOMMAND = const(0x88)
|
_COMMAND_TGGETINITIATORCOMMAND = const(0x88)
|
||||||
PN532_COMMAND_TGRESPONSETOINITIATOR = const(0x90)
|
_COMMAND_TGRESPONSETOINITIATOR = const(0x90)
|
||||||
PN532_COMMAND_TGGETTARGETSTATUS = const(0x8A)
|
_COMMAND_TGGETTARGETSTATUS = const(0x8A)
|
||||||
|
|
||||||
PN532_RESPONSE_INDATAEXCHANGE = const(0x41)
|
_RESPONSE_INDATAEXCHANGE = const(0x41)
|
||||||
PN532_RESPONSE_INLISTPASSIVETARGET = const(0x4B)
|
_RESPONSE_INLISTPASSIVETARGET = const(0x4B)
|
||||||
|
|
||||||
PN532_WAKEUP = const(0x55)
|
_WAKEUP = const(0x55)
|
||||||
|
|
||||||
PN532_SPI_STATREAD = const(0x02)
|
_SPI_STATREAD = const(0x02)
|
||||||
PN532_SPI_DATAWRITE = const(0x01)
|
_SPI_DATAWRITE = const(0x01)
|
||||||
PN532_SPI_DATAREAD = const(0x03)
|
_SPI_DATAREAD = const(0x03)
|
||||||
PN532_SPI_READY = const(0x01)
|
_SPI_READY = const(0x01)
|
||||||
|
|
||||||
PN532_I2C_ADDRESS = const(0x24)
|
_I2C_ADDRESS = const(0x24)
|
||||||
|
|
||||||
PN532_MIFARE_ISO14443A = 0x00
|
_MIFARE_ISO14443A = 0x00
|
||||||
|
|
||||||
# Mifare Commands
|
# Mifare Commands
|
||||||
MIFARE_CMD_AUTH_A = const(0x60)
|
MIFARE_CMD_AUTH_A = const(0x60)
|
||||||
|
@ -135,17 +135,20 @@ NDEF_URIPREFIX_URN_EPC_RAW = const(0x21)
|
||||||
NDEF_URIPREFIX_URN_EPC = const(0x22)
|
NDEF_URIPREFIX_URN_EPC = const(0x22)
|
||||||
NDEF_URIPREFIX_URN_NFC = const(0x23)
|
NDEF_URIPREFIX_URN_NFC = const(0x23)
|
||||||
|
|
||||||
PN532_GPIO_VALIDATIONBIT = 0x80
|
_GPIO_VALIDATIONBIT = const(0x80)
|
||||||
PN532_GPIO_P30 = 0
|
_GPIO_P30 = const(0)
|
||||||
PN532_GPIO_P31 = 1
|
_GPIO_P31 = const(1)
|
||||||
PN532_GPIO_P32 = 2
|
_GPIO_P32 = const(2)
|
||||||
PN532_GPIO_P33 = 3
|
_GPIO_P33 = const(3)
|
||||||
PN532_GPIO_P34 = 4
|
_GPIO_P34 = const(4)
|
||||||
PN532_GPIO_P35 = 5
|
_GPIO_P35 = const(5)
|
||||||
|
|
||||||
PN532_ACK = b'\x01\x00\x00\xFF\x00\xFF\x00'
|
_ACK = b'\x01\x00\x00\xFF\x00\xFF\x00'
|
||||||
PN532_FRAME_START = b'\x01\x00\x00\xFF'
|
_FRAME_START = b'\x01\x00\x00\xFF'
|
||||||
|
|
||||||
|
class BusyError(Exception):
|
||||||
|
"""Base class for exceptions in this module."""
|
||||||
|
pass
|
||||||
|
|
||||||
class PN532_I2C(object):
|
class PN532_I2C(object):
|
||||||
"""PN532 breakout board representation. Requires a SPI connection to the
|
"""PN532 breakout board representation. Requires a SPI connection to the
|
||||||
|
@ -162,7 +165,7 @@ class PN532_I2C(object):
|
||||||
the board's GPIO pins.
|
the board's GPIO pins.
|
||||||
"""
|
"""
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self._i2c = i2c_device.I2CDevice(i2c, PN532_I2C_ADDRESS)
|
self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
|
||||||
self._irq = irq
|
self._irq = irq
|
||||||
self.get_firmware_version()
|
self.get_firmware_version()
|
||||||
|
|
||||||
|
@ -179,16 +182,16 @@ class PN532_I2C(object):
|
||||||
# - Postamble (0x00)
|
# - Postamble (0x00)
|
||||||
length = len(data)
|
length = len(data)
|
||||||
frame = bytearray(length+8)
|
frame = bytearray(length+8)
|
||||||
frame[0] = PN532_PREAMBLE
|
frame[0] = _PREAMBLE
|
||||||
frame[1] = PN532_STARTCODE1
|
frame[1] = _STARTCODE1
|
||||||
frame[2] = PN532_STARTCODE2
|
frame[2] = _STARTCODE2
|
||||||
checksum = sum(frame[0:3])
|
checksum = sum(frame[0:3])
|
||||||
frame[3] = length & 0xFF
|
frame[3] = length & 0xFF
|
||||||
frame[4] = (~length + 1) & 0xFF
|
frame[4] = (~length + 1) & 0xFF
|
||||||
frame[5:-2] = data
|
frame[5:-2] = data
|
||||||
checksum += sum(data)
|
checksum += sum(data)
|
||||||
frame[-2] = ~checksum & 0xFF
|
frame[-2] = ~checksum & 0xFF
|
||||||
frame[-1] = PN532_POSTAMBLE
|
frame[-1] = _POSTAMBLE
|
||||||
# Send frame.
|
# Send frame.
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print('Write frame: ', [hex(i) for i in frame])
|
print('Write frame: ', [hex(i) for i in frame])
|
||||||
|
@ -200,6 +203,9 @@ class PN532_I2C(object):
|
||||||
# Build a read request frame.
|
# Build a read request frame.
|
||||||
frame = bytearray(count)
|
frame = bytearray(count)
|
||||||
with self._i2c:
|
with self._i2c:
|
||||||
|
self._i2c.readinto(frame, end=1) # read ready byte!
|
||||||
|
if frame[0] != 0x01: # not ready
|
||||||
|
raise BusyError
|
||||||
self._i2c.readinto(frame)
|
self._i2c.readinto(frame)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print("Reading: ", [hex(i) for i in frame])
|
print("Reading: ", [hex(i) for i in frame])
|
||||||
|
@ -258,7 +264,7 @@ class PN532_I2C(object):
|
||||||
"""
|
"""
|
||||||
# Build frame data with command and parameters.
|
# Build frame data with command and parameters.
|
||||||
data = bytearray(2+len(params))
|
data = bytearray(2+len(params))
|
||||||
data[0] = PN532_HOSTTOPN532
|
data[0] = _HOSTTOPN532
|
||||||
data[1] = command & 0xFF
|
data[1] = command & 0xFF
|
||||||
for i in range(len(params)):
|
for i in range(len(params)):
|
||||||
data[2+i] = params[i]
|
data[2+i] = params[i]
|
||||||
|
@ -267,14 +273,14 @@ class PN532_I2C(object):
|
||||||
if not self._wait_ready(timeout):
|
if not self._wait_ready(timeout):
|
||||||
return None
|
return None
|
||||||
# Verify ACK response and wait to be ready for function response.
|
# Verify ACK response and wait to be ready for function response.
|
||||||
if not PN532_ACK == self._read_data(len(PN532_ACK)):
|
if not _ACK == self._read_data(len(_ACK)):
|
||||||
raise RuntimeError('Did not receive expected ACK from PN532!')
|
raise RuntimeError('Did not receive expected ACK from PN532!')
|
||||||
if not self._wait_ready(timeout):
|
if not self._wait_ready(timeout):
|
||||||
return None
|
return None
|
||||||
# Read response bytes.
|
# Read response bytes.
|
||||||
response = self._read_frame(response_length+2)
|
response = self._read_frame(response_length+2)
|
||||||
# Check that response is for the called function.
|
# Check that response is for the called function.
|
||||||
if not (response[0] == PN532_PN532TOHOST and response[1] == (command+1)):
|
if not (response[0] == _PN532TOHOST and response[1] == (command+1)):
|
||||||
raise RuntimeError('Received unexpected command response!')
|
raise RuntimeError('Received unexpected command response!')
|
||||||
# Return response data.
|
# Return response data.
|
||||||
return response[2:]
|
return response[2:]
|
||||||
|
@ -283,10 +289,10 @@ class PN532_I2C(object):
|
||||||
"""Call PN532 GetFirmwareVersion function and return a tuple with the IC,
|
"""Call PN532 GetFirmwareVersion function and return a tuple with the IC,
|
||||||
Ver, Rev, and Support values.
|
Ver, Rev, and Support values.
|
||||||
"""
|
"""
|
||||||
response = self.call_function(PN532_COMMAND_GETFIRMWAREVERSION, 4, timeout=0.1)
|
response = self.call_function(_COMMAND_GETFIRMWAREVERSION, 4, timeout=0.1)
|
||||||
if response is None:
|
if response is None:
|
||||||
raise RuntimeError('Failed to detect the PN532')
|
raise RuntimeError('Failed to detect the PN532')
|
||||||
return (response[0], response[1], response[2], response[3])
|
return tuple(response)
|
||||||
|
|
||||||
def SAM_configuration(self):
|
def SAM_configuration(self):
|
||||||
"""Configure the PN532 to read MiFare cards."""
|
"""Configure the PN532 to read MiFare cards."""
|
||||||
|
@ -296,17 +302,21 @@ class PN532_I2C(object):
|
||||||
# - 0x01, use IRQ pin
|
# - 0x01, use IRQ pin
|
||||||
# Note that no other verification is necessary as call_function will
|
# Note that no other verification is necessary as call_function will
|
||||||
# check the command was executed as expected.
|
# check the command was executed as expected.
|
||||||
self.call_function(PN532_COMMAND_SAMCONFIGURATION, params=[0x01, 0x14, 0x01])
|
self.call_function(_COMMAND_SAMCONFIGURATION, params=[0x01, 0x14, 0x01])
|
||||||
|
|
||||||
def read_passive_target(self, card_baud=PN532_MIFARE_ISO14443A, timeout=1):
|
def read_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
|
||||||
"""Wait for a MiFare card to be available and return its UID when found.
|
"""Wait for a MiFare card to be available and return its UID when found.
|
||||||
Will wait up to timeout seconds and return None if no card is found,
|
Will wait up to timeout seconds and return None if no card is found,
|
||||||
otherwise a bytearray with the UID of the found card is returned.
|
otherwise a bytearray with the UID of the found card is returned.
|
||||||
"""
|
"""
|
||||||
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
|
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
|
||||||
response = self.call_function(PN532_COMMAND_INLISTPASSIVETARGET,
|
try:
|
||||||
params=[0x01, card_baud],
|
response = self.call_function(_COMMAND_INLISTPASSIVETARGET,
|
||||||
response_length=17)
|
params=[0x01, card_baud],
|
||||||
|
response_length=17,
|
||||||
|
timeout=timeout)
|
||||||
|
except BusyError:
|
||||||
|
return None # no card found!
|
||||||
# If no response is available return None to indicate no card is present.
|
# If no response is available return None to indicate no card is present.
|
||||||
if response is None:
|
if response is None:
|
||||||
return None
|
return None
|
||||||
|
@ -336,7 +346,7 @@ class PN532_I2C(object):
|
||||||
params[3:3+keylen] = key
|
params[3:3+keylen] = key
|
||||||
params[3+keylen:] = uid
|
params[3+keylen:] = uid
|
||||||
# Send InDataExchange request and verify response is 0x00.
|
# Send InDataExchange request and verify response is 0x00.
|
||||||
response = self.call_function(PN532_COMMAND_INDATAEXCHANGE,
|
response = self.call_function(_COMMAND_INDATAEXCHANGE,
|
||||||
params=params,
|
params=params,
|
||||||
response_length=1)
|
response_length=1)
|
||||||
return response[0] == 0x00
|
return response[0] == 0x00
|
||||||
|
@ -348,7 +358,7 @@ class PN532_I2C(object):
|
||||||
not read then None will be returned.
|
not read then None will be returned.
|
||||||
"""
|
"""
|
||||||
# Send InDataExchange request to read block of MiFare data.
|
# Send InDataExchange request to read block of MiFare data.
|
||||||
response = self.call_function(PN532_COMMAND_INDATAEXCHANGE,
|
response = self.call_function(_COMMAND_INDATAEXCHANGE,
|
||||||
params=[0x01, MIFARE_CMD_READ, block_number & 0xFF],
|
params=[0x01, MIFARE_CMD_READ, block_number & 0xFF],
|
||||||
response_length=17)
|
response_length=17)
|
||||||
# Check first response is 0x00 to show success.
|
# Check first response is 0x00 to show success.
|
||||||
|
@ -371,7 +381,7 @@ class PN532_I2C(object):
|
||||||
params[2] = block_number & 0xFF
|
params[2] = block_number & 0xFF
|
||||||
params[3:] = data
|
params[3:] = data
|
||||||
# Send InDataExchange request.
|
# Send InDataExchange request.
|
||||||
response = self.call_function(PN532_COMMAND_INDATAEXCHANGE,
|
response = self.call_function(_COMMAND_INDATAEXCHANGE,
|
||||||
params=params,
|
params=params,
|
||||||
response_length=1)
|
response_length=1)
|
||||||
return response[0] == 0x00
|
return response[0] == 0x00
|
||||||
|
|
23
examples/main.py
Normal file
23
examples/main.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from Adafruit_Circuitpython_PN532 import adafruit_pn532
|
||||||
|
from digitalio import DigitalInOut, Direction, Pull
|
||||||
|
import board
|
||||||
|
import time
|
||||||
|
import busio
|
||||||
|
# I2C connection:
|
||||||
|
i2c = busio.I2C(board.SCL, board.SDA)
|
||||||
|
pn532 = adafruit_pn532.PN532_I2C(i2c)
|
||||||
|
|
||||||
|
ic, ver, rev, support = pn532.get_firmware_version()
|
||||||
|
print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev))
|
||||||
|
|
||||||
|
# Configure PN532 to communicate with MiFare cards.
|
||||||
|
pn532.SAM_configuration()
|
||||||
|
|
||||||
|
print('Waiting for MiFare card...')
|
||||||
|
while True:
|
||||||
|
# Check if a card is available to read
|
||||||
|
uid = pn532.read_passive_target(timeout=0.25)
|
||||||
|
# Try again if no card is available.
|
||||||
|
if uid is None:
|
||||||
|
continue
|
||||||
|
print('Found card with UID:', [hex(i) for i in uid])
|
Loading…
Reference in a new issue