RFID dominator


  • Počas niekoľko hodinových eventov v extrémnych hrách typu Airsoft/Paintball/Nerf sa hrajú rôzne módy, napríklad King of The Hill, pre ktorý je tento projekt určený (klasický DOMINATOR). Každý tím získava body za dobu obsadenia daného bodu, resp za dobu jeho udržania. Využil som Arduino, RFID čítačku, LCD displej, hlásič a relé/samostatné ledky.
  • Dva nezávislé časy pre dva tímy, ktoré fungujú po priložení niektorej z kariet tímov práve pre štart času daného tímu. V praxi má každý člen tímu RFID kľúčenku, ktorú vie priložiť na čítačku a aktivovať čas.
  • Maximálny rozsah času:
  • 999 hodín, 59 minút a 59 sekúnd
  • Čas sa pripočítava do momentu, kým nie je zastavený druhým tímom priložením ich karty, alebo organizátorom/rozhodcom, ktorý vie čas pauzovať, alebo špeciálnou kľúčenkou/kartou vynulovať.
  • Hlásič signalizuje priloženie karty k čítačke a LED diódy/relé indikujú momentálny stav stopiek, signalizujú farbu tímu, ktorému sa čas pripočítava.
  • Projekt je určený pre (takmer) neobmedzený počet kľúčeniek, teda sa dajú nahodiť celé tímy, organizátori akcie, karty pre vymazanie výsledkov. Vhodné aj pre kluby hráčov, ktorí hrávajú podobné akcie pravidelne, alebo aj pre poskytovateľov služieb v tomto priemysle.
  • Kľúčenky sú spravidla odlišené farbou pre daný tím. Relé sa využívajú v prípade, že sa používajú silnejšie svetlá/diódy pre signalizáciu aktívneho tímu, ktorému sa pripočítava čas.
  • Čas je vypísaný na znakovom displeji rozmeru 16x2 alebo 20x4.
  • K čítačke stačí ľahko priložiť kľúčenku, čas sa okamžite začne pripočítavať a druhému tímu sa zastaví. Organizátor zastavuje oba časy a začnú sa pripočítavať až po priložení niektorej z kľúčeniek hráča z niektorého tímu. Eraser zmaže oba časy ihneď po priložení karty (pred novou hrou).
  • Riešenie je univerzálne, raz sa kódy kľúčeniek do kódu doplnia a funguje to permanentne. K projektu dodám aj schému zapojenia, potrebné knižnice a Arduino sketch v .ino formáte.
  • Hardvér pre projekt:
  • Arduino Uno Arduino Uno
  • RFID čítačka RC522 (13.56MHz) RFID čítačka
  • Kľúčenky/karty/náramky s kompatibilným štandardom Kľúčenky na 13.56MHz
  • Hlásič (pasívny buzzer) Buzzer
  • 2-kanálové relé, diódy Relé

  • Výsledok


    Relé

    Get addresses:

    #include <SPI.h>
    #include <MFRC522.h>
    #define RST_PIN         9
    #define SS_1_PIN        10
    #define NR_OF_READERS   1
    byte ssPins[] = {SS_1_PIN};
    MFRC522 mfrc522[NR_OF_READERS];
    void setup() {
      Serial.begin(9600);
      while (!Serial);
      SPI.begin();
      for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
        mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN);
        Serial.print(F("Reader "));
        Serial.print(reader);
        Serial.print(F(": "));
        mfrc522[reader].PCD_DumpVersionToSerial();
      }
    }
    
    void loop() {
      for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
        if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
          Serial.print(F("Reader "));
          Serial.print(reader);
          Serial.print(F(": Card UID:"));
          dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
          Serial.println();
          Serial.print(F("PICC type: "));
          MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
          Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));
          mfrc522[reader].PICC_HaltA();
          mfrc522[reader].PCD_StopCrypto1();
        }
      }
    }
    
    void dump_byte_array(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
      }
      Serial.print("Kod:");
      unsigned long kod = 10000 * buffer[4] + 1000 * buffer[3] + 100 * buffer[2] + 10 * buffer[1] + buffer[0]; //finalny kod karty
      Serial.print(kod);
    }
            

    Put addresses + DOMINATOR logic:

    #include <LiquidCrystal_I2C.h>
    #include <SPI.h>
    #include <MFRC522.h>
    
    #define RST_PIN         9          // Configurable, see typical pin layout above
    #define SS_1_PIN        10         // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
    #define SS_2_PIN        8          // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1
    
    #define NR_OF_READERS   1
    
    byte ssPins[] = {SS_1_PIN, SS_2_PIN};
    
    MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.
    
    #define I2C_ADDR    0x3F  // Define I2C Address where the PCF8574A is
                              // Address can be changed by soldering A0, A1, or A2
                              // Default is 0x27
    
    // map the pin configuration of LCD backpack for the LiquidCristal class
    #define BACKLIGHT_PIN 3
    #define En_pin  2
    #define Rw_pin  1
    #define Rs_pin  0
    #define D4_pin  4
    #define D5_pin  5
    #define D6_pin  6
    #define D7_pin  7
    
    LiquidCrystal_I2C lcd(I2C_ADDR,
                          En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,
                          BACKLIGHT_PIN, POSITIVE);
    unsigned long kod;
    boolean run = false;
    boolean run2 = false;
    long timer = 0; //The timer
    int second = 0;
    int minute = 0;
    int tenth = 0;
    int hour =0;
    int second2 = 0;
    int minute2 = 0;
    int tenth2 = 0;
    int hour2 =0;
    const int rfrele = 3;
    const int gdprele = 4;
    const int buzzer = 5;
    void setup() {
      Serial.begin(9600);
      SPI.begin();
      pinMode(rfrele,OUTPUT);
      pinMode(gdprele,OUTPUT);
      pinMode(buzzer,OUTPUT);
        for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
        mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
        Serial.print(F("Reader "));
        Serial.print(reader);
        Serial.print(F(": "));
        mfrc522[reader].PCD_DumpVersionToSerial();
      }
      lcd.begin(20, 4);                // intialise the LCD.
         lcd.setBacklight(HIGH); // Turn on backlight, LOW for off
      lcd.setCursor(0,0);
      lcd.print("  RP2018 DOMINATOR");
      lcd.setCursor(0,1);
       lcd.print("--------------------");
      lcd.setCursor(0,2);
      lcd.print("RF  00:00:00");
       lcd.setCursor(0,3);
       lcd.print("GDP 00:00:00");
    }
    
    void tickClock() {
      if((timer - millis()/100) >= 100 || timer == 0) {
        tick();
        tick2();
        timer = millis()/100;
      }
      
    }
    
    void loop() {
       for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
        if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
          Serial.print(F("Reader "));
          Serial.print(reader);
          // Show some details of the PICC (that is: the tag/card)
          Serial.print(F(": Card UID:"));
          dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
          Serial.println();
          Serial.print(F("PICC type: "));
          MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
          Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));
    
          // Halt PICC
          mfrc522[reader].PICC_HaltA();
          // Stop encryption on PCD
          mfrc522[reader].PCD_StopCrypto1();
        } //if (mfrc522[reader].PICC_IsNewC
      } //for(uint8_t reader
      if(kod==4294946665 || kod==23101 || kod==8151 || kod==4294951443 || kod==4294953039 || kod==24519 || kod==4294945657 || kod==3801 || kod==4294945187){
         
           digitalWrite(rfrele, LOW);
                 digitalWrite(gdprele, HIGH);
          run = false;
          run2 = true;
            }else if(kod==4294956915 || kod==4294958051 || kod==4294961082 || kod==4294960491 || kod==4294958039 || kod==4294958091 || kod==4294946987 || kod==4294961057 || kod==4294959927){
            
               digitalWrite(rfrele, HIGH);
                 digitalWrite(gdprele, LOW);
              run = true;
          run2 = false;
              }else if(kod==12619){
                
                 digitalWrite(rfrele, LOW);
                 digitalWrite(gdprele, LOW);
                run = false;
          run2 = false; 
                }else if(kod==4294962506){
               
                 digitalWrite(rfrele, LOW);
                 digitalWrite(gdprele, LOW);
           second = 0;
     minute = 0;
     tenth = 0;
     hour =0;
     second2 = 0;
     minute2 = 0;
     tenth2 = 0;
     hour2 =0;
     updateLCD();
     updateLCD2();
      run = false;
          run2 = false; 
                  }
      tickClock(); //Start ticking the clock
    }
    
    void tick() {
      if(run) {
        updateLCD();
        
        
        
        if(tenth == 9) {
          tenth = 0;
          
          if(second == 59) {
            second = 0;
            minute++;
            
          }else {
            second++;
          }
          
          if(minute == 60) {
            minute = 0;
            hour++;
            
          } 
        } else {
        tenth++;
        }
      }
    }
    void tick2() {
      if(run2) {
        updateLCD2();
        
        
        
        if(tenth2 == 9) {
          tenth2 = 0;
          
          if(second2 == 59) {
            second2 = 0;
            minute2++;
            
          }else {
            second2++;
          }
          
          if(minute2 == 60) {
            minute2 = 0;
            hour2++;
            
          } 
        } else {
        tenth2++;
        }
      }
    }
    void updateLCD() {
       lcd.setCursor(4,2);
     if(hour < 10) {      // If hour does not have 2 digits
        lcd.print("0");
      }
       lcd.print(hour, DEC);
      lcd.print(":");
      if(minute < 10) {      // If hour does not have 2 digits
        lcd.print("0");
      }
      lcd.print(minute, DEC);
      lcd.print(":");
    
      if(second < 10) {    // If minute does not have 2 digits
        lcd.print("0");
      }
      lcd.print(second, DEC);
      //
      
    }
    void updateLCD2() {
      lcd.setCursor(4,3);
      if(hour2 < 10) {      // If hour does not have 2 digits
        lcd.print("0");
      }
       lcd.print(hour2, DEC);
      lcd.print(":");
      if(minute2 < 10) {      // If hour does not have 2 digits
        lcd.print("0");
      }
      lcd.print(minute2, DEC);
      lcd.print(":");
    
      if(second2 < 10) {    // If minute does not have 2 digits
        lcd.print("0");
      }
      lcd.print(second2, DEC);
      
    }
    
    void dump_byte_array(byte *buffer, byte bufferSize) {
      for (byte i = 0; i < bufferSize; i++) {
    
      }
      kod = 10000*buffer[4]+1000*buffer[3]+100*buffer[2]+10*buffer[1]+buffer[0];  
        tone(buzzer, 4000, 100);
      Serial.println("Zaznamenany kod karty: ");
      Serial.println(kod);
    }
    
    

    Libs

  • RFID - https://github.com/miguelbalboa/rfid
  • I2C pre LCD - https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
  • Wiring:

    Arduino --> I2C LCD:
  • A4 --> SDA
  • A5 --> SCK/SCL
  • 5V --> Vcc
  • GND --> GND
  • Arduino --> RFID RC522:
  • 3.3V --> 3.3V
  • GND --> GND
  • D9 --> RST
  • D10 --> CS
  • D11 --> MOSI
  • D12 --> MISO
  • D13 --> SCK
  • Arduino --> buzzer:
  • 5V --> 5V
  • D5 --> INPUT
  • GND --> GND
  • Arduino --> LED + relay:
  • 5V --> 5V relay
  • GND --> GND
  • D3--> LED + relay IN1
  • D4 --> LED + relay IN2
  • Case:

    RFID DOMINATOR CASE Thing Inverse