RFID Tags are increasingly used for many applications such as identifying objects by means of a code or access control. In logistics RFIDs allows asset tracking, or monitoring conveyor belts; in shops tags are often used as anti theft. RFIDs are also used for presence detection and security, with several use cases, for example in computer and appliance access and user identification. Due to the importance of RFIDs we propose today a simple, stand-alone project, which is basically a simple transponder enabled lock. This lock is equipped with a relay to be used to control an electric gate opener or a simple lamp. We’ll use a great module, very practical because it incorporates everything you need to make a transponder reader: the ID-12 by Innovations Technology. This component integrates the exciter coil, the logic to control absorption and that for code identification.
We presented also a RFID shield for Arduino available in the store.
Furthermore ID-12 integrates a logic that is able to output the data read from the transponder tag (according to three standards: ASCII, Wiegan26 and Magnetic ABA Track2).
Precisely because it provides transponder recognition by itself, the ID-12 is the ideal device for many systems, including electronic access gates, counters, goods classifiers and cataloguers, etc..
From the 11 pins available, pin 7 defines the data format: to read read ASCII-12 it should be put to 0 logic, if connected to pin 11 it will read Magnet ABA Track2 tags, if attached t the power supply will read Wiegan26 transponders.
The component sports a TTL level serial interface, that is accessible from pin 9 (TX or D0) and 8, from which the data read is outputted. Another output is available at pin 10: it blinks at a 3 kHz each time the module detects the code of a tag encoded as expected. This signal can be used to operate a buzzer without electronics or a light emitting diode, from which to report the identification event. The module can’t store codes, it only warns that it recognized something as expected, then, whether to activate the circuit is in charge of the rest of the electronics.
Specification
-
Up to 127 tags can be stored.
-
Possibility to store\deletion of a single tag and memory reset.
-
Dynamic memory management: each tag is stored in the next available location.
-
Both bistable and monostable output operation (1 second activation).
-
Buzzer indicator of the passage of tag on the player.
Store
This RFID access control is available in the store
Circuit diagram
As said, the circuit is made easier thanks to the adoption of the ID-12: in the diagram we see that it is interfaced with:
-
a Microchip PIC12F683 microcontroller (a 8-bit micro-architecture RISC processor, with flash memory) to which it passes the data it reads from tags and
-
an NPN transistor (T2) that we use as a current amplifier needed to drive a buzzer.
Once fed, the ID-12 is ready to use.
In our case, pin 7 is connected to ground: the circuit will recognize tags encoded in ASCII and will output ASCII characters, which the microcontroller will either check for storing (in tracking applications) or compare with the codes in memory (as a lock).
In the circuit, the ID-12 is interfaced with a microcontroller that provides tag recognition, and the actions for the identification of one of the transponders available in memory.
Upon initialization, the PIC firmware sets GP0 and GP1 as direct controls of the diodes of the LD1 two-color LED, used to signal the operating conditions. GP5 is used to command the the relay through T1 transistor (with the base polarized from the R1/R2 divider). GP2, GP3 and GP4 are initialized as inputs, reading, respectively, the incoming data from the ID-12 module, the state of the P1 butto) and the JP1 jumper condition.
The entire circuit operates with continuous and stabilized 5 volts provided by the U1 regulator coming from the supply voltage applied to + and – PWR (between 11 and 15V DC). D1 protects the circuit from reversed polarity, C1 filters impulse noise in input voltage and C2 filters out the residual alternating current (ripple), C3 and C4 filter out the 5 volts.
BOM
R1: 10 kohm
R2, R3, R5, R7: 4,7 kohm
R4, R6: 470 ohm
C1, C3: 100 nF
C2: 220 μF 25 VL
C4: 220 μF 16 VL
C5, C6: 15 pF
BZ1: buzzer 12 V c
LD1: Led 5 mm red/green
P1: Microswitch
RFID1: ID-12
RL1: relay 12 V
T1, T2: BC547
U1: 7805
U2: PIC12F683 (MF829)
How it works
Once you plug the circuit and a tag approaches the reader module, pin 10 generates a one second pulse train at 3 kHz (which plays the buzzer through T2) and the micro prepares to read data from TX coming from RFID1; once data is read, the microcontroller pulls the code contained in them and compares it with those that in memory.
At this point, two things can happen: in case the code is not among those previously learnt the alarm is activated: the relay stays at rest, but the buzzer plays and the LED will turn red for a second. If the circuit works in bistable mode and the relay has been energized by a valid transponder the diode, now with green light, switches to red and then turns green again.
Instead if the transponder read is known, we have different behaviours according to the activation mode selected: in monostable setting the micro pulses RL1 for a second and this relay will be used to control an electric lock, a gate opener or other actions. Meanwhile, the two-color LED will pulse to green light, and then turn off with the release of the relay.
In bistable mode, however, the relay changes state each time the ID-12 is approaching a valid tag: the first time RL1 clicks and stays excited, highlighted by the stable green color lighting.
Notice that the firmware of the PIC was designed to signal tag reading in any case, irrespectively of being among those stored: indeed, if the ID-12 is approaching a non-ASCII transponder the two-color LED remains unchanged, but if you approach an ASCII tag, the message is different depending on whether the same is matched (light green) or not (red light).
Clearly the circuit can work with at least one RFID tag code: storing can be done as follows. After powering the board, press P1 button and keep it pressed until the LED lights up with an orange color. Then release the button and pass the transponder card that you want to store. If the LED turns off and on, the tag code has been stored, if the light remains on, the transponder code is already in memory, or the memory space may be exhausted.
At this point you can replicate the procedure to match other tags.
To exit the memory mode, press and hold the P1 button until the LED starts flashing meaning that is coming back to normal operation.
Tag Cancellation
At any time you can remove a code from the memory: just power the board, press P1 button and keep it pressed until the red LED stops lighting. At this point, release the button and pass the tag you want to delete: if the LED turns off and on, the card has been canceled, differently, in case light remains on, it means that you are trying to remove from memory a transponder that is not stored in the reader. To remove more tags, just pass them one after another. To exit the procedure, hold the button until the LED starts flashing.
Cancellation of all tags
To cancel all tags in a single shot just power the circuit with P1 button pressed. When the red LED lights up, release the button since the cancellation is done.
Firmware (Pic Basic Pro)
'**************************************************************** '* Name : * '* Author : Sottocornola Alessandro * '* Version : 2.1 * '* Notes : Versione con ID tessera compressa con numero di * '* byte da memorizzare impostabile con una variabile * '* PIC : PIC12F683 * '**************************************************************** INCLUDE "modedefs.bas" @ DEVICE INTRC_OSC_NOCLKOUT @ DEVICE MCLR_OFF DEFINE OSC 4 ADCON0 = %00000000 OPTION_REG=%00000000 WPU=%00000011 CMCON0 =%00000111 ANSEL=%00000000 IOCB=%00000000 INTCON=%00000000 'OSCCON=%0111011 symbol RELE = GPIO.5 SYMBOL JUMPER = GPIO.4 SYMBOL PUSH = GPIO.3 SYMBOL RX_PIC = GPIO.2 SYMBOL LED_R = GPIO.0 SYMBOL LED_V = GPIO.1 INPUT RX_PIC input push INDIRIZZO var WORD 'Indirizzo memoria su cui scrivere presente sul buffer ADDR var WORD 'Indirizzo memoria 24LC1024 I VAR byte 'Contatore di comodo LAMP VAR BYTE DATO_RX VAR BYTE[10] 'Dato ricevuto dalla seriale ID-12 DATO_I2C VAR BYTE[10] 'Dato letto dalla memoria SN VAR BYTE 'S: Posizione occupata in mem. - N: Posizione non occupata in mem. DATO_OK VAR BYTE 'Contatore per confronto dato letto in mem e da seriale TROVATO VAR BIT '0: Codice non trovato in mem - 1: Codice trovato in mem. CONTATORE VAR BYTE 'Contatore di comodo per verifica pressione pulsante FUNZIONE VAR BYTE '0:NESSUNA - 1:MEMORIZZA - 2: CANCELLA ID - 3: RESET RICERCA_TIPO VAR BYTE '1: Ricercare dato presente in me - N: Ricercare posizione libera in mem. TEMP VAR BYTE OUT_FUNZ var byte NUM_BYTE var BYTE 'MAX:5 --> NUM_BYTE*2 = Byte del codice del trasponder da memorizzare CODICI VAR BYTE 'Numero di codici possibili in memoria NUM_BYTE=2 CODICI= 255/NUM_BYTE '************* I N I Z I O P R O G R A M M A ************** GOSUB AVVIO MAIN: contatore=0 if funzione=0 then 'Attivo funzione memorizzazione/cancellazione se il pulsante è premuto WHILE PUSH=0 PAUSE 500 CONTATORE=CONTATORE+1 select case contatore case is >=18 'Uscita gosub out case is >=12 'Cancella HIGH led_R LOW led_V FUNZIONE=2 case is >=6 'Memorizza HIGH led_v HIGH led_r FUNZIONE=1 end select WEND else 'Se si è in memorizzazione/cancellazione controllo il pulsante per uscire dal menu WHILE PUSH=0 PAUSE 500 CONTATORE=CONTATORE+1 if contatore>=6 then gosub out endif wend endif serin2 RX_pic,84,1000,esci,[WAIT($02), STR DATO_RX\10] GOSUB COMPRIMI SELECT CASE FUNZIONE CASE 0 'FUNZIONAMENTO CHIAVE RICERCA_TIPO="S" GOSUB RICERCA IF TROVATO=1 THEN 'Codice trovato IF JUMPER=0 THEN 'Bistabile TOGGLE RELE TOGGLE led_v ELSE 'Monostabile HIGH rele high led_v PAUSE 1000 LOW RELE low led_V ENDIF ELSE 'Codice non trovato low led_v high led_r PAUSE 1000 low led_r if RELE=1 then 'Attiva il led verde se l'uscita era attiva prima di questo codice non valido high led_v endif ENDIF CASE 1 'FUNZIONAMENTO MEMORIZZAZIONE RICERCA_TIPO="S" 'Verifico se il codice è già in memoria GOSUB RICERCA if trovato=0 then 'Non è già in memoria allora lo memorizzo RICERCA_TIPO="N" GOSUB RICERCA IF TROVATO=1 THEN GOSUB SCRIVI ENDIF endif CASE 2 'FUNZIONAMENTO CANCELLAZIONE RICERCA_TIPO="S" GOSUB RICERCA IF TROVATO=1 THEN GOSUB CANCELLA ENDIF END SELECT GOSUB AZZERA ESCI: GOTO MAIN '**************** O U T **************** OUT: funzione=0 GOSUB LAMPEGGIA_V WHILE PUSH=0 'SE IL PULSANTE è ANCORA PREMUTO PER SBAGLIO NON FACCIO NULLA WEND if RELE=1 then LOW LED_R high led_v endif return '**************** L A M P E G G I A **************** LAMPEGGIA: low led_r low led_v for I=0 to 11 toggle led_v toggle led_r PAUSE 200 next i return '**************** L A M P E G G I A - V **************** LAMPEGGIA_V: low led_v low led_r for I=0 to 11 toggle led_v PAUSE 200 next i return '**************** S C R I V I **************** 'Scrittura nella locazione INDIRIZZO del codice letto dalla seriale SCRIVI: ADDR=indirizzo*NUM_BYTE for i=5-num_byte to 4 WRITE addr,DATO_RX[i] PAUSE 10 addr=addr+1 next i low led_v LOW LED_R PAUSE 1000 high led_v HIGH LED_R return '**************** C A N C E L L A **************** 'Cancellazione di una specifica locazione CANCELLA ADDR=indirizzo*NUM_BYTE for i=0 to num_byte-1 WRITE addr,$FF PAUSE 10 addr=addr+1 next i low led_r PAUSE 1000 high led_r RETURN '**************** R I C E R C A **************** 'Ricerca codice letto da seriale ID-12 con restituzione indirizzo RICERCA: select case ricerca_tipo case "S" 'Ricerca tra le locazioni di memoria occupate FOR INDIRIZZO=0 TO CODICI-1 ADDR=indirizzo*NUM_BYTE for i=5-num_byte to 4 read addr,dato_i2c[i] addr=addr+1 next i GOSUB CONTROLLO IF DATO_ok=NUM_byte THEN TROVATO=1 GOTO ESCI_RICERCA ENDIF next indirizzo case "N" 'Ricerca posizione non occupata dato_ok=0 FOR INDIRIZZO=0 TO CODICI-1 ADDR=indirizzo*NUM_BYTE for i=5-num_byte to 4 read addr,dato_i2c[i] if dato_i2c[i]=$FF then dato_ok=dato_ok+1 endif addr=addr+1 next i IF DATO_OK=num_byte THEN trovato=1 goto ESCI_RICERCA ENDIF next indirizzo end select ESCI_RICERCA: RETURN '**************** R E S E T _ M E M **************** 'Cancellazione totale memoria RESET_MEM: HIGH led_r pause 2000 FOR INDIRIZZO=0 TO 255 WRITE addr,$FF PAUSE 10 NEXT INDIRIZZO LOW led_r while push=0 'Se il pulsante è ancora premuto non faccio niente wend RETURN '**************** C O N T R O L L O **************** 'Confronto del dato letto in memoria e di quello letto da seriale ID-12 'se DATO_OK=10 allora i due dati sono uguali CONTROLLO: DATO_OK=0 for i=5-num_byte to 4 IF DATO_I2C[i]=DATO_RX[i] THEN DATO_OK=DATO_OK+1 ENDIF next i RETURN '**************** A Z Z E R A **************** 'Reset variabili AZZERA: trovato=0 FOR I=0 TO 9 DATO_RX[I]=0 DATO_I2C[I]=0 NEXT I RETURN '**************** I N I Z I A L I Z Z A **************** 'Fase di inizializzazione all'avvio INIZIALIZZA: TROVATO=0 CONTATORE=0 FUNZIONE=0 LOW RELE GOSUB AZZERA RETURN '**************** A V V I O **************** 'Controllo all'avvio, se il tasto è premuto per reset memoria oppure no AVVIO: GOSUB LAMPEGGIA IF PUSH=0 THEN 'Se tasto premuto all'avvio forzo il reset memoria GOSUB RESET_MEM ENDIF GOSUB INIZIALIZZA RETURN '**************** C O M P R I M I **************** 'Converto il codice da ASCII (10 byte) a HEX (5 byte) per risparmiare spazio 'in memoria e quindi rendere più veloce la ricerca. In HEX impiega la metà del 'tempo perchè vi è la metà dei byte da controllare COMPRIMI: I=0 WHILE I<9 TEMP=DATO_RX[I] IF TEMP>57 THEN TEMP=TEMP - 55 ELSE TEMP=TEMP - 48 ENDIF TEMP=TEMP * 16 DATO_RX[I]=TEMP TEMP=DATO_RX[I+1] IF TEMP>57 THEN TEMP=TEMP - 55 ELSE TEMP=TEMP - 48 ENDIF TEMP=TEMP + DATO_RX[I] DATO_RX[I]=TEMP I=I+2 WEND TEMP=DATO_RX[0] DATO_RX[0]=TEMP TEMP=DATO_RX[2] DATO_RX[1]=TEMP TEMP=DATO_RX[4] DATO_RX[2]=TEMP TEMP=DATO_RX[6] DATO_RX[3]=TEMP TEMP=DATO_RX[8] DATO_RX[4]=TEMP RETURN