2015-12-15 33 views
6

Sto cercando un modo per utilizzare l'RFID "RC522" su un Raspberry Pi 2.0 su Windows IOT.RFID RC522 Raspberry PI 2 Windows IOT

è ovviamente non ufficiale compatibile ...

Quello ufficiale (scheda demo OM5577) è modo costoso in Francia (non ho trovato alcun rivenditore che lo ha venduto senza un sacco di spese di spedizione (il costo totale è di circa 80 $)).

L'RC522 è economico (< 10 $). Funziona alla grande su Arduino e su Raspberry Pi 2.0 su Linux. Ma sfortunatamente non ancora su Windows IOT.

In realtà sto usando un arduino come un ponte ... Non è una soluzione ottimale; ma funzionano bene e costano sempre la metà del prezzo rispetto all'OM5577.

ho trovato this progetto e cercare di convertirli in un progetto VS (Visual C++) con il Windows IOT SIP e IO ... io miseramente fallire ...

Nel mio sogno sarei stato in grado per utilizzare questo dispositivo in C# con la classe standard IOT "ProximityDevice" di Windows.

Avete qualche idea per me?

Grazie in anticipo.

risposta

14

Ho finalmente trovato una soluzione.

Non ho successo nella portabilità dell'arudino; quindi ho usato il progetto this come punto di partenza.

Il progetto è scritto in C#. Ho appena adattato il codice per Windows IOT GPIO e SPI. Sta funzionando!

principale

 var mfrc = new Mfrc522(); 
     await mfrc.InitIO(); 

     while (true) 
     { 
      if (mfrc.IsTagPresent()) 
      { 
       var uid = mfrc.ReadUid(); 

       mfrc.HaltTag(); 
      } 

     } 

Biblioteca Mfrc522Lib.cs (tutto in uno)

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 
using Windows.Devices.Enumeration; 
using Windows.Devices.Gpio; 
using Windows.Devices.Spi; 

namespace Mfrc522Lib 
{ 
    public static class Registers 
    { 
     private const byte bitFraming = 0x0D; 
     private const byte comIrq = 0x04; 
     private const byte comIrqEnable = 0x02; 
     private const byte command = 0x01; 
     private const byte control = 0x0C; 
     private const byte error = 0x06; 
     private const byte fifoData = 0x09; 
     private const byte fifoLevel = 0x0A; 
     private const byte mode = 0x11; 
     private const byte rxMode = 0x13; 
     private const byte timerMode = 0x2A; 
     private const byte timerPrescaler = 0x2B; 
     private const byte timerReloadHigh = 0x2C; 
     private const byte timerReloadLow = 0x2D; 
     private const byte txAsk = 0x15; 
     private const byte txControl = 0x14; 
     private const byte txMode = 0x12; 
     private const byte version = 0x37; 

     public static byte BitFraming 
     { 
      get 
      { 
       return bitFraming; 
      } 
     } 

     public static byte ComIrq 
     { 
      get 
      { 
       return comIrq; 
      } 
     } 

     public static byte ComIrqEnable 
     { 
      get 
      { 
       return comIrqEnable; 
      } 
     } 

     public static byte Command 
     { 
      get 
      { 
       return command; 
      } 
     } 

     public static byte Control 
     { 
      get 
      { 
       return control; 
      } 
     } 

     public static byte Error 
     { 
      get 
      { 
       return error; 
      } 
     } 

     public static byte FifoData 
     { 
      get 
      { 
       return fifoData; 
      } 
     } 

     public static byte FifoLevel 
     { 
      get 
      { 
       return fifoLevel; 
      } 
     } 

     public static byte Mode 
     { 
      get 
      { 
       return mode; 
      } 
     } 

     public static byte RxMode 
     { 
      get 
      { 
       return rxMode; 
      } 
     } 

     public static byte TimerMode 
     { 
      get 
      { 
       return timerMode; 
      } 
     } 

     public static byte TimerPrescaler 
     { 
      get 
      { 
       return timerPrescaler; 
      } 
     } 

     public static byte TimerReloadHigh 
     { 
      get 
      { 
       return timerReloadHigh; 
      } 
     } 

     public static byte TimerReloadLow 
     { 
      get 
      { 
       return timerReloadLow; 
      } 
     } 

     public static byte TxAsk 
     { 
      get 
      { 
       return txAsk; 
      } 
     } 

     public static byte TxControl 
     { 
      get 
      { 
       return txControl; 
      } 
     } 

     public static byte TxMode 
     { 
      get 
      { 
       return txMode; 
      } 
     } 

     public static byte Version 
     { 
      get 
      { 
       return version; 
      } 
     } 
    } 
    public static class PiccResponses 
    { 
     private const ushort answerToRequest = 0x0004; 
     private const byte selectAcknowledge = 0x08; 
     private const byte acknowledge = 0x0A; 

     public static byte Acknowledge 
     { 
      get 
      { 
       return acknowledge; 
      } 
     } 

     public static byte SelectAcknowledge 
     { 
      get 
      { 
       return selectAcknowledge; 
      } 
     } 

     public static ushort AnswerToRequest 
     { 
      get 
      { 
       return answerToRequest; 
      } 
     } 
    } 
    public static class PiccCommands 
    { 
     private const byte anticollision_1 = 0x93; 
     private const byte anticollision_2 = 0x20; 
     private const byte authenticateKeyA = 0x60; 
     private const byte authenticateKeyB = 0x61; 
     private const byte halt_1 = 0x50; 
     private const byte halt_2 = 0x00; 
     private const byte read = 0x30; 
     private const byte request = 0x26; 
     private const byte select_1 = 0x93; 
     private const byte select_2 = 0x70; 
     private const byte write = 0xA0; 

     public static byte AuthenticateKeyA 
     { 
      get 
      { 
       return authenticateKeyA; 
      } 
     } 

     public static byte AuthenticateKeyB 
     { 
      get 
      { 
       return authenticateKeyB; 
      } 
     } 

     public static byte Halt_1 
     { 
      get 
      { 
       return halt_1; 
      } 
     } 

     public static byte Halt_2 
     { 
      get 
      { 
       return halt_2; 
      } 
     } 

     public static byte Read 
     { 
      get 
      { 
       return read; 
      } 
     } 

     public static byte Request 
     { 
      get 
      { 
       return request; 
      } 
     } 

     public static byte Select_1 
     { 
      get 
      { 
       return select_1; 
      } 
     } 

     public static byte Select_2 
     { 
      get 
      { 
       return select_2; 
      } 
     } 

     public static byte Write 
     { 
      get 
      { 
       return write; 
      } 
     } 

     public static byte Anticollision_1 
     { 
      get 
      { 
       return anticollision_1; 
      } 
     } 

     public static byte Anticollision_2 
     { 
      get 
      { 
       return anticollision_2; 
      } 
     } 
    } 

    public static class PcdCommands 
    { 
     private const byte idle = 0x00; 
     private const byte mifareAuthenticate = 0x0E; 
     private const byte transceive = 0x0C; 

     public static byte Idle 
     { 
      get 
      { 
       return idle; 
      } 
     } 

     public static byte MifareAuthenticate 
     { 
      get 
      { 
       return mifareAuthenticate; 
      } 
     } 

     public static byte Transceive 
     { 
      get 
      { 
       return transceive; 
      } 
     } 
    } 


    public class Uid 
    { 
     public byte Bcc { get; private set; } 
     public byte[] Bytes { get; private set; } 
     public byte[] FullUid { get; private set; } 
     public bool IsValid { get; private set; } 

     internal Uid(byte[] uid) 
     { 
      FullUid = uid; 
      Bcc = uid[4]; 

      Bytes = new byte[4]; 
      System.Array.Copy(FullUid, 0, Bytes, 0, 4); 

      foreach (var b in Bytes) 
      { 
       if (b != 0x00) 
        IsValid = true; 
      } 
     } 

     public sealed override bool Equals(object obj) 
     { 
      if (!(obj is Uid)) 
       return false; 

      var uidWrapper = (Uid)obj; 

      for (int i = 0; i < 5; i++) 
      { 
       if (FullUid[i] != uidWrapper.FullUid[i]) 
        return false; 
      } 

      return true; 
     } 

     public sealed override int GetHashCode() 
     { 
      int uid = 0; 

      for (int i = 0; i < 4; i++) 
       uid |= Bytes[i] << (i * 8); 

      return uid; 
     } 

     public sealed override string ToString() 
     { 
      var formatString = "x" + (Bytes.Length * 2); 
      return GetHashCode().ToString(formatString); 
     } 
    } 

    public sealed class Mfrc522 
    { 
     public SpiDevice _spi { get; private set; } 
     public GpioController IoController { get; private set; } 
     public GpioPin _resetPowerDown { get; private set; } 

     /* Uncomment for Raspberry Pi 2 */ 
     private const string SPI_CONTROLLER_NAME = "SPI0"; 
     private const Int32 SPI_CHIP_SELECT_LINE = 0; 
     private const Int32 RESET_PIN = 25; 

     internal async Task InitIO() 
     { 

      try 
      { 
       IoController = GpioController.GetDefault(); 

       _resetPowerDown = IoController.OpenPin(RESET_PIN); 
       _resetPowerDown.Write(GpioPinValue.High); 
       _resetPowerDown.SetDriveMode(GpioPinDriveMode.Output); 
      } 
      /* If initialization fails, throw an exception */ 
      catch (Exception ex) 
      { 
       throw new Exception("GPIO initialization failed", ex); 
      } 

      try 
      { 
       var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE); 
       settings.ClockFrequency = 1000000; 
       settings.Mode = SpiMode.Mode0; 

       String spiDeviceSelector = SpiDevice.GetDeviceSelector(); 
       IReadOnlyList<DeviceInformation> devices = await DeviceInformation.FindAllAsync(spiDeviceSelector); 

       _spi = await SpiDevice.FromIdAsync(devices[0].Id, settings); 

      } 
      /* If initialization fails, display the exception and stop running */ 
      catch (Exception ex) 
      { 
       throw new Exception("SPI Initialization Failed", ex); 
      } 


      Reset(); 
     } 

     public void Reset() 
     { 
      _resetPowerDown.Write(GpioPinValue.Low); 
      System.Threading.Tasks.Task.Delay(50).Wait(); 
      _resetPowerDown.Write(GpioPinValue.High); 
      System.Threading.Tasks.Task.Delay(50).Wait(); 

      // Force 100% ASK modulation 
      WriteRegister(Registers.TxAsk, 0x40); 

      // Set CRC to 0x6363 
      WriteRegister(Registers.Mode, 0x3D); 

      // Enable antenna 
      SetRegisterBits(Registers.TxControl, 0x03); 
     } 


     public bool IsTagPresent() 
     { 
      // Enable short frames 
      WriteRegister(Registers.BitFraming, 0x07); 

      // Transceive the Request command to the tag 
      Transceive(false, PiccCommands.Request); 

      // Disable short frames 
      WriteRegister(Registers.BitFraming, 0x00); 

      // Check if we found a card 
      return GetFifoLevel() == 2 && ReadFromFifoShort() == PiccResponses.AnswerToRequest; 
     } 

     public Uid ReadUid() 
     { 
      // Run the anti-collision loop on the card 
      Transceive(false, PiccCommands.Anticollision_1, PiccCommands.Anticollision_2); 

      // Return tag UID from FIFO 
      return new Uid(ReadFromFifo(5)); 
     } 

     public void HaltTag() 
     { 
      // Transceive the Halt command to the tag 
      Transceive(false, PiccCommands.Halt_1, PiccCommands.Halt_2); 
     } 

     public bool SelectTag(Uid uid) 
     { 
      // Send Select command to tag 
      var data = new byte[7]; 
      data[0] = PiccCommands.Select_1; 
      data[1] = PiccCommands.Select_2; 
      uid.FullUid.CopyTo(data, 2); 

      Transceive(true, data); 

      return GetFifoLevel() == 1 && ReadFromFifo() == PiccResponses.SelectAcknowledge; 
     } 

     internal byte[] ReadBlock(byte blockNumber, Uid uid, byte[] keyA = null, byte[] keyB = null) 
     { 
      if (keyA != null) 
       MifareAuthenticate(PiccCommands.AuthenticateKeyA, blockNumber, uid, keyA); 
      else if (keyB != null) 
       MifareAuthenticate(PiccCommands.AuthenticateKeyB, blockNumber, uid, keyB); 
      else 
       return null; 

      // Read block 
      Transceive(true, PiccCommands.Read, blockNumber); 

      return ReadFromFifo(16); 
     } 

     internal bool WriteBlock(byte blockNumber, Uid uid, byte[] data, byte[] keyA = null, byte[] keyB = null) 
     { 
      if (keyA != null) 
       MifareAuthenticate(PiccCommands.AuthenticateKeyA, blockNumber, uid, keyA); 
      else if (keyB != null) 
       MifareAuthenticate(PiccCommands.AuthenticateKeyB, blockNumber, uid, keyB); 
      else 
       return false; 

      // Write block 
      Transceive(true, PiccCommands.Write, blockNumber); 

      if (ReadFromFifo() != PiccResponses.Acknowledge) 
       return false; 

      // Make sure we write only 16 bytes 
      var buffer = new byte[16]; 
      data.CopyTo(buffer, 0); 

      Transceive(true, buffer); 

      return ReadFromFifo() == PiccResponses.Acknowledge; 
     } 


     protected void MifareAuthenticate(byte command, byte blockNumber, Uid uid, byte[] key) 
     { 
      // Put reader in Idle mode 
      WriteRegister(Registers.Command, PcdCommands.Idle); 

      // Clear the FIFO 
      SetRegisterBits(Registers.FifoLevel, 0x80); 

      // Create Authentication packet 
      var data = new byte[12]; 
      data[0] = command; 
      data[1] = (byte)(blockNumber & 0xFF); 
      key.CopyTo(data, 2); 
      uid.Bytes.CopyTo(data, 8); 

      WriteToFifo(data); 

      // Put reader in MfAuthent mode 
      WriteRegister(Registers.Command, PcdCommands.MifareAuthenticate); 

      // Wait for (a generous) 25 ms 
      System.Threading.Tasks.Task.Delay(25).Wait(); 
     } 

     protected void Transceive(bool enableCrc, params byte[] data) 
     { 
      if (enableCrc) 
      { 
       // Enable CRC 
       SetRegisterBits(Registers.TxMode, 0x80); 
       SetRegisterBits(Registers.RxMode, 0x80); 
      } 

      // Put reader in Idle mode 
      WriteRegister(Registers.Command, PcdCommands.Idle); 

      // Clear the FIFO 
      SetRegisterBits(Registers.FifoLevel, 0x80); 

      // Write the data to the FIFO 
      WriteToFifo(data); 

      // Put reader in Transceive mode and start sending 
      WriteRegister(Registers.Command, PcdCommands.Transceive); 
      SetRegisterBits(Registers.BitFraming, 0x80); 

      // Wait for (a generous) 25 ms 
      System.Threading.Tasks.Task.Delay(25).Wait(); 

      // Stop sending 
      ClearRegisterBits(Registers.BitFraming, 0x80); 

      if (enableCrc) 
      { 
       // Disable CRC 
       ClearRegisterBits(Registers.TxMode, 0x80); 
       ClearRegisterBits(Registers.RxMode, 0x80); 
      } 
     } 


     protected byte[] ReadFromFifo(int length) 
     { 
      var buffer = new byte[length]; 

      for (int i = 0; i < length; i++) 
       buffer[i] = ReadRegister(Registers.FifoData); 

      return buffer; 
     } 

     protected byte ReadFromFifo() 
     { 
      return ReadFromFifo(1)[0]; 
     } 

     protected void WriteToFifo(params byte[] values) 
     { 
      foreach (var b in values) 
       WriteRegister(Registers.FifoData, b); 
     } 

     protected int GetFifoLevel() 
     { 
      return ReadRegister(Registers.FifoLevel); 
     } 


     protected byte ReadRegister(byte register) 
     { 
      register <<= 1; 
      register |= 0x80; 

      var writeBuffer = new byte[] { register, 0x00 }; 

      return TransferSpi(writeBuffer)[1]; 
     } 

     protected ushort ReadFromFifoShort() 
     { 
      var low = ReadRegister(Registers.FifoData); 
      var high = (ushort)(ReadRegister(Registers.FifoData) << 8); 

      return (ushort)(high | low); 
     } 

     protected void WriteRegister(byte register, byte value) 
     { 
      register <<= 1; 

      var writeBuffer = new byte[] { register, value }; 

      TransferSpi(writeBuffer); 
     } 

     protected void SetRegisterBits(byte register, byte bits) 
     { 
      var currentValue = ReadRegister(register); 
      WriteRegister(register, (byte)(currentValue | bits)); 
     } 

     protected void ClearRegisterBits(byte register, byte bits) 
     { 
      var currentValue = ReadRegister(register); 
      WriteRegister(register, (byte)(currentValue & ~bits)); 
     } 


     private byte[] TransferSpi(byte[] writeBuffer) 
     { 
      var readBuffer = new byte[writeBuffer.Length]; 

      _spi.TransferFullDuplex(writeBuffer, readBuffer); 

      return readBuffer; 
     } 
    } 
} 

Schema

Schema

+0

Ho usato questa libreria Mfrc522Lib nel mio progetto, è molto goog ma non può leggere il blocco con la funzione ReadBlock. per favore aiutatemi per questo compito –

+0

Come posso importare la libreria Mfrc522Lib.cs nel mio progetto? –

1

Poiché utilizza SPI, non dovrebbe esserci un problema di compatibilità hardware. Se non si desidera tradurre il codice Arduino esistente, Microsoft dispone di una tecnologia che consente di utilizzare schizzi e librerie Arduino esistenti. Puoi leggere maggiori informazioni qui: http://ms-iot.github.io/content/en-US/win10/ArduinoWiringProjectGuide.htm

+1

Grazie. Sto provando questa soluzione. Il codice è compilato su Visual Studio. Tutti i pin sono legati. Ma ho già un timeout sulla comunicazione. Guardo di più negli ultimi giorni e pubblicherò la soluzione se funziona. – David