Hi, I would like to build a RFID Tracker to track a race and lap of runners. I would like some help in the following code that i had modified to my use case. It could already track the RFID Tag and provide the timing, but I just couldn’t get the lap to increase to track their 2nd, 3rd and on going laps.
I am using the Arduino Uno and the Simultaneous RFID Reader M6E as shield.
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Constantly reads and outputs any tags heard
If using the Simultaneous RFID Tag Reader (SRTR) shield, make sure the serial slide
switch is in the 'SW-UART' position
*/
//Used for transmitting to the device
//If you run into compilation errors regarding this include, see the README
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
#include "SparkFun_UHF_RFID_Reader.h" //Library for controlling the M6E Nano module
RFID nano; //Create instance
bool scanning = true;
//place variables - data placement
int place = 1;
float seconds;
float personTime;
unsigned long currentMillis = 0;
unsigned long prevMillis = millis;
unsigned long minutes = 0;
int heat = 1;
#define piezo 10
int note = 2000;
#define buzzgnd 9
int gunCounter = 1;
int lapno = 1;
// create structure to filter
struct DubFilter {
uint8_t EPC[12];
//unsigned long LastTime; // optionally you could add data to capture
};
// maximum number of unique EPC
#define MaxEPC 30
struct DubFilter dub[MaxEPC];
void setup() {
Serial.begin(115200);
while (!Serial)
; //Wait for the serial port to come online
if (setupNano(38400) == false) //Configure nano to run at 38400bps
{
Serial.println(F("Module failed to respond. Please check wiring."));
while (1)
; //Freeze!
}
nano.setRegion(REGION_NORTHAMERICA); //Set to North America
nano.setReadPower(500); //5.00 dBm. Higher values may caues USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
// init de-dub
for (uint8_t i = 0; i < MaxEPC; i++)
dub[i].EPC[0] = 0;
Serial.println(F("Press '1' to begin and '2' to Stop."));
}
void startRace() {
lapno = 1;
Serial.print("Race ");
Serial.print(heat);
Serial.println(" started");
heat++;
lap();
}
void lap() {
Serial.print("Lap ");
Serial.println(lapno);
place = 1;
for (uint8_t i = 0; i < MaxEPC; i++)
dub[i].EPC[0] = 0;
lapno++;
}
//where the magic happens
void runTimer() {
currentMillis = millis();
seconds = currentMillis - prevMillis;
float personTime = seconds / 1000;
unsigned minutes = (personTime + .0005) / 60;
personTime -= minutes * 60;
//data - THIS IS WHERE IT ALL GOES DOWN
if (nano.check() == true) {
byte responseType = nano.parseResponse();
if (responseType == RESPONSE_IS_TAGFOUND) {
// it is already in the list
if (DeDub()) return;
Serial.print(place);
Serial.print(" ");
byte tagEPCBytes = nano.getTagEPCBytes();
for (byte x = 0 ; x < tagEPCBytes ; x++)
{
if (nano.msg[31 + x] < 0x10) Serial.print(F("0")); //Pretty print
Serial.print(nano.msg[31 + x], HEX);
Serial.print(F(" "));
}
Serial.print(" ");
Serial.print(minutes);
Serial.print(':');
if ((personTime + 0.0005) < 10)
Serial.print('0');
Serial.println(personTime, 2);
place++;
}
}
}
/**
* This routine will check against the table
* If EPC is already in the table true will be returned.
* if NOT EPC will be added to the list and false is turned
*/
bool DeDub() {
uint8_t i, x;
bool MissMatch = false;
// get the num EPC bytes
uint8_t tagEPCBytes = 12;
// check each entry in the table
for (i = 0; i < MaxEPC; i++) {
// if empty entry
if (dub[i].EPC[0] == 0) break;
MissMatch = false;
for (x = 0; x < tagEPCBytes; x++) {
// check for miss match
if (nano.msg[31 + x] != dub[i].EPC[x]) {
MissMatch = true;
break;
}
}
// A this point we check for MisMatch (false means we have a Match)
if (!MissMatch) return true;
}
// EPC was not in the list already
if (i == MaxEPC) {
Serial.println("Table is full\nCan NOT add more");
} else {
// add to the list
for (x = 0; x < tagEPCBytes; x++) {
// Add to the list
dub[i].EPC[x] = nano.msg[31 + x];
}
}
return (false);
}
void flash() {
}
void stopTimer() {
seconds = 0;
place = 1;
minutes = 0;
prevMillis = millis();
}
void loop() {
if (Serial.available() > 0) {
char code = Serial.read();
if (code == 'S' || 's') {
gunCounter == 2;
}
else if (Serial.available() > 0) {
char code = Serial.read();
if (code == 'E' || 'e') {
gunCounter == 1;
}
}
if (gunCounter % 2 != 0) {
startRace();
gunCounter++;
tone(piezo, note, 1000);
delay(150);
}
else if (gunCounter % 2 == 0) {
gunCounter++;
Serial.print("Race ");
Serial.print(heat - 1);
Serial.println(" Ended");
tone(piezo, note, 1000);
delay(150);
}
}
if (gunCounter % 2 == 0) {
runTimer();
}
if (gunCounter % 2 != 0) {
stopTimer();
for (uint8_t i = 0; i < MaxEPC; i++)
dub[i].EPC[0] = 0;
}
if (Serial.available() > 0) {
char code = Serial.read();
if (code == '1') {
nano.startReading();
Serial.println("RFID ON");
gunCounter == 2;
}
if (code == '2') {
nano.stopReading();
Serial.println("RFID OFF");
gunCounter == 3;
}
}
//end loop
}
// ============================================================== Below Code are Previous =======================================
// #define MAX_TAGS 10
// byte myEPC[12]; // Add this line
// // Array to store unique tags
// byte epcArray[MAX_TAGS][12];
// int tagCount = 0;
// void loop() {
// if (scanning) {
// bool isDuplicate = false;
// if (nano.check() == true) //Check to see if any new data has come in from module
// {
// byte responseType = nano.parseResponse(); //Break response into tag ID, RSSI, frequency, and timestamp
// if (responseType == RESPONSE_IS_KEEPALIVE) {
// Serial.println(F("Scanning"));
// } else if (responseType == RESPONSE_IS_TAGFOUND) {
// //If we have a full record we can pull out the fun bits
// int rssi = nano.getTagRSSI(); //Get the RSSI for this tag read
// long freq = nano.getTagFreq(); //Get the frequency this tag was detected at
// long timeStamp = nano.getTagTimestamp(); //Get the time this was read, (ms) since last keep-alive message
// byte tagEPCBytes = nano.getTagEPCBytes(); //Get the number of bytes of EPC from response
// // Read tag into myEPC
// byte myEPClength = sizeof(tagEPCBytes);
// nano.readTagEPC(tagEPCBytes, myEPClength); // Use myEPC here
// // Check for duplicate
// for (int i = 0; i < tagCount; i++) {
// if (memcmp(epcArray[i], tagEPCBytes, 12) == 0) {
// isDuplicate = true;
// Serial.print("Dulplicate Found ");
// // break;
// }
// }
// // Add unique tag to array
// if (!isDuplicate) {
// memcpy(epcArray[tagCount], tagEPCBytes, 12);
// tagCount++;
// }
// /*
// Serial.print(F(" rssi["));
// Serial.print(rssi);
// Serial.print(F("]"));
// Serial.print(F(" freq["));
// Serial.print(freq);
// Serial.print(F("]"));
// Serial.print(F(" time["));
// Serial.print(timeStamp);
// Serial.print(F("]"));
// */
// // Print tags from array
// for (int i = 0; i < tagCount; i++) {
// Serial.print("EPC: ");
// for (byte x = 0; x < tagEPCBytes; x++) {
// if (nano.msg[31 + x] < 0x10) Serial.print(F("0")); //Pretty print
// Serial.print(nano.msg[31 + x], HEX);
// Serial.print(F(" "));
// }
// Serial.print(F("]"));
// Serial.println();
// for (int j = 0; j < 12; j++) {
// Serial.print(epcArray[i][j]);
// Serial.print(" ");
// }
// Serial.println();
// }
// /*
// //Print EPC bytes, this is a subsection of bytes from the response/msg array
// Serial.print(F(" epc["));
// for (byte x = 0 ; x < tagEPCBytes ; x++)
// {
// if (nano.msg[31 + x] < 0x10) Serial.print(F("0")); //Pretty print
// Serial.print(nano.msg[31 + x], HEX);
// Serial.print(F(" "));
// }
// Serial.print(F("]"));
// Serial.println();
// */
// } else if (responseType == ERROR_CORRUPT_RESPONSE) {
// Serial.println("Bad CRC");
// } else {
// //Unknown response
// Serial.print("Unknown error");
// }
// }
// }
// if (Serial.available()) {
// char key = Serial.read();
// if (key == 'S' || key == 's') {
// scanning = false;
// Serial.println("Stopped scanning");
// nano.stopReading();
// }
// }
// if (Serial.available()) {
// char key = Serial.read();
// if (key == 'R' || key == 'r') {
// scanning = true;
// Serial.println("Start scanning");
// nano.startReading();
// }
// }
// }
//Gracefully handles a reader that is already configured and already reading continuously
//Because Stream does not have a .begin() we have to do this outside the library
boolean setupNano(long baudRate) {
nano.begin(softSerial); //Tell the library to communicate over software serial port
//Test to see if we are already connected to a module
//This would be the case if the Arduino has been reprogrammed and the module has stayed powered
softSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
while (softSerial.isListening() == false)
; //Wait for port to open
//About 200ms from power on the module will send its firmware version at 115200. We need to ignore this.
while (softSerial.available()) softSerial.read();
nano.getVersion();
if (nano.msg[0] == ERROR_WRONG_OPCODE_RESPONSE) {
//This happens if the baud rate is correct but the module is doing a ccontinuous read
nano.stopReading();
Serial.println(F("Module continuously reading. Asking it to stop..."));
delay(1500);
} else {
//The module did not respond so assume it's just been powered on and communicating at 115200bps
softSerial.begin(115200); //Start software serial at 115200
nano.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
softSerial.begin(baudRate); //Start the software serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
nano.getVersion();
if (nano.msg[0] != ALL_GOOD) return (false); //Something is not right
//The M6E has these settings no matter what
nano.setTagProtocol(); //Set protocol to GEN2
nano.setAntennaPort(); //Set TX/RX antenna ports to 1
return (true); //We are ready to rock
}
Thank you