I have the following test sketch running on a Micromod Single Board + ESP32 + Qwiic.
No other components are connected, power is over USB.
The purpose of the setup is to just detect the presence of a device, like:
reading “00000” = no device is present (myRfid.getTag() returns 000000 when no tag was detected)
reading “number wrong” = device (tag) is present but the wrong one (in my example, 5809122368250)
reading “number correct” = device (tag) is present and the right one (in my example, 580912131888)
After exactly 20 readings (with the 21st) this happens (this is repeatable):
the readings gets wrong (it reads 59102000232 instead of 580912131888)
myRfid.clearTags() seems to not be executed any more as myRfid.getTag() delivers the same result again and again, even when there is no tag present any more
with every additional reading, the read number changes (increases)
if I continue reading tags, eventually a crash happens (i2c.master: I2C hardware NACK detected))
this happens no matter if I change NFC tags or use the same over and over again
I found that in the SparkFun_Qwiic_Rfid.h file there is #define MAX_TAG_STORAGE 20 I assume this means that 20 read tags are stored and are cleared with clearTags(), so that I do not get the last read tag when calling myRfid.getTag() but get the 000000 mentioned above.
What I have tried:
Changing MAX_TAG_STORAGE to e.g. 1 does not solve the issue.
removing calling myRfid.getTag() when a tag was detected does not solve the issue
The issue persists even when I reboot the board once it starts to read wrong. The only thing that helps resetting the Reader is with power cycle.
I wonder if I am using the library functions wrong (I based my program on the example), do something unallowed (const char* String compare..) or if I hit a bug in the library?
//repeat reading tag 21 times
//after 20 reads, tag starts to show 59102000232 (instead of 580912131888)
//it does not reset/clear the read then but goes up to 60102000232
//then with every subsequent read the number changes a bit: 62102000232
//next read: 63102000232
//next read: 64102000232
//eventually this becomes: 92102000232
//after that, there is a crash (E (199983) i2c.master: I2C hardware NACK detected)
#define LOGENABLED
#ifdef LOGENABLED
#define LOG_PRINT(x) Log(x)
#else
#define LOG_PRINT(x)
#endif
#include <Wire.h>
#include "SparkFun_Qwiic_Rfid.h"
#define RFID_ADDR 0x13 // Default I2C address
Qwiic_Rfid myRfid(RFID_ADDR);
String tagRead = "0000000000000000"; //length 16
const char* tagEmpty = "000000";
const char* tagRequired = "580912131888";
const char* textNoTag = "TAG_0";
const char* textTrueTag = "TAG_1";
const char* textFalseTag = "TAG_2";
bool nfcDetected;
unsigned long nfcUpdateLast = 0;
unsigned long nfcUpdateInterval = 500;
int reading = 0;
void setup()
{
Serial.begin(115200);
while(!Serial) delay(10);
Wire.begin();
if(!myRfid.begin())
{
while(1);
}
myRfid.clearTags();
}
void loop()
{
if (millis() - nfcUpdateLast >= nfcUpdateInterval)
{
nfcUpdateLast = millis();
LoopNFC();
}
}
void LoopNFC()
{
//Reset values before the next reading
if (nfcDetected == 1)
{
myRfid.clearTags();
nfcDetected = 0;
tagRead = tagEmpty;
}
//Read tag
tagRead = myRfid.getTag();
LOG_PRINT(tagRead);
if (tagRead.equals(tagEmpty))
{
LOG_PRINT(textNoTag);
}
else
{
reading++;
nfcDetected = 1;
}
if (nfcDetected == 1)
{
if (tagRead.equals(tagRequired))
{
LOG_PRINT(textTrueTag);
}
else
{
LOG_PRINT(textFalseTag);
}
//clear all discovered tags after everything is done this loop, otherwise myRfid delivers wrong results
//myRfid.clearTags();
Serial.println(reading);
}
}
void Log(String pText)
{
#ifdef LOGENABLED
Serial.println(pText);
#endif
}
The firmware has a FIFO with 20 entries and 2 pointers: newestTag and oldestTag. The newestTAG is the “write pointer” and oldestTag is the “read-pointer”. They turnaround to zero when exceeding the 20 entries. Apart from some small errors, it looks to me it should work.
BUT that firmware-source is 4 years old, where it seems to be new firmware binary uploaded 2 years ago. Not sure where the source is of that.
Line 103 in the main loop there is delay(11);//Necessary to not overwhelm the ID-XXLA module baud rate.
From everything I read about the I2C bus and hardware errors, mostly someone mentions that it is a very bad idea to use delay (basically pausing the loop) together with I2C as a kind of “slow down”. Or am I mixing up something here and this delay is not causing problems?
It fails.. The problem related to the moment the pointers return to zero !
MAX_TAG_STORAGE is defined as 20 and thus positions 0 - 19.
The FIFO is defined as:
struct {
byte tagID[6]; //The Uniqe identifier of the RFID tag, converted from ASCII to HEX will be six bytes in size.
unsigned long tagTime; //When was the RFID tag sensed?
} tagEvent[MAX_TAG_STORAGE];
The turnaround pointer check is done AFTER the a new tag has been added: if( newestTag++ == MAX_TAG_STORAGE ) newestTag = 0;
As newestTag is increment AFTER the compare it can contain position 20 to store the next TAG. This is beyond the FIFO size and a such will overwrite memory that is used for other variables. The result is undefined.. but not good…
Changing the turn around check to BEFORE doing the check, solves the issue if( ++newestTag == MAX_TAG_STORAGE ) newestTag = 0;
btw the same should be done for OldestTag : if (++oldestTag == MAX_TAG_STORAGE) oldestTag = 0;
Hello @michaelheiml82 and @paulvha
I have been having the same problem for over a year and did not know the problem was with the Qwiic board. I have two readers connected in series and after a few reads, one of the readers spits out a fake non-existent tag constantly. And if another tag comes close to the reader, the fake number increases in value and my arduino project crashes after some time. A previous lab member tells me that older boards were fine (when the addresses were 0x7C and 0x7D. The problem started with a new line of products, but we still have not figured out a solution. Could you please tell me what you guys did to fix the issue?
As paulvha writes, it seems that with this commit the issue was solved in the source code.
@TS-Russell I wonder, will there be a firmware binary update and how do I apply that update to the reader? I found this How-To update an ATTiny with the help of an Arduino Uno, but that looks rather complicated..
Or will there be a hardware revision and can I exchange my faulty reader with a new one?
@michaelheiml82 i was about to ask the same thing. i have zero experience with electronics and I thought the firmware was the same as the arduino code, but it looks like it is different. I do not know how to make the updates from the recent commit to my project and make it work. I will ask around and get back to you this afternoon.
As far as I understand, updating the Reader would mean to first have a new firmware binary (I do not know how to create that) and then wire the chip on the reader (an ATTiny) to an Arduino board and flash that firmware onto the reader via the Arduino board.
I found a how-to as linked above but it shows the ATTiny chip inserted into a “ZIF Test DIP” but we have the chip soldered on the reader, so I assume it would mean to somehow solder cables directly onto the pins of the chip. That seems to be a very finicky task as those pins are very small and I have no idea what to connect where when you look at the image (https://cdn.sparkfun.com/assets/learn_tutorials/8/5/7/QwiicConnectors1.jpg)
So I hope Sparkfun can help us out here? @TS-Russell or whom should we mention?
@edspark I am sorry if I am dragging you back to an old project; the beer offer still stands. I saw that you contributed to the ATtiny85_firmware on the Sparkfun Qwiic RFID reader boards. Since then, Sparkfun has changed the I2C address but that resulted in issues with the ATtiny85. People on this thread, including myself and other labs, have been struggling with the board since the changes. The last change made was last week in the github. The board can read 20 rfid tags but goes haywire after that. @michaelheiml82 describes the problem well here Qwiic RFID wrong readings after 20 reads