Stalker V2 Remote RFID Logger Sketch

I am working on a batttery-powered waterproof RFID logger using:

Seeeduino Stalker V2 - http://www.seeedstudio.com/depot/seeeduino-stalker-v2-p-727.html?cPath=132_133
0.5w Solar Panel 55x70 - http://www.seeedstudio.com/depot/05w-solar-panel-55x70-p-632.html?cPath=155
2A Li-Po Battery - http://www.seeedstudio.com/depot/lithium-ion-polymer-batteries-2a-p-603.html?cPath=178_183
Seeeduino Stalker v2 enclosure - http://www.seeedstudio.com/depot/seeeduino-stalker-v2-enclosure-p-734.html?cPath=178_184
125Khz RFID module - UART -http://garden.seeedstudio.com/index.php?title=125Khz_RFID_module_-_UART
NCP1400-5V Step-Up Breakout Used to step-up 3.3v to 5 for RFID module- NCP1400-5V Step-Up Breakout - PRT-08999 - SparkFun Electronics
RFID tag combo (125khz) - 5 pcs http://www.seeedstudio.com/depot/rfid-tag-combo-125khz-5-pcs-p-700.html?cPath=144_153

My sketch below, will log to SD the time, date, day and serial number of any RFID tag detected along with the temp.

There are also sections in the sketch to switch betweed three modes, RFID logging mode, dump all logged date from SD over serial port to PC, Erase the data file mode, so no need to remove SD card - Needs more work, at the moment this can only be changed by re uploading the sketch.

I am continually working on this sketch so check back for updates.

Feel free to leave suggestions, comments etc. so I can improve my sketch.

Things to do, feel free to suggest ways to do the following:
Convert RFID tag serial number from HEX to decimal so it matches what is printed on the tags, at the moment it logs a HEX value.
Log battery voltage and charge status <- for some reason I could not get this to work
Add button to switch between modes

Sketch In Posts Below Due To Post Length Limit

Example of output via serial

Seeeduino Stalker V2 RFID Logger V1
Initializing SD Card...
SD Card Ready.

RFID Tag correctly received.
Checksum OK!
Will try to write data to RFIDlog.csv on SD now.
RFID Tag ID:,000C15B0,Checksum:97,Date:,22/5/11,Day:,Sunday,Time:,9:53:19,Temp D
eg. C,17.81,
Done!

Example of data file

RFID Tag ID:,0052E46C,Day,Tuseday,Date:,17/5/11,Time:,1:54:58,Temp,21.94
RFID Tag ID:,009067FE,Day,Tuseday,Date:,17/5/11,Time:,1:55:4,Temp,21.94
RFID Tag ID:,00CDEB36,Day,Tuseday,Date:,17/5/11,Time:,1:55:9,Temp,21.94
RFID Tag ID:,0052E46C,Day,Tuseday,Date:,17/5/11,Time:,1:55:14,Temp,21.94
RFID Tag ID:,000C15B0,Day,Tuseday,Date:,17/5/11,Time:,1:55:19,Temp,21.94

First Part Of Code:

/*

 ********Seeeduino Stalker V2 RFID Logger V1 - Godslust*********
 
 SD card datalogger (RFID swipe-time logger) - 21/11/2011
 
 *  Tested on arduino 0022
 *  Logs to .csv file on SD card
 *  Logs rfid tags serial number in HEX format from 125mhz UART RFID reader
 *  Validates the rfd tags checksum 
 *  Logs temp sensor reading
 *  Logs time and date
 *  Uses SD library, tested using SanDisk 8gb micro SDHC Class 4 & Kingmax 128mb micro SD 
 *  Uses RX8052 library 
 *  RFID reader connected using NewSoftSerial via Digital pins 2 and 3, no need to unplug rfid reader to upload new versions of sketch 
 *  Serial monitor 38400 baud (can change this in void setup())
 *  Can Dump data file via serial (change in void loop()) No need to remove SD!!
 *  Can Erase data file (change in void loop()) No need to remove SD!!
 *  LED on pin 8 HIGH while reading and saving to sd
 */

#include <RX8025.h> 
#include <Wire.h>  
#include <SD.h>
#include <NewSoftSerial.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

//for rfid
//Dont forget to change the values in 'NewSoftSerial' below if you move the rfid rx and tx pins somewhere else
NewSoftSerial mySerial(2, 3);
int counter;
byte data[14];
byte hexBlock1,hexBlock2,hexBlock3,hexBlock4,hexBlock5;
byte hexCalculatedChecksum,hexChecksum;
#define stx 2//Define the value of rfid start bit 
#define etx 3//Define the value of rfid end bit 

//for time and date 
int rtc_sec, rtc_min, rtc_hou, rtc_wee, rtc_dat, rtc_mon, rtc_yea;

//bytes for temp calculations
byte res;
byte msb;
byte lsb;
int val;

void setup() {
  //LED pin set to OUTPUT
  pinMode(8,OUTPUT); 

  //start serial and myserial
  Serial.begin(38400);
  mySerial.begin(9600);

  //Start RTC
  RX8025.init();

  //To set the clock - uncomment two lines below
  //unsigned char RX8025_time[7]={0x00,0x36,0x20,0x06,0x21,0x05,0x11  };//second, minute, hour, weekday, date, month, year, BCD format
  //RX8025.setRtcTime(RX8025_time);

  //Announce the script 
  Serial.println("Seeeduino Stalker V2 RFID Logger V1");
  //initializ sd card
  InitiSD();
}

void loop() {

  read_and_log(); //read rfid tags and log data to RFIDlog.csv on SD
  //data_file_dump(); //dumps data file RFIDlog.csv to serial then waits for 2 min
  //erase_dataFile(); //deletes data file RFIDlog.csv from sd

}

Rest Of Code:

void read_and_log (){
  //read the rfid tag if present
  if (mySerial.available() > 0) {
    data[counter] = mySerial.read();
    counter++;
    if(counter > 13) {
      //we read the whole message, so reset counter
      counter = 0;
      //check if start of text and end of text is correct
      if(data[0] == stx && data[13] == etx) {
        //Turn LED on pin 8 ON
        digitalWrite(8,HIGH);
        Serial.println("RFID Tag correctly received.");
        //Hex ID blocks. Two transmitted Bytes form one Hex ID block.
        //Hex ID blocks:      6   2  |  E   3  |  0   8  |  6   C  |  E   D
        //Transmitted Bytes: 36H 32H | 45H 33H | 30H 38H | 36H 43H | 45H 44H
        hexBlock1 = AsciiCharToNum(data[1])*16 + AsciiCharToNum(data[2]);
        hexBlock2 = AsciiCharToNum(data[3])*16 + AsciiCharToNum(data[4]);
        hexBlock3 = AsciiCharToNum(data[5])*16 + AsciiCharToNum(data[6]);
        hexBlock4 = AsciiCharToNum(data[7])*16 + AsciiCharToNum(data[8]);
        hexBlock5 = AsciiCharToNum(data[9])*16 + AsciiCharToNum(data[10]);
        //Transmitted checksum.
        hexChecksum = AsciiCharToNum(data[11])*16 + AsciiCharToNum(data[12]);
        //XOR algorithm to calculate checksum of ID blocks.
        hexCalculatedChecksum = hexBlock1 ^ hexBlock2 ^ hexBlock3 ^ hexBlock4 ^ hexBlock5;
        if ( hexCalculatedChecksum == hexChecksum )
        {
          Serial.println("Checksum OK!");
          // gets the date and time
          RX8025.getRtcTime(&rtc_sec, &rtc_min, &rtc_hou, &rtc_wee, &rtc_dat, &rtc_mon, &rtc_yea);
          //going to write it all to sd now 
          Serial.println("Will try to write data to RFIDlog.csv on SD now.");
          // open RFIDlog.csv. note that only one file can be open at a time,
          // so you have to close this one before opening another.
          File dataFile = SD.open("RFIDlog.csv", FILE_WRITE);
          // if the file is available, write to it:
          if (dataFile) {
            //Write the RFID Card ID
            dataFile.print("RFID Tag ID:,");
            dataFile.print(data[3], BYTE);
            dataFile.print(data[4], BYTE);
            dataFile.print(data[5], BYTE);
            dataFile.print(data[6], BYTE); 
            dataFile.print(data[7], BYTE);
            dataFile.print(data[8], BYTE);
            dataFile.print(data[9], BYTE);
            dataFile.print(data[10], BYTE);
            dataFile.print(",");
            //Log day
            dataFile.print("Day:,");
            switch(rtc_wee)
            {
            case 0x00:
              {
                dataFile.print("Sunday,");   
                break;
              }
            case 0x01:
              {
                dataFile.print("Monday,");
                break;
              }
            case 0x02:
              {
                dataFile.print("Tuesday,");
                break;
              }
            case 0x03:
              {
                dataFile.print("Wednesday,");
                break;
              }
            case 0x04:
              {
                dataFile.print("Thursday,");
                break;
              }
            case 0x05:
              {
                dataFile.print("Friday,");
                break;
              }
            case 0x06:
              {
                dataFile.print("Saturday,");
                break;
              }
            }
            //Log Date
            dataFile.print("Date:,");
            dataFile.print(rtc_dat,DEC);
            dataFile.print("/");
            dataFile.print(rtc_mon,DEC);
            dataFile.print("/");
            dataFile.print(rtc_yea,DEC);
            dataFile.print(",");
            //Log time
            dataFile.print("Time:,");
            dataFile.print(rtc_hou,DEC);
            dataFile.print(":");
            dataFile.print(rtc_min,DEC);
            dataFile.print(":");
            dataFile.print(rtc_sec,DEC);
            dataFile.print(",");
            //get and log temp
            Logtemp();
            dataFile.print("Temp,");
            dataFile.print(val*0.0625);   
            dataFile.println(",");
            //close the RFIDlog.csv file
            dataFile.close();
            // print to the serial port for monitoring this line can be removed along with 
            // 'void monitorout()' at the end of the script to reduce sketch size, but 
            // only do this if you are sure every thing works and you DO NOT need a diag output
            // when writing the data to the SD card  
            monitorout();
            // flush newsoftserial and delay to prevent mutiple readings of same RFID tag
            delay(2500);
            mySerial.flush();
            //turn led off
            digitalWrite(8,LOW);
          }  
          // if the file RFIDlog.csv isn't open, pop up an error:
          else {
            Serial.println("Error opening file - RFIDlog.csv");
            return;
          } 
        }
        else {
          Serial.println("Checksum didn't match transmitted checksum. Corrupt data!");
          // don't do anything more:
          return;
        }
      }
    }
  }
}

uint8_t AsciiCharToNum(byte data) {
  //First substract 48 to convert the char representation
  //of a number to an actual number.
  data -= '0';
  //If it is greater than 9, we have a Hex character A-F.
  //Substract 7 to get the numeral representation.
  if (data > 9)
    data -= 7;
  return data;
}


void data_file_dump () {
  File dataFile = SD.open("RFIDlog.csv");
  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      Serial.write(dataFile.read());
    }
    dataFile.close();
    Serial.print("Finished dumping, waiting for 2 min");
    delay(120000);    //delay for 2 minutes after dumping RFIDlog.csv
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("Error opening RFIDlog.csv to dump data");
    delay(2000);
  }
}

void monitorout(){
  //Print Tags ID
  Serial.print("RFID Tag ID:"); 
  Serial.print(",");
  Serial.print(data[3], BYTE);
  Serial.print(data[4], BYTE);
  Serial.print(data[5], BYTE);
  Serial.print(data[6], BYTE); 
  Serial.print(data[7], BYTE);
  Serial.print(data[8], BYTE);
  Serial.print(data[9], BYTE);
  Serial.print(data[10], BYTE);
  Serial.print(",");
  //print tags checksum
  Serial.print("Checksum:");
  Serial.print(data[11], BYTE);
  Serial.print(data[12], BYTE);   
  Serial.print(",");
  //print date
  Serial.print("Date:");  
  Serial.print(",");
  Serial.print(rtc_dat,DEC);
  Serial.print("/");
  Serial.print(rtc_mon,DEC);
  Serial.print("/");
  Serial.print(rtc_yea,DEC);
  Serial.print(",");
  //print day
  Serial.print("Day:,");
  switch(rtc_wee)
  {
  case 0x00:
    {
      Serial.print("Sunday,");   
      break;
    }
  case 0x01:
    {
      Serial.print("Monday,");
      break;
    }
  case 0x02:
    {
      Serial.print("Tuesday");
      break;
    }
  case 0x03:
    {
      Serial.print("Wednesday");
      break;
    }
  case 0x04:
    {
      Serial.print("Thursday");
      break;
    }
  case 0x05:
    {
      Serial.print("Friday");
      break;
    }
  case 0x06:
    {
      Serial.print("Saturday,");
      break;
    }
  }
  //print time
  Serial.print("Time:");
  Serial.print(",");
  Serial.print(rtc_hou,DEC);
  Serial.print(":");
  Serial.print(rtc_min,DEC);
  Serial.print(":");
  Serial.print(rtc_sec,DEC);
  Serial.print(",");
  //print temp.
  Serial.print("Temp Deg. C"); 
  Serial.print(",");
  Serial.print(val*0.0625);
  Serial.println(","); 
  //Done now
  Serial.println("Done!");
  Serial.println(" ");
}

void InitiSD(){
  //initializ sd card
  Serial.println("Initializing SD Card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("SD Card failed, or not present.");
    // don't do anything more:
    return;
  }
  Serial.println("SD Card Ready.");
  Serial.println(" ");
}

void erase_dataFile(){
  Serial.println("Removing RFIDlog.csv...");
  SD.remove("RFIDlog.csv");
  Serial.println("RFIDlog.csv Removed");
  delay(20000);
  if (SD.exists("RFIDlog.csv")){ 
    Serial.println("RFIDlog.csv exists.");
    delay(5000);
  }
  else {
    Serial.println("RFIDlog.csv doesn't exist.");
    delay(5000);
  }
}

void Logtemp(){
  res = Wire.requestFrom(72,2); 
  if (res == 2) {
    msb = Wire.receive(); /* Whole degrees */
    lsb = Wire.receive(); /* Fractional degrees */
    val = ((msb) << 4);   /* MSB */
    val |= (lsb >> 4);    /* LSB */
    //dataFile.print("Temp,");
    //dataFile.print(val*0.0625);   
  }
}

I would be interested to know if Australian cattle tags called NLIS tags can be read by this?
I have noticed a difference in manufacturers produce . General RFID that I have seen will not read NLIS

Anybody know?

Hey looks like a good result though . I think I will have a go at following you
Thanks

@tytower -

The reader reads 125Khz, EM4100 standard Tags, not sure about NLIS tags, I suspect if you got hold of an rfid module that could read NLSI tags, the sketch could be adjusted.

EDIT:
More info on NLIS:

The International Standards Organization (ISO) and the Australian/New Zealand standards for the electronic identification of animals are based on LF 134.2 kHz RFID technology. (ISO11784/11785, AS5018/5019) The Texas Instruments LF RFID technology was selected by the ISO as the basis for these standards.

TI-RFID™ 134.2 kHz LF technology has been adopted by the NLIS in Australia after exhaustive field testing of all available technologies. Through these trials the TI-RFID half-duplex (HDX) technology was demonstrated to have superior performance under practical conditions. NLIS tags have now been in use for several years, with great success.

@tytower -

I stumbled across this, it might be of use for you:

RFIDLOG animal tag rfid data logger - http://www.priority1design.com.au/shopfront/index.php?main_page=product_info&cPath=1&products_id=29

Thanks -just saw this
I sent them an email ,will see how it goes

Just wondering whether you have experienced any issues with your rtc on your rfid logger... I had built one similar but with lcd and wireless interface and found my stalker v2 would lock up randomly. I traced it to the rtc and found that the i2c was failing because the 10k pull up resistors on the days lines were too weak. I put another 10k in parallel to make it 5k on the i2c lines and no more lock ups or garbage from the clock. All works perfectly now!

Edit: I thought I should add that I used the id12 rfid module with the same tags and a serial lcd back board on a lcd from toysdownunder.com

Hi Godslust, I'm starting to work on a similar project, but want to use smaller, higher frequency tags that would need another module. Specifically, I'm looking at using nonatec 13.56 khz tags with this rfid module:

Any sense of whether or not this sketch would work for this module? Just starting out, and any help would be much appreciated!

cheers,
James