Arduino Examples
Let's take an in-depth look at most of the examples included in the SparkFun Simultaneous RFID Reader Arduino Library.
UART Switch Position & Software Serial
Make sure the Serial Selection Switch is in the "SER" position when using this library. All of the examples in this Arduino library use the Software Serial Library so if you are not using the SparkFun RedBoard IoT and following the assembly instructions in the Hardware Assembly section, make sure to connect the RX/TX pins on the SER header to compatible pins on your chosen development board. Note, this library
Code to Note
The latest version of the Simultaneous RFID Reader Library has a couple of settings to take note of and adjust accordingly depending on your hardware and setup.
Serial Selection (Software vs Hardware)
If you're using a development board that supports Software Serial, uncomment the following lines and adjust the pins for RX/TX if necessary:
The next option selects which type of serial is used. The code lists a couple of examples for both software serial and hardware so adjust the definition as needed. For example, if you're using a software serial library, define this as softserial
. If you're using a hardware serial port on your development board, select the serial port (eg. Serial1) as shown below:
// #define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
#define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
Baud Rate Selection
Next, you'll want to define the baud rate for rfidBaud
. We recommend using the settings shown below with 38400 when using software serial and 115200 when using hardware serial:
Module Selection
Since this library supports both the M6E Nano and M7E Hecto, you'll need to define which module you are using. Adjust or comment/uncomment the moduleType
definition to set it to the correct module:
Example 1 - Constant Read
The first example sets the M7E to constantly scan and report any tags it sees in the vicinity. Open the example by navigating to File > Examples > SparkFun Simultaneous RFID Reader Library > Example 1 Constant Read. Select your Board and Port and click the "Upload" button. Once the code finishes uploading, open the serial monitor with the baud set to 115200.
Example 1 - Constant Read
/*
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
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while (!Serial); //Wait for the serial port to come online
if (setupRfidModule(rfidBaud) == false)
{
Serial.println(F("Module failed to respond. Please check wiring."));
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.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
Serial.println(F("Press a key to begin scanning for tags."));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
rfidModule.startReading(); //Begin scanning for tags
}
void loop()
{
if (rfidModule.check() == true) //Check to see if any new data has come in from module
{
byte responseType = rfidModule.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 = rfidModule.getTagRSSI(); //Get the RSSI for this tag read
long freq = rfidModule.getTagFreq(); //Get the frequency this tag was detected at
long timeStamp = rfidModule.getTagTimestamp(); //Get the time this was read, (ms) since last keep-alive message
byte tagEPCBytes = rfidModule.getTagEPCBytes(); //Get the number of bytes of EPC from response
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 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 (rfidModule.msg[31 + x] < 0x10) Serial.print(F("0")); //Pretty print
Serial.print(rfidModule.msg[31 + x], HEX);
Serial.print(F(" "));
}
Serial.print(F("]"));
Serial.println();
}
else if (responseType == ERROR_CORRUPT_RESPONSE)
{
Serial.println("Bad CRC");
}
else if (responseType == RESPONSE_IS_HIGHRETURNLOSS)
{
Serial.println("High return loss, check antenna!");
}
else
{
//Unknown response
Serial.println("Unknown error");
}
}
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
The code attempts to set up the module with the defined baud rate and if that fails, it prints "Module failed to respond. Please check wiring" If you see this prompt, double-check your connections to your development board and retry. On successful module startup and setup, the code prints "Press a key to begin scanning for tags." Send any key message and the M7E will begin to scan for any tags in range and print out their EPC as the screenshot below shows:
Example 2 - Read EPC
The second example demonstrates how to perform a single-shot read of one tag in the reader's range and print out the EPC value over serial. This example uses the .readTagEPC()
function to pass it an array of bytes (in almost all cases EPCs are 12 bytes), the size of the array (12), and the amount of time to scan before giving up (500ms is default). This returns RESPONSE_SUCCESS when the M7E detects a tag and stores the EPC in the array given.
Example 2 - Read EPC
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Single shot read - Ask the reader to tell us what tags it currently sees. And it beeps!
If using the Simultaneous RFID Tag Reader (SRTR) shield, make sure the serial slide
switch is in the 'SW-UART' position.
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
#define BUZZER1 9
//#define BUZZER1 0 //For testing quietly
#define BUZZER2 10
void setup()
{
Serial.begin(115200);
pinMode(BUZZER1, OUTPUT);
pinMode(BUZZER2, OUTPUT);
digitalWrite(BUZZER2, LOW); //Pull half the buzzer to ground and drive the other half.
while (!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Press a key to scan for a tag"));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
byte myEPC[12]; //Most EPCs are 12 bytes
byte myEPClength;
byte responseType = 0;
while (responseType != RESPONSE_SUCCESS)//RESPONSE_IS_TAGFOUND)
{
myEPClength = sizeof(myEPC); //Length of EPC is modified each time .readTagEPC is called
responseType = rfidModule.readTagEPC(myEPC, myEPClength, 500); //Scan for a new tag up to 500ms
Serial.println(F("Searching for tag"));
}
//Beep! Piano keys to frequencies: http://www.sengpielaudio.com/KeyboardAndFrequencies.gif
tone(BUZZER1, 2093, 150); //C
delay(150);
tone(BUZZER1, 2349, 150); //D
delay(150);
tone(BUZZER1, 2637, 150); //E
delay(150);
//Print EPC
Serial.print(F(" epc["));
for (byte x = 0 ; x < myEPClength ; x++)
{
if (myEPC[x] < 0x10) Serial.print(F("0"));
Serial.print(myEPC[x], HEX);
Serial.print(F(" "));
}
Serial.println(F("]"));
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
Note, this example also includes definitions and code to set up and use the buzzer found on the Simultaneous RFID Reader - M6E Nano which is not present on the Simultaneous RFID Reader - M7E though users can wire a buzzer like this for an audio feedback when a tag is scanned.
Example 3 - Write EPC
Example 3 shows how to write a character string and store it as a custom EPC value. This is a great way to keep track of which tag is which by setting the EPC to something like WRENCH
or PILL#317
. Note, EPCs can only be written in an even number of bytes like the example sets it to:
Example 3 - Write EPC
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Write a new EPC (Electronic Product Code) to a tag
This is a good way to assign your own, easy to read ID to a tag.
Most tags have 12 bytes available for EPC
EPC is good for things like UPC (this is a gallon of milk)
User data is a good place to write things like the milk's best by date
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
rfidModule.setWritePower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Write TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Get all tags out of the area. Press a key to write EPC to first detected tag."));
if (Serial.available()) Serial.read(); //Clear any chars in the incoming buffer (like a newline char)
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
//"Hello" Does not work. "Hell" will be recorded. You can only write even number of bytes
//char stringEPC[] = "Hello!"; //You can only write even number of bytes
//byte responseType = nano.writeTagEPC(stringEPC, sizeof(stringEPC) - 1); //The -1 shaves off the \0 found at the end of string
char hexEPC[] = {0xFF, 0x2D, 0x03, 0x54}; //You can only write even number of bytes
byte responseType = rfidModule.writeTagEPC(hexEPC, sizeof(hexEPC));
if (responseType == RESPONSE_SUCCESS)
Serial.println("New EPC Written!");
else
Serial.println("Failed write");
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
char stringEPC[] = "Hello!"; //You can only write even number of bytes
byte responseType = nano.writeTagEPC(stringEPC, sizeof(stringEPC) - 1); //The -1 shaves off the \0 found at the end of string
setWritePower()
. This sets the power level when writing to a tag similar to setReadPower
so it can be boosted up to the same values as read power.
nano.setWritePower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Write TX Power is 27.00 dBm and may cause temperature-limit throttling
Examples 4 & 5 - Read/Write User Data
Example 4 shows how to detect and read a tag's available user memory. Not all UHF RFID tags have user memory and may not be configurable.
Example 4 - Read User Data
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Read the user writeable data from a detected tag
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Press a key to read user data"));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
//Read the data from the tag
byte responseType;
byte myData[64];
byte myDataLength = sizeof(myData); //Tell readUserData to read up to 64 bytes
responseType = rfidModule.readUserData(myData, myDataLength); //readUserData will modify myDataLength to the actual # of bytes read
if (responseType == RESPONSE_SUCCESS)
{
//Print User Data
Serial.print(F("Size ["));
Serial.print(myDataLength);
Serial.print(F("] User data["));
for (byte x = 0 ; x < myDataLength ; x++)
{
if (myData[x] < 0x10) Serial.print(F("0"));
Serial.print(myData[x], HEX);
Serial.print(F(" "));
}
Serial.println(F("]"));
}
else
Serial.println(F("Error reading tag data"));
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
Example 5 demonstrates how to edit a tag's user data through the .writeUserData()
function. This function lets you pass an array of characters to the function and records it to the first tag detected by the reader.
Example 5 - Write User Data
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Write new data to the user data area
Some tags have 64, 16 4, or 0 bytes of user data available for writing.
If you write more bytes than is available (10 bytes and only 4 available) module will simply timeout.
EPC is good for things like UPC (this is a gallon of milk)
User data is a good place to write things like the milk's best by date
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.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
rfidModule.setWritePower(900); //9.00 dBm. Higher values may caues USB port to brown out
//Max Write TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println();
Serial.println(F("Get all tags out of the area. Press a key to write DATA to first detected tag."));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
//"Hello" is recorded as "Hell". You can only write even number of bytes
uint8_t testData[] = "ACBD"; //You can only write even number of bytes
byte responseType = rfidModule.writeUserData(testData, sizeof(testData) - 1); //The -1 shaves off the \0 found at the end of string
if (responseType == RESPONSE_SUCCESS)
Serial.println("New Data Written!");
else
{
Serial.println();
Serial.println("Failed write");
Serial.println("Did you write more data than the tag has memory?");
Serial.println("Is the tag locked?");
}
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
char testData[] = "ACBD"; //Must be even number of bytes. "Hello" is recorded as "Hell".
byte responseType = nano.writeUserData(testData, sizeof(testData) - 1); //The -1 shaves off the \0 found at the end of string
A few bytes of editable memory may not sound like a lot be remember these are passive tags - no batteries required! You can query a tag for the user's dietary restrictions. Or you could adjust the lighting depending on who walked in the room. Or you could set the time at which a medication must be taken. Perhaps a prosthetic leg goes into a more aggressive mode when basketball shorts are worn.
Examples 6, 7, 8 - Passwords
The next three examples all deal with passwords to lock a tag with an Access Password or disable a tag with a Kill Password.
Example 6 - Read Passwords displays the Access and Kill passwords for a tag detected by the reader. The Access password allows a user to lock a tag, preventing modification of various parts of the memory (EPC, User, etc). The Kill password is needed to disable a tag. Both passwords are 0x00000000
by default.
Example 6 - Read Passwords
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Don't get too excited, this only reads the passwords if they are unlocked.
There are two passwords associated with any given tag: the Kill PW and the Acess PW
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while (1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Get all tags out of the area. Press a key to read PWs from first detected tag."));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
byte response;
byte myPW[4];
byte pwLength = sizeof(myPW);
//Read Kill password
response = rfidModule.readKillPW(myPW, pwLength);
if (response == RESPONSE_SUCCESS)
{
Serial.println("PW read!");
Serial.print("KillPW: [");
for(byte x = 0 ; x < pwLength ; x++)
{
if(myPW[x] < 0x10) Serial.print("0");
Serial.print(myPW[x], HEX);
Serial.print(" ");
}
Serial.println("]");
}
else
Serial.println("Failed read");
//Read Access PW
pwLength = sizeof(myPW); //Reset this variable. May have been changed above.
response = rfidModule.readAccessPW(myPW, pwLength);
if (response == RESPONSE_SUCCESS)
{
Serial.println("PW read!");
Serial.print("AccessPW: [");
for(byte x = 0 ; x < pwLength ; x++)
{
if(myPW[x] < 0x10) Serial.print("0");
Serial.print(myPW[x], HEX);
Serial.print(" ");
}
Serial.println("]");
}
else
Serial.println("Failed read");
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
Example 7 - Write Passwords shows you how to write new passwords for both Access and Kill.
Example 7 - Write Passwords
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
Obviously, be careful because this premanently and irrevocably destroys a tag.
This shows how to send the right command (with password) to disable a tag.
Arduino pin 2 to Nano TX
Arduino pin 3 to Nano RX
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while(!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while(1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
rfidModule.setWritePower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Write TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Get all tags out of the area. Press a key to write PWs to first detected tag."));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
byte myKillPW[] = {0xEE, 0xFF, 0x11, 0x22};
byte response = rfidModule.writeKillPW(myKillPW, sizeof(myKillPW));
if (response == RESPONSE_SUCCESS)
Serial.println("New Kill PW Written!");
else
Serial.println("Failed write");
byte myAccessPW[] = {0x12, 0x34, 0x56, 0x78};
response = rfidModule.writeAccessPW(myAccessPW, sizeof(myAccessPW));
if (response == RESPONSE_SUCCESS)
Serial.println("New Access PW Written!");
else
Serial.println("Failed write");
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
These values can be adjusted from the passwords set in the example by changing the following lines for myKillPW and myAccessPW:
After running Example 7, re-run Example 6 to see the updated passwords and ensure they are correct. It may seem odd that you can view the passwords. The Gen2 protocol has quite a few methods to lock out various portions of the memory preventing them from being read. Once the Access password is set the ability to read passwords, read user memory, and read portions of the EPC can all be controlled; this is called locking. Currently, locking is not supported in the Arduino library but it is available in the URA and in the Mercury API.
Example 8 - Kill Tag is an interesting example. It's pretty rare that you'll need to kill a tag but we find the concept fascinating and wanted to build in support for it.
Danger!
Note: Killing a tag blows an internal fuse to the IC and makes the tag irreversibly dead.
Example 8 - Kill Tag
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
To kill a tag the tag's kill password must be set. When tags are shipped their passwords
are set to 0x00000000. See the Write_Passwords example to write access and kill passwords.
Obviously, be careful because this premanently and irrevocably destroys a tag.
This shows how to send the right command (with password) to disable a tag.
*/
// Library for controlling the RFID module
#include "SparkFun_UHF_RFID_Reader.h"
// Create instance of the RFID module
RFID rfidModule;
// By default, this example assumes software serial. If your platform does not
// support software serial, you can use hardware serial by commenting out these
// lines and changing the rfidSerial definition below
#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3); //RX, TX
// Here you can specify which serial port the RFID module is connected to. This
// will be different on most platforms, so check what is needed for yours and
// adjust the definition as needed. Some examples are provided below
#define rfidSerial softSerial // Software serial (eg. Arudino Uno or SparkFun RedBoard)
// #define rfidSerial Serial1 // Hardware serial (eg. ESP32 or Teensy)
// Here you can select the baud rate for the module. 38400 is recommended if
// using software serial, and 115200 if using hardware serial.
#define rfidBaud 38400
// #define rfidBaud 115200
// Here you can select which module you are using. This library was originally
// written for the M6E Nano only, and that is the default if the module is not
// specified. Support for the M7E Hecto has since been added, which can be
// selected below
#define moduleType ThingMagic_M6E_NANO
// #define moduleType ThingMagic_M7E_HECTO
void setup()
{
Serial.begin(115200);
while(!Serial);
Serial.println();
Serial.println("Initializing...");
if (setupRfidModule(rfidBaud) == false)
{
Serial.println("Module failed to respond. Please check wiring.");
while(1); //Freeze!
}
rfidModule.setRegion(REGION_NORTHAMERICA); //Set to North America
rfidModule.setReadPower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Read TX Power is 27.00 dBm and may cause temperature-limit throttling
rfidModule.setWritePower(500); //5.00 dBm. Higher values may cause USB port to brown out
//Max Write TX Power is 27.00 dBm and may cause temperature-limit throttling
}
void loop()
{
Serial.println(F("Get all tags out of the area. Press a key to KILL first detected tag."));
while (!Serial.available()); //Wait for user to send a character
Serial.read(); //Throw away the user's character
byte myKillPW[] = {0x1A, 0x2B, 0x3C, 0x4E}; //This must be edited to match your kill password
// byte myKillPW[] = {0xEE, 0xFF, 0x11, 0x22};
byte response = rfidModule.killTag(myKillPW, sizeof(myKillPW));
if (response == RESPONSE_SUCCESS)
Serial.println("Tag has been killed!");
else
{
Serial.println("Kill Failed");
Serial.println("Did you set the kill PW to something other than 0s?");
}
}
//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 setupRfidModule(long baudRate)
{
rfidModule.begin(rfidSerial, moduleType); //Tell the library to communicate over 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
rfidSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
delay(100); //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 (rfidSerial.available())
rfidSerial.read();
rfidModule.getVersion();
if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
{
//This happens if the baud rate is correct but the module is doing a ccontinuous read
rfidModule.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
rfidSerial.begin(115200); //Start serial at 115200
rfidModule.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg
rfidSerial.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250);
}
//Test the connection
rfidModule.getVersion();
if (rfidModule.msg[0] != ALL_GOOD)
return false; //Something is not right
//The module has these settings no matter what
rfidModule.setTagProtocol(); //Set protocol to GEN2
rfidModule.setAntennaPort(); //Set TX/RX antenna ports to 1
return true; //We are ready to rock
}
It is very good to see that the protocol has the kill feature. Killing a tag makes sense after an item has been purchased (gallon of milk) or a process has been completed (dry cleaning has been picked up). By limiting the life-span of a tag you can help protect end user privacy and tracking.
The Gen2 protocol is well written and prevents a user from walking into a Wal-Mart and blasting away all the tags that haven't been configured. The default Kill password is all 0s but any tag will ignore the kill command with the password set to 0s. Therefore, you must first write a non-zero kill password (using Example7) then you must issue the kill command using the new password.
If you're very paranoid about someone else using an UHF RFID reader/writer to reconfigure your tags consider writing new Access and Kill passwords to your tags then use the Universal Reader Assistant to lock the tags.