Utilizzare il Netduino per calcolare il crc del tag rfid

Nell’articolo scritto qualche tempo, che mostrava come impiegare un Netduino ed un lettore rfid ID-12 della Innovations, ho descritto solamente la parte che acquisiva l’id del tag, senza analizzare come calcolare il crc indispensabile per avere la certezza che il dato letto fosse corretto.

Riprendo questo argomento su segnalazione di una gentilissima visitatrice Sabrina Cosolo, che ringrazio per avermi fatto notare un errore nell’illustrazione del calcolo del crc, infatti scrissi che i due byte del crc fossero ottenuti ponendo in OR i 10 byte dell’id del tag.
Questo non è vero in quanto bisogna mettere in XOR i valori esadecimali ottenuti dalla conversione in ASCII dei byte letti dal lettore.

Mi spiego meglio impiegando l’illustrazione seguente

calcolare il crc lettore Innovations ID-12

i 10 byte rappresentano l’id del tag, mentre i due byte rappresentano il valore di crc. Il calcolo viene eseguito convertendo i singoli byte in valori ASCII, per ottenere 5 valori esadecimali prendendo 2 byte alla volta, come visibile in figura. Eseguendo un calcolo XOR di questi valori esadecimali otteniamo il calore del CRC.

Ora la difficoltà che ho riscontrato è quella di convertire un byte in un valore esadecimale, semplicissimo da fare con il .Net framework ma non altrettanto con la versione micro (non sono riuscito a trovare delle risorse che svolgessero questo compito!), quindi ho scritto un po di codice per arrangiarmi, mi rendo conto che non è il massimo ma diciamo che per questo esempio funziona!!

Ho commentato il codice per spiegare meglio il funzionamento.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

using System.IO.Ports;
using System.Text;

namespace Netduino_ID12Reader
{
public class Program
{
    public static Byte ConvHexToByte(String Value)
    {
      if (Value.Length == 2)
      {
        String str1 = Value.Substring(0, 1);
        String str2 = Value.Substring(1, 1);

        if (str1.ToUpper() == "A")
          str1 = "10";

        if (str1.ToUpper() == "B")
          str1 = "11";

        if (str1.ToUpper() == "C")
          str1 = "12";

        if (str1.ToUpper() == "D")
          str1 = "13";

        if (str1.ToUpper() == "E")
          str1 = "14";

        if (str1.ToUpper() == "F")
          str1 = "15";

        //###########################
        if (str2.ToUpper() == "A")
          str2 = "10";

        if (str2.ToUpper() == "B")
          str2 = "11";

        if (str2.ToUpper() == "C")
          str2 = "12";

        if (str2.ToUpper() == "D")
          str2 = "13";

        if (str2.ToUpper() == "E")
          str2 = "14";

        if (str2.ToUpper() == "F")
          str2 = "15";

        //converto i singoli caratteri in valori byte
        Byte b1 = Byte.Parse(str1);
        Byte b2 = Byte.Parse(str2);
        //onverto i duebyte in un valore hex
        Byte cv = (Byte)(b1 * 16 + b2);

        //Debug.Print(cv.ToString());

        return cv;

      }

      return 0;
    }

    public static void Main()
    {
      SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8);
      OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
      UTF8Encoding asen = new UTF8Encoding();

      //apro la oprta seriale per acquisire i dati dal lettore id-12
      sp.Open();

      while (true)
      {
        Thread.Sleep(200);
        led.Write(false);

        //controllo ciclicamente che arrivino tutti i
        //byte dal lettore
        if (sp.BytesToRead == 16)
        {
          Byte[] b = new Byte[sp.BytesToRead];
          Byte[] tag = new Byte[10];

          Byte Hex01, Hex02, Hex03, Hex04, Hex05, crc;

          //leggo tutti i byte provenienti dal lettore
          sp.Read(b, 0, b.Length);

          //copio i 10 byte dell'ID del tag in un array dedicato
          Array.Copy(b, 1, tag, 0, 10);

          //converto i byte in una stringa ASCII
          String ValoriAsc = new String(UTF8Encoding.UTF8.GetChars(tag));

          //ottengo i valori esadecimali dalla coppia di byte Ascii
          Hex01 = ConvHexToByte(ValoriAsc.Substring(0, 2));
          Hex02 = ConvHexToByte(ValoriAsc.Substring(2, 2));
          Hex03 = ConvHexToByte(ValoriAsc.Substring(4, 2));
          Hex04 = ConvHexToByte(ValoriAsc.Substring(6, 2));
          Hex05 = ConvHexToByte(ValoriAsc.Substring(8, 2));

          //calcolo il crc mettendo in xor i valori hex
          crc = (byte)(Hex01 ^ Hex02 ^ Hex03 ^ Hex04 ^ Hex05);

          //printo il valore di crc
          Debug.Print(crc.ToString());

          if (b[0] == 0x02 && b[13] == 0xD && b[14] == 0xA && b[15] == 0x03)
            led.Write(true);

        }

      }

    }
}
}

 

Il calcolo del crc può risultare utile nel caso di applicazioni dove la certezza di aver letto bene l’id del tag è fondamentale, come, per esempio in applicazioni come alcune delle applicazioni illustrate nella pagina di wikipedia dedicata al sistema RFID.

Per considerazioni e spiegazioni aggiuntive vi invito a scrivermi nei commenti o tramite mail

al prossimo articolo…