Qwiic RFID wrong readings after 20 reads

Hi,

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):

  1. the readings gets wrong (it reads 59102000232 instead of 580912131888)
  2. 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
  3. with every additional reading, the read number changes (increases)
  4. if I continue reading tags, eventually a crash happens (i2c.master: I2C hardware NACK detected))
  5. 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
}

Given that you need to power cycle, made me look at the RFID reader. The firmware can be found on SparkFun_Qwiic_RFID_ID-XXLA/Firmware/ATtiny85_Firmware/Qwiic_RFID_IDXXLA/Qwiic_RFID_IDXXLA.ino at master · sparkfun/SparkFun_Qwiic_RFID_ID-XXLA · GitHub.

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.

Do you know if there is someone at Sparkfun that could be asked that?

@TS-Russel do you know where the latest source of the Qwiic RFID can be found ?

I’ve sent a ping, it looks like they might be out until tomorrow but hang tight! :smiley:

Thanks @TS-Russell for forwarding the issue.

While we wait for a reply, I wonder about this:

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?

1 Like

It seems I am not the only one who stumbles upon this issue, these postings are likely about the same problem:

I have taken some time to simulate the FIFO and the 2 pointers: NewestTag OldestTag as defined in the sketch :SparkFun_Qwiic_RFID_ID-XXLA/Firmware/ATtiny85_Firmware/Qwiic_RFID_IDXXLA/Qwiic_RFID_IDXXLA.ino at master · sparkfun/SparkFun_Qwiic_RFID_ID-XXLA · GitHub

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;

Attached the sketch I used to simulate.
RFID_QWIIC_FIFO.txt (3.2 KB)

2 Likes

Hi @paulvha

great you figured that out! I am very thankful for your support :slight_smile:

Do I understand that right, that this is a problem in the firmware of the Reader which could only be fixed by a FW update?

This means flash the Attiny using an Arduino; which is complicated but doable as @micropuller suggests in this posting: Qwiic RFID keeps sending tag identifier, even if there is no tag present when quickly changing tags - #16 by micropuller

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?

I have only done some analyses to find the reason/root cause, but have not fixed it. Just looked at the source code again, and the sketch for the on-board Attiny84 has been updated with the changes I had indicated above (SparkFun_Qwiic_RFID_ID-XXLA/Firmware/ATtiny85_Firmware/Qwiic_RFID_IDXXLA at master · sparkfun/SparkFun_Qwiic_RFID_ID-XXLA · GitHub)
So it is maybe expected that you need to update yourself, but I don’t have instructions. The binary files have not been updated.

1 Like

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?

1 Like

@michaelheiml82 @paulvha thank you so much both of you. I will make adjustments with the new commit and see if the problem is fixed

@happy_kass do you have a way to build the firmware and flash it onto the reader? If so, how do you do that?

@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.

Ok then we are in the same boat here :wink:

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 promise to buy you beer if you are ever in Nashville. Any chance you might be able to help with the firmware updates?

I’m not sure what firmware you’re referring to but I haven’t worked with sparkfun boards since 2022.

@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

@michaelheiml82 i talked to some people in lab and flashing the ATtiny was not their recommendation. we may need to purchase another type of board :worried: