Problems Multiplexing OLEDS with TCA9548A

I'm working on a small Arduino Uno project which will require 4 OLEDs (using I2C displays) for which I'm using a TCA9548A. I've tested all 4 displays individually to make sure they work. I'm new to Arduino with limited coding experience, so I decided to start with 2 OLEDs to figure out the multiplexing bit, but I cannot get them to work together. I ran the TCAScan code which I found searching the forums and that correctly found/identified both displays.

When I run the cobbled together code below, the first display works until the loop oled2() is run for the second time, at which point the first display goes black...and the second display never displays anything. Following the serial monitor, the code appears to fully execute. If I comment out the oled2() from my loop (i.e. if the oled2 function never runs) the first display works perfectly. I've tried with and without the pullup resistors for the OLED data and clock lines as I've seen demonstrations both ways, but with no change in the results.

Any thoughts on if this may be a hardware or coding issue?

/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

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


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)

// Define address for TCA
#define TCAADDR 0x70

// Create an object for each OLED display
//Adafruit_SSD1306 display1(OLED_RESET);
//Adafruit_SSD1306 display0(OLED_RESET);


Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display0(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


char textDisplayOne[] = "Display 1";
char textDisplayTwo[] = "Display 2";


void TCA9548A(uint8_t bus)
{
  Wire.beginTransmission(TCAADDR); //TCA9548A address is 0x70
  Wire.write(1 << bus);         // send byte to select bus
  Serial.println("TCA Loop "); Serial.println(bus);
  Wire.endTransmission();
}


void setup() {
  Serial.begin(9600);
  Serial.println(("Start"));

  // start wire library for I2C
  Wire.begin();

//initialize OLED at ox3C (set multiplexer to channel 1 and initialize OLED-0 with I2C addr 0x3C


    TCA9548A(0);
    display0.begin(SSD1306_SWITCHCAPVCC, 0x3C);
     Serial.println(("Initialize 0"));
 

     TCA9548A(1);
     display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    Serial.println(("Initialize 1"));


}



void oled1() {

 TCA9548A(0);
  //clear display
display0.clearDisplay();
//set color (always white)
display0.setTextColor(WHITE);
//set font size
display0.setTextSize(2);
//set the cursor coordinates
display0.setCursor(0,0);
display0.print(textDisplayOne);
display0.display();
 Serial.println(("Write Display One"));
delay(5000);
}


void oled2() {

TCA9548A(1);
display1.clearDisplay();
//set color (always white)
display1.setTextColor(WHITE);
//set font size
display1.setTextSize(2);
//set the cursor coordinates
display1.setCursor(0,0);
display1.print(textDisplayTwo);
display1.display();
 Serial.println(("Write Display Two"));
delay(5000);  
}



  
void loop() {
oled1();
oled2();


}

What is your target Arduino?
Each Adafruit_SSD1306 object claims 1kB SRAM for a display buffer. A Uno can only manage one buffer.

You are either going to use a single buffer or separate buffers if you can afford it.

The single buffer means: Clear buffer, write to buffer, display buffer to current OLED.
Separate buffers mean: Update buffers at will. Display specific buffer to its associated OLED.

The TCA9548A should be fine.
Using 4 SPI displays would be simpler.

David.

Problem Solved.

Thank you, David. I am using the Uno (to be fair, an uno clone), so I re-worked the code to use a single Adafruit_SSD1306 object and a single buffer and now it appears to be working fine on both displays. I'll try all four tonight, but I expect that'll work just fine. I never thought about the capability of the Uno as I was parroting examples from various forums and youtube, but obviously I was not fully understanding what was happening.

I was suspect of the TCA9545A only because the first one I had didn't work at all (would cause the code to hang) and I'm now using the backup which I couldn't prove wasn't working, but I still wasn't confident in it.

For this project, I think I can work with the single buffer as I'm only displaying text which doesn't need to be updated very quickly. Nevertheless, I am going to order up some SPI displays for future projects or the inevitable "I wonder if I can make it do ..."

Thanks again for your help David.

You will have the same buffer memory issue with SPI.

Quite honestly, drawing time on a 128x64 is seldom a problem. Whether constructing the image in the buffer or sending the whole buffer to the display.

I mentioned SPI because it does not require any extra electronics.

David.

I am having a problem with running two 1306 OLEDs with the Adafruit multiplexor. When I set the resolution of both OLEDs to 128x32 all works fine. However, if I set one of them to 128x64 the software seems to hang. (Incidentally, when both are set at 128x32, as I would expect, the 128x64 display uses every other line.)

I am setting the resolution using:
Adafruit_SSD1306 display0(128,32, &Wire, OLED_RESET);
Adafruit_SSD1306 display1(128,32, &Wire, OLED_RESET);

which works fine in my sketch, but if I change it to:
Adafruit_SSD1306 display0(128,32, &Wire, OLED_RESET);
Adafruit_SSD1306 display1(128,64, &Wire, OLED_RESET);

the sketch balks.

Thoughts?

Fred

If you are using a multiplexor you might just as well use a single oled object (with single buffer). Just redraw each oled when you change to the "other" one.

If you are only using two physical oleds with different I2C addresses, you would use separate oled objects. But the buffers use up a lot of SRAM memory on a Uno/Nano.

Oh, and don't use the OLED_RESET argument when you have multiple oleds.

David.

Thanks for the reply, David.
I am using a 128x64 and a 128x32 OLED which have same I2C address of (0x3C).
I don't quite understand how the 'single buffer' would work. In my final project (which would be
on a MEGA) each display would build up a lot of complex text and graphics, hard to recreate all of it when switching to the other OLED.
I dropped the OLED_RESET parm - no change in problem. When the 128x64 size is specified, the test sketch just dies.

Fred

The Mega has plenty of SRAM. So you can have two independent objects.

It is much easier to alter the I2C address than to mess around with multiplexers.
Change one OLED to 0x3D

You still need to omit OLED_RESET args

David.

As these things use 3.3 V logic, would you not be better off to use an ESP8266 for more "grunt"?

Yes, David. Since I did not want to do SMD resistor jumper re-soldering (to change address on an OLED display) I wanted to pursue to MUX approach.

As you suggested, the UNO does not have enough SRAM memory to hold the display buffers for both the 128x32 and the 128x64 displays. (It did work with just two 128x32 buffers) My sketch must have migrated the buffers into the STACK, hence the sketch failure.

Running the identical sketch on a MEGA resolves the problem.

Fred

SMD resistor 0R jumper is not too daunting.
Just place your iron on top of the 0R resistor. It will leave the pcb. Lost forever.

Then make the new link with a blob of solder.

Personally, I try to always use a (3.3V) Uno for Arduino projects.

David.