I am using a Simultaneous RFID reader with a SparkX UHF RFID ring antenna, and an ESP32. I have a heat sink on the reader and it doesn’t feel too hot to me. My goal is to have an object light up in a different color depending on who is handling it, with each individual wearing a passive tag ID card. It “works” with the attached wiring. The problem is my range is very inconsistent—sometimes it is 2ft (good enough for my application), sometimes it is only a couple inches (not good enough). Sometimes the serial monitor kicks out a lot of “Bad CRC” responses—more at the highest read power. Does anyone have advice for getting a more consistent range (or for simply increasing it)? I am using a Anker battery, 5V 2A 5000mAh to power all three: reader, ESP32, and neopixels. Thank you for your time.
/*
Reading multiple RFID tags, simultaneously!
By: Nathan Seidle @ SparkFun Electronics
Date: October 3rd, 2016
https://github.com/sparkfun/Simultaneous_RFID_Tag_Reader
KCCR May18 2022:changed Serial5 to Serial2 and used with ESP32
I used this example with an ESP32 (in my case the DOIT DEVKIT V1) and the hardware serial pins.
I used Serial2, which corresponds to RX2 and TX2 on pins 16 and 17 respectively.
The serial slide switch must be in the 'HW-UART' position
Connections:
Nano ESP32
GND GND
VCC VUSB
RXI 17 (make sure to have voltage divider /resistors in place to bump 5V logic on nano down to 3.3V for ESP32)
TXO 16
*/
#include "SparkFun_UHF_RFID_Reader.h" //Library for controlling the M6E Nano module
#include <Adafruit_NeoPixel.h>
#define pixelPin 32
#define LED_COUNT 30
#define BRIGHTNESS 50
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LED_COUNT, pixelPin, NEO_GRB + NEO_KHZ800);
//neopixel CONSTANTS
//RBG for different colors
const byte numColors = 5; //4 colors/chacter types, 1 neutral/white
int colors[numColors][3] = {
{209, 0, 0}, //red
{ 0, 255, 0}, //green
{ 78, 244, 255}, //blue
{255, 255, 0}, //yellow
{ 10, 0, 10}, //purple-white
};
String colorNames[5] = {"Red", "Green", "Blue", "Yellow", "Purple"};
// What is the "correct" UID that should be detected by the reader
//You'll need to figure these out first run on the serial monitor
uint8_t correctUid[][12] = {
{0xE2, 0x0, 0x0, 0x1D, 0x1, 0xA, 0x1, 0x40, 0x25, 0x10, 0x6E, 0xAA}, // Red
{0xE2, 0x0, 0x0, 0x1D, 0x1, 0xA, 0x1, 0x69, 0x24, 0x70, 0x90, 0x50}, // Green
{0xE2, 0x0, 0x0, 0x1D, 0x1, 0xA, 0x2, 0x34, 0x25, 0x40, 0xD2, 0xB9}, // Blue
{0xE2, 0x0, 0x0, 0x1D, 0x1, 0xA, 0x0, 0x66, 0x26, 0x10, 0x24, 0x69}, // Yellow
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, // Purple
};
RFID nano; //Create instance
void setup()
{
//setup neopixels
pixels.begin(); // This initializes the NeoPixel library.
pixels.show();
pixels.setBrightness(BRIGHTNESS);
//setup nano
Serial.begin(115200);
while (!Serial); //Wait for the serial port to come online
// Print out the file and the date at which it was last compiled
Serial.println(__FILE__ __DATE__);
//Because we are using a hardware serial port in this example we can
//push the serial speed much faster to 115200bps
if (setupNano(115200) == false) //Configure nano to run at 115200bps
{
Serial.println(F("Module failed to respond. Please check wiring."));
while (1); //Freeze!
}
nano.setRegion(REGION_NORTHAMERICA); //Set to North America
nano.setReadPower(2700); //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
//Eventually replace key-press start with MSQTT start from node red
//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
nano.startReading(); //Begin scanning for tags
}
void loop()
{
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.
//RSSI is signal strength -100(weak) to 0(strong). Can be used as a proxy for distance
//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
uint8_t tagEPC[tagEPCBytes];
for (byte x=0 ; x<tagEPCBytes ; x++)
{
tagEPC[x] = nano.msg[31+x];
}
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 (nano.msg[31 + x] < 0x10) Serial.print(F("0")); //Pretty print
Serial.print(nano.msg[31 + x], HEX);
Serial.print(F(" "));
}
Serial.print(F("]"));
//check if tag matches one in our predefined set
for (int k=0; k<numColors; k++) {
if(memcmp(tagEPC, correctUid[k], 12) == 0) {
Serial.print(colorNames[k]);
pixels.fill(pixels.Color(colors[k][0], colors[k][1], colors[k][2]));
pixels.show();
}
}
Serial.println();
}
else if (responseType == ERROR_CORRUPT_RESPONSE)
{
Serial.println("Bad CRC");
}
else
{
//Unknown response
Serial.print("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 setupNano(long baudRate)
{
//nano.enableDebugging(Serial); //Print the debug statements to the Serial port
//nano.begin(softSerial); //Tell the library to communicate over software serial port
nano.begin(Serial2); //Tell the library to communicate over ESP32 Serial Port # 2 (pins 16/17)
//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
//Software serial
//softSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
//while (softSerial.isListening() == false); //Wait for port to open
//Hardware serial
Serial2.begin(baudRate); //For this test, assume module is already at our desired baud rate
while(!Serial2);
//About 200ms from power on the module will send its firmware version at 115200. We need to ignore this.
//while (softSerial.available()) softSerial.read();
while (Serial2.available()) Serial2.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
Serial2.begin(115200); //Start hw 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
Serial2.begin(baudRate); //Start the serial port, this time at user's chosen baud rate
delay(250); //this isn't in the software serial example, don't know why
}
//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
}