RFID, SD card and real time clock door lock

Hello,
I am trying to make a RFID lock that logs who swipes their card and when, onto a SD card. I am planning to use parallax’s RFID reader, http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/rfid/List/0/SortField/4/ProductID/114/Default.aspx And Adafruit’s Sd card and RTC Arduino shield, http://www.adafruit.com/products/1141

This is my current code, it is made up of example code from both the shield and RFID reader. Any help would be appreciated.

Thanks

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//Begin RTC
    #include <Wire.h>
    #include "RTClib.h"
 
    RTC_DS1307 RTC;
//End RTC

//Begin RFID
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

    #define TAG_LEN 12
    char tag[12] = {'3', '6', '0', '0', '7', '8', '9', '9', '8', '7'}; //tag 1
    char tag2[12] = {'3', '6', '0', '0', '7', '8', '9', 'B', 'B', '5'}; //tag 2
    char code[12];
    int bytesread = 0;
    //Connections to be made:
    int ledPin = 13; // Connect LED to pin 13
    int rfidPin = 2; // RFID enable pin connected to digital pin 2
    //Connect SOUT Pin to pin 0, does not need to be defined because 0 is the default RX pin
    int val=0;
//End RFID

//Begin SD
    #include <SD.h>
 
    File myFile;
//End SD


 
void setup () {
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // uncomment it & upload to set the time, date and start run the RTC!
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  pinMode(10, OUTPUT);
 
}
 
void loop () {
  DateTime now = RTC.now();
  //Begin RFID
  digitalWrite(ledPin,LOW); //LED off
digitalWrite(rfidPin, LOW); // Activate the RFID reader
 lcd.clear(); //Clears LCD
 lcd.setCursor(0, 0);
 lcd.print("  Please Swipe");
 lcd.setCursor(0, 1);
 lcd.print("   Your Card");
  if(Serial.available() > 0) {	    // if data available from reader
    if((val = Serial.read()) == 10) {   // check for header
	bytesread = 0;
	while(bytesread<10) {		  // read 10 digit code
	  if( Serial.available() > 0) {
	    val = Serial.read();
	    if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
		break;			     // stop reading
	    }
	    code[bytesread] = val;	   // add the digit
	    bytesread++;			 // ready to read next digit
digitalWrite(rfidPin, HIGH); //Turns off RFID reader, THIS IS IMPORTANT so it doesn't double read the card
	  }
	}
//End RFID

if(bytesread >= 10) {		  // if 10 digit read is complete
 
	 if(strcmp(code, tag) == 0) {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" Access Granted");
 lcd.setCursor(0, 1);
 lcd.println(code);
 delay (1500);
 lcd.setCursor(0, 1);
 lcd.print("Jonnyblanch  ");
         digitalWrite(ledPin,HIGH);
	   Serial.print("Tag matches: ");
	   Serial.println(code);
           //digitalWrite(ledPin,HIGH);
           digitalWrite(rfidPin, HIGH);
           myFile = SD.open("log.txt", FILE_WRITE);
           // if the file opened okay, write to it:
            if (myFile) {
              Serial.print("Writing to log.txt...");
              myFile.print("Jonnyblanch");
              myFile.print(now.month(), DEC);
              myFile.print('/');
              myFile.print(now.day(), DEC);
              myFile.print(' ');
              myFile.print(now.hour(), DEC);
              myFile.print(':');
              myFile.print(now.minute(), DEC);
              myFile.print(':');
              myFile.print(now.second(), DEC);
              myFile.println();
          	// close the file:
              myFile.close();
            delay(2000);	     // wait for a second or two
           return;                   //Go to the top, skip the bottom
         }
      }  else {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("Access Denied");
 lcd.setCursor(0, 1);
 lcd.println(code);
	   Serial.print(code);
	   Serial.println(" does not match");
           digitalWrite(rfidPin, HIGH);
        }
      }
  bytesread = 0;
	     delay(2000);	     // wait for a second
        digitalWrite(ledPin,LOW);    
    }
  }
}

So in short, I have included what I believe to be everything, I have done some of the setup, and I have set it so that if a certain card is swiped, it unlocks the lock and logs it to the SD card. I have not completed the setup portion of the code due to the fact that I am not sure what to set the baud rate as. The example sketches for the SD shield and the RFID reader both have the baud rate set differently, the RFID is 2400 and the SD shield is 9600. So I am not sure what to set it as. Once again, any help would be greatly appreciated.

Why does the SD card need any specific serial speed? The RFID reader needs to be at that speed so set it up as 2400.

I honestly don't know why the SD card has a different baud rate, but I guess 2400 could work for the whole project. Thank you. But is anyone up to the challenge of reading over my code? Thanks.

I have not completed the setup portion of the code due to the fact that I am not sure what to set the baud rate as. The example sketches for the SD shield and the RFID reader both have the baud rate set differently, the RFID is 2400 and the SD shield is 9600.

I honestly don't know why the SD card has a different baud rate

This is rubbish. The SD card is not a serial device, so there is no concept of a baud rate when dealing with the SD card.

You really should develop some functions. You don't really intend to repeat that huge block of code to write another entry to the file, for another person, do you?

But is anyone up to the challenge of reading over my code?

I did. What am I looking for, though?

When I read the example sketch for the Adafruit SdDcard and Real Time Clock, It says serial.begin(9600). Although I have been using Arduino for a little while now, I Know next to nothing about baud rate rate and all of this stuff that made me come here for help.

I quite new to programming so when you say functions, I am not totally sure what you mean, i'm sorry. IS that when you define a "function" such as, "Print.Time", and then in the loop you call that "function"?

And finally there is nothing in particular that you are looking for in my code. I just posted it so that you could see how I was doing all of this, and also so that someone might be able to spot a bug for me. I do not have the SD and RTC shield yet, nor do I have the RFID reader, so I can't test if it will work yet.

I quite new to programming so when you say functions,...

We expect you to take the hint and look up what a function actually is, they are important for reusing code and packaging it up into small chunks you can arrange more easly.

A baud rate only matters if it is communicating with something that you dan't change the baud rate of. So the SD card examples just use serial as a feedback so the baud rate can be anything you can set the serial monitor to. The RFID however is fixed.

OK, I get it now,thanks. I'll go look up functions now. Sorry, I just asked what they are because I have a feeling that you guys might explain it a little better. Thanks

Ok, so I set up a couple of functions, do you think this is better?

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//Begin RTC
    #include <Wire.h>
    #include "RTClib.h"

    RTC_DS1307 RTC;
//End RTC

//Begin RFID
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

    #define TAG_LEN 12
    char tag[12] = {'3', '6', '0', '0', '7', '8', '9', '9', '8', '7'}; //tag 1
    char tag2[12] = {'3', '6', '0', '0', '7', '8', '9', 'B', 'B', '5'}; //tag 2
    char code[12];
    int bytesread = 0;
    //Connections to be made:
    int ledPin = 13; // Connect LED to pin 13
    int rfidPin = 2; // RFID enable pin connected to digital pin 2
    //Connect SOUT Pin to pin 0, does not need to be defined because 0 is the default RX pin
    int val=0;
//End RFID

//Begin SD
    #include <SD.h>
 
    File myFile;
//End SD


 
void setup () {
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // uncomment it & upload to set the time, date and start run the RTC!
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  pinMode(10, OUTPUT);
  
   
 
}
 
void loop () {
 
  //Begin RFID
startRFID();
//End RFID
Jonnyblanch();


  bytesread = 0;
	     delay(2000);	     // wait for a second
        digitalWrite(ledPin,LOW);    
    }
  


void startRFID()
{
   digitalWrite(ledPin,LOW); //LED off
digitalWrite(rfidPin, LOW); // Activate the RFID reader
 lcd.clear(); //Clears LCD
 lcd.setCursor(0, 0);
 lcd.print("  Please Swipe");
 lcd.setCursor(0, 1);
 lcd.print("   Your Card");
  if(Serial.available() > 0) {	    // if data available from reader
    if((val = Serial.read()) == 10) {   // check for header
	bytesread = 0;
	while(bytesread<10) {		  // read 10 digit code
	  if( Serial.available() > 0) {
	    val = Serial.read();
	    if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
		break;			     // stop reading
	    }
	    code[bytesread] = val;	   // add the digit
	    bytesread++;			 // ready to read next digit
digitalWrite(rfidPin, HIGH); //Turns off RFID reader, THIS IS IMPORTANT so it doesn't double read the card
	  }
	} 
    }
  }
}

void Jonnyblanch()
{
   DateTime now = RTC.now();
  if(bytesread >= 10) {		  // if 10 digit read is complete
 
	 if(strcmp(code, tag) == 0) {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" Access Granted");
 lcd.setCursor(0, 1);
 lcd.println(code);
 delay (1500);
 lcd.setCursor(0, 1);
 lcd.print("Jonnyblanch  ");
         digitalWrite(ledPin,HIGH);
	   Serial.print("Tag matches: ");
	   Serial.println(code);
           //digitalWrite(ledPin,HIGH);
           digitalWrite(rfidPin, HIGH);
           myFile = SD.open("log.txt", FILE_WRITE);
           // if the file opened okay, write to it:
            if (myFile) {
              Serial.print("Writing to log.txt...");
              myFile.print("Jonnyblanch");
              myFile.print(now.month(), DEC);
              myFile.print('/');
              myFile.print(now.day(), DEC);
              myFile.print(' ');
              myFile.print(now.hour(), DEC);
              myFile.print(':');
              myFile.print(now.minute(), DEC);
              myFile.print(':');
              myFile.print(now.second(), DEC);
              myFile.println();
          	// close the file:
              myFile.close();
            delay(2000);	     // wait for a second or two
           return;                   //Go to the top, skip the bottom
         }
      }  else {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("Access Denied");
 lcd.setCursor(0, 1);
 lcd.println(code);
	   Serial.print(code);
	   Serial.println(" does not match");
           digitalWrite(rfidPin, HIGH);
        }
      }
}

Look at the setup and loop function. That is what your functions should look like only with diffrent names. That code will not compile. Do not use #includes inside a function.

I don't see any #includes in any of my functions. Also, I don't see a real difference in the structure of my functions and the loop and setup functions. I looked up functions and, honestly, mine seems to make sense(as far as I know). Also, my sketch does compile, but that doesn't mean that it will work.

When I try and compile your code I get:-

Arduino: 1.0.5 (Mac OS X), Board: "Arduino Uno" sketch_jul20a.ino: In function 'void setup()': sketch_jul20a:38: error: 'class RTC_DS1307' has no member named 'isrunning'

Anyway your function Jonnyblanch() while contains the chunk of code you copied from the original is very specific. The point about functions is that you should try to make them general. In this case you should pass in the string containing the name and also a number representing the tag. This can then be checked against your list of allowed tags. If you write the function the way you have done the you need to write that same function with minor modifications for everyone who is allowed access. Where you have a constant, make it a variable and pass those variables into the function. That way they are reusable.

delay(2000);         // wait for a second or two

It's two. :) Why wait?

I'm not sure why i get an error and i don't, odd. I honestly don't really understand what you are trying to get me to do, but, would it make sens to, instead of have the whole jonnyblanch function, have a function for the get time, so that instead of having to have thoes 10 or lines each time, i just have a function. And I could also have a function for the access granted part, but not for a specific tag, to be more generic?

would it make sens to, instead of have the whole jonnyblanch function,

No no sense at all, that is not what computing is about.

but not for a specific tag, to be more generic?

Yes you can you pass the tag into the function as a variable instead of having it hard coded.

..... Just as an aside, did you know that what you are trying to do is illegal in some countries, mainly Scandinavia. Recording of positive information, that is the time and data of an access by a person authorized to access is considered a breach of your privacy. In other countries this is not illegal.

So instead of what I put before, it would be something more like this?

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//Begin RTC
    #include <Wire.h>
    #include "RTClib.h"
 
    RTC_DS1307 RTC;
//End RTC

//Begin RFID
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

    #define TAG_LEN 12
    char tag[12] = {'3', '6', '0', '0', '7', '8', '9', '9', '8', '7'}; //tag 1
    char tag2[12] = {'3', '6', '0', '0', '7', '8', '9', 'B', 'B', '5'}; //tag 2
    char code[12];
    int bytesread = 0;
    //Connections to be made:
    int ledPin = 13; // Connect LED to pin 13
    int rfidPin = 2; // RFID enable pin connected to digital pin 2
    //Connect SOUT Pin to pin 0, does not need to be defined because 0 is the default RX pin
    int val=0;
//End RFID

//Begin SD
    #include <SD.h>
 
    File myFile;
//End SD


 
void setup () {
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // uncomment it & upload to set the time, date and start run the RTC!
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  pinMode(10, OUTPUT);
 
}
 
void loop () {
  
  //Begin RFID
  digitalWrite(ledPin,LOW); //LED off
digitalWrite(rfidPin, LOW); // Activate the RFID reader
 lcd.clear(); //Clears LCD
 lcd.setCursor(0, 0);
 lcd.print("  Please Swipe");
 lcd.setCursor(0, 1);
 lcd.print("   Your Card");
  if(Serial.available() > 0) {	    // if data available from reader
    if((val = Serial.read()) == 10) {   // check for header
	bytesread = 0;
	while(bytesread<10) {		  // read 10 digit code
	  if( Serial.available() > 0) {
	    val = Serial.read();
	    if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
		break;			     // stop reading
	    }
	    code[bytesread] = val;	   // add the digit
	    bytesread++;			 // ready to read next digit
digitalWrite(rfidPin, HIGH); //Turns off RFID reader, THIS IS IMPORTANT so it doesn't double read the card
	  }
	}
//End RFID

if(bytesread >= 10) {		  // if 10 digit read is complete
 
    if(strcmp(code, tag) == 0) {
         accessgranted();
         lcd.print("Jonnyblanch  ");
         digitalWrite(ledPin,HIGH);
	 Serial.print("Tag matches: ");
	 Serial.println(code);
         //digitalWrite(ledPin,HIGH);
         digitalWrite(rfidPin, HIGH);
         myFile = SD.open("log.txt", FILE_WRITE);
         // if the file opened okay, write to it:
         if (myFile) {
           Serial.print("Writing to log.txt...");
           myFile.print("Jonnyblanch");
           timestamp();
           // close the file:
           myFile.close();
           delay(2000);	     // wait for a second or two
           return;                   //Go to the top, skip the bottom
         }
      }  else {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("Access Denied");
 lcd.setCursor(0, 1);
 lcd.println(code);
	   Serial.print(code);
	   Serial.println(" does not match");
           digitalWrite(rfidPin, HIGH);
        }
      }
  bytesread = 0;
	     delay(2000);	     // wait for a second
        digitalWrite(ledPin,LOW);    
    }
  }
}

void timestamp()
{
  DateTime now = RTC.now();
              myFile.print(now.month(), DEC);
              myFile.print('/');
              myFile.print(now.day(), DEC);
              myFile.print(' ');
              myFile.print(now.hour(), DEC);
              myFile.print(':');
              myFile.print(now.minute(), DEC);
              myFile.print(':');
              myFile.print(now.second(), DEC);
              myFile.println();
}

void accessgranted()
{
  lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print(" Access Granted");
 lcd.setCursor(0, 1);
 lcd.println(code);
 delay (1500);
 lcd.setCursor(0, 1);
}

Also, I had no idea that this is illegal in some countries. At least I’m only going to be using this on the door to my room. :slight_smile:

If I were doing this I would start off by defining the tags as variables

  // char tag[12] = {'3', '6', '0', '0', '7', '8', '9', '9', '8', '7'}; //tag 1
   // char tag2[12] = {'3', '6', '0', '0', '7', '8', '9', 'B', 'B', '5'}; //tag 2
long long  tags[] = { 0x3600789987, 0x3600789BB5 }; // define an array with two tags in it
char* names[] = { "my first name", "my second name"} // define an array of names

See http://arduino.cc/en/Reference/String Then the main loop would look something like this:-

void loop(){
tag = checkInput()
if (tag != 0) {
    idNumber = validate(tag);
        if (idNumber != -1) {  // -1 indicates no access
          accessGrant(idNumber); // open door and print out name on LCD
          logAccess(idNumber);
          inviteLogin(); // set display to invite new login
        }
else {
    accessDenied(idNumber);
     inviteLogin(); // set display to invite new login
    }
 }
}

This is called top down design. I have used functions I have yet to write but should show the clear logic of the operation. When you are satisfied with how it is supposed to work then go and implement those functions. Those functions may well call other functions like time stamp and so on.

What if, instead of this for each tag that that is accepted,

 if(strcmp(code, tag) == 0) {
         accessgranted();
         lcd.print("Jonnyblanch  ");
         digitalWrite(ledPin,HIGH);
     Serial.print("Tag matches: ");
     Serial.println(code);
         //digitalWrite(ledPin,HIGH);
         digitalWrite(rfidPin, HIGH);
         myFile = SD.open("log.txt", FILE_WRITE);
         // if the file opened okay, write to it:
         if (myFile) {
           Serial.print("Writing to log.txt...");
           myFile.print("Jonnyblanch");
           timestamp();
           // close the file:
           myFile.close();
           delay(2000);         // wait for a second or two
           return;                   //Go to the top, skip the bottom
         }
      }

I had just one. I was thinking instead of, if(strcmp(code, tag) == 0), I were to have something like, if(strcmp(code, tag || tag2) == 0). Then for each spot in which it displays information for each specific card, it then somehow were to print the info. for the card that was actually swiped. The only way that I can think of to do that would be to have more if statements within this one, which would defeat the purpose of this whole idea. I looked around online but I couldn't ind anything to help.

Oh, and I forgot to mention having the strings for each id tag and name like you mentioned in your last post.

I don't think you are taking on board my suggestions of not using string compares for the token matching. If the token is put into a numeric variable then you can just use the normal ==.

You might get some ideas from the code of this project:- http://www.thebox.myzen.co.uk/Hardware/RFID_Sequencer.html I know there is a lot of stuff you don't need but it covers enrolling a token, storing it into EEPROM and matching a found token with a stored one.

I kinda get what you are saying, in theory, but I still can't really put it into my code just yet. What I don't really get in what you are telling me I should do is, for each tag that is allowed access, do I need to copy what you had in the loop again? Also, I don't quite understand how it know "idnumber" relates to the name of the person too. Would it make sense to take as much of the loop as possible, and put it into different functions(as long as its not specific to a certain id code/person)?

By the way, that was a very cool project you made.