Mesin Absensi Arduino dengan Smart Card/RFID

Mesin absensi dengan arduino
Mesin Absensi Arduino dengan Smart Card
Sebelumnya saya sudah membahas beberapa langkah dasar yang nantinya digunakan dalam tutorial ini. silahkan dibaca-baca dulu mengenai konfigurasi Arduino-modul PN532 dengan komunikasi I2C, dan proses penyimpanan data dari arduino ke MySQL database. Dari kedua tutorial tersebut saya akan membuat suatu project yaitu mesin absensi menggunakan Arduino. Proses Absensi menggunakan tanda pengenal berupa smart card yang nanti akan dibaca oleh modul PN532. Selanjutnya modul PN532 akan menulis status kehadiran dalam memory kartu. Dengan demikian sudah kita dapatkan 2 parameter yaitu UID dan Status kehadiran. Kedua parameter ini kita kirimkan ke Database melalui komunikasi TCP/IP (ethernet). Dari database kita akan olah menjadi report absensi termasuk juga dengan nama user dari si pemegang kartu.
Arduino Time Attendance
Alat dan Bahan
Arduino Uno, Ethernet Shield W5200, Kabel LAN(UTP RJ45), XAMPP (WAMP juga boleh), Notepad ++. Pastikan baca-baca dulu materi sebelumnya DISINI

1. Data Base
Jalankan XAMPP (servis apache dan mysql). Buka php myadmin, buat databsenya. saya membuat dengan nama absen_db. Atau langsung saja eksekusi code SQL berikut. Dalam tutorial ini, database masih default ya, Username= root dan tanpa password
CREATE DATABASE absen_db;
 CREATE TABLE absen_db.data_absen (
    id integer primary key auto_increment,
    date_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    uid varchar(20),
    status_absen varchar(20)
  );
Mesin Absensi Arduino dengan Smart Card

2. Injector
File injector ini merupakan program PHP yang digunakan untuk menyimpan data ke database mysql. Buat file dengan nama injector.php simpan di direktori C:\xampp\htdocs\absensi_gabut . Code programnya adalah sebagai berikut.

<?php
class absensi{
 public $link='';
 function __construct($uid, $status_absen){
  $this->connect();
  $this->storeInDB($uid, $status_absen);
 }
 
 function connect(){
  $this->link = mysqli_connect('localhost','root','') or die('Cannot connect to the DB');
  mysqli_select_db($this->link,'absen_db') or die('Cannot select the DB');
 }
 
 function storeInDB($uid, $status_absen){
  $query = "insert into data_absen set uid='".$uid."', status_absen='".$status_absen."'";
  $result = mysqli_query($this->link,$query) or die('Errant query:  '.$query);
  if($result === TRUE){echo "Data Tersimpan";}else{echo "Gagal Menyimpan data";}
 }
 
}
if($_GET['uid'] != '' and  $_GET['status'] != ''){
 $absensi=new absensi($_GET['uid'],$_GET['status']);
}

?>
Arduino PN532 mysql database

3. Wiring
Mesin Absensi Arduino

4. Arduino Program
Sebelumnya pastikan telah terinstall library yang diperlukan dalam project ini yaitu Adafruit PN532 dan LiquidCrystal_I2C. Pertama-tama kita akan menuliskan data pada kartu berupa nama user dan status awal. Untuk status awal ini kita akan tulis START namun untuk selanjutnya status ini akan berubah menjadi status kehadiran (IN atau OUT).

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_PN532.h>

#define PN532_IRQ   (2)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

void setup(void) {
  Serial.begin(115200);
  Serial.println("Hello!");

  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  
  Serial.println("Waiting for an ISO14443A Card ...");
}


void loop(void) {
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
    
  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");
    
    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ... 
      Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
   
      // Now we need to try to authenticate it for read/write access
      // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
      Serial.println("Trying to authenticate block 4 with default KEYA value");
      uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
   
   // Start with block 4 (the first block of sector 1) since sector 0
   // contains the manufacturer data and it's probably better just
   // to leave it alone unless you know what you're doing
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
   
      if (success){
        Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
        uint8_t data[16];
  
        // If you want to write something to block 4 to test with, uncomment
      // the following line and this text should be read back in a minute
        Serial.print("Writing Block 4: .....");
        memcpy(data, (const uint8_t[]){ 'A', 'R', 'D', 'U', 'C', 'O', 'D', 'I', 'N', 'G', 0, 0, 0, 0, 0, 0 }, sizeof data);
        success = nfc.mifareclassic_WriteDataBlock (4, data);
        Serial.println("Success");

        // Try to read the contents of block 4
        success = nfc.mifareclassic_ReadDataBlock(4, data);
  
        if (success){
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 4:");
          nfc.PrintHexChar(data, 16);
          Serial.println("");
        }
        else{
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else{
        Serial.println("Ooops ... authentication failed: Try another key?");
      }

      //BLOK 5
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 5, 0, keya);
    
      if (success){
        Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
        uint8_t data[16];
        // If you want to write something to block 4 to test with, uncomment
        // the following line and this text should be read back in a minute
        Serial.print("Writing Block 5: .....");
        memcpy(data, (const uint8_t[]){ 'S', 'T', 'A', 'R', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, sizeof data);
        success = nfc.mifareclassic_WriteDataBlock (5, data);
        Serial.println("Success");

        // Try to read the contents of block 5
        success = nfc.mifareclassic_ReadDataBlock(5, data);
    
        if (success){
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 5:");
          nfc.PrintHexChar(data, 16);
          Serial.println("Command Complete!");
      
          // Wait a bit before reading the card again
          delay(2000);
        }
        else{
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else{
        Serial.println("Ooops ... authentication failed: Try another key?");
      }
    }
  }
}
Arduino PN532 Application
Nah dari contoh program diatas kita menuliskan nama user pada blok 4 dengan ARDUCODING, dan menulis status pada blok 5 dengan START. selain itu diketahui UID dari kartu adalah 27D51634. Dari sini kita sudah mendapatkan dua parameter penting yang digunakan sebagai acuan dalam sistem per absenan. Kita kembangkan lagi dengan memadukan tutorial sebelumnya terkait dengan menyimpan data ke database MySQL. Ok daripada muter-muter saya akan lanjutkan untuk bagian program arduinonya. Mari kita asumsikan bahwa file injector (injector.php) kita taruh di direktori C:\xampp\htdocs\absensi_gabut.
#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_PN532.h>

#define PN532_IRQ   (2)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //MAC Address
char server[] = "192.168.10.10";
IPAddress ip(192,168,10,5); //arduino IP
EthernetClient client; 
const int ledPin =  LED_BUILTIN;
String UID_CARD;
String attendance_status;
String user_card;
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

void setup(void) {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  Serial.begin(115200);
  Serial.println("Mesin Absen Gabut");
  lcd.begin();
  //intro gak penting
  lcd.setCursor(0,0);
  lcd.print("  MESIN ABSEN");
  lcd.setCursor(0,1);
  lcd.print("     GABUT");
  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  Ethernet.begin(mac, ip);
  Serial.print("Local IP: ");
  Serial.println(Ethernet.localIP());
  delay(2000);
  lcd.clear();
  Serial.println("Waiting for an ISO14443A Card ...");
}


void loop(void) {
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
    
  lcd.setCursor(0,0);
  lcd.print("Tempelkan Kartu");
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");
    
    uint32_t szUid;
    String uidData;
    for (szUid=0; szUid < uidLength; szUid++){
          uidData += String(uid[szUid]&0xFF, HEX);
    }
    uidData.toUpperCase(); //biarhuruf besar
    Serial.println(uidData);
    UID_CARD =uidData;
    
    if (uidLength == 4){
      //Serial.println("Seems to be a Mifare Classic card (4 byte UID)");   
      //Data Nama disimpan di blok 4 data Status di blok 5
      Serial.println("Trying to authenticate block 4 with default KEYA value");
      uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
      
      //baca blok4
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
    
      if (success){
        Serial.println("Blocks 4) has been authenticated");
        uint8_t data[16];
        // Try to read the contents of block 4
        success = nfc.mifareclassic_ReadDataBlock(4, data);
    
        if (success){
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 4:");
          nfc.PrintHexChar(data, 16);
          Serial.println("");

          uint32_t szPos;
          String phrase;
          for (szPos=0; szPos < 16; szPos++){
                phrase += (char)data[szPos];
          }
          Serial.print("User: ");
          Serial.println(phrase);//Nama pengguna
          user_card=phrase;
          //user_card += "";
        }
        else{
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else{
        Serial.println("Ooops ... authentication failed: Try another key?");
      }

      //baca blok5
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 5, 0, keya);
      if (success){
        Serial.println("Blocks 5) has been authenticated");
        uint8_t data1[16];
        // Try to read the contents of block 5
        success = nfc.mifareclassic_ReadDataBlock(5, data1);
    
        if (success){
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 5:");
          nfc.PrintHexChar(data1, 16);
          Serial.println("");

          uint32_t szPos;
          String phrase;
          for (szPos=0; szPos < 16; szPos++){
                phrase += (char)data1[szPos];
          }
          
          Serial.println(phrase);
          if ((phrase == "IN") || (phrase == "START")){
              digitalWrite(ledPin, HIGH);
              memcpy(data1, (const uint8_t[]){ 'O', 'U', 'T', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, sizeof data1);
              success = nfc.mifareclassic_WriteDataBlock (5, data1);
              attendance_status = "OUT";
              delay(200);
              digitalWrite(ledPin, LOW);
              SendtoDB();
              
           }else if (phrase == "OUT"){
              digitalWrite(ledPin, HIGH);
              memcpy(data1, (const uint8_t[]){ 'I', 'N', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, sizeof data1);
              success = nfc.mifareclassic_WriteDataBlock (5, data1);
              attendance_status = "IN";
              delay(200);
              digitalWrite(ledPin, LOW);
              SendtoDB();
           }else{
            Serial.println("invalid card");
            lcd.setCursor(0,0);
            lcd.print("Invalid Card!  ");
           }
          
          // Wait a bit before reading the card again
          delay(4000);
          lcd.clear();
        }
        else{
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else{
        Serial.println("Ooops ... authentication failed: Try another key?");
      }
    }
    
    if (uidLength == 7){
      Serial.println("Kartu anda ilegal, colongan ya?");
    }
  }
}

//insert data ke DB via injeksi injector.php
void SendtoDB(){
   if (client.connect(server, 80)) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(user_card);lcd.print("  ");
    lcd.setCursor(0,1);
    lcd.print("Status:");
    lcd.setCursor(8,1);
    lcd.print(attendance_status);
    
    Serial.println("");
    Serial.println("connected");
    // Make a HTTP request:
    Serial.print("GET /absensi_gabut/injector.php?uid=");
    Serial.print(UID_CARD);
    Serial.print("&status=");
    Serial.println(attendance_status);
    Serial.println("");
    
    client.print("GET /absensi_gabut/injector.php?uid=");     //YOUR URL
    client.print(UID_CARD);
    client.print("&status=");
    client.print(attendance_status);
    client.print(" ");      //SPACE BEFORE HTTP/1.1
    client.print("HTTP/1.1");
    client.println();
    client.println("Host: 192.168.10.5");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
    lcd.setCursor(0,0);
    lcd.print("connection to   ");
    lcd.setCursor(0,1);
    lcd.print("server is failed");
  }
 }

Mesin Absensi Arduino dengan Smart Card

Mesin Absen Arduino dengan Smart Card

Nah.. untuk basicnya sampai disini aja. Intinya aktivitas kedatangan dan kepulangan tersimpan dengan baik ke data base. Pengembangan bisa dari bagian database nya, misal kita tambahkan relasi untuk usernya. Misal untuk uid 2E14567 merupakan id kartu untuk user ARDUCODING, kita relasikan dengan tabel terkait dengan keterangan dari user atas nama ARDUCODING. Pengambangan lainnya mungkin dengan menulikan data User ke dalam kartu secara lengkap dan selanjutnya dijadikan parameter untuk disimpan pada database, dan masih banyak lagi pengembangan-pengembangan yang bisa dilakukan.



Pencarian Terkait: