hi, about to dive in to OSC to oled this week and was curious to know if an i2c multiplexer like this is ok to use?
was hoping to use four 0.96 oled's to display values from SC, thanks
https://coolcomponents.co.uk/products/tca9548a-i2c-multiplexer
i2c multiplexer for oled's
that should work, will require some changes to the code.
giuliomoro just got this on the breadboard and looking over the code, anything i should look out for?
- Edited
It looks like you may need an extra class to select the currently active address. By the looks of it, this should work. Add this at the top of main.cpp
:
#include <I2c.h>
#include <stdexcept>
class TCA9548A : I2c
{
public:
TCA9548A(int bus, int address)
{
int ret = initI2C_RW(bus, address, -1);
if(ret || select(-1)) // disable all channels and at the same time verify address is valid
throw std::runtime_error("Unable to open TCA9548A. Ensure the multiplexer is connected and the bus and address are correct.");
}
int readI2C() override {return 0;};
int select(int channel)
{
i2c_char_t byte = channel < 0 || channel >= 8 ? 0 : 1 << channel;
return (sizeof(byte) != write(i2C_file, &byte, sizeof(byte)));
}
};
TCA9548A tca(1, 0x70);
Then to select the current screen call tca.select(x);
before writing to the display, where x
is the multiplexer channel you want to enable (use -1
to disable all channels). I think you may have to duplicate code the initialisation code for each screen you are using.
giuliomoro just crosschecking this is going at the top of the new osc2oled main cpp?
if so, i keep getting these run time fails
Yes . What i2c bus is the multiplexer connected to?
giuliomoro 1 i assume. same as the trills. i2c bus 2 is audio codec?
can you run i2cdetect -y -r 1
in the console at the bottom of the IDE and report what you get in response?
- Edited
@giuliomoro this is weird but its reports nothing. it doesn't recognise any address.
it must be my end
giuliomoro yeah im so perplexed, my solder is p clean, bad board?
do you mean it doesn't display nothing at all or it displays this?
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
ah that's good, it's there at 70
(0x70). I looked at the code again and realised I made a mistake. I amended it in the previous post. Try once more with the amended code!
Can you try to rebuild it? Make a small change on main.cpp (e.g.: add a space somewhere) and rebuild
giuliomoro still getting the same output
can you show your main.cpp
?
#include <I2c.h>
#include <stdexcept>
class TCA9548A : I2c
{
public:
TCA9548A(int bus, int address)
{
int ret = initI2C_RW(bus, address, -1);
if(ret || select(-1)) // disable all channels and at the same time verify address is valid
throw std::runtime_error("Unable to open TCA9548A. Ensure the multiplexer is connected and the bus and address are correct.");
}
int readI2C() override {return 0;};
int select(int channel)
{
i2c_char_t byte = channel < 0 || channel >= 8 ? 0 : 1 << channel;
return (sizeof(byte) != write(i2C_file, &byte, sizeof(byte)));
}
};
TCA9548A tca(1, 0x70);
#include <signal.h>
#include <libraries/OscReceiver/OscReceiver.h>
#include <unistd.h>
#include "u8g2/cppsrc/U8g2lib.h"
const unsigned int SSD1306_addr = 0x3c;
class U8G2_SSD1306_128X64_NONAME_F_HW_I2C_LINUX : public U8G2 {
public: U8G2_SSD1306_128X64_NONAME_F_HW_I2C_LINUX(const u8g2_cb_t *rotation) : U8G2() {
u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, rotation, u8x8_byte_linux_i2c, u8x8_linux_i2c_delay);
}
};
U8G2_SSD1306_128X64_NONAME_F_HW_I2C_LINUX u8g2(U8G2_R0);
OscReceiver oscReceiver;
int localPort = 7562; //port for incoming OSC messages
int gStop = 0;
// Handle Ctrl-C by requesting that the audio rendering stop
void interrupt_handler(int var)
{
gStop = true;
}
int parseMessage(oscpkt::Message msg, void* arg)
{
u8g2.clearBuffer();
int displayWidth = u8g2.getDisplayWidth();
int displayHeight = u8g2.getDisplayHeight();
std::string trString;
std::string trString1;
std::string trString2;
std::string trString3;
std::string trString4;
float param1Value;
float param2Value;
float param3Value;
float param4Value;
std::string text1;
std::string text2;
std::string text3;
if (msg.match("/osc-test").isOkNoMoreArgs())
{
printf("received /osc-test\n");
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setFontRefHeightText();
u8g2.drawStr(0, displayHeight * 0.5, "OSC TEST SUCCESS!");
u8g2.sendBuffer();
} else if (msg.match("/number").popStr(trString1).popStr(trString2).popStr(trString3).popStr(trString4).isOkNoMoreArgs())
{
const char *ctrStr1 = trString1.c_str();
const char *ctrStr2 = trString2.c_str();
const char *ctrStr3 = trString3.c_str();
const char *ctrStr4 = trString4.c_str();
printf("received /number %s %s %s %s\n", ctrStr1,ctrStr2,ctrStr3,ctrStr4);
u8g2.drawUTF8(0, 0, ctrStr1);
u8g2.drawUTF8(2, 0, ctrStr2);
u8g2.drawUTF8(4, 0, ctrStr3);
u8g2.drawUTF8(6, 23, ctrStr4);
u8g2.sendBuffer();
} else if (msg.match("/ratio").popStr(trString).isOkNoMoreArgs())
{
const char *ctrStr = trString.c_str();
printf("received /ratio %s\n", ctrStr);
u8g2.drawUTF8(0, 0, ctrStr);
u8g2.sendBuffer();
} else if (msg.match("/display-text").popStr(text1).popStr(text2).popStr(text3).isOkNoMoreArgs())
{
const char *ctrStr1 = text1.c_str();
const char *ctrStr2 = text2.c_str();
const char *ctrStr3 = text3.c_str();
printf("received /display-text string %s %s %s\n", ctrStr1, ctrStr2, ctrStr3);
u8g2.setFont(u8g2_font_4x6_tf);
u8g2.setFontRefHeightText();
u8g2.drawUTF8(displayWidth * 0.5, displayHeight * 0.25, ctrStr1);
u8g2.drawUTF8(displayWidth * 0.5, displayHeight * 0.5, ctrStr2);
u8g2.drawUTF8(displayWidth * 0.5, displayHeight * 0.75, ctrStr3);
u8g2.sendBuffer();
} else if (msg.match("/parameters").popFloat(param1Value).popFloat(param2Value).popFloat(param3Value).popFloat(param4Value).isOkNoMoreArgs())
{
printf("received /parameters float %f float %f float %f float %f\n", param1Value, param2Value, param3Value, param4Value);
u8g2.setFont(u8g2_font_4x6_tf);
u8g2.setFontRefHeightText();
u8g2.drawStr(0, 0, "PARAMETER 1:");
u8g2.drawBox(0, 10, u8g2.getDisplayWidth() * param1Value, 10);
u8g2.drawStr(0, 22, "PARAMETER 2:");
u8g2.drawBox(0, 32, u8g2.getDisplayWidth() * param2Value, 10);
u8g2.drawStr(0, 44, "PARAMETER 3:");
u8g2.drawBox(0, 54, u8g2.getDisplayWidth() * param3Value, 10);
u8g2.drawStr(0, 66, "PARAMETER 4:");
u8g2.drawBox(0, 76, u8g2.getDisplayWidth() * param4Value, 10);
u8g2.sendBuffer();
} else if (msg.match("/lfos").popFloat(param1Value).popFloat(param2Value).popFloat(param3Value).isOkNoMoreArgs())
{
printf("received /lfos float %f float %f float %f\n", param1Value, param2Value, param3Value);
u8g2.drawEllipse(displayWidth * 0.2, displayHeight * 0.5, 10, displayHeight * 0.5 * param1Value);
u8g2.drawEllipse(displayWidth * 0.5, displayHeight * 0.5, 10, displayHeight * 0.5 * param2Value);
u8g2.drawEllipse(displayWidth * 0.8, displayHeight * 0.5, 10, displayHeight * 0.5 * param3Value);
u8g2.drawHLine(0, displayHeight * 0.5, displayWidth);
u8g2.sendBuffer();
} else if (msg.match("/waveform"))
{
oscpkt::Message::ArgReader args(msg);
if(args)
{
const unsigned int nValues = args.nbArgRemaining();
float values[nValues];
for(unsigned int n = 0; n < nValues; ++n)
{
if(args.isFloat())
{
args.popFloat(values[n]);
} else if(args.isInt32()) {
int i;
args.popInt32(i);
values[n] = i;
} else {
fprintf(stderr, "Wrong type at argument %d\n", n);
return -1;
}
}
// now tenValues contains the 10 values.
// prepare a bitmap:
printf("received /waveform floats:");
for(unsigned int n = 0; n < 10; ++n)
printf("%f ", values[n]);
printf("\n");
for(unsigned int x = 0; x < displayWidth; ++x)
{
// we interpret each value as the vertical displacement and
// we want to draw a series of horizontal lines at the specified points
unsigned int valIdx = x * float(nValues) / displayWidth;
unsigned int y = values[valIdx] * displayHeight;
u8g2.drawPixel(x, y);
}
}
} else
{
printf("unhandled message to: %s \n", msg.addressPattern().c_str());
}
u8g2.drawStr(0, 56," ");
u8g2.sendBuffer();
return 0;
}
int main(int main_argc, char *main_argv[])
{
// Set up interrupt handler to catch Control-C and SIGTERM
signal(SIGINT, interrupt_handler);
signal(SIGTERM, interrupt_handler);
u8g2.setI2CAddress(SSD1306_addr);
u8g2.initDisplay();
u8g2.setPowerSave(0);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_4x6_tf);
u8g2.setFontRefHeightText();
u8g2.setFontPosTop();
u8g2.drawStr(0, 0, " ");
u8g2.drawStr(0, 7, " ");
u8g2.drawStr(0, 14," ");
u8g2.drawStr(0, 21," ");
u8g2.drawStr(0, 28," ");
u8g2.drawStr(0, 35," ");
u8g2.drawStr(0, 42," ");
u8g2.drawStr(0, 56,"");
u8g2.sendBuffer();
// OSC
oscReceiver.setup(localPort, parseMessage);
while(!gStop)
{
usleep(100000);
}
return false;
}
can you try to build and run another project? Also what is the output you get if you run df -h
in the console?
giuliomoro i think something might be up, i just tried to run that i2c encoder example that is in progress and it wont run.
here is the console output