橙色 PI 上的双 RC522
Posted
技术标签:
【中文标题】橙色 PI 上的双 RC522【英文标题】:Dual RC522 on Orange PI 【发布时间】:2017-05-12 00:39:26 【问题描述】:我的目标是使用双 RFID RC522 阅读器和 Orange PI。 到目前为止,我已经设法使只有一个工作。 (阅读 google、armbian 和 orange pi 论坛)。这是我到目前为止所做的:
硬件连接:
single RC 522
MOSI ——————————> pin 19
MISO ——————————-> pin 21
SCLK ——————————-> pin 23
SDA ——————————–> pin 24
RST ———————————> pin 22
IRQ ———————————-> NONE
第二个读卡器使用共享引脚,除了 SDA,它转到橙色 PI 上的引脚 26
软件:
安装python开发
apt-get install python-dev
安装 orangepi_PC_gpio_pyH3 库
git clone https://github.com/duxingkei33/orangepi_PC_gpio_pyH3.git
cd orangepi_PC_gpio_pyH3
python setup.py install
安装 SPI-Py 库
git clone https://github.com/lthiery/SPI-Py.git
cd SPI-Py
python setup.py install
安装MFRC522-python
git clone https://github.com/rasplay/MFRC522-python.git
棘手的部分是,MFRC522-python 是在橙色 pi 上与 RASPBERRY PI 一起工作的,有人通过修改 MFRC522.py 提供了一个解决方案
#import RPi.GPIO as GPIO
import pyA20.gpio as GPIO
import spi
import signal
class MFRC522:
NRSTPD = 22
MAX_LEN = 16
PCD_IDLE = 0x00
PCD_AUTHENT = 0x0E
PCD_RECEIVE = 0x08
PCD_TRANSMIT = 0x04
PCD_TRANSCEIVE = 0x0C
PCD_RESETPHASE = 0x0F
PCD_CALCCRC = 0x03
PICC_REQIDL = 0x26
PICC_REQALL = 0x52
PICC_ANTICOLL = 0x93
PICC_SElECTTAG = 0x93
PICC_AUTHENT1A = 0x60
PICC_AUTHENT1B = 0x61
PICC_READ = 0x30
PICC_WRITE = 0xA0
PICC_DECREMENT = 0xC0
PICC_INCREMENT = 0xC1
PICC_RESTORE = 0xC2
PICC_TRANSFER = 0xB0
PICC_HALT = 0x50
MI_OK = 0
MI_NOTAGERR = 1
MI_ERR = 2
Reserved00 = 0x00
CommandReg = 0x01
CommIEnReg = 0x02
DivlEnReg = 0x03
CommIrqReg = 0x04
DivIrqReg = 0x05
ErrorReg = 0x06
Status1Reg = 0x07
Status2Reg = 0x08
FIFODataReg = 0x09
FIFOLevelReg = 0x0A
WaterLevelReg = 0x0B
ControlReg = 0x0C
BitFramingReg = 0x0D
CollReg = 0x0E
Reserved01 = 0x0F
Reserved10 = 0x10
ModeReg = 0x11
TxModeReg = 0x12
RxModeReg = 0x13
TxControlReg = 0x14
TxAutoReg = 0x15
TxSelReg = 0x16
RxSelReg = 0x17
RxThresholdReg = 0x18
DemodReg = 0x19
Reserved11 = 0x1A
Reserved12 = 0x1B
MifareReg = 0x1C
Reserved13 = 0x1D
Reserved14 = 0x1E
SerialSpeedReg = 0x1F
Reserved20 = 0x20
CRCResultRegM = 0x21
CRCResultRegL = 0x22
Reserved21 = 0x23
ModWidthReg = 0x24
Reserved22 = 0x25
RFCfgReg = 0x26
GsNReg = 0x27
CWGsPReg = 0x28
ModGsPReg = 0x29
TModeReg = 0x2A
TPrescalerReg = 0x2B
TReloadRegH = 0x2C
TReloadRegL = 0x2D
TCounterValueRegH = 0x2E
TCounterValueRegL = 0x2F
Reserved30 = 0x30
TestSel1Reg = 0x31
TestSel2Reg = 0x32
TestPinEnReg = 0x33
TestPinValueReg = 0x34
TestBusReg = 0x35
AutoTestReg = 0x36
VersionReg = 0x37
AnalogTestReg = 0x38
TestDAC1Reg = 0x39
TestDAC2Reg = 0x3A
TestADCReg = 0x3B
Reserved31 = 0x3C
Reserved32 = 0x3D
Reserved33 = 0x3E
Reserved34 = 0x3F
serNum = []
def __init__(self,spd=1000000):
spi.openSPI(speed=spd)
# GPIO.setmode(GPIO.BOARD)
# GPIO.setup(22, GPIO.OUT)
# GPIO.output(self.NRSTPD, 1)
self.MFRC522_Init()
def MFRC522_Reset(self):
self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE)
def Write_MFRC522(self,addr,val):
spi.transfer(((addr<<1)&0x7E,val))
def Read_MFRC522(self,addr):
val = spi.transfer((((addr<<1)&0x7E) | 0x80,0))
return val[1]
def SetBitMask(self, reg, mask):
tmp = self.Read_MFRC522(reg)
self.Write_MFRC522(reg, tmp | mask)
def ClearBitMask(self, reg, mask):
tmp = self.Read_MFRC522(reg);
self.Write_MFRC522(reg, tmp & (~mask))
def AntennaOn(self):
temp = self.Read_MFRC522(self.TxControlReg)
if(~(temp & 0x03)):
self.SetBitMask(self.TxControlReg, 0x03)
def AntennaOff(self):
self.ClearBitMask(self.TxControlReg, 0x03)
def MFRC522_ToCard(self,command,sendData):
backData = []
backLen = 0
status = self.MI_ERR
irqEn = 0x00
waitIRq = 0x00
lastBits = None
n = 0
i = 0
if command == self.PCD_AUTHENT:
irqEn = 0x12
waitIRq = 0x10
if command == self.PCD_TRANSCEIVE:
irqEn = 0x77
waitIRq = 0x30
self.Write_MFRC522(self.CommIEnReg, irqEn|0x80)
self.ClearBitMask(self.CommIrqReg, 0x80)
self.SetBitMask(self.FIFOLevelReg, 0x80)
self.Write_MFRC522(self.CommandReg, self.PCD_IDLE);
while(i<len(sendData)):
self.Write_MFRC522(self.FIFODataReg, sendData[i])
i = i+1
self.Write_MFRC522(self.CommandReg, command)
if command == self.PCD_TRANSCEIVE:
self.SetBitMask(self.BitFramingReg, 0x80)
i = 2000
while True:
n = self.Read_MFRC522(self.CommIrqReg)
i = i - 1
if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)):
break
self.ClearBitMask(self.BitFramingReg, 0x80)
if i != 0:
if (self.Read_MFRC522(self.ErrorReg) & 0x1B)==0x00:
status = self.MI_OK
if n & irqEn & 0x01:
status = self.MI_NOTAGERR
if command == self.PCD_TRANSCEIVE:
n = self.Read_MFRC522(self.FIFOLevelReg)
lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
if lastBits != 0:
backLen = (n-1)*8 + lastBits
else:
backLen = n*8
if n == 0:
n = 1
if n > self.MAX_LEN:
n = self.MAX_LEN
i = 0
while i<n:
backData.append(self.Read_MFRC522(self.FIFODataReg))
i = i + 1;
else:
status = self.MI_ERR
return (status,backData,backLen)
def MFRC522_Request(self, reqMode):
status = None
backBits = None
TagType = []
self.Write_MFRC522(self.BitFramingReg, 0x07)
TagType.append(reqMode);
(status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType)
if ((status != self.MI_OK) | (backBits != 0x10)):
status = self.MI_ERR
return (status,backBits)
def MFRC522_Anticoll(self):
backData = []
serNumCheck = 0
serNum = []
self.Write_MFRC522(self.BitFramingReg, 0x00)
serNum.append(self.PICC_ANTICOLL)
serNum.append(0x20)
(status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,serNum)
if(status == self.MI_OK):
i = 0
if len(backData)==5:
while i<4:
serNumCheck = serNumCheck ^ backData[i]
i = i + 1
if serNumCheck != backData[i]:
status = self.MI_ERR
else:
status = self.MI_ERR
return (status,backData)
def CalulateCRC(self, pIndata):
self.ClearBitMask(self.DivIrqReg, 0x04)
self.SetBitMask(self.FIFOLevelReg, 0x80);
i = 0
while i<len(pIndata):
self.Write_MFRC522(self.FIFODataReg, pIndata[i])
i = i + 1
self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC)
i = 0xFF
while True:
n = self.Read_MFRC522(self.DivIrqReg)
i = i - 1
if not ((i != 0) and not (n&0x04)):
break
pOutData = []
pOutData.append(self.Read_MFRC522(self.CRCResultRegL))
pOutData.append(self.Read_MFRC522(self.CRCResultRegM))
return pOutData
def MFRC522_SelectTag(self, serNum):
backData = []
buf = []
buf.append(self.PICC_SElECTTAG)
buf.append(0x70)
i = 0
while i<5:
buf.append(serNum[i])
i = i + 1
pOut = self.CalulateCRC(buf)
buf.append(pOut[0])
buf.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
if (status == self.MI_OK) and (backLen == 0x18):
print "Size: " + str(backData[0])
return backData[0]
else:
return 0
def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
buff = []
buff.append(authMode)
buff.append(BlockAddr)
i = 0
while(i < len(Sectorkey)):
buff.append(Sectorkey[i])
i = i + 1
i = 0
while(i < len(serNum)):
buff.append(serNum[i])
i = i +1
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT,buff)
if not(status == self.MI_OK):
print "AUTH ERROR!!"
if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0:
print "AUTH ERROR(status2reg & 0x08) != 0"
return status
def MFRC522_Read(self, blockAddr):
recvData = []
recvData.append(self.PICC_READ)
recvData.append(blockAddr)
pOut = self.CalulateCRC(recvData)
recvData.append(pOut[0])
recvData.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData)
if not(status == self.MI_OK):
print "Error while reading!"
print "Got data size: "+str(backLen)
i = 0
if len(backData) == 16:
print "Sector "+str(blockAddr)+" "+str(backData)
def MFRC522_Write(self, blockAddr, writeData):
buff = []
buff.append(self.PICC_WRITE)
buff.append(blockAddr)
crc = self.CalulateCRC(buff)
buff.append(crc[0])
buff.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff)
if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A):
status = self.MI_ERR
print str(backLen)+" backdata &0x0F == 0x0A "+str(backData[0]&0x0F)
if status == self.MI_OK:
i = 0
buf = []
while i < 16:
buf.append(writeData[i])
i = i + 1
crc = self.CalulateCRC(buf)
buf.append(crc[0])
buf.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,buf)
if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A):
print "Error while writing"
if status == self.MI_OK:
print "Data writen"
def MFRC522_Init(self):
# GPIO.output(self.NRSTPD, 1)
self.MFRC522_Reset();
self.Write_MFRC522(self.TModeReg, 0x8D)
self.Write_MFRC522(self.TPrescalerReg, 0x3E)
self.Write_MFRC522(self.TReloadRegL, 30)
self.Write_MFRC522(self.TReloadRegH, 0)
self.Write_MFRC522(self.TxAutoReg, 0x40)
self.Write_MFRC522(self.ModeReg, 0x3D)
self.AntennaOn()
def GPIO_CLEEN(self):
GPIO.cleanup()
注释了 4 行 (109 - 111, 357),第一行被替换为使用 pyA20.gpio 而不是 RPi.GPIO。
之后,我运行 read.py,它就像一个魅力。
import MFRC522
import signal
continue_reading = True
MIFAREReader = MFRC522.MFRC522()
cardA = [5,74,28,185,234]
cardB = [83,164,247,164,164]
cardC = [20,38,121,207,132]
def end_read(signal, frame):
global continue_reading
continue_reading = False
print "Ctrl+C captured, ending read."
MIFAREReader.GPIO_CLEEN()
signal.signal(signal.SIGINT, end_read)
while continue_reading:
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
if status == MIFAREReader.MI_OK:
print "Card detected"
(status,backData) = MIFAREReader.MFRC522_Anticoll()
if status == MIFAREReader.MI_OK:
print "Card read UID: "+str(backData[0])+","+str(backData[1])+","+str(backData[2])+","+str(backData[3])+","+str(backData[4])
if backData == cardA:
print "is Card A"
elif backData == cardB:
print "is Card B"
elif backData == cardC:
print "is Card C"
else:
print "wrong Card"
这就是在 ORANGE PI PC 上使用阅读器的方法。我用谷歌搜索并进一步阅读,为了使用第二个阅读器,我需要修改我评论的完全相同的行以使其工作。它用那个 SDA PIN 控制 RC522,选择从哪个读卡器读取数据。我尝试取消注释其中任何一个,但出现错误。看起来那些使用特定的 RPi.GPIO 功能。我的python知识非常基础。我试图找到描述的引脚在哪里使用,但失败了。试图用 26 替换那个引脚 24,以便从第二个读取的数据中读取数据。至今没有成功。
【问题讨论】:
我在 Orange Pi Zero 上尝试相同的步骤,甚至单个 MFRC-522 也无法正常工作。我尝试了图像 armbian image 5.24 (Debian Jessie)/5.25(Ubuntu Xenial)。除了此处提到的步骤之外,您是否启用了其他功能? 对不起,迟到的答案,我没有,但是因为第二个读者没有成功放弃该项目,现在半年前,再次尝试,甚至无法启动单个 rc522,(不同的 opi 板和 armbian发布),不知道为什么,没有显示错误,也没有读数 让它工作,这里描述了如何。 forum.armbian.com/index.php?/topic/… @Gailu(以及任何其他像我一样发现这个的人)我让 MFRC522 在 Orangepi Zero 上工作。这些说明不适用于零。我浏览了有关引脚排列的所有详细信息,您可以使用一个命令下载/安装。看看:github.com/BiTinerary/OrangePiZeroMFRC522 对于这条指令不起作用的人,在新版本的armbian上有2个模块需要加入黑名单才能工作:blacklist pcf8591 blacklist bmp085,卸载它们不起作用,需要加入黑名单并重新启动系统 【参考方案1】:我的设置非常相似,也遇到过类似的问题。
似乎我设法解决了它们,就在昨晚! :)
我的项目涉及:
橙色圆周率零 12-13个RFID-RC522模块(目前只有2个) SPI 通信 因为我需要大量数字输出引脚,所以我将使用 12-13 个移位寄存器 IC (74HC595)方法和问题:
将SCK、MISO和MOSI引脚连接在一起,将RST拉高,通过修改MFRC522类分别控制每条SS线。不行,可能是我的时间不对,应该连接逻辑分析仪看看。
将 SCK、MISO、MOSI 和 SS 引脚连接在一起,将 RST 拉高,打开/关闭 Vcc 或 GND 引脚(关闭除一个之外的所有读取器,从那个读取,切换到下一个)。没有工作,并提出了非常有趣的情况。在某些情况下,即使 Vcc 或 GND 或两个引脚都断开连接,RFID 模块也可以读取卡片!!!信号引脚有一些明显的泄漏电流。在这里,我尝试了解复用器、移位寄存器、线路驱动器 IC,但没有任何效果。
最后,采用可行的方法。将 SCK、MISO、MOSI 和 SS 引脚连接在一起,控制 RST 引脚。 RST 拉低时关闭模块。向上拉即可开机。因此,最初所有 RST 引脚都被拉低,然后一个接一个地被拉高,允许模块启动的小延迟(我使用 200ms),调用 MFRC522_Init()(不确定每个周期是否有必要,不伤害我猜),执行读取,将 RST 拉低,切换到下一个模块。这种方法的好处是低功耗:2 个断电模块消耗 3.6mA,1 个开启 - 1 个关闭消耗 18mA。
希望这会有所帮助! :)
【讨论】:
【参考方案2】:已经有一段时间了,我学到了一点,让两个 RC522 阅读器在 ESP8266 上工作,但同样的场景可以在 ORANCE PI 上使用,在我之前的尝试中,我试图让它们在单独的 SPI 接口中工作,现在我使用一个接口并用 SS (SDA) 信号控制它们,当它发送低电平时,阅读器处于活动状态进行通信。这种方式可以使用多个并以这种方式控制它们。希望对在这里寻求答案的人有所帮助:)
【讨论】:
以上是关于橙色 PI 上的双 RC522的主要内容,如果未能解决你的问题,请参考以下文章
Raspberry Pi 3B 和 RFID RC522 - Python TypeError