Swordfish Module - RFID.bas (EM4100)

rfid_400x300

EM4100 readers are somewhat popular because they are cheap, widely available and easy to use. You can pick up an EM4100 RFID reader for ~$40 or less. The module used in this example may not work for every EM Reader out there - though it offers an approach to start with. If you do create a new module for a different device, then please share it here at digital-diy.com

 

What's an EM4100 RFID Card?

RFID_Card1

It's a type of RFID Card obviously! They operate on the Low Frequency (LF) band (125KHz). In that frequency band there are several kinds of tags that all communicate differently. The EM family of tags come from a single manufacturer; EM Microelectronic. The EM4100 is simply a type of tag from their line of tags that operates at 125KHz. There are other models such as EM4002, EM4102 and the newer EM4200.

 

There are some standards that several RFID chip makers adhere to, but many chip types (like the EM4100) do not conform to any standard, and several reader manufacturers develop hardware to support reading those types of chips.

 

Interfacing

A Card Reader does all of the hard work - it looks after energising the card, reads the transmitted RF signal, and if everything went well - it outputs the Card ID. There are two important points to consider when interfacing with a reader:

  • How to interface with your PIC (UART, RS232, RS485 etc)?
  • What protocol is it using? (Packet start and end symbols/headers etc)

Discovering how to interface with it should be pretty easy - either via the readers datasheet or an ident plate on the back of it.

 

The Protocol

After finding out how to interface with it, figuring out the protocol can be interesting! If you have the datasheet, then it will be listed there. If not, make a simple echo program on your PIC, to pass anything onto a terminal program (such as the PK2 UART Tool or iHyperTerminal). This allows you to decode what is going on - it will only take 2-3 cards to discover how the card ID is encapsulated. All you need to find is:

  • Start Symbol (usually hex code 02 - which means 'start of text')
  • Card Number itself (EM4100 cards have 5 byte IDs such as 11002FBB4D
  • CRC (some protocols use a CRC - usually a simple XOR of each Card ID byte. Some Readers will not send a CRC)
  • End Symbol (usually hex code 0D - which means 'carriage return' - 13 in decimal

 

I had to discover what was going on through analysing the raw output, as my datasheet did not describe how the data was encoded. This is not hard to do, consider the following raw hexadecimal outputs for 4 different cards:

$02,$30,$46,$30,$30,$35,$33,$38,$33,$30,$34,$0D,$0A,$03
$02,$31,$31,$30,$30,$34,$36,$35,$45,$45,$32,$0D,$0A,$03
$02,$31,$31,$30,$30,$32,$46,$42,$42,$34,$44,$0D,$0A,$03
$02,$30,$31,$30,$33,$45,$35,$43,$30,$38,$44,$0D,$0A,$03

As I am working with EM4100 cards, I am looking for a 5 byte address (that much I could get from the datasheet). The packet appears to be ASCII encoded, so my Card ID will actually be 10 bytes long.

There are 14 bytes sent with each packet, and it helps to either be familiar with ASCII codes or have an ASCII table handy. I can strip some of the information straight away as the packets have a common setup to what I am used to: ASCII Code (ASC) $02 = Start of Text, ASC $0D = Carriage Return, ASC $0A = Line Feed and ASC $03 = End of Text.

With the above bytes removed ($02, $0D, $0A, $03), I can identify the ASCII formatted 10 byte card ID (the only 10 bytes left!). This also implies there is no CRC being used.

$02,$30,$46,$30,$30,$35,$33,$38,$33,$30,$34,$0D,$0A,$03
$02,$31,$31,$30,$30,$34,$36,$35,$45,$45,$32,$0D,$0A,$03
$02,$31,$31,$30,$30,$32,$46,$42,$42,$34,$44,$0D,$0A,$03
$02,$30,$31,$30,$33,$45,$35,$43,$30,$38,$44,$0D,$0A,$03

A key point to remember here is that the whole packet is ASCII formatted.This means that each of the 10 bytes forms an ASCII code for what the Card ID actually is. For example:

$30,$46,$30,$30,$35,$33,$38,$33,$30,$34 = 0F00538304
$31,$31,$30,$30,$34,$36,$35,$45,$45,$32 = 1100465EE2
$31,$31,$30,$30,$32,$46,$42,$42,$34,$44 = 11002FBB4D
$30,$31,$30,$33,$45,$35,$43,$30,$38,$44 = 0103E5C08D

RFID_EM4100.bas allows both a start and an end symbol to be defined. This tells the program when to start clocking in the Card ID, and when to stop. In this case:

$02,$30,$46,$30,$30,$35,$33,$38,$33,$30,$34,$0D,$0A,$03
$02,$31,$31,$30,$30,$34,$36,$35,$45,$45,$32,$0D,$0A,$03
$02,$31,$31,$30,$30,$32,$46,$42,$42,$34,$44,$0D,$0A,$03
$02,$30,$31,$30,$33,$45,$35,$43,$30,$38,$44,$0D,$0A,$03

Now I have a Start Symbol, Card ID, and an End Symbol - and am ready to use the module, RFID_EM4100.bas

Click on the following slide to view the Swordfish code for RFID_EM4100.bas

 

RFID_EM4100.bas
// RFID (EM4100) Module By Mitchy
 
// Module Use:  
//
//  Include "RFID_EM4100.bas"   
//
//  While True  
//      If RFID.WaitForCard Then        ' card number received, stored in public string CardNumber  
                                        ' card numbers are 10 characters long, and terminate with a null (0) 
//      Else                               ' error occurred, CardNumber does not contain valid information
//
//      EndIf 
//  Wend   
 
// Default Module Options:   
// #option _RFID_Length = 10 
// Card ID = 10 bytes
// #option _RFID_Start = $02
// Start Symbol = $02 #option _RFID_End = $0D 
// End Symbol = $0D #option _RFID_Timeout = 10 
// RFID Timeout after 10mS
//
// For more information regarding this module, please search "RFID.bas" at www.digital-diy.com }
 
Module RFID
 
#option _RFID_Length = 10               // Card ID = 10 bytes
#option _RFID_Start = $02               // Start Symbol = $02
#option _RFID_End = $0D                 // End Symbol = $0D
#option _RFID_Timeout = 10              // RFID Timeout after 10mS
 
 
Include "USART.bas"
 
Const RFID_TimeOut = _RFID_Timeout
Const RFID_Start = _RFID_Start
Const RFID_End = _RFID_End
Const RFID_Length = _RFID_Length
 
 
// public variable to access Card Number (Card ID)
Public Dim CardNumber As String(RFID_Length+1)
 
// blocking call that waits for card detection
// returns false if error occurred during RX
// returns true if all appeared well
Public Sub WaitForCard()
Dim i As Byte
Dim tmpByte As Byte
Dim Complete As Boolean
 
Repeat
    // set the complete flag - sub must pass every step or else the flag
    // is set to false on error condition - resulting in a repeat
    Complete = True
    // clear any UART errors
    USART.ClearOverrun
    // wait for start of Card ID symbol
    USART.WaitFor(RFID_Start)
 
    // build card number - break if timeout occurs
    For i = 0 To RFID_Length-1
        If USART.DataAvailableTimeout(RFID_TimeOut) Then
            tmpByte = USART.ReadByte
            // check if capturing card number info or RFID_End
            If i < 10 Then
                CardNumber(i) = tmpByte
            Else 
                If tmpByte <> RFID_End Then
                    // last byte rxd was not the specified end byte
                    Complete = False
                    Break
                EndIf
            EndIf
        Else
            // timeout occurred
            Complete = False
            Break
        EndIf
    Next 
Until Complete = True
 
// add null to end of string
CardNumber(RFID_Length) = Null 
End Sub
 
Sub Init()
USART.SetBaudrate(br9600) 
End Sub
 
Init

 

 

 

Example Program

In the following program, I am calling a sub routine which is a blocking call (will not return until something is received). After that happens, the Card ID is displayed in both ASCII and Raw Hex on the PICKit 2 UART Terminal.

Device = 18F2520
Clock = 8
Config MCLRE = Off
 
// all includes can be found @ digital-diy.com ("Swordfish - Module Pack")
Include "InternalOscillator.bas"
Include "RFID_EM4100.bas"
Include "USART.bas"
Include "Convert.bas"
 
 
// display card number in decimal and hex
Sub DisplayCardNumber()
 Dim i As Byte
 
 USART.Write("______________________________________",13,10)
 USART.Write("RFID CARD DETECTED!",13,10) 
 USART.Write("ASCII : ", CardNumber,13,10) 
 USART.Write("RAW HEX: ")
 For i = 0 To 9
 USART.Write(HexToStr(CardNumber(i),2)," ")
 Next 
 USART.Write(13,10) 
End Sub
 
// main program loop
While true
 RFID.WaitForCard()
 DisplayCardNumber()
Wend

 

The Result

I am using the PICKit 2 UART Tool to view the program outputs. Here's an animation of several different cards being passed over the reader:

mt_ignore:RFID

 

Schematic

Although I could have made a very simple daughter board for the TAP-28, I was actually joining this project with a Bluetooth module (giving my computer RFID capability!). There were a few too many components, so I made my own development board.

My Card Reader has an RS232 interface (+/-12V) - Given I was using 3.3V with this design, a MAX3223 handled voltage level switching.

It may look like there's a lot going on - but consider its just the following:

  • 3.3V Regulator.
  • RFID Reader (powered by 12 volts).
  • MAX3223 for level switching.
  • PIC & PICKit 2 connectors.

thumb RFID EM4100 copyClick to enlarge

 

Forum Activity

  • No posts to display.

Member Access