Arduino RFID Kapı Kilit Sistemi
Önceki yazılarımızda RFID veri okuma ve yazma gibi temel konuları işlemiştik. Arduino RFID kapı kilit sistemi, bir çok projeye entegre edebileceğiniz, EEPROM çalışma mantığını kavrayabileceğiniz güzel bir alıştırma olacaktır.
Projeye geçmeden önce RFID hakkında ufak bir bilgilendirme yapalım;
Bir RFID sistemi, tanımlanmasını istediğimiz nesne üzerinde bulunan bir transponder veya bir etiket ve bir alıcı-verici veya bir okuyucu olmak üzere iki ana bileşenden oluşur.
RFID okuyucu, bir radyo frekans modülü, bir kontrol ünitesi ve yüksek frekanslı elektromanyetik alan oluşturan bir anten bobininden oluşur. Öte yandan, etiket genellikle sadece bir anten ve bir elektronik mikroçipten oluşan pasif bir bileşendir, bu nedenle alıcı-vericinin elektromanyetik alanına yaklaştığında, indüksiyon nedeniyle anten bobininde bir voltaj üretilir ve bu voltaj, mikroçip için güç görevi görür.
Etikete güç verildiğinde, iletilen mesajı okuyucudan çıkarabilir ve mesajı okuyucuya geri göndermek için yük manipülasyonu adı verilen bir teknik kullanır. Etiketin antenindeki bir yükün açılıp kapanması, okuyucunun anteninin voltaj düşüşü olarak ölçülebilen güç tüketimini etkileyecektir. Voltajdaki bu değişiklikler birler ve sıfırlar olarak yakalanacak ve veriler bu şekilde etiketten okuyucuya aktarılacaktır.
Okuyucu ile etiket arasında geri saçılmış bağlantı adı verilen başka bir veri aktarımı yolu da vardır. Bu durumda etiket, okuyucunun anteni tarafından alınacak olan başka bir elektromanyetik alan oluşturmak için alınan gücün bir kısmını kullanır.
RFID ve Arduino
Temel çalışma prensibini öğrendiğimize göre şimdi RFID’yi Arduino ile nasıl kullanabileceğimize ve kendi RFID kapı kilidimizi nasıl oluşturabileceğimize bakalım.
Bu etiketler 1 kB belleğe ve aritmetik işlemleri yapabilen bir mikroçipe sahiptir. Çalışma frekansları 13.56 MHz olup, çalışma mesafesi anten geometrisine bağlı olarak 10 cm’ye kadardır. Bu etiketlerden birinin içerisini incelersek, daha önce bahsettiğimiz anteni ve mikroçipi görebiliriz.
RFID okuyucu modülüne gelince, Arduino kartı ile iletişim için SPI protokolünü kullanır. Modülün VCC’sini 3.3V’a bağlamamız gerektiğini ve diğer pinleri doğru bağladığımıza emin olalım ayrıca, RFID okuyucu modülü çalışmıyorsa buradaki inceleme yazımıza göz atabilirsiniz.
Modülü bağladıktan sonra GitHub‘dan MFRC522 kitaplığını indirmemiz gerekiyor. Kütüphane, modülün nasıl kullanılacağını öğrenebileceğimiz birkaç örnekle birlikte gelir.
Öncelikle “DumpInfo” örneğini yükleyebilir ve sistemimizin düzgün çalışıp çalışmadığını test edebiliriz. Şimdi Seri Monitörü çalıştırırsak ve etiketi modülün yanına getirirsek, okuyucu etiketi okumaya başlayacak ve etiketten gelen tüm bilgiler seri monitörde bu şekilde görüntülenecektir.
Burada etiketin UID numarasını ve aslında 16 bölgeye, her bölge 4 bloğa ve her blok 2 bayt veri depolayabilen 1 KB’lık belleği görebiliriz. Bu eğitim için etiketin hafızasının hiçbirini kullanmayacağız, sadece etiketin UID numarasını kullanacağız.
RFID kapı kilidi projemizin koduna geçmeden önce bu projenin bileşenlerine ve devre şemasına bir göz atalım.
Gerekli Malzemeler
- Arduino Geliştirme Kartı
- MFRC522 13.56 MHz RFID Okuyucu ve 13.56 MHz Kart/Etiket
- Servo Motor
- 16×2 LCD Ekran
- Breadboard/Devre tahtası
- Yakınlık/Yaklaşım Sensörü CNY70
Bağlantı Şeması
Proje aşağıdaki iş akışına sahiptir: Önce bir ana etiket(yetkili) belirlememiz gerekiyor ve ardından sistem normal moda geçiyor. Bilinmeyen bir etiketi tararsak erişim reddediliyor, ancak yetkili kartı tararsak bilinmeyen etiketi ekleyip yetkilendirebileceğimiz bir program moduna girebiliriz. Eğer etiketi tekrar tararsak, kapıyı açabilmemiz için erişim verilecektir.
Kapıyı kapattıktan sonra kapı otomatik olarak kilitlenecektir. Sistemden bir etiketi kaldırmak istiyorsak, tekrar program moduna geçmemiz gerekiyor, bilinen etiketi tarayın ve kaldırılacaktır.
Arduino Kodu
Şimdi koda bir göz atalım. Bu yüzden öncelikle RFID modülü, ekran ve servo motor için kütüphaneleri dahil etmemiz, aşağıdaki program için gerekli bazı değişkenleri tanımlamamız ve kütüphanelerin örneklerini oluşturmamız gerekiyor.
#include <SPI.h> #include <MFRC522.h> #include <LiquidCrystal.h> #include <Servo.h> #define RST_PIN 9 #define SS_PIN 10 byte readCard[4]; char* myTags[100] = {}; int tagsCount = 0; String tagID = ""; boolean successRead = false; boolean correctTag = false; int proximitySensor; boolean doorOpened = false; // Create instances MFRC522 mfrc522(SS_PIN, RST_PIN); LiquidCrystal lcd(2, 3, 4, 5, 6, 7); Servo myServo; // Servo motor
Kurulum bölümünde önce modülleri başlatıyoruz ve servo motorun başlangıç değerini kilitli konuma getiriyoruz. Ardından ekrana ilk mesajı yazdırıyoruz ve aşağıdaki “while” döngüsü ile bir ana etiket taranana kadar bekliyoruz. getID() özel işlevi, etiket UID’sini alır ve onu myTags[0] dizisinin ilk konumuna yerleştirir.
void setup() { // Initiating SPI.begin(); // SPI baslatma mfrc522.PCD_Init(); // MFRC522 lcd.begin(16, 2); // LCD ekran myServo.attach(8); // Servo motor myServo.write(10); // servo kilit pozisyonu // Prints the initial message lcd.print("-Yetkili Kart Yok"); lcd.setCursor(0, 1); lcd.print(" Taratin"); // taranana kadar bekle while (!successRead) { successRead = getID(); if ( successRead == true) { myTags[tagsCount] = strdup(tagID.c_str()); // yetkili karti 0. eleman olarak ayarlar lcd.clear(); lcd.setCursor(0, 0); lcd.print("Yetkili ayarlandi!"); tagsCount++; } } successRead = false; printNormalModeMessage(); }
Şimdi getID() özel işlevine bir göz atalım. Önce okuyucunun yanına yeni bir etiket konup konmadığını kontrol eder ve eğer öyleyse etiketin UID’sini alacak olan “for” döngüsüne devam ederiz. Kullandığımız etiketlerin 4 bayt UID numarası var, bu yüzden bu döngü ile 4 yineleme yapmamız gerekiyor ve concat() işlevini kullanarak 4 baytı tek bir String değişkenine ekliyoruz. Ayrıca string’in tüm karakterlerini büyük harfe ayarlıyoruz ve sonunda okumayı durduruyoruz.
uint8_t getID() { // Getting ready for Reading PICCs if ( ! mfrc522.PICC_IsNewCardPresent()) { return 0; } if ( ! mfrc522.PICC_ReadCardSerial()) { return 0; } tagID = ""; for ( uint8_t i = 0; i < 4; i++) { readCard[i] = mfrc522.uid.uidByte[i]; tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); } tagID.toUpperCase(); mfrc522.PICC_HaltA(); return 1; }
Ana döngüye girmeden önce, kurulum bölümünün sonunda, ekrana “Erişim Kontrolü” mesajını yazdıran printNormalModeMessage() özel fonksiyonunu da çağırıyoruz.
void printNormalModeMessage() { delay(1500); lcd.clear(); lcd.print("Erisim Kontrolu"); lcd.setCursor(0, 1); lcd.print(" Kartı Okutun!"); }
Ana döngüde, bize kapının kapalı olup olmadığını söyleyen yakınlık sensörünün değerini okuyarak başlıyoruz.
int proximitySensor = analogRead(A0);
Yani kapı kapalıysa, getID() özel işlevinde tanımladığımız aynı satırları kullanarak yeni etiketin UID’sini tarayıp alacağız. Burada “if” ifadelerindeki “return” satırları nedeniyle bir etiketi tarayana kadar kodun daha fazla ilerlemeyeceğini görebiliriz.
Etiketi taradıktan sonra o etiketin daha önce kaydettiğimiz yetkili olup olmadığını kontrol ederiz ve bu doğruysa program moduna gireriz. Bu modda zaten yetkilendirilmiş bir etiketi tararsak sistemden kaldırılır veya etiket bilinmiyorsa yetkili olarak sisteme eklenir.
if (tagID == myTags[0]) { lcd.clear(); lcd.print("Programlama modu:"); lcd.setCursor(0, 1); lcd.print("Ekle/Sil"); while (!successRead) { successRead = getID(); if ( successRead == true) { for (int i = 0; i < 100; i++) { if (tagID == myTags[i]) { myTags[i] = ""; lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Silindi!"); printNormalModeMessage(); return; } } myTags[tagsCount] = strdup(tagID.c_str()); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Eklendi!"); printNormalModeMessage(); tagsCount++; return; } } }
Program modunun dışında, bir sonraki “for” döngüsü ile taranan etiketin kayıtlı etiketlerden herhangi birine eşit olup olmadığını kontrol ederiz veya kapının kilidini açarız ya da erişimi reddederiz. Sonunda “else” ifadesinin sonunda kapı kapanana kadar bekleriz, ardından kapıyı kilitleriz ve tekrar normal mod mesajını yazdırırız.
for (int i = 0; i < 100; i++) { if (tagID == myTags[i]) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Erisim verildi!"); myServo.write(170); printNormalModeMessage(); correctTag = true; } } if (correctTag == false) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Erisim reddedildi!"); printNormalModeMessage(); } } // If door is open... else { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Kapi Acildi!"); while (!doorOpened) { proximitySensor = analogRead(A0); if (proximitySensor > 200) { doorOpened = true; } } doorOpened = false; delay(500); myServo.write(10); printNormalModeMessage(); }
Projenin Tam Kodu:
#include <SPI.h> #include <MFRC522.h> #include <LiquidCrystal.h> #include <Servo.h> #define RST_PIN 9 #define SS_PIN 10 byte readCard[4]; char* myTags[100] = {}; int tagsCount = 0; String tagID = ""; boolean successRead = false; boolean correctTag = false; int proximitySensor; boolean doorOpened = false; MFRC522 mfrc522(SS_PIN, RST_PIN); LiquidCrystal lcd(2, 3, 4, 5, 6, 7); Servo myServo; void setup() { SPI.begin(); // SPI iletisime mfrc522.PCD_Init(); // MFRC522 lcd.begin(16, 2); // LCD ekran myServo.attach(8); // Servo motor myServo.write(10); lcd.print("Yetkili kart yok"); lcd.setCursor(0, 1); lcd.print(" TARAT"); while (!successRead) { successRead = getID(); if ( successRead == true) { myTags[tagsCount] = strdup(tagID.c_str()); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Yetkili Kart Var"); tagsCount++; } } successRead = false; printNormalModeMessage(); } void loop() { int proximitySensor = analogRead(A0); if (proximitySensor > 200) { if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } if ( ! mfrc522.PICC_ReadCardSerial()) { return; } tagID = ""; for ( uint8_t i = 0; i < 4; i++) { // readCard[i] = mfrc522.uid.uidByte[i]; tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); } tagID.toUpperCase(); mfrc522.PICC_HaltA(); correctTag = false; if (tagID == myTags[0]) { lcd.clear(); lcd.print("Programlama:"); lcd.setCursor(0, 1); lcd.print("Ekle/Sil"); while (!successRead) { successRead = getID(); if ( successRead == true) { for (int i = 0; i < 100; i++) { if (tagID == myTags[i]) { myTags[i] = ""; lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Silindi!"); printNormalModeMessage(); return; } } myTags[tagsCount] = strdup(tagID.c_str()); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Eklendi!"); printNormalModeMessage(); tagsCount++; return; } } } successRead = false; for (int i = 0; i < 100; i++) { if (tagID == myTags[i]) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Erisim Verildi"); myServo.write(170); printNormalModeMessage(); correctTag = true; } } if (correctTag == false) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Erism Reddedildi"); printNormalModeMessage(); } } else { lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Kapi Acildi!"); while (!doorOpened) { proximitySensor = analogRead(A0); if (proximitySensor > 200) { doorOpened = true; } } doorOpened = false; delay(500); myServo.write(10); printNormalModeMessage(); } } uint8_t getID() { if ( ! mfrc522.PICC_IsNewCardPresent()) { return 0; } if ( ! mfrc522.PICC_ReadCardSerial()) { return 0; } tagID = ""; for ( uint8_t i = 0; i < 4; i++) { readCard[i] = mfrc522.uid.uidByte[i]; tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); } tagID.toUpperCase(); mfrc522.PICC_HaltA(); return 1; } void printNormalModeMessage() { delay(1500); lcd.clear(); lcd.print("-Kontrol-"); lcd.setCursor(0, 1); lcd.print("Kartı Okutun!"); }
Yorum yapma özelliği, forum tarafından gelen istek sebebiyle kapatılmıştır. Lütfen tartışmalar ve sorularınız için topluluk forumumuza katılın.