Hi! I recently purchased the Simultaneous RFID reader and external antenna, connected to my Arduino Uno. I wrote a program to time a race and use the tag’s EPC as the identifier for the person (before the race, I would write the person’s name to the tag). It all works great, except for one problem: the entire time the tag is in the read range of the antenna, the Serial monitor is printing the data. I only want the tag to be printed once on the serial monitor, and I’m not exactly sure how to do that. Any help is much appreciated!
My code:
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3);
#include "SparkFun_UHF_RFID_Reader.h"
RFID nano;
#define buzzer 9
#define buzzergnd 10
//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;
//switches and such
const int buttonPin = 6;
int buttonPushCounter = 1;
int buttonState = 0;
int lastButtonState = 0;
void setup() {
//RFID
pinMode(buzzer, OUTPUT);
pinMode(buzzergnd, OUTPUT);
digitalWrite(buzzergnd, LOW);
Serial.begin(115200);
while(!Serial);
if(setupNano(38400) == false){
Serial.println("Module failed to respond");
while (1);
}
nano.setRegion(REGION_NORTHAMERICA);
nano.setReadPower(2700);
Serial.println("Ready");
Serial.println("Press a key to start RFID Reader");
while(!Serial.available());
Serial.read();
nano.startReading();
Serial.println("RFID Reader active. Ready to begin race");
//timing
pinMode(buttonPin, INPUT);
}
void startRace(){
Serial.print("Race ");
Serial.print(heat);
Serial.println(" started");
heat++;
flash();
}
//where the magic happens
void runTimer(){
currentMillis = millis();
seconds = currentMillis - prevMillis;
float personTime = seconds/1000;
if(seconds < 100){
startRace();
}
//data - THIS IS WHERE IT ALL GOES DOWN
if(nano.check() == true){
byte responseType = nano.parseResponse();
if(responseType == RESPONSE_IS_TAGFOUND){
Serial.print(place);
Serial.print(" ");
byte tagEPCBytes = nano.getTagEPCBytes();
for(byte x = 0 ; x< tagEPCBytes ; x++){
if(nano.msg[31 + x] < 0x10) Serial.print("0");
Serial.print(char(nano.msg[31 + x]));
Serial.print((""));
}
unsigned minutes = (personTime + .0005) /60;
personTime -= minutes * 60;
Serial.print(" ");
Serial.print(minutes);
Serial.print(':');
if ((personTime + 0.0005) < 10)
Serial.print('0');
Serial.println(personTime, 2);
place++;
// flash();
// delay(10);
}
}
}
void flash(){
tone(buzzer, 2349);
delay(150);
noTone(buzzer);
}
void stopTimer(){
seconds = 0;
place = 1;
minutes = 0;
prevMillis = millis();
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH){
runTimer();
}
else{
stopTimer();
}
}
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
}
Have not tried that is works, but added a DeDub function
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3);
#include "SparkFun_UHF_RFID_Reader.h"
RFID nano;
#define buzzer 9
#define buzzergnd 10
//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;
//switches and such
const int buttonPin = 6;
int buttonPushCounter = 1;
int buttonState = 0;
int lastButtonState = 0;
// create structure to filter
struct DubFilter {
char EPC[12];
//unsigned long LastTime; // optionally you could add data to capture
};
// maximum number of unique EPC
#define MaxEPC 10
struct DubFilter dub[MaxEPC];
void setup() {
//RFID
pinMode(buzzer, OUTPUT);
pinMode(buzzergnd, OUTPUT);
digitalWrite(buzzergnd, LOW);
Serial.begin(115200);
while(!Serial);
if(setupNano(38400) == false){
Serial.println("Module failed to respond");
while (1);
}
nano.setRegion(REGION_NORTHAMERICA);
nano.setReadPower(2700);
// init de-dub
for (uint8_t i=0 ; i < MaxEPC ; i++)
dub[i].EPC[0] = 0;
Serial.println("Ready");
Serial.println("Press a key to start RFID Reader");
while(!Serial.available());
Serial.read();
nano.startReading();
Serial.println("RFID Reader active. Ready to begin race");
//timing
pinMode(buttonPin, INPUT);
}
void startRace(){
Serial.print("Race ");
Serial.print(heat);
Serial.println(" started");
heat++;
flash();
}
//where the magic happens
void runTimer(){
currentMillis = millis();
seconds = currentMillis - prevMillis;
float personTime = seconds/1000;
if(seconds < 100){
startRace();
}
//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("0");
Serial.print(char(nano.msg[31 + x]));
Serial.print((""));
}
unsigned minutes = (personTime + .0005) /60;
personTime -= minutes * 60;
Serial.print(" ");
Serial.print(minutes);
Serial.print(':');
if ((personTime + 0.0005) < 10)
Serial.print('0');
Serial.println(personTime, 2);
place++;
// flash();
// delay(10);
}
}
}
/**
* 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;
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
if(dub[i].EPC[x] = nano.msg[31 + x]) continue;
}
}
return(false);
}
void flash(){
tone(buzzer, 2349);
delay(150);
noTone(buzzer);
}
void stopTimer(){
seconds = 0;
place = 1;
minutes = 0;
prevMillis = millis();
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH){
runTimer();
}
else{
stopTimer();
}
}
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
}
Thanks for the help! It almost works. The first tag it only prints once, but the second tag it sees it will print ten times and then say “table is full”.
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3);
#include "SparkFun_UHF_RFID_Reader.h"
RFID nano;
#define buzzer 9
#define buzzergnd 10
//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;
//switches and such
const int buttonPin = 6;
int buttonPushCounter = 1;
int buttonState = 0;
int lastButtonState = 0;
// 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 10
struct DubFilter dub[MaxEPC];
void setup() {
//RFID
pinMode(buzzer, OUTPUT);
pinMode(buzzergnd, OUTPUT);
digitalWrite(buzzergnd, LOW);
Serial.begin(115200);
while(! Serial);
if(setupNano(38400) == false){
Serial.println("Module failed to respond");
while (1);
}
nano.setRegion(REGION_NORTHAMERICA);
nano.setReadPower(2700);
// init de-dub
for (uint8_t i=0 ; i < MaxEPC ; i++)
dub[i].EPC[0] = 0;
Serial.println("Ready");
Serial.println("Press a key to start RFID Reader");
while(!Serial.available());
Serial.read();
nano.startReading();
Serial.println("RFID Reader active. Ready to begin race");
//timing
pinMode(buttonPin, INPUT);
}
void startRace(){
Serial.print("Race ");
Serial.print(heat);
Serial.println(" started");
heat++;
flash();
}
//where the magic happens
void runTimer(){
currentMillis = millis();
seconds = currentMillis - prevMillis;
float personTime = seconds/1000;
if(seconds < 100){
startRace();
}
//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("0");
Serial.print(nano.msg[31 + x], HEX);
Serial.print((""));
}
unsigned minutes = (personTime + .0005) /60;
personTime -= minutes * 60;
Serial.print(" ");
Serial.print(minutes);
Serial.print(':');
if ((personTime + 0.0005) < 10)
Serial.print('0');
Serial.println(personTime, 2);
place++;
// flash();
// delay(10);
}
}
}
/**
* 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(){
tone(buzzer, 2349);
delay(150);
noTone(buzzer);
}
void stopTimer(){
seconds = 0;
place = 1;
minutes = 0;
prevMillis = millis();
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH){
runTimer();
}
else{
stopTimer();
}
}
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
}