Multiplexing I2C with Teensy LC

Hello All,

I am trying to use a multiplex to drive several oLED on a Teensy LC.
When running the code below, I would have expected each screen to display a number. However, only the first screen display anything. The final number on my screen #1 is NUMBER_SCREENS -1 (6). I wanted to display 1 on the screen 1, 2 on the screen 2 etc..
Note that I am not using a pull down resistor (I think the multiplexer does have an internal 10k on the input, the screen 1 works so I am not sure I need to add pull resistor on the output of the multiplexer either)

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define NUMBER_SCREENS 7
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Select I2C BUS
void TCA9548A(uint8_t bus){
  Wire.beginTransmission(0x70);  // TCA9548A address
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
  Serial.print(bus);
}

void identifyScreen() {
  for (uint8_t i = 0; i< NUMBER_SCREENS; i++){
    TCA9548A(i);
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println(F("SSD1306 allocation failed"));
      for(;;);
      } 
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println(random());  //I use random to double check my latest version of the code is indeed uploaded correctly. This is for debugging purpose. 
    display.setTextSize(3);
    display.setCursor(0, 39);
    display.println(i);  

    display.display();
    
   

    

  }
}
 
void setup() {
  Serial.begin(9600);
  

  // Start I2C communication with the Multiplexer
  Wire.begin();
  identifyScreen();
  
}
 
void loop() {
  
}

Please adapt similar to what is shown in this tutorial fof Arduino:

https://randomnerdtutorials.com/tca9548a-i2c-multiplexer-esp32-esp8266-arduino/

May want to search through Paul's forum as there may be some minor changes in I2C for Teensy.

Hi Ray,

I saw that tutorial before. It instantiates 4 displays. Other that that the code is pretty much the same. I have 8 oLED so it would be very memory intensive for me to go that route.
Is that the only options ?
I will run the tutorial to see if the multiple instantiation solve the issue.

As Arduino is C++, the instantiation of multiple objects is the nominal way of dealing with several I2C displays. This provides the ability to initialize the displays, set fonts, position characters all independently of other displays.

But, over the years, discussions have taken place around the word "only":

https://forum.arduino.cc/t/multiple-i2c-lcds/51746/4

I would suggest going with a uC that would have sufficient SRAM to manage your needs rather than concocting a one-off solution.

Ray

Maybe try this

if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C, false, false)) {

I tried but no difference

Can you prove that ? Show a screendump of the datasheet where it says that. Show a photo of your module and circle the pullup resistors (or give a link to your module).

As far as I know, there are no pullup resistors. The Adafruit I2C multiplexer has pullup resistors on the primary I2C bus and none at the secondary (sub)I2C buses.

Do you have an other board ? Because I can not pinpoint a problem in your sketch :cry:

Can you show a photo of your project ? Maybe you overlooked something.

Hello Koepel,

I am using the following multiplexer
I tried to add pull-up resistors (5kOhm) on all the I2C connections ( Teensy LC to Multiplexer and each of the two screens) but it didn't help. I still only see one of the screen responding.
I checked the screens are working by swapping the wires between screen 1 and 2. No issue with the screens themself.
I use the same multiplexer with a Arduino Micro and it worked fine.

Here are few pictures of the current setup




Thank you for the photos.

Your multiplexer module has 10k pullup resistors at the main I2C bus, so that is good.
It is a copy of the Adafruit multiplexer.
I forgot if the OLED displays have pullup resistors.

Is everything (multiplexer and OLED) powered from 3.3V ?

The Arduino Micro is from the AVR family. They have a stronger I2C bus and a I2C filter. They do better than what is required by I2C standard.

Pull you wires apart please. Keep SDA away from SCL. The I2C bus can not deal with crosstalk between SDA and SCL.

I hope that I sleep tonight, because something worries me. The power is going to the Teensy board, and that is where the GND stops. The GND magically appears at the multiplexer and that is connected to the OLED displays.

yes though I did try with 5V.

Not sure I follow you. The 2 screens, the Teensy and multiplexer are directly wired (GND and VIN) to the breadboard with is fed by the 9V battery via the power controller.

It's probably a good idea but I don't think that's the issue since both screens work (not together) if I change the code to TCA9548A(0 or 1) instead of i.

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1,1000000);

Adding the frequency 1000000 (1MHz) seem to fix the issue. Not sure why though.

FWIW here is the code that works for me.
No pull-up where used.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define NUMBER_SCREENS 7
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1,1000000);

// Select I2C BUS
void TCA9548A(uint8_t bus){
  Wire.beginTransmission(0x70);  // TCA9548A address
  Wire.write(1 << bus);          // send byte to select bus
  Wire.endTransmission();
  Serial.print(bus);
}

void identifyScreen() {
  for (uint8_t i = 0; i< NUMBER_SCREENS; i++){
    TCA9548A(i);
    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println(F("SSD1306 allocation failed"));
      for(;;);
      } 
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println(random());  //I use random to double check my latest version of the code is indeed uploaded correctly. This is for debugging purpose. 
    display.setTextSize(2);
    display.setCursor(0, 39);
    display.print("Screen ");  
    display.print(i); 
    display.display();
    
   

    

  }
}

I still can't see the GND from the power to the board and the modules and the displays :mag: but I assume it is there.

You can damage something when powering a 3.3V device with 5V. The OLED and the multiplexer can deal with 5V and 5V leaking into the SDA and SCL pin (via a pullup resistor) of the Teensy board is just a small current. So I think you are good :relieved:

Changing the board and changing the frequency has influence :thinking: That smells like a "timing" and "glitch" and "grounding problem" :nose: That means you should try to split the wires apart, and also check the ground path.

afbeelding

Did you know that you can measure the sink current of SDA and SCL in the circuit ?
Activate the I2C bus and keep the I2C bus idle, then measure the shortcut current from SDA to GND and the shortcut current from SCL to GND.
That means you can call "Wire.begin();" in setup() and then select one of the (sub) I2C buses with the multiplexer. Measure those currents in the activated I2C buses. They should be below 3mA, but not too small. I prefer between 1mA and 3mA.

Suppose there is 10k pullup to 3.3V, then the sink current is 3.3V/10k = 0.3mA

The Teensy LC has a VIN rated 3.7V to 5.5V. The multiplex is 3V to 5V compliant and so are the oLED.

I am assuming you mean untwisting the wires and keep them apart to avoid any sort of electromagnetic induction interference ?
I will check the conductivity of the ground wires. Currently the Teensy LC is grounded via the PIN between VIN and the 3.3V pin. It's possible something is loose on the breadboard side. The multiplex is now directly grounded to the Teensy.

So basically do

and measure between the SDA (resp, SCL) pins of the Teensy LC and the multiplexer ?

The Teensy has a 3.3V processor with a 3.3V I2C bus. All kind of things happen when you apply 5V to something that is connected to that 3.3V I2C bus.

Yes, I mean untwisting them. The I2C bus can not deal with crosstalk between SDA and SCL.
This is the official I2C standard: UM10204.pdf
Go to page 54, paragraph 7.5 and read about the crosstalk.
If you have read that page, then you can order a cap with the embroidery text: "I2C expert", because no one reads that page and everyone does it wrong as I wrote here.

afbeelding

Yes, such a sketch.
The sink current in the I2C bus is the current to make a signal low. You can measure the sink current by shortcutting SDA to GND with a multimeter in current mode. The same for SCL to ground. The same for SDA and SCL on the (sub) I2C bus.

What a mess! I'm sorry to have to tell you this, but you are not getting the point of breadboards. Everything that can plug into a breadboard should be plugged into a breadboard. If there is not enough room, get more breadboards. Clip them together to form a larger breadboard. The Teensy, the TCA multiplexer, the OLEDs should all be plugged into a breadboard. Lose those screw-terminal boards. Don't waste breadboard real-estate by taping a PP3 9V battery to it! Plus that white square thing (what is that?).

And that battery: also a waste of space and the planet's resources! If you are regulating 9V down to 3.3V you are wasting two thirds of that battery's capacity. 3xAA non-rechargeable or better still 4xAA NiMH would waste much less of their capacity and give you more capacity and current into the bargain.

So sorry for ranting...