Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

ID-12/ID-20 RFID Reader Driver


  • Please log in to reply
61 replies to this topic

#1 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 05 January 2011 - 04:51 PM

I have a new contribution to the community and a feedback request... This is a simple encapsulation class for the ID-2/ID-12/ID-20 RFID Card Reader modules.

It is also my first attempt at using callbacks and my first use of the class Destructor routine. Could someone look at both of these and let me know if they are implemented properly?

Thanks in advance, and enjoy!

Actual reader class:


using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.IO.Ports;
using System.Threading;

namespace IDx2Reader
{
    // Callback function delegate.
    delegate void onCardReadCallback(string str); 

    class idReader
    {
        private SerialPort rfidPort; // Serial port the reader is connected on.
        private SerialDataReceivedEventHandler _serialReadEvent; // Serial event handler.
        private OutputPort rfidResetPort; // Digital port the reader's reset pin is connected to.
        private onCardReadCallback onCardRead; // Storage for the callback function.
        private int readDelay; // How long to wait between card reads.
        private bool _readerRunning = false; // State of the reader.

        // Buffers for incoming card data.
        byte[] rawData = new byte[16]; // Incoming raw bytes from the serial connection.
        char[] idStringData = new char[12]; // ID String data.

        public idReader(string _rfidSerialPort, Cpu.Pin _rfidResetPin, onCardReadCallback _onCardRead, int _readDelay = 500)  
        {
            // Set up the ports as necessary.
            rfidPort = new SerialPort(_rfidSerialPort, 9600, Parity.None, 8, StopBits.One);
            rfidResetPort = new OutputPort(_rfidResetPin, false);

            // Store the callback function.
            onCardRead = _onCardRead;

            // Set up the event handler.
            _serialReadEvent = new SerialDataReceivedEventHandler(_rfidCardDataReceived);

            // Open the port and set an event handler to receive incoming serial data.
            rfidPort.Open();
            rfidPort.DataReceived += _serialReadEvent;

            // Store other passed parameters.
            readDelay = _readDelay;
        }

        ~idReader()
        {
            // Disable the reader.
            if (_readerRunning) rfidResetPort.Write(false);

            // Close the serial port.
            rfidPort.Close();
            
            // Detach the event handler.
            rfidPort.DataReceived -= _serialReadEvent;

            // GC will do the rest. (???)
        }

        // Start watching for a card.
        public void start()
        {
            // Do nothing if the reader is already running.
            if (_readerRunning) return;

            // Release the reader from the reset state.
            rfidResetPort.Write(true);

            // Open the callback function to receive data and handle it.
            _readerRunning = true;
        }

        // Stop watching for a card.
        public void stop()
        {
            // Do nothing if the reader is already stopped.
            if (!_readerRunning) return;

            // Lock the reader to the reset state.
            rfidResetPort.Write(false);

            // Close the callback function.
            _readerRunning = false;
        }

        // Property to determine the reader's state.
        public bool isRunning
        {
            get { return _readerRunning; }
        }

        /* This method receives card data from the RFID reader via serial callback. */
        private void _rfidCardDataReceived(object _cardPort, SerialDataReceivedEventArgs unused)
        {
            // Do nothing if the reader is not supposed to be running.
            if (!_readerRunning) return;

            // Capture the port that the data was received on.
            SerialPort cardPort = (SerialPort)_cardPort;

            // Read the ID string.
            cardPort.Read(rawData, 0, rawData.Length);
            
            // Isolate the actual ID string.
            for (int i = 0; i < idStringData.Length; i++)
            {
                idStringData[i] = (char)rawData[i + 1];
            }

            // Convert the ID character array to a proper string.
            String finishedID = new String(idStringData);

            // Wipe the receive buffer for next time.
            for (int i = 0; i < rawData.Length; i++)
            {
                rawData[i] = 0;
            }

            // Send the received card ID to the approprate callback function.
            onCardRead(finishedID);
        }
    }
}

And how to use it:


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

namespace IdReaderDemo
{
    public class HardwareAbstraction
    {
        // Hardware device class instance.
        private idReader rfidReader;

        // Callback function prototype for the hardware device class.
        private onCardReadCallback rfidCall;

        /* This method is called when a card is read by the RFID reader. */
        private void _rfidCardRead(string _cardID)
        {
            Debug.Print("Card scanned: " + _cardID);
        }

        public HardwareAbstraction()
        {
            // Set up the callback function for the ID reader.
            rfidCall = new onCardReadCallback(_rfidCardRead);

            // Set up the reader itself.
            rfidReader = new idReader(SerialPorts.COM1, Pins.GPIO_PIN_D4, rfidCall);

            // Start listening for RFID cards.
            rfidReader.start();
        }

    }

    public class Program
    {
        public static void Main()
        {
            HardwareAbstraction IDtest = new HardwareAbstraction();

            // You can do something else useful here.
        }
    }
}


#2 kenNET

kenNET

    Advanced Member

  • Members
  • PipPipPip
  • 69 posts
  • LocationSweden

Posted 07 January 2011 - 05:11 PM

Thanks works great! Why need I use GPIO_PIN_D4 to RST? I see some example where RST is direct to 5+ (and that also works with your code) I'm using ID-12 reader. /Ken

#3 kenNET

kenNET

    Advanced Member

  • Members
  • PipPipPip
  • 69 posts
  • LocationSweden

Posted 07 January 2011 - 06:07 PM

I did a few small changes on the callback for easier use on "main class".

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.IO.Ports;
using System.Threading;

namespace IDx2Reader
{
   
    public class idReader
    {
        //(** new **)
        #region Public Event 

        public delegate void RfidEventDelegate(object sender, RfidEventArgs e);

        public event RfidEventDelegate RfidEvent;

        public class RfidEventArgs : EventArgs
        {
            private string _RFID;
            private DateTime _ReadTime;

            public string RFID
            {
                get { return _RFID; }
                set { _RFID = value; }
            }

            public DateTime ReadTime
            {
                get { return _ReadTime; }
                set { _ReadTime = value; }
            }

        }

        private void OnRfidEvent(RfidEventArgs e)
        {
            if (RfidEvent != null)
            {
                RfidEvent(this, e);
            }
        }

        #endregion

        private SerialPort rfidPort; // Serial port the reader is connected on.
        private SerialDataReceivedEventHandler _serialReadEvent; // Serial event handler.
        private OutputPort rfidResetPort; // Digital port the reader's reset pin is connected to.
        private int readDelay; // How long to wait between card reads.
        private bool _readerRunning = false; // State of the reader.

        // Buffers for incoming card data.
        byte[] rawData = new byte[16]; // Incoming raw bytes from the serial connection.
        char[] idStringData = new char[12]; // ID String data.

        public idReader(string _rfidSerialPort, Cpu.Pin _rfidResetPin, int _readDelay = 500)
        {
            // Set up the ports as necessary.
            rfidPort = new SerialPort(_rfidSerialPort, 9600, Parity.None, 8, StopBits.One);
            rfidResetPort = new OutputPort(_rfidResetPin, false);

            // Set up the event handler.
            _serialReadEvent = new SerialDataReceivedEventHandler(_rfidCardDataReceived);

            // Open the port and set an event handler to receive incoming serial data.
            rfidPort.Open();
            rfidPort.DataReceived += _serialReadEvent;

            // Store other passed parameters.
            readDelay = _readDelay;
        }

        ~idReader()
        {
            // Disable the reader.
            if (_readerRunning) rfidResetPort.Write(false);

            // Close the serial port.
            rfidPort.Close();

            // Detach the event handler.
            rfidPort.DataReceived -= _serialReadEvent;

            // GC will do the rest. (???)
        }

        // Start watching for a card.
        public void Start()
        {
            // Do nothing if the reader is already running.
            if (_readerRunning) return;

            // Release the reader from the reset state.
            rfidResetPort.Write(true);

            // Open the callback function to receive data and handle it.
            _readerRunning = true;
        }

        // Stop watching for a card.
        public void stop()
        {
            // Do nothing if the reader is already stopped.
            if (!_readerRunning) return;

            // Lock the reader to the reset state.
            rfidResetPort.Write(false);

            // Close the callback function.
            _readerRunning = false;
        }

        // Property to determine the reader's state.
        public bool isRunning
        {
            get { return _readerRunning; }
        }

        /* This method receives card data from the RFID reader via serial callback. */
        private void _rfidCardDataReceived(object _cardPort, SerialDataReceivedEventArgs unused)
        {
            // Do nothing if the reader is not supposed to be running.
            if (!_readerRunning) return;

            // Capture the port that the data was received on.
            SerialPort cardPort = (SerialPort)_cardPort;

            // Read the ID string.
            cardPort.Read(rawData, 0, rawData.Length);

            // Isolate the actual ID string.
            for (int i = 0; i < idStringData.Length; i++)
            {
                idStringData[i] = (char)rawData[i + 1];
            }

            // Convert the ID character array to a proper string.
            String finishedID = new String(idStringData);

            // Wipe the receive buffer for next time.
            for (int i = 0; i < rawData.Length; i++)
            {
                rawData[i] = 0;
            }

            // Send the received card ID to the approprate callback function.

            //(** new **)
            RfidEventArgs _args = new RfidEventArgs();
            _args.RFID = finishedID;
            _args.ReadTime = DateTime.Now;
            OnRfidEvent(_args);
        }
    }
}


I use it like this:


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 IDx2Reader;

namespace MyRFID
{
    
    public class Program
    {
        private static idReader _idReader;
       
        private static void StartRFID()
        {
            _idReader = new idReader(SerialPorts.COM1, Pins.GPIO_PIN_D4);
            _idReader.RfidEvent += new idReader.RfidEventDelegate(_idReader_RfidEvent);
            _idReader.Start();
        }

        static void _idReader_RfidEvent(object sender, idReader.RfidEventArgs e)
        {
            Debug.Print("Card scanned: " + e.RFID + ", time: " + e.ReadTime);
        }

      

        public static void Main()
        {
            // write your code here

            StartRFID();

            Thread.Sleep(Timeout.Infinite);

        }
 
   }
}


/Ken

#4 Fernanda

Fernanda

    New Member

  • Members
  • Pip
  • 1 posts

Posted 09 February 2011 - 01:00 PM

which version of visual studio and sdk what you used in this project?

#5 kenNET

kenNET

    Advanced Member

  • Members
  • PipPipPip
  • 69 posts
  • LocationSweden

Posted 09 February 2011 - 04:30 PM

which version of visual studio and sdk what you used in this project?



I use VS2010 Pro and .NET Micro Framework SDK v4.1 + Netduino SDK v4.1.0.

http://www.netduino.com/downloads/

/Ken

#6 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 11 February 2011 - 05:05 AM

Thanks for the improvements! Could you tell me what each line does? I'm afraid it's a bit over my head without comments.

#7 Charles

Charles

    Advanced Member

  • Members
  • PipPipPip
  • 192 posts

Posted 11 February 2011 - 05:19 AM

which version of visual studio and sdk what you used in this project?


I use it to enable and disable the reader.

That way you can directly use the reader's pin 10 on a diode or buzzer - It will not be activated if the reader is in reset mode.

#8 kenNET

kenNET

    Advanced Member

  • Members
  • PipPipPip
  • 69 posts
  • LocationSweden

Posted 11 February 2011 - 11:27 AM

Thanks for the improvements! Could you tell me what each line does? I'm afraid it's a bit over my head without comments.


Hi,

It only makes it easier to use in the mainclass, having the EventDelegate in the RFID class.

/Ken

#9 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 27 February 2011 - 03:35 AM

That you for sharing this class. First time using the Netduino and loving it. I'm having some problems getting it to work. The card says it is reading data, but it is just returning all 255's. Card scanned: ÿÿÿÿÿÿÿÿÿ, time: 01/01/2009 00:36:19 I have tried putting together just a simple serial reader and end up with the same output. I can't seem to figure out why I'm not getting a valid RFID. I have two cards and I'm pretty sure the code for both are not ÿÿÿÿÿÿÿÿÿ. I'm pretty much using the class the same way you specify. I coped the wiring from some other thread I found. Pins: 11,2 = 5v 1,7 = gnd 10 = led 9 = Netduino pin 1 Hopefully I have something wired up wrong, I would hate to think i have a bad ID-20. Thanks, Trey Aughenbaugh

#10 Dan Morphis

Dan Morphis

    Advanced Member

  • Members
  • PipPipPip
  • 188 posts

Posted 27 February 2011 - 06:50 AM

I'm having some problems getting it to work.
The card says it is reading data, but it is just returning all 255's.
Card scanned: ÿÿÿÿÿÿÿÿÿ, time: 01/01/2009 00:36:19
I have tried putting together just a simple serial reader and end up with the same output.
I can't seem to figure out why I'm not getting a valid RFID.
I have two cards and I'm pretty sure the code for both are not ÿÿÿÿÿÿÿÿÿ.


I'm pretty much using the class the same way you specify.
I coped the wiring from some other thread I found.
Pins:
11,2 = 5v
1,7 = gnd
10 = led
9 = Netduino pin 1
Hopefully I have something wired up wrong, I would hate to think i have a bad ID-20.


Trey, you do have it wired up correctly. Are you sure the cards you have are compatible with the ID-20? The ID-20 cannot read HID cards.

If you need cards, SparkFun sells compatible cards for $1.95 each.

#11 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 27 February 2011 - 10:15 PM

Trey, you do have it wired up correctly. Are you sure the cards you have are compatible with the ID-20? The ID-20 cannot read HID cards.

If you need cards, SparkFun sells compatible cards for $1.95 each.

Dan,
Thanks for the response.
I'm using these cards.
http://www.sparkfun.com/products/10169
I stated how I have them wired in the previous post.
I'm assuming that is correct.
I have an LED on pin 10. It turns on when I scan a card.
Would it turn on for an invalid card?
Again, I get data, but it sure does not look like a proper card ID.

Thanks,
Trey

#12 Dan Morphis

Dan Morphis

    Advanced Member

  • Members
  • PipPipPip
  • 188 posts

Posted 27 February 2011 - 11:09 PM

I'm using these cards.
http://www.sparkfun.com/products/10169

Those are the cards I have, and those do work.

I stated how I have them wired in the previous post.
I'm assuming that is correct.
I have an LED on pin 10. It turns on when I scan a card.
Would it turn on for an invalid card?
Again, I get data, but it sure does not look like a proper card ID.


The LED only turns on for a valid card so its kind of puzzling that your getting invalid data. I just re-read your first post, you have pin 9 from the ID-20 hooked up to pin 1 of the Netduino? If so, thats the transmit pin. It should be hooked up to pin 0, the receive pin.

#13 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 28 February 2011 - 05:23 AM

Those are the cards I have, and those do work.



The LED only turns on for a valid card so its kind of puzzling that your getting invalid data. I just re-read your first post, you have pin 9 from the ID-20 hooked up to pin 1 of the Netduino? If so, thats the transmit pin. It should be hooked up to pin 0, the receive pin.

Sorry, Pin 9 is hooked up to pin 0.

#14 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 01 March 2011 - 02:12 AM

OK, so I unplugged the ID-20 to make sure I had it wired up correctly and when I plugged in back in, it seemed to be showing numbers now instead of odd data. Which is odd since I have done the same thing several times checking my wiring. I guess it is possible my bread board has some issues. Dan thanks for you help. One other note, I set the time as well. I can't believe that would make a difference. Now that I'm getting data, the cards from sparkfun don't tell you what your ID should be. I'm getting 12 characters out. My understanding is I should only have 10 characters. Any ideas why I'm seeing 12 characters. Here is an example :450052C2FE2B. Both cards start with 450052. I guess I don't even know if this is the correct ID I should see. Anyone know where I can get a card with the ID printed in it or at least it labeled somewhere? Thanks again, Trey

#15 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 01 March 2011 - 03:10 AM

I think what I am seeing is the Check sum. 450052C2FE is the code and 2B is the check sum. The 1byte (2 ASCII characters) Check sum is the “Exclusive OR” of the 5 hex bytes (10 ASCII) Data characters. -trey

#16 Hinnie

Hinnie

    New Member

  • Members
  • Pip
  • 9 posts

Posted 01 March 2011 - 04:45 PM

The RFID number is the last six positions right before the checksum code
A piece of code to determine this is as follows:

            for (int i = 0; i < idStringData.Length; i++)
            {
                idStringData[i] = (char)rawData[i+1];   // skip first STX char 
            }
            String str = new string(idStringData);
            if (str.Length == 12)
            {
                int[] chk = new int[6];
                chk[0] = hexConvert(str.Substring(0, 2));
                chk[1] = hexConvert(str.Substring(2, 2));
                chk[2] = hexConvert(str.Substring(4, 2));
                chk[3] = hexConvert(str.Substring(6, 2));
                chk[4] = hexConvert(str.Substring(8, 2));
                chk[5] = hexConvert(str.Substring(10, 2));
                if ((chk[0] ^ chk[1] ^ chk[2] ^ chk[3] ^ chk[4]) == chk[5])
                {
                    RfidEventArgs _args = new RfidEventArgs();
                    _args.RFID = ((chk[2] << 8 | chk[3]) << 8 | chk[4]);   
                    _args.ReadTime = DateTime.Now;
                    OnRfidEvent(_args);
                }
            }
The RFID number is returned as an integer

The code used for the hex conversion:
       public byte hexNibble(string s)
        {
            char[] hexValue = new char[16] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
            byte b = 0xFF;
            char[] sa = new char[1];
            sa = s.ToCharArray(); 
            for (int i=0; i<=15; i++)
            {
                if (sa[0] == hexValue[i])
                {
                    b = (byte)i;
                    break;
                }
            }
            return b;
        }

        public int hexConvert(string hex)
        {
            return (hexNibble(hex.Substring(0, 1)) << 4) + hexNibble(hex.Substring(1, 1));
        }


#17 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 01 March 2011 - 07:46 PM

Hinnie,
Thanks for sharing. Great Code!

The RFID number is returned as an integer


Also good to know.


Thanks again,
Trey

#18 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 01 March 2011 - 10:04 PM

Hinnie,
Based on this:

_args.RFID = ((chk[2] << 8 | chk[3]) << 8 | chk[4]);


To get it to compile in MS VC# Express 2010 I had to add this.

_args.RFID = ((chk[2] << 8 | chk[3]) << 8 | chk[4]).ToString();


Why is chk[0] and chk[1] not getting used?
Based on your code, 450052C2FE2B is turned into 5423870.
Sorry if I'm not understanding something simple here.
I can see how << must be shifting the bits 8 times but why only starting at chk[2]?

-Trey

#19 Hinnie

Hinnie

    New Member

  • Members
  • Pip
  • 9 posts

Posted 02 March 2011 - 11:03 AM

Why is chk[0] and chk[1] not getting used?

I think the first two characters of the RFID code read a reference to the manufacturer.
In the next two characters were to me always 0 hence omitted.
In my program I had _args.RFID defined as integer but now as a string
The read code rfidtag is the same as the number which is printed on the tag.

The code has now changed to:
         _args.RFID = (((chk[1] << 8 | chk[2]) << 8 | chk[3]) << 8 | chk[4]).ToString();  

Late last year I made a video in which the RFID reader is connected to the PC.
YouTube video

But now I have it converted to work with NETMF

#20 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 03 March 2011 - 03:03 PM

Thanks for all your help Hinnie.

I've included a small test file to help with testing your code.
Just thought I would share a quick way to do some tests.

I used Snippet Compiler.
If you have not used it, its perfect for testing small amounts of code without having to load Visual Studio.

Hopefully someone finds it useful.

Thanks again to Charles for sharing a great class.

-Trey

Attached Files

  • Attached File  RFID.cs   3.11KB   47 downloads





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.