Multiplexing 2 OLED's

Hello all,

I am preparing a project. There are going to be 2 OLED's, 1 DHT sensor, 1 Clock module. OLED A will show time and temperature in every 5 seconds (5 seconds time then 5 seconds temperature), OLED B will show maybe hundreds of bitmap arrays if it is a weekday. 1 Multiplexer is connecting 2 OLED's to Arduino Mega.

I have plugged everything, coded the basics but my problem is kinda strange. When i upload the code OLED B works perfectly (usually) but when i plug the USB cable out and reconnect it, or when i press the reset button it's not working anymore. This is going to be a gift so i have to finish it perfectly. I am pasting all my code here, you will see tons of PROGMEM arrays, you can skip them. You will see that i didn't put tcaselect(0) cause i couldn't be sure but it is working like that when i plug the USB and upload the code. Problem is at Display1. I am attaching ino and sketch image.

Can you please help me, thanks in advance!

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

#define MUX_Address 0x70        // TCA9548A Encoders address
#define DS3231_I2C_ADDRESS 0x68 // DS3231 address
#define SCREEN_WIDTH 128        // OLED display width, in pixels
#define SCREEN_HEIGHT 64        // OLED display height, in pixels
#define OLED_RESET     4        // Reset pin # (or -1 if sharing Arduino reset pin)

int count = 0;
const int cntTotalTextBitmap = 35;

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

int pinDHT11 = 13;
SimpleDHT11 dht11(pinDHT11);

byte decToBcd(byte val)
{
	return ((val / 10 * 16) + (val % 10));
}


byte bcdToDec(byte val)
{
	return ((val / 16 * 10) + (val % 16));
}


void tcaselect(uint8_t i2c_bus)
{
	if (i2c_bus > 7) return;
	Wire.beginTransmission(MUX_Address);
	Wire.write(1 << i2c_bus);
	Wire.endTransmission();
}


//void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
//{
//	tcaselect(2);
//	// sets time and date data to DS3231
//	Wire.beginTransmission(DS3231_I2C_ADDRESS);
//	Wire.write(0); // set next input to start at the seconds register
//	Wire.write(decToBcd(second)); // set seconds
//	Wire.write(decToBcd(minute)); // set minutes
//	Wire.write(decToBcd(hour)); // set hours
//	Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
//	Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
//	Wire.write(decToBcd(month)); // set month
//	Wire.write(decToBcd(year)); // set year (0 to 99)
//	Wire.endTransmission();
//}


void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
	tcaselect(2);
	Wire.beginTransmission(DS3231_I2C_ADDRESS);
	Wire.write(0); // set DS3231 register pointer to 00h
	Wire.endTransmission();

	// request seven bytes of data from DS3231 starting from register 00h
	Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
	*second = bcdToDec(Wire.read() & 0x7f);
	*minute = bcdToDec(Wire.read());
	*hour = bcdToDec(Wire.read() & 0x3f);
	*dayOfWeek = bcdToDec(Wire.read());
	*dayOfMonth = bcdToDec(Wire.read());
	*month = bcdToDec(Wire.read());
	*year = bcdToDec(Wire.read());
}


// TONS OF const unsigned char image[] PROGMEM = {.....} HERE




void printTemperature()
{
	byte temperature = 0;
	byte humidity = 0;
	int err = SimpleDHTErrSuccess;

	if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess)
	{
		display.print("DHT11 sensörü okumasında hata oluştu, Hata=");
		display.print(err);
		return;
	}
	tcaselect(1);

	display.clearDisplay();
	display.setTextSize(3);      // Normal 1:1 pixel scale
	display.setTextColor(WHITE); // Draw white text
	display.cp437(true);         // Use full 256 char 'Code Page 437' font

	display.drawBitmap(0, 25, thermo, 32, 32, 1);

	display.setCursor(45, 30);
	display.print((int)temperature); display.print(" C ");

	display.setTextSize(2);
	display.setCursor(80, 26);
	display.print("o");

	display.display();
	delay(500);
}


void printClock(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
{
	tcaselect(1);

	display.clearDisplay();
	display.setTextSize(2.5);
	display.setTextColor(WHITE);
	display.cp437(true);

	display.setCursor(0, 40);

	if (hour < 10)
	{
		display.print("0");
	}
	display.print(hour);

	display.print(':');

	if (minute < 10)
	{
		display.print("0");
	}
	display.print(minute);

	display.print(':');

	if (second < 10)
	{
		display.print("0");
	}
	display.print(second);

	display.setCursor(32, 2);
	display.setTextSize(2);

	if (dayOfMonth < 10)
	{
		display.print("0");
	}
	display.print(dayOfMonth);

	display.print('/');

	if (month < 10)
	{
		display.print("0");
	}
	display.print(month);

	display.print('/');

	//display.print("20");
	display.print(year);

	display.drawBitmap(0, 0, calendar, 32, 32, 1);
	display.drawBitmap(96, 30, clock, 32, 32, 1);

	display.display();
}


void ClockInit()
{
	tcaselect(2);   // Loop through each connected displays on the I2C buses  
	Wire.beginTransmission(DS3231_I2C_ADDRESS);
	Wire.write(0); // set DS3231 register pointer to 00h
	Wire.endTransmission();
}


void DisplayInit()
{
	for (int i = 0; i < 2; i++)
	{
		tcaselect(i);   // Loop through each connected displays on the I2C buses  
		display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
		display.display();
	}
}


struct text_bitmap
{
	const uint8_t* picture;
	char text0[10];
	char text1[10];
	char text2[10];
	char text3[10];
	char text4[10];
	char text5[10];
};


struct text_bitmap text_bitmap_list[cntTotalTextBitmap] =
{
	{ acorn_fill, "", "", "", "", "", "" },
	{ bangs, "", "", "", "", "", "" },
	{ beard, "", "", "", "", "", "" },
	{ beer_stroke, "", "", "", "", "", "" },
	{ beers_fill, "", "", "", "", "", "" },
	{ cake_fill, "", "", "", "", "", "" },
	{ camp, "", "", "", "", "", "" },
	{ cat_stroke, "", "", "", "", "", "" },
	{ cats_fill, "", "", "", "", "", "" },
	{ chicken, "", "", "", "", "", "" },
	{ coffee, "", "", "", "", "", "" },
	{ comment_stroke, "", "", "", "", "", "" },
	{ diving, "", "", "", "", "", "" },
	{ dress_fill, "", "", "", "", "", "" },
	{ eggs, "", "", "", "", "", "" },
	{ go_away, "", "", "", "", "", "" },
	{ hands, "", "", "", "", "", "" },
	{ hug, "", "", "", "", "", "" },
	{ icecream_fill, "Burcucum", "en cok", "limonlu", "dondurma", "sever. Ve", "kapta yer" },
	{ instagram_fill, "", "", "", "", "", "" },
	{ kitten_fill, "", "", "", "", "", "" },
	{ mussel, "", "", "", "", "", "" },
	{ necklace, "", "", "", "", "", "" },
	{ noodle, "", "", "", "", "", "" },
	{ pepper_fill, "", "", "", "", "", "" },
	{ pit, "", "", "", "", "", "" },
	{ sakura, "", "", "", "", "", "" },
	{ salmon, "", "", "", "", "", "" },
	{ sickness, "", "", "", "", "", "" },
	{ summer, "", "", "", "", "", "" },
	{ sushi, "", "", "", "", "", "" },
	{ twins, "", "", "", "", "", "" },
	{ twitter_fill, "", "", "", "", "", "" },
	{ very_funny, "", "", "", "", "", "" }
	{ waffle_fill, "", "", "", "", "", "" }
};


void print_text_bitmap(struct text_bitmap arr[], int i)
{
	//tcaselect(0);

	display.clearDisplay();
	display.setTextSize(1);      // Normal 1:1 pixel scale
	display.setTextColor(WHITE); // Draw white text
	display.cp437(true);         // Use full 256 char 'Code Page 437' font
	display.setCursor(66, 0);
	display.print(arr[i].text0);
	display.setCursor(66, 10);
	display.print(arr[i].text1);
	display.setCursor(66, 20);
	display.print(arr[i].text2);
	display.setCursor(66, 30);
	display.print(arr[i].text3);
	display.setCursor(66, 40);
	display.print(arr[i].text4);
	display.setCursor(66, 50);
	display.print(arr[i].text5);
	display.drawBitmap(0, 0, arr[i].picture, 64, 64, 1);
	display.display();
}


void setup()
{
	Serial.begin(9600);
	DisplayInit(); // Initialize the displays 
	ClockInit();   // Initialize the clock
}


void loop()
{
	//Display1
	byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
	readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

	if ((dayOfWeek == 2 || dayOfWeek == 3 || dayOfWeek == 4 || dayOfWeek == 5 || dayOfWeek == 6) && (second == 0))
	{
		if (count < cntTotalTextBitmap)
		{
			print_text_bitmap(text_bitmap_list, count);
			delay(2000);

			if (count != cntTotalTextBitmap - 1)
			{
				count = count + 1;
			}
			else
			{
				count = 0;
			}
		}
	}

	//Display2
	if ((second / 5) % 2 == 0)
	{
		printClock(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
	}
	else
	{
		printTemperature();
	}
}

Saatli_OLEDli_kutu.ino (124 KB)

First of all, quote-tags != code-tags :wink:

Next, why on earth use a mux? The whole idea of a bus, like I2C, is to have multiple devices on it. Including multiple displays. Just set them to different addresses.

Due to 9000 character limit, i was forced to remove my all "const unsigned char image[] PROGMEM = {............}" codes but you can find them at my ino file.

Here are my sensors:

1 Arduino Mega R3
1 TCA9548A Multiplexer
2 0.96 inch 128X64 OLED Display
1 DS3231 AT24C32 Clock module
1 Clock sensor

septillion:
First of all, quote-tags != code-tags :wink:

Next, why on earth use a mux? The whole idea of a bus, like I2C, is to have multiple devices on it. Including multiple displays. Just set them to different addresses.

Thank you! Sorry i don't know how to publish codes here =/ I knew that the addresses of these OLED's are fixed and it is 0x3C? Am i wrong? I am setting their addresses with this code:

void DisplayInit()
{
for (int i = 0; i < 2; i++)
{
tcaselect(i); // Loop through each connected displays on the I2C buses
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
}
}

Buura:
Sorry i don't know how to publish codes here =/

That's why there is is big fat tickey at the top of each board called "How to use this forum - please read".

Buura:
Am i wrong?

Most likely, the SSD1306 can have multiple addresses. And all SSD1306-breakouts I know have address selection jumpers (resistors) on the back.

septillion:
That's why there is is big fat tickey at the top of each board called "How to use this forum - please read".
Most likely, the SSD1306 can have multiple addresses. And all SSD1306-breakouts I know have address selection jumpers (resistors) on the back.

I have corrected the code, sorry =) So you say me to solder the jumber for one of the OLED's and readdress them to this new address and stop using mux?

Yep :slight_smile: Way easier approach.

septillion:
Yep :slight_smile: Way easier approach.

If you check this post:
https://forum.arduino.cc/index.php?topic=248663.0

I am not sure if i can solder this pin, not the component pins, the thin legs that connect screen to PCB. It would be better if i do it with code =/

Can you pot a link to the exact screens you have?

Because there seem to be screens without jumpers. But mine all do. And if yours don't, it might still be easier to just order one that has.

It would be better if i do it with code =/

It would but there is no way you can do it in code.
Just think about it for a moment. How are you going to change the address of one device if two devices both respond to the same commands?

From the data sheet:-

The slave address is following the start condition for recognition use. For the SSD1306, the slave address is either “b0111100” or “b0111101” by changing the SA0 to LOW or HIGH (D/C pin acts as SA0).

How are you multiplexing them at the moment?