Problem with I2C after powering off

Hi everyone

This is the first time for me looking for help in this forum, so please let me know if I can improve the way of asking of if I am in the wrong category :slight_smile:

I am working with a JOY-IT R3DIP (Arduino compatible) with a ATmega328P microcontroller to read RFID-chips. Since I need several RFID readers I use a "Grove- 8 Channel I2C Hub". In the end the state of each reader will be sent to a server by a post request but at the moment, in order to check weheather the program does work: every time a new card is detected by one of the reader and if a card is removed, a tone is played (using an active piezo buzzer).
I try to upload a picture of the hardware and hope that it works.

So far, everything works as expected when I upload the code.
But if it is powerd of and on again (by just pull out the plug and plug it in again), the program still works but no cards are detected anymore. By pressing the reset button of the arduino or uploading the sketch again, the problem resolves.

Since theoretically, there should be no difference between resetting/uploading the sketch and powering off and on, I suppose that the bus somehow hangs itself when powered off.
Furthermore, I tried to directly connect one reader to the board without the intermediate bus and the problem did not occure then.
In order to clear and restart the bus I implemented the method that is described here . The method did work and the function I2C_ClearBus() did return 0, however, the cards were still not detected after powering off and on.

Does someone have an idea what the problem could be and how to resolve it?

Here is my code:

#include <Wire.h>
#include "MFRC522_I2C.h"
#include <SPI.h>

#define RST_PIN 6                     // Arduino UNO Pin
MFRC522_I2C mfrc522(0x28, RST_PIN);   // Create MFRC522 instance.

const int amountOfScanners = 1;       // set amount of scanners here
String    content = "";

void TCAChannel(uint8_t i) {          // I2C Multiplexer
  Wire.beginTransmission(0x70);
  Wire.write(1 << i);
  Wire.endTransmission();
}

byte mac[] = { 0x2C, 0xF7, 0xF1, 0x08, 0x32, 0x6B };

String queryString[amountOfScanners];                          // Liste mit jeweils den zu sendenden Daten in der Form eines "query strings"
String saveQueryString[amountOfScanners];                      // Liste in welcher die letzten gesendeten Daten für jeden Leser gespeichert werden -> um eine Änderung feststellen zu können
int    buzzer = 9;                                             // Pin, an welchem der active piezo buzzer angeschlossen ist

void setup() {  // -------------------------------------------------------------------------------------------------------
  
  Wire.begin(); 
  delay(5000);
  mfrc522.PCD_Init(); // Init MFRC522   
 
  } 

void loop() {   //-------------------------------------------------------------------------------------------------------
  
  
  // Going through amount of connected scanners to read
  for (int n = 0; n < amountOfScanners; n++) {  
    TCAChannel(n);                                                                                     // Bestimmt den Eingang beim Multiplexer, der untersucht werden soll
    mfrc522.PICC_ReadCardSerial();
   
    // Look for new cards, and select one if present
    if (  ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {                     // if no card, do nothing
      content= "";
      queryString[n] = content;
      }
    else { // if new card, do this
      content = "";
      for (byte i = 0; i < mfrc522.uid.size; i++) {                                                    //generiert die ausgelesene HEX ID
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : ""));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
      }
      queryString[n] = content;                                                                        // setzt den aktuellen "query string" zusammen
                                                                  
    }   
  }

  for (int n = 0; n < amountOfScanners; n++) {   // Durchführung für jeden Eingang separat
    
    // überprüft, ob sich der Status vom Lesegerät verändert hat -> API und ersetzt den Speicher
    if(queryString[n] != saveQueryString[n]){    
      tone(buzzer,500);
      delay(500);  
      noTone(buzzer);
      delay(500);
      saveQueryString[n] = queryString[n];      // überschreibt den Speicher mit dem aktuell ausgelesenen Status vom Lesegerät
    }
  }
  
}               

And here a picture of my Hardware:

I am happy for any help :slight_smile:

1 Like

Thanks for the code between code tags and the photo, but it can use more links :stuck_out_tongue_winking_eye:

Joy-IT Uno clone: https://joy-it.net/en/products/ARD_R3DIP
Seeed I2C Hub: https://www.seeedstudio.com/Grove-8-Channel-I2C-Hub-TCA9548A-p-4398.html

Which library do you use ? This one ? https://github.com/kkloesener/MFRC522_I2C
The PCD_Init() function is here.

The PCD_Init() function communicates with the RFID reader, but you did not open its I2C channel yet.
You have to call PCD_Init() for each RFID readers and you have to open its I2C channel before calling it.

You also need more RFID objects, one object for each RFID receiver:

MFRC522_I2C mfrc522(0x28, RST_PIN);      // several of these

That I2C_ClearBus() function from www.forward.com.au is good, he knows what he is doing. I think that you don't need that function.

Where did you buy those Grove wires ? Please split those cables, so they become individual wires.

Is that a W5500 Ethernet Shield ? https://www.seeedstudio.com/W5500-Ethernet-Shield.html
We don't use that anymore, because it is low level Ethernet. The ESP32 or Nina modules are now used for Wifi.

2 Likes

Hi,

When you pull the plug, count to 10seconds before plugging it back in and see what happens.

If you briefly pull the plug the RFID may power down, but the controller may still be operational.

Can you post a circuit diagram of your project please?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

1 Like

Thank you so much for your answers!

Yes this is exactly the hardware I use and I am pretty sure that I use this library.

Can I create all objects on the same pin? And how is the I2C channel opened?

Yes it is. Thank you for the tip. In this case I will look for a new one.

The time I wait inbetween does not make any difference.

I will try to create a circuit diagram and post it.

Thank you very much

1 Like

The I2C hub can connect the Arduino board to one of the (sub) I2C buses.
You use the function TCAChannel() for that.
Before calling .PCD_INIT() you can to "connect" the Arduino to that (sub) I2C bus, or "open" that I2C channel, or "select" a (sub) I2C bus. How would you call it ?

for (int i = 0; i < amountOfScanners; i++) 
{  
  TCAChannel(i);          // open / select / connect to one of the (sub) I2C buses
  mfrc522[i].PCD_Init();
}

If all the objects are set to the same 0x28 I2C address and the same RST_PIN, that is okay.

I'm not sure what the best way is to get the parameters for the constructor into an array of objects. I used 'new' myself (here), but a vector class could be prettier.
Could you try this :

MFRC522_I2C mfrc522[3] = 
{
  MRFC522_I2C(0x28,RST_PIN),
  MRFC522_I2C(0x28,RST_PIN),
  MRFC522_I2C(0x28,RST_PIN)
};
1 Like

Thank you so much for your help. Right at the moment I need to fix some other machines but as soon as this is over I will come back to this issue an try your solution.

Your proposal did solve the problem :grinning:
Thank you so much for your help!
Nevertheless it does not make sense to me why it worked after uploading the sketch/ resetting...

However, I post the working code if someone has a similar problem:

#include <Wire.h>
#include "MFRC522_I2C.h"
#include <SPI.h>

#define RST_PIN 6                     // Arduino UNO Pin

//----------------------------------------------------------------

const int amountOfScanners = 3;       // set amount of scanners here
String    content = "";

MFRC522_I2C mfrc522[amountOfScanners]=
{ MFRC522_I2C(0x28,RST_PIN),
  MFRC522_I2C(0x28,RST_PIN),
  MFRC522_I2C(0x28,RST_PIN)
};                                    // Create MFRC522 instance.
void TCAChannel(uint8_t i) {          // I2C Multiplexer
  Wire.beginTransmission(0x70);
  Wire.write(1 << i);
  Wire.endTransmission();
}

byte mac[] = { 0x2C, 0xF7, 0xF1, 0x08, 0x32, 0x6B };

String queryString[amountOfScanners];                          // Liste mit jeweils den zu sendenden Daten in der Form eines "query strings"
String saveQueryString[amountOfScanners];                      // Liste in welcher die letzten gesendeten Daten für jeden Leser gespeichert werden -> um eine Änderung feststellen zu können
int    buzzer = 9;                                             // Pin, an welchem der active piezo buzzer angeschlossen ist

void(* resetFunc) (void) = 0;



void setup() {  // -------------------------------------------------------------------------------------------------------
  
  Wire.begin(); 
  delay(5000);
  
  for (int i = 0; i < amountOfScanners; i++){
    TCAChannel(i);
    mfrc522[i].PCD_Init();
  }
  
  }
 

void loop() {   //-------------------------------------------------------------------------------------------------------
  
  
  // Going through amount of connected scanners to read
  for (int n = 0; n < amountOfScanners; n++) {  
    TCAChannel(n);                                                                                     // Bestimmt den Eingang beim Multiplexer, der untersucht werden soll
    mfrc522[n].PICC_ReadCardSerial();
   
    // Look for new cards, and select one if present
    if (  ! mfrc522[n].PICC_IsNewCardPresent() || ! mfrc522[n].PICC_ReadCardSerial() ) {                     // if no card, do nothing
      content= "";
      queryString[n] = content;
      }
    else { // if new card, do this
      content = "";
      for (byte i = 0; i < mfrc522[n].uid.size; i++) {                                                    //generiert die ausgelesene HEX ID
        content.concat(String(mfrc522[n].uid.uidByte[i] < 0x10 ? "0" : ""));
        content.concat(String(mfrc522[n].uid.uidByte[i], HEX));
      }
      queryString[n] = content;                                                                        // setzt den aktuellen "query string" zusammen
                                                                  
    }   
  }

  for (int n = 0; n < amountOfScanners; n++) {   // Durchführung für jeden Eingang separat
    
    // überprüft, ob sich der Status vom Lesegerät verändert hat -> API und ersetzt den Speicher
    if(queryString[n] != saveQueryString[n]){    
      tone(buzzer,500);
      delay(500);  
      noTone(buzzer);
      delay(500);
      saveQueryString[n] = queryString[n];      // überschreibt den Speicher mit dem aktuell ausgelesenen Status vom Lesegerät
    }
  }
  
}               

I'm glad it is working :smiley:

Worry about good code, don't spend time thinking how wrong code causes weird things.
By the way, a reset of the Arduino did not reset the I2C multiplexer, so if you select a channel in the loop() then it was still selected after the reset in setup() and the PCD_Init() was actually executed. Now you know, so now you can forget it :sunglasses:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.