I2C multiplexer and RFID reader at the same time with Wemos D1

Hi,

I am currently working on a project where I want to use an RFID reader and five SH1106 OLED displays together. These are the components I am using:

  • Wemos D1 (not the mini one; clone)
  • I2C Multiplexer TCA9548A
  • 5xOLED SH1106
  • RC522 RFID Reader

I managed to get the multiplexer to run with the displays just fine. Also I was able to run the RFID reader. But I can't manage to get both to run at the same time. When I comment out LINE A and BLOCK C in the following code, the displays work and when I comment out BLOCK B the RFID works. Here is my code:

#include <Arduino.h>
#include <MFRC522.h>
#include <SPI.h>

#include <services/displayservice/DisplayService_h>

#include "SH1106Wire.h"

#define SS_PIN D4
#define RST_PIN D0

MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;

// Init array that will store new NUID
byte nuidPICC[4];

DisplayService displayService;

/**
   Helper routine to dump a byte array as hex values to Serial.
*/
void printHex(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

/**
   Helper routine to dump a byte array as dec values to Serial.
*/
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

void setup() {
    Serial.begin(115200);
    SPI.begin();
    rfid.PCD_Init(); // Init MFRC522 <- LINE A
}

int num = 0;

void loop() {

    // --- BLOCK B ---
    for (int i = 2; i <= 6; i++) {
        SH1106Wire* display = displayService.display(i);
        display->clear();
        display->flipScreenVertically();
        display->setFont(ArialMT_Plain_24);
        display->setTextAlignment(TEXT_ALIGN_CENTER);
        display->drawString(64, 20, String(num));
        display->display();
    }
    num++;
    // --- END BLOCK B ---

     // --- BLOCK C ---
    // Reset the loop if no new card present on the sensor/reader. This saves
    // the entire process when idle.
    if (!rfid.PICC_IsNewCardPresent()) return;

    // Verify if the NUID has been readed
    if (!rfid.PICC_ReadCardSerial()) return;

    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
    Serial.println(rfid.PICC_GetTypeName(piccType));

    // Check is the PICC of Classic MIFARE type
    if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
        piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
        piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println(F("Your tag is not of type MIFARE Classic."));
        return;
    }

    if (rfid.uid.uidByte[0] != nuidPICC[0] ||
        rfid.uid.uidByte[1] != nuidPICC[1] ||
        rfid.uid.uidByte[2] != nuidPICC[2] ||
        rfid.uid.uidByte[3] != nuidPICC[3]) {
        Serial.println(F("A new card has been detected."));

        // Store NUID into nuidPICC array
        for (byte i = 0; i < 4; i++) {
            nuidPICC[i] = rfid.uid.uidByte[i];
        }

        Serial.println(F("The NUID tag is:"));
        Serial.print(F("In hex: "));
        printHex(rfid.uid.uidByte, rfid.uid.size);
        Serial.println();
        Serial.print(F("In dec: "));
        printDec(rfid.uid.uidByte, rfid.uid.size);
        Serial.println();
    } else
        Serial.println(F("Card read previously."));

    // Halt PICC
    rfid.PICC_HaltA();

    // Stop encryption on PCD
    rfid.PCD_StopCrypto1();
    // --- END BLOCK C ---
}

with DisplayService.cpp:

#include <Wire.h>

#include "Arduino.h"
#include "DisplayService_h"
#include "SH1106Wire.h"

SH1106Wire displayInstance(0x3C, SDA, SCL);  // ADDRESS, SDA, SCL
uint8 activeDisplay = 0;

DisplayService::DisplayService() {}

SH1106Wire* DisplayService::display(uint8 displayNumber) {
    if (activeDisplay == displayNumber) {
        return &displayInstance;
    } else {
        this->changeDisplay(displayNumber);
        activeDisplay = displayNumber;
        displayInstance.init(); // <-- LINE D
        return &displayInstance;
    }
}

void DisplayService::changeDisplay(uint8 displayNumber) {
    Wire.beginTransmission(0x70);    // TCA9548A address
    Wire.write(1 << displayNumber);  // send byte to select bus
    Wire.endTransmission();
}

I guess it has something to do with how the SDA Ports are used. Do you have any idea on how I can get around this issue.

Thanks in advance!

P.S.: After switching I2C channels, I always have to reinit the display which makes it flicker (see LINE D). Is there a way I can avoid that, too?

My eyes are failing. Can you help by posting links to each of the hardware items. Your picture is useless, can you post an annotated schematic as you have it wired?

I guess with „links to the hardware items“ you mean links to their data sheets?

My drawing should be fine to grasp how everything is connected:

  • Mosi,miso,sda,scl, 3.3v and gnd go to the respective pins on the rfid board
  • the other sda, scl and the 5v and gnd go to the respective ports on the multiplexer.
  • A0, A1 and A2 of the multiplexer are connected to gnd
  • every individual display is connected to an other SD and SC output pin of the multiplexer and to the controllers 5v and gnd as well.

That’s all.

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