#include #include #include #include #define BTN_PIN A0 // lcd buttons are Voltage-Divider analog #define LCD_BACKLIGHT 10 #define LCD_RS 8 #define LCD_EN 9 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D6 6 #define LCD_D7 7 #define MIFARE_SELECT 2 #define MIFARE_RESET 3 #define EEP_CLIENT_MAX 40 // how many UID we can store #define EEP_ADDR_UID_INCREMENT 12 // address increment value (size of a UID) #define EEP_ADDR_START 20 // start of cards address #define EEP_ADDR_LOG_START 620 // start of Log address #define EEP_ADDR_LOG_LENGTH 10 // how many log items we can store MFRC522 mfrc522(MIFARE_SELECT, MIFARE_RESET); MFRC522::MIFARE_Key key; LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7); boolean cardWasPresent = true; long lastActionMillis = 0; boolean unlocked = false; boolean outputOn = false; int displayLogIndex = -1; int displayLogIndexLast = -1; int displayCardsIndex = -1; int displayCardsIndexLast = -1; boolean cardsshow=false; void setup() { pinMode(10, OUTPUT); // LCD backlight pinMode(A4, OUTPUT); // relais 1 pinMode(A5, OUTPUT); // relais 2 set_output(false); digitalWrite(A5, HIGH); Serial.begin(115200); SPI.begin(); mfrc522.PCD_Init(); lcd_backlight(true); lcd.begin(16, 2); lcd.print("hello, world!"); // Prepare the security key for the read and write functions // all six key bytes are set to 0xFF at chip delivery from the factory. // we do not use the security key feature for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } // check if we already have a master key MFRC522::Uid masterUid = get_uid(0, EEP_ADDR_START); if(masterUid.size == 0 || masterUid.size == 0xff) { // we don't have one, so we request it lcd.clear(); lcd.print("Kein Masterkey"); lcd.setCursor(0, 1); while(true) { if(mfrc522.PICC_IsNewCardPresent()) { if(mfrc522.PICC_ReadCardSerial()) { lcd.clear(); lcd.print("Karte ID:"); lcd.setCursor(0, 1); lcd_print_uid(&(mfrc522.uid)); save_master_uid(&(mfrc522.uid)); delay(500); lcd.clear(); lcd.print("OK!"); delay(1000); break; } } } } lcd_print_home(); /* Serial.println("storage dump:"); dump_uid(EEP_CLIENT_MAX +1, EEP_ADDR_START); Serial.println("log dump:"); dump_uid(EEP_ADDR_LOG_LENGTH, EEP_ADDR_LOG_START); */ } void lcd_print_home() { displayLogIndex = -1; lcd.clear(); lcd.print("Karte Bitte"); if(unlocked) { lcd.setCursor(15, 0); lcd.print("U"); } else { lcd.setCursor(0, 1); lcd.print("Ausgang: "); lcd.print(outputOn ? "AN": "AUS"); } } void handleCards(long currentMillis) { if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { mfrc522.PICC_HaltA(); cardWasPresent = true; lastActionMillis = currentMillis; lcd_backlight(true); lcd.clear(); lcd_print_uid(&(mfrc522.uid)); int cardIndex = check_uid(&(mfrc522.uid)); if(cardIndex == 0) { // card is master lcd.setCursor(0, 1); if(unlocked) { unlocked = false; lcd.print("Gesperrt"); } else { lcd.print("Entsperrt"); unlocked = true; } } else if(cardIndex > 0) { // card is client if(unlocked) { // if we are unlocked and detect a client card // we remove this card from EEPROM delete_uid(cardIndex, EEP_ADDR_START); lcd.clear(); lcd.print("Karte wurde"); lcd.setCursor(0, 1); lcd.print("geloescht"); } else { // if we are locked, we switch out Output if(outputOn) { set_output(false); } else { add_log(&(mfrc522.uid)); set_output(true); } lcd.setCursor(0, 1); lcd.print("Ausgang: "); lcd.print(outputOn ? "AN": "AUS"); } } else { // card is neither master nor slave if(unlocked) { if(save_client_uid(&(mfrc522.uid))) { lcd.clear(); lcd.print("Hinzugefuegt"); lcd.setCursor(0, 1); lcd.print(""); lcd_print_uid(&(mfrc522.uid)); delay(500); while(!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()){ delay(50); } lcd.setCursor(0, 0); lcd.print(" "); delay(200); } else { lcd.clear(); lcd.print("Fehler beim"); lcd.setCursor(0, 1); lcd.print("hinzufuegen"); } } else { lcd.setCursor(0, 1); lcd.print("Unbekannte Karte"); } } delay(1000); lcd_print_home(); } } void loop() { long currentMillis = millis(); handleCards(currentMillis); if(readButtons() == 1 && !cardsshow) { //select button shows log, if not showing cards atm displayLogIndex++; displayLogIndex %= 10; lastActionMillis = currentMillis; delay(200); } // log display function if(displayLogIndex != displayLogIndexLast) { if(displayLogIndex >= 0) { lcd_backlight(true); lcd.clear(); lcd.print("Log "); lcd.print(displayLogIndex); lcd.setCursor(0, 1); MFRC522::Uid uid = get_uid(displayLogIndex, EEP_ADDR_LOG_START); lcd_print_uid(&uid); } displayLogIndexLast = displayLogIndex; } if(readButtons() == 3) { //down displayCardsIndex++; displayCardsIndex %= EEP_CLIENT_MAX; lastActionMillis = currentMillis; cardsshow=true; delay(200); } if(readButtons() == 4) { //up displayCardsIndex--; if (displayCardsIndex<0){ displayCardsIndex=EEP_CLIENT_MAX-1; } displayCardsIndex %= EEP_CLIENT_MAX; lastActionMillis = currentMillis; cardsshow=true; delay(200); } // saved cards display function if(displayCardsIndex != displayCardsIndexLast) { if(displayCardsIndex >= 0) { lcd_backlight(true); lcd.clear(); lcd.print("SLOT "); lcd.print(displayCardsIndex); if (displayCardsIndex==0){ lcd.print(" Master"); } lcd.setCursor(0, 1); MFRC522::Uid uid = get_uid(displayCardsIndex, EEP_ADDR_START); lcd_print_uid(&uid); } displayCardsIndexLast = displayCardsIndex; } //card removal if(readButtons() == 1 && cardsshow && unlocked) { //cards are shown, is unlocked an select pressed lastActionMillis = currentMillis; lcd.clear(); lcd.print("Karte"); lcd.setCursor(0, 1); lcd.print("entfernt"); delete_uid(displayCardsIndex, EEP_ADDR_START); delay(1000); } // timeout handling for returning to locked state if(currentMillis - lastActionMillis > 30000) { unlocked = false; displayLogIndex = -1; displayCardsIndex = -1; cardsshow=false; lcd_backlight(false); if(cardWasPresent) { cardWasPresent = false; lcd_print_home(); } } }