Hi there, I am working on a project to display color reading values to an OLED display. I am using an Elegoo uno r3. I have this connected to a TCA9548a multiplexer. Connected to the multiplexer are 2 color readers (TCS3472) and a 0.96inch OLED display.
The display works when I connect it via i2c to just the arduino A4 and A5, and the color readers work as well, both by themselves and at the same time in the multiplexer.
The trouble arises when I have now connected the OLED to the multiplexer as well, and I can't seem to get anything to display on it.
I'll include the whole code of my project, the majority of it is controls to navigate between menu screens on the OLED, and those all work when I tested just the display. But now with the multiplexer no dice. So I'm thinking problems arise around line 134 when I try to begin the display but I'm unsure.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_TCS34725.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define TCAADDR 0x70
#define SAMPLE_COUNT 50 // Number of samples to take over 5 seconds
float glucoseGValues[SAMPLE_COUNT];
float uricAcidGValues[SAMPLE_COUNT];
float averageGlucoseG = 0;
float averageUricAcidG = 0;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_TCS34725 cs1 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Adafruit_TCS34725 cs2 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
// Button pins
const int btnLeft = 2;
const int btnRight = 4;
const int btnSelect = 8;
const int btnReturn = 10;
enum MenuState {
WELCOME,
MAIN_MENU,
TIME_CHECK,
LOADING,
GLUCOSE,
URIC_ACID
};
MenuState currentState = WELCOME;
int selectedOption = 0;
bool timeCheckAnswer = false;
// glucose bitmap
const unsigned char PROGMEM logo_glucose[] = {
0x01, 0x80, 0x06, 0x60, 0x18, 0x18, 0x60, 0x06, 0x98, 0x39, 0x86, 0xc1, 0x81, 0x01, 0x91, 0x11,
0xa1, 0x21, 0x81, 0x45, 0x85, 0x09, 0x89, 0x01, 0x61, 0x06, 0x19, 0x18, 0x05, 0x60, 0x03, 0x80
};
//Uric acid bitmap
const unsigned char PROGMEM logo_uric_acid[] = {
0x03, 0xc0, 0x0c, 0x20, 0x10, 0x10, 0x13, 0x08, 0x26, 0x08, 0x24, 0x11, 0x40, 0x22, 0x40, 0x3c,
0x40, 0x3c, 0x40, 0x22, 0x20, 0x11, 0x20, 0x08, 0x10, 0x08, 0x10, 0x10, 0x0c, 0x20, 0x03, 0xc0
};
// Main logo array here
const unsigned char PROGMEM main_logo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00,
0x18, 0x0c, 0x7e, 0xff, 0xdf, 0x86, 0x1f, 0x1f, 0x10, 0x10, 0xf8, 0xf8, 0x01, 0x09, 0x00, 0xe0,
0x1c, 0x0c, 0x60, 0x0c, 0x19, 0x86, 0x30, 0x18, 0x18, 0x11, 0x80, 0xc0, 0x00, 0x82, 0x03, 0xb0,
0x1c, 0x1c, 0x60, 0x0c, 0x18, 0xc6, 0x20, 0x18, 0x1c, 0x11, 0x00, 0xc0, 0x00, 0x7c, 0x0e, 0x10,
0x1e, 0x1c, 0x60, 0x0c, 0x18, 0xc6, 0x20, 0x18, 0x14, 0x11, 0x00, 0xc0, 0x00, 0x00, 0x38, 0xd8,
0x1e, 0x3c, 0x60, 0x0c, 0x19, 0x86, 0x30, 0x18, 0x16, 0x11, 0x80, 0xc0, 0x00, 0x00, 0xe1, 0x28,
0x1b, 0x2c, 0x60, 0x0c, 0x1f, 0x06, 0x18, 0x18, 0x13, 0x10, 0xe0, 0xc0, 0x00, 0x03, 0x81, 0x2c,
0x1b, 0x2c, 0x7e, 0x0c, 0x1f, 0x06, 0x0e, 0x1f, 0x11, 0x10, 0x30, 0xf8, 0x00, 0x0e, 0x00, 0xc4,
0x19, 0xec, 0x60, 0x0c, 0x19, 0x86, 0x03, 0x18, 0x11, 0x90, 0x18, 0xc0, 0x00, 0x38, 0x00, 0x06,
0x19, 0xcc, 0x60, 0x0c, 0x18, 0xc6, 0x01, 0x18, 0x10, 0xd0, 0x08, 0xc0, 0x00, 0xe3, 0x80, 0x0e,
0x18, 0x8c, 0x60, 0x0c, 0x18, 0xc6, 0x01, 0x18, 0x10, 0x50, 0x08, 0xc0, 0x03, 0x84, 0x40, 0x38,
0x18, 0x0c, 0x60, 0x0c, 0x18, 0x46, 0x01, 0x18, 0x10, 0x70, 0x08, 0xc0, 0x0e, 0x04, 0x40, 0xe0,
0x18, 0x0c, 0x60, 0x0c, 0x18, 0x66, 0x03, 0x18, 0x10, 0x30, 0x18, 0xc0, 0x38, 0x04, 0x43, 0x80,
0x18, 0x0c, 0x7e, 0x0c, 0x18, 0x66, 0x3e, 0x1f, 0x10, 0x11, 0xf0, 0xf8, 0xe0, 0x03, 0x8e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x38, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x03, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// 'check', 20x20px
const unsigned char PROGMEM check_icon[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x40, 0x00, 0x00, 0xa0, 0x00, 0x01, 0x10, 0x00, 0x02, 0x20, 0x00, 0x04, 0x40, 0x00, 0x08,
0x80, 0x10, 0x11, 0x00, 0x28, 0x22, 0x00, 0x44, 0x44, 0x00, 0x22, 0x88, 0x00, 0x11, 0x10, 0x00,
0x08, 0x20, 0x00, 0x04, 0x40, 0x00, 0x02, 0x80, 0x00, 0x01, 0x00, 0x00
};
// 'x', 20x20px
const unsigned char PROGMEM x_icon[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x14, 0x02, 0x80, 0x22, 0x04, 0x40, 0x11,
0x08, 0x80, 0x08, 0x91, 0x00, 0x04, 0x62, 0x00, 0x02, 0x04, 0x00, 0x01, 0x08, 0x00, 0x01, 0x08,
0x00, 0x02, 0x04, 0x00, 0x04, 0x62, 0x00, 0x08, 0x91, 0x00, 0x11, 0x08, 0x80, 0x22, 0x04, 0x40,
0x14, 0x02, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void setup() {
Wire.begin();
pinMode(btnLeft, INPUT_PULLUP);
pinMode(btnRight, INPUT_PULLUP);
pinMode(btnSelect, INPUT_PULLUP);
pinMode(btnReturn, INPUT_PULLUP);
delay(100); // Add a short delay
tcaselect(0);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
for (;;)
;
}
display.clearDisplay();
display.setTextColor(WHITE);
drawWelcomeScreen();
tcaselect(1);
if (!cs1.begin()) {
// Handle error
}
tcaselect(2);
if (!cs2.begin()) {
// Handle error
}
}
void loop() {
handleButtons();
if (currentState == LOADING) {
static unsigned long startTime = millis();
if (millis() - startTime < 5000) {
drawLoadingScreen();
} else {
currentState = selectedOption == 0 ? GLUCOSE : URIC_ACID;
drawSubmenu();
}
}
delay(100);
}
void handleButtons() {
if (digitalRead(btnLeft) == LOW || digitalRead(btnRight) == LOW || digitalRead(btnSelect) == LOW) {
if (currentState == WELCOME) {
currentState = MAIN_MENU;
drawMainMenu();
} else if (currentState == MAIN_MENU) {
if (digitalRead(btnLeft) == LOW) selectedOption = 0;
if (digitalRead(btnRight) == LOW) selectedOption = 1;
if (digitalRead(btnSelect) == LOW) {
currentState = TIME_CHECK;
drawTimeCheck();
} else {
drawMainMenu();
}
} else if (currentState == TIME_CHECK) {
if (digitalRead(btnLeft) == LOW) timeCheckAnswer = true;
if (digitalRead(btnRight) == LOW) timeCheckAnswer = false;
if (digitalRead(btnSelect) == LOW) {
if (timeCheckAnswer) {
currentState = LOADING;
} else {
currentState = MAIN_MENU;
drawMainMenu();
}
}
drawTimeCheck();
}
}
if (digitalRead(btnReturn) == LOW) {
if (currentState == GLUCOSE || currentState == URIC_ACID || currentState == TIME_CHECK) {
currentState = MAIN_MENU;
drawMainMenu();
} else if (currentState == MAIN_MENU) {
currentState = WELCOME;
drawWelcomeScreen();
}
}
}
void drawWelcomeScreen() {
tcaselect(0);
display.clearDisplay();
// Draw your 128x48 logo
display.drawBitmap(0, 0, main_logo, 128, 48, WHITE);
display.setTextSize(1);
// Center "Press any button to begin" text
const char* text1 = "Press any button";
const char* text2 = "to begin";
int16_t x1, y1, x2, y2;
uint16_t w1, h1, w2, h2;
display.getTextBounds(text1, 0, 0, &x1, &y1, &w1, &h1);
display.getTextBounds(text2, 0, 0, &x2, &y2, &w2, &h2);
display.setCursor((SCREEN_WIDTH - w1) / 2, 48);
display.println(text1);
display.setCursor((SCREEN_WIDTH - w2) / 2, 56);
display.println(text2);
display.display();
}
void drawMainMenu() {
tcaselect(0);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(24, 0);
display.println("Select Analyte");
// Glucose option
display.drawBitmap(20, 24, logo_glucose, 16, 16, WHITE);
display.setTextSize(1);
display.setCursor(8, 42);
display.println("Glucose");
// Uric Acid option
display.drawBitmap(88, 24, logo_uric_acid, 16, 16, WHITE);
display.setCursor(70, 42);
display.println("Uric Acid");
// Selection box
if (selectedOption == 0) {
display.drawRect(0, 18, 56, 40, WHITE);
} else {
display.drawRect(64, 18, 64, 40, WHITE);
}
display.display();
}
void drawTimeCheck() {
tcaselect(0);
display.clearDisplay();
// Draw title
display.setTextSize(1);
display.setCursor(20, 0);
display.println("Has sample sat");
display.setCursor(28, 8);
display.println("for 5 mins?");
// Draw Yes option
display.drawBitmap(24, 24, check_icon, 20, 20, WHITE);
display.setCursor(24, 46);
display.println("Yes");
// Draw No option
display.drawBitmap(88, 26, x_icon, 20, 20, WHITE);
display.setCursor(94, 46);
display.println("No");
// Draw selection box
if (timeCheckAnswer) {
display.drawRect(16, 20, 36, 36, WHITE);
} else {
display.drawRect(80, 20, 36, 36, WHITE);
}
display.display();
}
void drawSubmenu() {
tcaselect(0);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
if (currentState == GLUCOSE) {
display.println("Glucose Level:");
display.setTextSize(2);
display.setCursor(32, 32);
display.print(averageGlucoseG, 1);
} else if (currentState == URIC_ACID) {
display.println("Uric Acid Level:");
display.setTextSize(2);
display.setCursor(32, 32);
display.print(averageUricAcidG, 1);
}
display.display();
}
void drawLoadingScreen() {
unsigned long startTime = millis();
int sampleIndex = 0;
while (millis() - startTime < 5000) {
tcaselect(0);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(4, 24);
display.println("Reading...");
display.display();
// Read from glucose sensor
tcaselect(1);
float r, g, b;
cs1.getRGB(&r, &g, &b);
glucoseGValues[sampleIndex] = g;
// Read from uric acid sensor
tcaselect(2);
cs2.getRGB(&r, &g, &b);
uricAcidGValues[sampleIndex] = g;
sampleIndex++;
if (sampleIndex >= SAMPLE_COUNT) sampleIndex = 0;
delay(100); // Adjust this delay to get about 50 samples over 5 seconds
}
// Calculate averages
averageGlucoseG = 0;
averageUricAcidG = 0;
for (int i = 0; i < SAMPLE_COUNT; i++) {
averageGlucoseG += glucoseGValues[i];
averageUricAcidG += uricAcidGValues[i];
}
averageGlucoseG /= SAMPLE_COUNT;
averageUricAcidG /= SAMPLE_COUNT;
}
I would appreciate any help if anyone's encountered a similar issue or knows of a solution. I tried looking at similar posts but their code was not helpful unfortunately.
And I've uploaded a schematic of what is set up currently.