RFID čítačka II

Z SensorWiki
Prejsť na: navigácia, hľadanie
Autori: Martinkovič a Valach
Študijný odbor: Aplikovaná mechatronika 2. Ing. (2014)

Zadanie

Pomocou RFID čítačky navrhnite elektronický zámok na kód. Popíšte princíp RFID vyhodnocovanie, zistite akú triedu RFID prvkov je schopná čítačka rozpoznať a zmerajte ukážkové data a vyhodnoťte meranie.

Parallax RFIDreader.jpg

http://www.parallax.com/product/28140


Literatúra:

  • Zoznam použitej literatúry, vrátane katalógových údajov (datasheet), internetových odkazov a pod.

Analýza

V tejto časti popíšete ako idete daný problém riešiť. Uvediete sem aj všetky potrebné technické údaje, ktoré sú potrebné na úspešné vyriešenie projektu. Napríklad:

  • popis komunikačnej zbernice (i2c, 1-wire, RS-232 a pod.)
  • obrázok zapojenia vývodov použitej súčiastky
  • odkaz na katalógový list
  • priebehy dôležitých signálov
RFID.jpg
Popis pinov PCF 8583
PINSkratka-označenieKrátky popisI/O
1VCCNapájanie +5V P
2/ENABLETento pin nastavený do LOW nastaví RFID čítačku a aktivuje anténuI
3SOUTSeriový výstupO
4GNDNapájacia zemG


Rozhranie UART

Pri asynchrónnom prenose je dátový rámec definovaný nasledovne:

  • Štart bit – začiatok prenosu, slúži na zosynchronizovanie vysielača a prijímača, stav linky je v log. 0
  • Dátové bity – môže ich byť 5 až 9, začína sa bitom najnižšej váhy (LSB)
  • Parity bit – slúži ako kontrolná suma pri prenose dát
  • Stop bity (1 alebo 2) – ukončenie prenosu, stav linky je v log. 1
  • Stav nečinnosti – ak sa žiadne dáta po linke neodosielajú ostáva v log. 1.
Byt.jpg

Popis registrov: Modul USART mikropočítača Atmega8 obsahuje štyri 8-bitové registre:

  • údajový register UDR,
  • riadiaci a stavový register A, UCSRA
  • riadiaci a stavový register B, UCSRB
  • riadiaci a stavový register C, UCSRC

Médiá:28140-28340-RFID-Reader-Documentation-v2.2.pdf

Princíp RFID (Radio Frequency Identification):

Základný princíp komunikácie medzi RFID čítačkou (reader) a kartou (tag) je cez elektromagnetické pole generované cievkou, ktorá sa nachádza sa v čítačke. Cievka, ktorá sa nachádza na karte, prijíma elektromagnetické pole od čítačky a vytvára prúd v obvode karty, ktorý sa použiva na napájanie katry a odosielanie dát z karty na čítačku.

Bez názvu.jpg

V zadaní sme pracovali s Paralax RFID čítačkou, ktorá je napájaná 5V, podporuje sériovú komunikáciu UART pracujúcu na rýchlosti 2400 Baud . Čítačka je schopná načítavať 125 kHz karty, ktoré majú 10 digitové ID. Komunikačný protokol: využíva štart bit, jeden stop bit a osem dátových bitov po asynchrónnej zbernici. Keď je čítačka aktívna tak po priložení naprogramovanej karty sa ID karty odosiela ako 12 bytoví ASCII string vo formáte uvedenom nižšie:

Data.jpg

Štart a Stop bit sú použité pre ošetrenie správneho prijatia dát, dokým stredných desať bytov predstavuje ID karty. Ako príklad sa uvádza naprogramovaná karta s ID: 0F0184F07A a byty, ktoré sú odoslané sú nasledovné: 0x0A, 0x30, 0x46, 0x30, 0x31, 0x38, 0x34, 0x46, 0x30, 0x37, 0x41, 0x0D.

Princíp funkcie:

Bez názvu.png

Ako prvé čítačka načíta kartu(Tag). Na základe kódu karty sa zistí či je daná karta Master Tag(Master karta) alebo User Tag(Užívateľská karta). Master karta realizuje naprogramovanie alebo vymazanie ďalších užívateľských kárt do systému. Pokiaľ po Master karte sa načíta karta, ktorá je systému známa tak sa daná karta vymaže z databázy nahratých užívateľských kariet. Ak je karta po načítaní master karty neznáma tak sa uloží do databázy a je ňou možné otvárať daný zámok. Ak je užívateľská karta v systéme nahratá, tak po priložení na čítačku, systém porovnáva kód s uloženými kódmi kariet v databáze. Ak je kód uložený prístup sa povolí. Ak nieje uložený kód karty v databáze tak sa prístup zamietne.

Popis riešenia

Za úlohu sme mali naprogramovať RFID čítačku na otvorenie zámku dverí. Zapojenie čítačky k procesoru vyzerá nasledovne:

Zapojenie1.jpg

Popis činnosti: Po zapojení na napätie sa RFID čítačka inicializuje. Pri načítaní prvej karty zasiela ID karty procesoru na spracovanie. Procesor na základe naprogramovaného kódu rozhodne či ID karty patrí Master karte ktorá je už nahratá v EEPROM pamäti alebo užívateľskej karte. Pokiaľ načíta master kartu, "rozbliká sa" biela dióda na 5 sekúnd( čo značí, že je v programovacom móde po 5-tich sekundách sa programovací mód vypne). V programovacom móde ak vložíme užívateľskú kartu, ktorej ID nieje uložené v EEPROM pamäti tak ID karty do nej uloží. Ak tam ID karty uložené je, tak ho vymaže. Takýmto spôsobov sa pridávajú alebo odoberajú užívatelia zámku. Rozsvietenie zelenej diódy značí, že prístup je povolený teda ID karty je uložené v EEPROM pamäti. Ak sa rozsvieti červená dióda tak ID karty uložené nieje v pamäti EEPROM.

Ulozena master karta.jpg

Na obrázku je možné vidieť výpis z pamäti EEPROM pomocou Terminal.exe. Vyznačené ID je ID master karty, ktorá spúšťa programovací mód. Každé ďalšie ID karty je ukladané alebo vymazávané do/z znázornených "chlievikov" oddelených symbolom "|" za sebou.


Algoritmus a program

Uveďte stručný popis algoritmu, v akom jazyku a verzii vývojového prostredia ste ho vytvorili. Je vhodné nakresliť aspoň hrubú štruktúru programu napríklad vo forme vývojového diagramu. Rozsiahly program pre lepšiu prehľadnosť rozdeľte do viacerých súborov.

Vyberte podstatné časti zdrojového kódu, použite na to prostredie source:

#include "common.h"
#include <avr/interrupt.h>
#include <stdlib.h>
#include "serial.h"
#include<stdio.h>
#include <avr\io.h>
#include <util/delay.h>
#include <avr/eeprom.h>


FILE uart_output = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, recchar, _FDEV_SETUP_READ);

static void RFID_init(void);
static void RFID_ena(uint8_t ena);
static void TunedDelay(uint16_t);

void blinkRed();
void blinkGreen();
void blinkWhite();
void longWhiteBlink();

void blinkAll();
void printAllEeprom(); //vypise vsetko z eepromu
void printAll();  //vypise vsetky z pola
void clearEeprom(); //vymaz vsetko z eepromu
void saveCardToEeprom(int card[12]); //uloz jednu do eepromu
int findPosition(int card[12]); //najdi poziciu karty v poli
void deleteCard(int card[12]); //vymaz kartu z pola a eepromu
void saveCard(int card[12]); //uloz kartu do pola a eepromu
void loadCard(int position); // nacitaj kartu do pola z eepromu na pozicii i
void loadCardsFromEeprom(); // nacitaj vsetky karty z eepromu -> pri startovani 
int containsCard(int card[12]); //nachadza sa karta v poli? -> ma povoleny pristup? 


#define RFID_IN     PIND2
#define RFID_ENA    PIND3


#define CENTER_DELAY            471
#define INTRABIT_DELAY          950

#define MAX_CARDS 				102
#define PROGRAM_MODE_MAX_SECONDS    5
#define EEPROM_MAX               512
#define PROGRAM_MODE                2


static volatile uint8_t bDataReady;
static volatile uint8_t rxIdx;
int RFID_tag[12];
   
int cards[102][5];
int cardArraySize = 0;

int mode = 0;
int saveModePassedSeconds=0;


int main()
{

	inituart();
	stdout = &uart_output;
	stdin = &uart_input;  
	DDRD = (1<<DDD6) | (1<<DDD5);			//Zapni D5(zelena LED), zapni D6(cervena LED)
	PORTD = (0<<PD6) | (0<<PD5);			//Vypni D5, vypni D6
  

    RFID_init();
    RFID_ena(1);
    TunedDelay(947); 

		
	//clearEeprom();  
	
	printAllEeprom();
	loadCardsFromEeprom();   //inicializacia pola kariet
	printAll(); //vypis nacitane karty z pola


	printf("RFID Initialized");
	blinkAll();

	printf(" %d cards saved", cardArraySize);

    while(1)
    {

		if(mode == PROGRAM_MODE){
			blinkWhite();
			saveModePassedSeconds++;
		}
		if(saveModePassedSeconds >= PROGRAM_MODE_MAX_SECONDS){ //ak ubehlo PROGRAM_MODE_MAX_SECONDS (5s) 
			saveModePassedSeconds=0;	
			mode=0;
		}
        if (bDataReady){
				printf(" %d cards saved", cardArraySize);

				//saveCard(RFID_tag);
			
				printf("RFID tag: ");
                for(uint8_t x = 1; x <= 10; x++)
                {
				x++;
				  printf("%i",RFID_tag[x]);
                  if (x%2==0 && x<9)
                       printf("-");
                }

                printf("\n");

				if(mode == PROGRAM_MODE){ // ak sme v programovacom mode, uloz/vymaz kartu					
					saveCard(RFID_tag);	
					//blinkRed();
					longWhiteBlink();
					rxIdx = 0;
					bDataReady = 0;			
					continue;			
				}

				int ret = containsCard(RFID_tag); //zapis do premennej ret ci sa karta nachadza v poli

				if(ret == 2){  // master card pouzita -> zapisovaci mod								
					mode = PROGRAM_MODE;
					_delay_ms(500);
				}else if(ret == 1){			
					printf("Správny kód");
					printf("Prístup povolený \n");
					blinkGreen();				
				}
				else {
					printf("Nesprávny kód!! \n");
					printf("Priloz inu kartu!\n\n");
	  				blinkRed();		
				}

            rxIdx = 0;
            bDataReady = 0;
			
        }
    }
}


void RFID_init()
{
    bDataReady = 0;
    rxIdx = 0;
    			// RFID_IN input from RFID Reader SOUT, RFID_ENA output to RFID Reader /ENA
    BSET(DDRD, RFID_ENA);
    BSET(PORTD,RFID_IN);    // pullup

    BSET(PCICR,PCIE2);  // pin change interrupt control register pcie2 -> PCICR = 0b00000100
    BSET(PCMSK2,PCINT18); // enable pin change interrupt for PCINT18 (PD2) -> PCMSK2 = 0b00000100
    BSET(SREG,7);       // Set SREG I-bit -> SREG = 0b10000000
}

ISR(PCINT2_vect)
{
    if (BCHK(PIND,RFID_IN)) 			// Start bit goes low
        return;
    uint8_t bit = 0;
    TunedDelay(CENTER_DELAY);       	// Center on start bit
    for (uint8_t x = 0; x < 8; x++)
    {
        TunedDelay(INTRABIT_DELAY); 
        if (BCHK(PIND,RFID_IN))		
            BSET(bit,x);
        else
            BCLR(bit,x);
    }
    TunedDelay(INTRABIT_DELAY);
    RFID_tag[rxIdx] = bit;
    ++rxIdx;
    if (rxIdx == 12)
        bDataReady = 1;
	//else{
//		printf("bdata not ready   ");
//	}
}

void RFID_ena(uint8_t ena)
{
    if (ena)
        BCLR(PORTD,RFID_ENA);
    else
        BSET(PORTD,RFID_ENA);
}

void TunedDelay(uint16_t delay)			// delay function
{
  uint8_t tmp=0;

  asm volatile("sbiw    %0, 0x01 \n\t"
    "ldi %1, 0xFF \n\t"
    "cpi %A0, 0xFF \n\t"
    "cpc %B0, %1 \n\t"
    "brne .-10 \n\t"
    : "+r" (delay), "+a" (tmp)
    : "0" (delay)
    );

}

void CriticalSegment(uint8_t ena)
{
    static uint8_t sreg;
    if (ena)
    {
        sreg = SREG;    // save off our global status register
        cli();          // zastav globalne prerusenia
    } else
    {
        SREG = sreg;    // restore global interrupt flag (and any other prev settings)
    }
}


void blinkRed(){
	PORTD = (1<<PD6);					
	_delay_ms(2000);
	PORTD = (0<<PD6);
}

void blinkGreen(){
	PORTD = (1<<PD5);					
	_delay_ms(2000);
	PORTD = (0<<PD5);
}

void blinkWhite(){
	PORTD = (1<<PD7);
	_delay_ms(500);	
	PORTD = (0<<PD7);					
	_delay_ms(500);
}

void longWhiteBlink(){
	PORTD = (1<<PD7);
	_delay_ms(2000);	
	PORTD = (0<<PD7);	
}

void blinkAll(){
	PORTD = (1<<PD6);
	_delay_ms(500);
	PORTD = (1<<PD5);
	_delay_ms(500);
	PORTD = (1<<PD7);
	_delay_ms(500);
	PORTD = (0<<PD6);
	PORTD = (0<<PD5);
	PORTD = (0<<PD7);
}

void printAllEeprom(){
	for(int i=0; i< EEPROM_MAX; i++){
		printf("%d ", eeprom_read_byte(i));	
		if((i+1) % 5 == 0 && i != 1 && i != 0){
			printf(" | ");
		}
	}
}

void printAll(){
	for(int i=0; i< cardArraySize; i++){
		printf("%d ", cards[i]);	
	}
}

void clearEeprom(){
	for(int i=0; i< EEPROM_MAX; i++){
		eeprom_write_byte(i, 255);	
	}	
}


void saveCardToEeprom(int card[12]){
	int i=0;

	while(eeprom_read_byte(i) != 255){
		i++;
	}

	for(int j=2; j<12; j+=2){
		eeprom_write_byte(i, card[j]);
		i++;	
	}
	
}

int findPosition(int card[12]){
	
	for(int i = 0; i < cardArraySize; i++){
		int k=2;
		int j;
		for(j=0; j < 5; j++){
			if(cards[i][j] != card[k]){
				break;
			}
			k+=2;
		}
		if(j==5){ // vrat poziciu
			return i;
		}
	}

}

void deleteCard(int card[12]){
	if(containsCard(card) != 1){ //ak karta nie je zapisana, vyskoc z funkcie (nemame co mazat)
		return;
	}

	int position = findPosition(card);

	if(position == 0) //nedovolime vymazat master (prvu)
		return;

	for(int i=0; i < 5; i++){
		cards[position][i] = 255;
		eeprom_write_byte((position * 5) + i, 255);
	}
	
}

void saveCard(int card[12]){
	
	if(containsCard(card)){  // ak je karta uz zapisana, pokus sa ju vymazat
		deleteCard(card);
		saveModePassedSeconds=0;
		mode=0;
//		blinkAll(); 
		return;
	}

	int i=0;
	cardArraySize+=1;
	for(int j=2; j<12; j+=2){   //zapis kartu do pola
		cards[cardArraySize][i] = card[j];
	//	printf("savujem na %d miesto   %d ", i, card[j]);
		i++;	
	}	
	saveCardToEeprom(card); //zapis kartu do eepromu
	
//	blinkAll();
//	_delay_ms(1000);
//	blinkAll();


	cardArraySize+=1;


	saveModePassedSeconds=0;
	mode=0;
}

void loadCard(int position){
	int j=0;
	for(int i = position; i < position + 5; i++){
		int temp = eeprom_read_byte(i);
		if(temp == 255){
			cardArraySize--;
			break;
		}
		cards[cardArraySize][j] = temp;
		//printf("%d ", cards[cardArraySize][j]);
		j++;	
	}
	cardArraySize++;
}

void loadCardsFromEeprom(){
 int i=0;
	while(i <= 255){
		loadCard(i);
		i+=5;
	}
}

int containsCard(int card[12]){
	//printf("card size: %d  ", cardArraySize);
		

	for(int i = 0; i < cardArraySize; i++){
		int k=2;
		int j;
		for(j=0; j < 5; j++){

			//printf(" porovnanie: %d   %d ",cards[i][j],card[k] );
			if(cards[i][j] != card[k]){
				//printf("vyskakujem z loopu");
				break;
			}
			k+=2;
		}
		//printf("J: %d  ", j);
		if(i == 0 && j==5){ //ak sme na prvej karte a vsetkych 5 sa zhodovalo, vrat 2
			return 2;
		}
		if(j == 5){
			return 1;
		}
	}

	return 0;
		
}

Nezabudnite však nahrať aj kompletné zdrojové kódy vášho programu!

Zdrojový kód: Médiá:Zadanie.c serial.h serial.c ubre.c ubre.h

Overenie

Video funkčnosti RFID čítačky