橙色 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

rfid-rc522用串口怎么接线

rc522寻卡失败并且出现该卡片为其他类型

使用 RPi2 在 Python 中使用 RC522 和 USB SERIAL 读取标签 UID

005_STM32程序移植之_RC522读卡模块

非接触式读写芯片--SI522超低功耗13.56Mhz/PIN对PIN完全兼容RC522