Pages: [1]   Go Down
Author Topic: Timing an RFID tag between two points  (Read 1569 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,
  I am using the following hardware,

Arduino Mega 2560
ITBD02 moudule
3.2" TFT touchscreen module
ID-12 RFID reader x 2  (The ID-12's are connected to serial 2 & 3)
Momentary switch x 2 (The switches are connected to pins 8 & 9)

Lets say I have an RFID reader and switch at the 'start' and the the same at the 'end'. 

What I would like to be able to do is scan an RFID tag at the start and then activate a switch which logs the time interval the switch was activated against that specific tag. 
At the end the reverse would happen, a switch would be activated and time logged then the system would wait for an RFID tag to be scanned which will then be associated with the time just logged. 
Once an RFID tag has gone through both start and end procedure I would like the time taken to be displayed on the TFT screen in minute/second/milisecond format.

This is the code I have so far, all it does is prove my hardware works, I get time intervals displayed on the screen and RFIDs spat out over serial but im not sure what I need to do next to accomplish my objective.

Any and all feedback and advice much appreciated!  Regards Jason.

Code:
const int startPin = 8;
const int finishPin = 9;

// variables will change:
int buttonState;             // variable for reading the pushbutton status
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

#include <UTFT.h>

// Declare which fonts we will be using
extern uint8_t SmallFont[];

UTFT myGLCD(ITDB32S,38,39,40,41);   // Remember to change the model parameter to suit your display module!

unsigned long time;
unsigned short minutes;
unsigned short seconds;

unsigned long startTime;
unsigned long stopTime;
unsigned long result;

boolean newresult = false;

void setup() {
 
  // initialize the pushbutton pin as an input:
  pinMode(startPin, INPUT); 
  pinMode(finishPin, INPUT);
 
// Setup the LCD
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);

 
  Serial.begin(9600);    // connect to the serial port for output to serial monitor
  Serial2.begin(9600);   // serial port of RFID reader at start
  Serial3.begin(9600);   // serial port of RFID reader at finish
}

void loop () {
 
  // Clear the screen and draw the frame
 
  time = millis();
  seconds = time / 1000;
  minutes = seconds / 60;
  //result = start - millis();
 
 /* myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect(0, 0, 319, 13);
  myGLCD.setColor(64, 64, 64);
  myGLCD.fillRect(0, 226, 319, 239);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setBackColor(255, 0, 0);
  */
 
 
   // read the state of the switch into a local variable:
  int startState = digitalRead(startPin);
  int finishState = digitalRead(finishPin);
  int reading = 0;

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
  lastDebounceTime = millis();
  }
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
  if (startState == HIGH){
    startTime = time;
  }
 
  if (finishState == HIGH){
    result = time - startTime;
    newresult=true;
  }
 
 if (newresult==true){
  myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect(0, 0, 319, 13);
  myGLCD.setColor(64, 64, 64);
  myGLCD.fillRect(0, 226, 319, 239);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setBackColor(255, 0, 0);
 
   // set the LED using the state of the button:
   myGLCD.printNumI(result, CENTER, 1); 
 }
  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
 
  byte i = 0;
  byte val = 0;
  byte code[6];
  byte checksum = 0;
  byte bytesread = 0;
  byte tempbyte = 0;

  if(Serial2.available() > 0) {
    if((val = Serial2.read()) == 2) {                  // check for header
      bytesread = 0;
      while (bytesread < 12) {                        // read 10 digit code + 2 digit checksum
        if( Serial2.available() > 0) {
          val = Serial2.read();
          if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
            break;                                    // stop reading
          }

          // Do Ascii/Hex conversion:
          if ((val >= '0') && (val <= '9')) {
            val = val - '0';
          } else if ((val >= 'A') && (val <= 'F')) {
            val = 10 + val - 'A';
          }

          // Every two hex-digits, add byte to code:
          if (bytesread & 1 == 1) {
            // make some space for this hex-digit by
            // shifting the previous hex-digit with 4 bits to the left:
            code[bytesread >> 1] = (val | (tempbyte << 4));

            if (bytesread >> 1 != 5) {                // If we're at the checksum byte,
              checksum ^= code[bytesread >> 1];       // Calculate the checksum... (XOR)
            };
          } else {
            tempbyte = val;                           // Store the first hex digit first...
          };

          bytesread++;                                // ready to read next digit
        }
      }

      // Output to Serial:

      if (bytesread == 12) {                          // if 12 digit read is complete
       // Serial.print("5-byte code: ");
        String thisString;
        if (code[0] < 16){
          thisString = String(0);
          thisString += String(code[0], HEX);
        }
        else {
        thisString = String(code[0], HEX);
        }
        for (i=1; i<5; i++) {
        if (code[i] < 16) thisString += 0;
       thisString += String(code[i], HEX);
       //   Serial.print(code[i]);
         // Serial.print(" ");
        }
        Serial.print(thisString);
        Serial.println();

      //  Serial.print("Checksum: ");
       // Serial.print(code[5], HEX);
       // Serial.println(code[5] == checksum ? " -- passed." : " -- error.");
       // Serial.println();
      }

      bytesread = 0;
    }
  }

if(Serial3.available() > 0) {
    if((val = Serial3.read()) == 2) {                  // check for header
      bytesread = 0;
      while (bytesread < 12) {                        // read 10 digit code + 2 digit checksum
        if( Serial3.available() > 0) {
          val = Serial3.read();
          if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
            break;                                    // stop reading
          }

          // Do Ascii/Hex conversion:
          if ((val >= '0') && (val <= '9')) {
            val = val - '0';
          } else if ((val >= 'A') && (val <= 'F')) {
            val = 10 + val - 'A';
          }

          // Every two hex-digits, add byte to code:
          if (bytesread & 1 == 1) {
            // make some space for this hex-digit by
            // shifting the previous hex-digit with 4 bits to the left:
            code[bytesread >> 1] = (val | (tempbyte << 4));

            if (bytesread >> 1 != 5) {                // If we're at the checksum byte,
              checksum ^= code[bytesread >> 1];       // Calculate the checksum... (XOR)
            };
          } else {
            tempbyte = val;                           // Store the first hex digit first...
          };

          bytesread++;                                // ready to read next digit
        }
      }

      // Output to Serial:

      if (bytesread == 12) {                          // if 12 digit read is complete
       
        String thisString;
        if (code[0] < 16){
          thisString = String(0);
          thisString += String(code[0], HEX);
        }
        else {
        thisString = String(code[0], HEX);
        }
        for (i=1; i<5; i++) {
        if (code[i] < 16) thisString += 0;
       thisString += String(code[i], HEX);
     
        }
        Serial.print(thisString);
        Serial.println();

     
      }

      bytesread = 0;
    }
  }
newresult=false;
}


Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 169
Posts: 12446
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First thing to do is to make two functions

void readRFID(pin) ;
bool RFIDavailable(pin) ;

that takes care of reading the RFID. This code is now twice in your program and that can be simpler.

Q: How many RFID's can be in progress simultaneously?

Q: do they come in the same order? always? sure? smiley-wink

I would define an array of structs,
and fill the array when it passes the start RFID reader
and at the end search the rfid in the array, display it, and remove from array.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for your help  smiley

Quote
Q: How many RFID's can be in progress simultaneously?
Several, a maximum of 10 in progress at any one time.

Quote
Q: do they come in the same order? always? sure?
No, they can end in a different order that they start, some may not ever reach the end.

I realised that I would need to use an array (or several, indexed?) but unsure about how to go about that as I am completely new to this.
What kind of array would I need to be able to cope with the unique HEX code of each tag?

Thanks again!
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 169
Posts: 12446
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
No, they can end in a different order that they start, some may not ever reach the end.

That means that your array will need to be infinite or you should check that a specific is overdue and remove it from the array.

This is the code outline how I would start to tackle this one: it compiles but it is just the overall structure with several functions to be filled in and others to be written
Code:
#define STARTPIN 3
#define ENDPIN 5

struct
{
  char rfid[16];
  uint32_t start;  // start time for determining duration.
}
progress[25];

int idx = 0;

void setup()
{
  // setup thingies here
}

void loop()
{
  if (RFIDavailable(STARTPIN))
  {
    doStart();
  }

  if (RFIDavailable(ENDPIN))
  {
    doEnd();
  }

  if (RFIDoverdue())
  {
    doOverdue();
  }   
}

bool RFIDavailable(int pin)
{
  if (pin == STARTPIN) return Serial2.available() >=12; // assuming 12 chars in RFID
  if (pin == ENDPIN) return Serial3.available() >=12;
  return false;
}

bool RFIDoverdue()
{
  return false; // dummy
}

void doStart()
{
  // read RFID and add to array
  for (int i=0; i< 12; i++) progress[idx].rfid[i] = Serial2.read();
  progress[idx].rfid[13] = 0; // null terminated string
  progress[idx].start = millis();
  idx++; 
}

void doEnd()
{
  // read RFID,
  // they might be removed due to overdue
  char rfid[16];
  for (int i=0; i< 12; i++) rfid[i] = Serial3.read();
  rfid[13] = 0;
  // search in array
  // if not found ==> error
  // calculate duration   
  // display rfid tag + duration
  // remove rfid from array
  // idx--;
}

void doOverdue()
{
  // handle overdue items in array + remove them
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks again for your help and advice.  I will have a play and post back my results or more likely when im stuck again!

Quote
No, they can end in a different order that they start, some may not ever reach the end.

That means that your array will need to be infinite or you should check that a specific is overdue and remove it from the array.
Do you mean like a timeout if the tag has been in progress too long?  10 minutes would be long enough for my application.
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 169
Posts: 12446
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yep that's what I meant.
after 10 minutes you must remove the item from the the array, but there is a chance that the item will pop up suddenly smiley


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is where I am up to so far.

I have copy and pasted bits of what I already had into the template you provided me.

Now i can scan a tag on the start RFID and then push the start button to get the tag ID shown on the serial monitor.  There is some behaviour I need to change, it will queue tag reads and then display them all when the start button is pushed, it needs to work with only one tag at a time so it disregards every other read after the first one until the start button has been activated.

With regards to the overdue tags, would I need to specify a time period in milis of more than 600,000 to have them removed from the array after 10 minutes?

The current code is below, I hope I am on the right track!

Code:
#define STARTPIN 8
#define ENDPIN 9
#include <UTFT.h>


extern uint8_t SmallFont[];   // Declare which fonts we will be using

UTFT myGLCD(ITDB32S,38,39,40,41);   // Remember to change the model parameter to suit your display module!

struct
{
  char rfid[16];
  uint32_t start;  // start time for determining duration.
}
progress[25];

int idx = 0;

void setup()
{
 // initialize the pushbutton pin as an input:
  pinMode(STARTPIN, INPUT); 
  pinMode(ENDPIN, INPUT);
 
// Setup the LCD
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);

 
  Serial.begin(9600);    // connect to the serial port for output to serial monitor
  Serial2.begin(9600);   // serial port of RFID reader at start
  Serial3.begin(9600);   // serial port of RFID reader at finish
}

void loop()
{
  if (RFIDavailable(STARTPIN))
  {
    doStart();
  }

  if (RFIDavailable(ENDPIN))
  {
    doEnd();
  }

  if (RFIDoverdue())
  {
    doOverdue();
  }   
}

bool RFIDavailable(int pin)


  int finishState = digitalRead(ENDPIN);
  if (pin == STARTPIN) {
     int startState = digitalRead(STARTPIN);
     if (startState == HIGH) return Serial2.available() > 0; // assuming 12 chars in RFID
  }
 
  if (pin == ENDPIN) return Serial3.available() > 0;
  return false;
}

bool RFIDoverdue()
{
  return false; // dummy
}

void doStart()
{
  // read RFID and add to array
  //for (int i=0; i< 12; i++) progress[idx].rfid[i] = Serial2.read();
  //progress[idx].rfid[13] = 0; // null terminated string
  //progress[idx].start = millis();
  //idx++;
  byte i = 0;
  byte val = 0;
  byte code[6];
  byte checksum = 0;
  byte bytesread = 0;
  byte tempbyte = 0;
 
    if((val = Serial2.read()) == 2) {                  // check for header
      bytesread = 0;
      while (bytesread < 12) {                        // read 10 digit code + 2 digit checksum
        if( Serial2.available() > 0) {
          val = Serial2.read();
          if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
            break;                                    // stop reading
          }

          // Do Ascii/Hex conversion:
          if ((val >= '0') && (val <= '9')) {
            val = val - '0';
          } else if ((val >= 'A') && (val <= 'F')) {
            val = 10 + val - 'A';
          }

          // Every two hex-digits, add byte to code:
          if (bytesread & 1 == 1) {
            // make some space for this hex-digit by
            // shifting the previous hex-digit with 4 bits to the left:
            code[bytesread >> 1] = (val | (tempbyte << 4));

            if (bytesread >> 1 != 5) {                // If we're at the checksum byte,
              checksum ^= code[bytesread >> 1];       // Calculate the checksum... (XOR)
            };
          } else {
            tempbyte = val;                           // Store the first hex digit first...
          };

          bytesread++;                                // ready to read next digit
        }
      }

      // Output to Serial:
      if (bytesread == 12) {                          // if 12 digit read is complete
       // Serial.print("5-byte code: ");
        String thisString;
        if (code[0] < 16){
          thisString = String(0);
          thisString += String(code[0], HEX);
        }
        else {
        thisString = String(code[0], HEX);
        }
        for (i=1; i<5; i++) {
        if (code[i] < 16) thisString += 0;
       thisString += String(code[i], HEX);

        }
        Serial.print(thisString);
        Serial.println();
      }

      bytesread = 0;
    }
 
}

void doEnd()
{
  // read RFID,
  // they might be removed due to overdue
  char rfid[16];
  for (int i=0; i< 12; i++) rfid[i] = Serial3.read();
  rfid[13] = 0;
  // search in array
  // if not found ==> error
  // calculate duration   
  // display rfid tag + duration
  // remove rfid from array
  // idx--;
}

void doOverdue()
{
  // handle overdue items in array + remove them
}
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 169
Posts: 12446
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I don't know how long an RFID string is but you must wait that they are all available!

Serial2.available() > 0; // assuming 12 chars in RFID

should be

Serial2.available() >= 12; // assuming 12 chars in RFID

otherwise you might do a Serial.Read() from an empty queue resulting in erroronous values.

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have had a go at putting my program logic into flow charts, one for the start and on for the finish.  Feedback and criticism appreciated!



Logged

Pages: [1]   Go Up
Jump to: