Go Down

Topic: RFID, SD card and real time clock door lock (Read 13958 times) previous topic - next topic

Grumpy_Mike

If I were doing this I would start off by defining the tags as variables
Code: [Select]

  // 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:-
Code: [Select]

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.

ColeH

What if, instead of this for each tag that that is accepted,
Code: [Select]
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.

ColeH

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

Grumpy_Mike

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.

ColeH

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.

Grumpy_Mike

Quote
, for each tag that is allowed access, do I need to copy what you had in the loop again?

No the point in coding is that you let the data drive the code, so if you want more of any data you don't have more code. There should be a fixed amount of code that could handle anything from one to a very large number.

Quote
I don't quite understand how it know "idnumber" relates to the name of the person too.

Basically these are unrelated pieces of data. You make them related by having them in the same place in two lists ( or arrays ) So the third tag ID in the tag ID list will correspond to the third name in the name list.

You will want to store these lists in a none volatile way, that is you need the data to persist through power cycles. That is why you think you need to include literal names in the actual code. However if the tag IDs and names are stored in EEPROM then there is no need to include these in the actual hard code. This of course means more code to store and retrieve data from EEPROM.

Programming is all about abstracting data out of the code and into variables.

It's a long haul but if you know what you are aiming at I think it helps.

ColeH

Okay, I totally get what you are trying to get me to do now, but when I run my code I am left with multiple errors and a few questions.
Code: [Select]
// 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
    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
    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(2400);
    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, tags) == 0) {
         idNumber = validate(tags);
         accessgranted();
         lcd.print(idNumber);
         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(idNumber);
           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);
}


The first of the errors says this, integer constant is too large for 'long' type.  The question that I now have is, in your quick example code using the strings, how do you setup a function like this?  "accessGrant(idNumber); // open door and print out name on LCD"  I did some research but I can't be sure how to set up a function that way, especially the for accessGranted part.  MY only guess would be something like this
Code: [Select]
void accessgranted(idNumber)
{
  lcd.print(idNumber);
  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(idNumber);
    timestamp();
    // close the file:
    myFile.close();
    delay(2000);      // wait for a second or two
    return;                   //Go to the top, skip the bottom
  } 
}


Is that correct? 

Grumpy_Mike

Ok the problem with the tags is I forgot to put ll on the end of the constants so that line becomes:-
Code: [Select]
long long tags[] = { 0x3600789987ll, 0x3600789BB5ll }; // define an array with two tags in it

As I wrote that top level code the grant access function takes in not the tag number but the place in the list where the match was found:-
so you get something like this:-
Code: [Select]

void accessgranted(idNumber)
{
  lcd.print(names[idNumber]+" access granted");
// proceed to log it

ColeH

I really get what I should do now, but when I ran my code, I still get errors.
Code: [Select]
// 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
    long long tags[] = { 0x3600789987ll, 0x3600789BB5ll }; // define an array with two tags in it
    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(2400);
    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

   accessgranted();
      }
  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(idNumber)
{
if(strcmp(code, tags) == 0) {
   idNumber = validate(tag);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print(" Access Granted");
   lcd.setCursor(0, 1);
   lcd.print(names[idNumber]+"access");
   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(names[idNumber]);
       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);
        }
}


Did I not set it up properly?

Grumpy_Mike

What errors?
Can you give links to the libaries you use.

ColeH

this page has the libraries I am using.
http://learn.adafruit.com/adafruit-data-logger-shield/downloads

There are 10 or so errors.

Grumpy_Mike

Thanks for the link
you use
Code: [Select]

if(bytesread >= 10) {   // if 10 digit read is complete

   accessgranted();
      }
  bytesread = 0;

but you do not pass any number into the function accessgranted, yet in the function declaration you have a number you pass in. You also need to say what type of number this is. You want to pass the token just read into this.

You can't use isrunning with the library it is not implemented.

Next you have
Code: [Select]
if(strcmp(code, tags) == 0) {
Now you have defined tags as a long long so you can't do a string compare. This is the place where you search through your list of tags and see if it matches the one you have just read.
Next line says
Quote
idNumber = validate(tag);

There is no validate function in the code.

Anyway I stopped there.

Grumpy_Mike

Quote
Anyway I stopped there.

Well no I didn't however I stopped when I found out that the RTClib that you linked to is so out of date it won't compile on my machine.
This is as far as I got. Note you need to put the read token into a long long token to pass it to the function. See comments.
Code: [Select]

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

//Begin RFID

    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
    long long tags[] = { 0x3600789987ll, 0x3600789BB5ll }; // define an array with two tags in it
    char* names[] = {"fred","mike"};
    int maxTags = 2; // maximum number of tags - each name needds a tag
    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


    File myFile;
//End SD



void setup () {
    Serial.begin(2400);
    Wire.begin();
    RTC.begin();
/* -- this calss has no member isrunning
  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
    accessgranted(0x123LL); // YOU NEED TO PASS THE VALUE OF THE TOKEN YOU JUST READ HERE
  }
  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(long long tag)
{
  int idNumber = validate(tag);
if(idNumber != -1) { // no match returns -1 otherwise
   idNumber = validate(tag);
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print(" Access Granted");
   lcd.setCursor(0, 1);
   lcd.print(names[idNumber]);
   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(names[idNumber]);
       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);
        }
}
int validate(long long newRead){
  int place = -1;
    for(int i=0; i<maxTags; i++){
      if(newRead == tags[i]) place = i;
    }
   return place;
}

ColeH

Do you personally think that this version of the code would work?
Code: [Select]
// 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);
}


I know that you have will most likely have no way to test it, but what do you think?

Grumpy_Mike

Are we not back to the old problem of needing more code for every tag that has access?

Go Up