Proximity Reader (Weigand) aka RFID


Closed Thread
Results 1 to 1 of 1
  1. #1
    Join Date
    May 2009
    Location
    USA
    Posts
    16

    Post Proximity Reader (Weigand) aka RFID

    Well after a good day of getting used to the basic I/O of some of the PICs I have I decided to tackle a RFID card reader project. The use of an oscilloscope was definitely a huge help in the process. It's taken me about 4 days to get the program to it's current state, really the only thing left to do is replace the "TODO" comments with actual code, but I'll leave that up to whoever actually uses the code. Note: LCD code was taken from pic16.com examples so I can't take credit for that; the original was written in C and I had to port it over to PBP

    Here's the hardware:
    QL200 Pic Development Board (ebay)
    Mini Weigand 26 Card Reader (ebay)
    Trine electric strike (16-24 volt model but works fine at 12VDC) (ebay)
    PIC 16F8778A (came with the board)
    LCD screen (not serial interfaced / connected to portD[0:7])
    IRF520 -- interface between PIC output and strike, the strike needs at least 500mA to activate!
    RA4 has a pullup resistor

    Code:
    '''''''''''''''''''''''''''''''
    ''' Set up I/O
    '''''''''''''''''''''''''''''''
    ADCON1     = %00000111  
    TRISA	   = %00000000
    TRISD	   = %00000000
    TRISC      = %11111111
    '''''''''''''''''''''''''''''''
    ''' Tell PBP we are running 
    ''' at 20 MHz
    '''''''''''''''''''''''''''''''
    DEFINE osc 20
    ''''''''''''''''''''''''''
    '    Initialize EEPROM   '
    ''''''''''''''''''''''''''
    ' 33971 33972 33973 other are 65535 i.e FF or uninitialized
    DATA @0, 179, 132, 180, 132, 181, 132, 255, 255, 255, 255
    DATA @10, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
    DATA @20, 03 'Number of users stored in EEPROM
    '''''''''''''''''''''''''''''''
    ''' LCD Screen I/O
    '''''''''''''''''''''''''''''''
    rs var PortA.1 'Register Select (Data/Command Register)
    rw var PortA.2 'Register Read/Write
    e  var PortA.3 'LCD Enable
    'DB0 - DB7 located at PortD
    '''''''''''''''''''''''''''''''
    ''' Temporary variables
    '''''''''''''''''''''''''''''''
    x var byte
    i var byte
    '''''''''''''''''''''''''''''''
    ''' Most important variables
    '''''''''''''''''''''''''''''''
    CardRead	var bit
    GoodCard	var bit
    PgrmMode	var bit
    BitCount	var byte
    CardWordH	var word     'Need two words for 26 bit card
    CardWordL	var word
    Users		var word[10] 'Word array of users containing only user codes
    NumUsers	var byte
    SiteCode 	con 209
    StrikeTime 	con 5000 'time in ms to unlock door
    '''''''''''''''''''''''''''''''
    ''' Weigand reader I/O
    '''''''''''''''''''''''''''''''
    Data0		var PORTC.0
    Data1		var PORTC.1
    Strike		var PORTA.5
    Buzzer		var PORTA.0
    GreenLED	var PORTA.4
    PgrmSw		var PORTC.2
    '''''''''''''''''''''''''''''''
    ''' Initialize variables
    ''' Card Users and
    ''' I/O ports For first use
    '''''''''''''''''''''''''''''''
    InitUsers:
    Read 20, NumUsers
    if NumUsers = $FF then NumUsers = 0 'Just in case EEPROM has nothing.
    For i = 0 to NumUsers*2 'Bytes are written reversed For easy reading ;-)
    	Read i, Users.lowbyte(i)
    Next i
    BitCount = 0
    CardRead = 0
    CardWordL = 0
    CardWordH = 0
    LOW strike 
    HIGH buzzer
    HIGH GreenLed
    '''''''''''''''''''''''''''''''
    ''' Set up LCD and splash screen
    '''''''''''''''''''''''''''''''
    GoSub LCD_init
    GoSub write_splash
    '''''''''''''''''''''''''''''''
    ''' Here is the main program
    '''''''''''''''''''''''''''''''
    loop:
    If PgrmSW = 0 then
    	If CardRead = 1 Then
    		PORTD = %00000001 'clr screen 
    		GoSub lcd_cmd
    		For i = 15 to 0 step -1 'This loop writes the Site Code to Line 1
    			x = 0
    			x = CardWordH.0(i)
    			x = x | %00110000 'Make x a character
    			GoSub lcd_data
    		Next i
    		PORTD = %11000000 'set the 2nd line display address
    		GoSub lcd_cmd
    		Pause 100
    		For i = 15 to 0 step -1 'This loop writes the User Code to Line 2
    			x = 0
    			x = CardWordL.0(i)
    			x = x | %00110000 'Make x a character
    			GoSub lcd_data
    		Next i
    		CardRead = 0
    		GoodCard = 0
    		For i = 0 to NumUsers - 1
    			If CardWordL = Users[i] and CardWordH = SiteCode Then
    				HIGH  Strike 'Activate electric strike
    				LOW  GreenLED 'Green LED activated on gnd
    				Pause StrikeTime
    				PORTD = %00000001 'clr screen 
    				GoSub lcd_cmd
    				For i = 0 to 15
    					LOOKUP i, ["CARD ACCEPTED   "], x
    					GoSub lcd_data
    				Next i
    				LOW  Strike
    				HIGH  GreenLED
    				GoodCard = 1
    			EndIf
    		Next i
    		If GoodCard = 0 then 'Invalid Card
    			For i = 0 to 2 'Beep 3 times
    				LOW  Buzzer
    				Pause 100
    				HIGH  Buzzer
    				Pause 100
    			Next i
    		EndIf
    		CardWordH = 0
    		CardWordL = 0
    	EndIf
    	GoSub ReadCard
    Else
    	'Init Program Mode
    	While PgrmSw = 1:	Wend
    	PgrmMode = 1
    	PORTD = %00000001 'clr screen 
    	GoSub lcd_cmd
    	For i = 0 to 15
    		LOOKUP i, ["Program Mode    "], x
    		GoSub lcd_data
    	Next i
     	While PgrmMode = 1
    		If PgrmSW = 1 then
    			While PgrmSw = 1:	Wend
    			PgrmMode = 0
    		EndIf
    		'Main Program Mode Menu Here
    	Wend
    	'Exit Program Mode / UPDATE EEPROM
    	PORTD = %00000001 'clr screen after exiting program mode
    	GoSub lcd_cmd
    EndIf
    Goto loop
    
    'For Program Mode:
    		'For i = 0 to 1 'Bytes are written reversed For easy reading later ;-)
    			'write j, CardWordL.lowbyte(i)
    			'j = j + 1
    		'Next i
    
    '''''''''''''''''''''''''''''''
    ''' Card Reading subroutine
    '''''''''''''''''''''''''''''''
    ReadCard:
    if Data0 = 1 and Data1 = 1 then Return
    ReadLoop:
    	If Data0 = 0 Then 
    		If BitCount > 9 Then ' Bits 0 - 9 go to CardWordH, 10-25 go to CardWordL
    			CardWordL = CardWordL << 1
    			CardWordL.0 = 0
    		Else
    			CardWordH = CardWordH << 1
    			CardWordH.0 = 0
    		EndIf
    		BitCount = BitCount + 1
    		While Data0 = 0:	Wend
    	EndIf
    	If Data1 = 0 Then
    		If BitCount > 9 Then
    			CardWordL = CardWordL << 1
    			CardWordL.0 = 1
    		Else
    			CardWordH = CardWordH << 1
    			CardWordH.0 = 1
    		EndIf
    		BitCount = BitCount + 1
    		While Data1 = 0 :	Wend
    	EndIf
    	If BitCount < 26 Then
    'TODO: Make sure that we don't end up in an infinite loop here; utilize the i counter
    		i = i + 1
    		Goto ReadLoop
    	Else
    		BitCount = 0
    'TODO: Instead of dropping off parity, check parity and if error clear CardRead and CardWordH/L
    'Even Parity: LSB should be 0 
    'Odd  Parity: LSB should be 1
    		CardWordL = CardWordL >> 1 'Drop odd parity
    		CardWordL.15 = CardWordH.0 'CardWordL contains full user code
    		CardWordH.9 = 0 'Drop even parity
    		CardWordH = CardWordH >> 1 'We copied this bit to CardWordL already so drop it
    		CardRead = 1
    	EndIf
    Return
    '''''''''''''''''''''''''''''''
    ''' LCD subroutines below
    '''''''''''''''''''''''''''''''
    LCD_init:
    	PORTD = %00000001 'clr screen 
    	GoSub lcd_cmd
    	portd = %00111000 '8 bits 2 lines 5*7 mode.
    	GoSub lcd_cmd
    	portd = %00001101 'display on, cursor off, blink on.
    	GoSub lcd_cmd
    	portd = %00000110 'no shift, cursor move right.
    	GoSub lcd_cmd
    	portd = %10000000 'set ddram address?
    	GoSub lcd_cmd
    return
    
    write_splash:
    	PORTD = %00000001 'clr screen 
    	GoSub lcd_cmd
    	For i = 0 to 15
    		LOOKUP i, ["RFID CONTROLLER "], x
    		GoSub lcd_data
    	Next i
    	PORTD = %11000000 'set the 2nd line display address
    	GoSub lcd_cmd
    	For i = 0 to 15
    		LOOKUP i, ["(C) TONY FULLER "], x
    		GoSub lcd_data
    	Next i
    	Pause 1000
    return
    
    lcd_data:
    	PORTD = x 'Set up PORTD[0:7] with correct outputs from temp variable
    	rs = 1 'Data
    	rw = 0 'Write mode
    	e = 0 'make enable port low
    	Pause 10
    	e = 1 'now create edge
    return
    
    lcd_cmd:
    	rs = 0 'Command
    	rw = 0 'Write mode
    	e = 0 'make enable port low
    	Pause 10
    	e = 1 'now create edge
    return
    
    '''''''''''''''''''''''''''''''
    ''' That's all folks
    '''''''''''''''''''''''''''''''
    end
    One note about the EEPROM data is that the site code is not stored, it's in a separate constant. The stored data is actually backwards: The first entry is 33971 in hex that is 84B3 so in the EEPROM data it is stored as B3 84. It becomes easier to read that way in the for loop.
    Last edited by GoldStar; - 23rd May 2009 at 06:00.
    Why is the email address verification case sensitive?

Similar Threads

  1. Parallax RFID Reader code example
    By dan-tron in forum Code Examples
    Replies: 4
    Last Post: - 19th April 2013, 22:16
  2. how synchronize with rfid reader
    By karellen in forum Serial
    Replies: 9
    Last Post: - 6th December 2009, 15:13
  3. Replies: 3
    Last Post: - 12th March 2008, 05:33
  4. Serial interface with RFID reader
    By brid0030 in forum Serial
    Replies: 8
    Last Post: - 23rd January 2007, 06:23
  5. Proximity Card Reader
    By Sphere in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 6th November 2005, 14:43

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts