Multiplex two SSD1306 OLED I2C Displays using TCA9548A

Hello - I am trying to understand how multiplexing with TCA9548A works, I2C and how I can send data from different sensors to two OLED displays that have the same fixed address 0x3c. I am using a Feather M4 board as a master and 2 ADAFRUIT 128 x 32 displays and wired them up to a TCA9548A multiplexer (see image attached)

I ran a multiplexer scan to confirm everything is wired up right and printed results in serial monitor

TCAScanner ready!
TCA Port #0
Found I2C 0x3C
TCA Port #1
Found I2C 0x3C
TCA Port #2
TCA Port #3
TCA Port #4
TCA Port #5
TCA Port #6
TCA Port #7

done

Here is the code that I sort of cobbled from different examples but none basic enough to do a simple test. I have seen some with BME sensors and a large number of OLEDs and LCDs - but no success yet


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

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


#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

#define TCAADDR 0x70

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


// Helper function for changing TCA output channel
void tcaselect(uint8_t channel) {
  if (channel > 7) return;
  
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << channel);
  Wire.endTransmission();  
}

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

  Wire.begin();

  tcaselect(0);

  delay(2000);
  display1.clearDisplay();

  display1.setTextSize(1);
  display1.setTextColor(WHITE);
  display1.setCursor(0, 10);
  
  tcaselect(1);

  delay(2000);
  display2.clearDisplay();

  display2.setTextSize(1);
  display2.setTextColor(WHITE);
  display2.setCursor(0, 10);

}
void loop() {
  // Display static text
  display1.println("Hello, world!");
  display1.display(); 

  display2.println("Hello, world!");
  display2.display(); 
}

The code compiles and uploads - results below

Sketch uses 22676 bytes (4%) of program storage space. Maximum is 507904 bytes.
Device       : ATSAMD51x19
Version      : v1.1 [Arduino:XYZ] May 17 2020 17:56:23
Address      : 0x0
Pages        : 1024
Page Size    : 512 bytes
Total Size   : 512KB
Planes       : 1
Lock Regions : 32
Locked       : none
Security     : false
BOD          : false
BOR          : true
Write 22948 bytes to flash (45 pages)
[==============================] 100% (45/45 pages)
Done in 0.273 seconds
Verify 22948 bytes of flash
[==============================] 100% (45/45 pages)
Verify successful
Done in 0.554 seconds

But there is no display (I did test both displays individually using the Arduino examples and they work fine). I suspect my code might need a little help

Thank you!

You need to use the tcaselect call in your loop function too.

I do not see any calls to begin() for the displays.

Thanks for the generous support and tips. While waiting for responses - I continued looking around and found an example code at RandomNerdsTutorials.com. This was almost exactly what I was looking for so I modified it for my setup using 128 x 32 OLEDs instead of 128 x 64 OLEDS

I am providing this here for others who may be looking for this example as well

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


#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

#define TCAADDR 0x70

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Helper function for changing TCA output channel
void tcaselect(uint8_t channel) {
  if (channel > 7) return;
  
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << channel);
  Wire.endTransmission();
  Serial.print(TCAADDR);  
}

void setup() {
  
  Serial.begin(9600);
 
  // Start I2C communication with the Multiplexer
  Wire.begin();

  // Init OLED display on bus number 0
  tcaselect(0);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 

   // Clear the buffer
  display.clearDisplay();
  
  // Init OLED display on bus number 1
   tcaselect(1);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  
  // Clear the buffer
  display.clearDisplay();

  // Write to OLED on bus number 0
  tcaselect(0);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 8);
  // Display static text
  display.println("Hello World Disp 0");
  display.display(); 

  
  // Write to OLED on bus number 1
  tcaselect(1);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 8);
  // Display static text
  display.println("Hello World Disp 1");
  display.display(); 


}
void loop() {
  
}

Here is the result

One thing I learned is that I only needed to define the display once instead of one for each display and use the MUX address to print individualized messages for each display.

Now I can add different sensors or display different sensor attributes to each display next! I will post next time!

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