Help using OLED SSD1306 I2C on SCL1 and SDA1

Status
Not open for further replies.

FRS

Active member
Anyone know how I can get an OLED SSD1306 running on the I2C buss to work with SCL1 and SDA1 rather than SCL0 and SDA0?

I've got a project, and have tested the display using SCL0 and SDA0 and works fine. The audio code has also been tested on it's own and works fine. However when I add the audio portion to this display code, no audio and no display updates. I'm assuming there are conflicts for the audio card and display addresses as both are connected to SCL0 and SDA0.

Ideally, I would like them on their own pins anyway.

I'm using the adafruit_GFX.h and adafruit_SSD1306.h libraries for the OLED display.

Any advice would be appreciated, as I need to have this code up and running in a couple days for a show.
 
I assume you are using a Teensy LC? What audio library?

So assuming you wish to move the display to the SCL1 and SDA1, this then goes to Wire1 instead of Wire.

My guess there is no version of this library that is setup to do this for you to use Wire1 instead of Wire.

You can probably edit the library and try replacing all of the references to Wire to instead use Wire1.

There may be additional minor changes. Or I wonder if there are other libraries for this display that may be using something like i2c_t3 instead which allows you to simply configure for which I2C buss you are using.

Good luck
 
I'm using a Teensy 3.2 board, with the audio shield soldered on top of the teensy.

I saw other posts mention the i2c_t3 and was looking into that, but it only brings up more questions. It sounds like people are using i2c_t3 as a replacement for Wire.

Looking at the underlying code in the SSD1306.ccp/.h files I see they are including Wire. So I'm not really sure if I can just edit the SSD1306 files to say "Wire1" everywhere/line of code that is currently written as "Wire" now and that will do the trick?
That makes sense to me, however, I don't think Wire knows what pins SCL1 and SDA1 are for the Teensy.

So then let's assume I replace include.wire in my sketch with include.i2c_t3... won't this confuse the Teensy Audio shield? And would I then replace lines of code in the SSD1306.ccp/.h files with Wire1 instead of Wire or what? This is where I get confused.
 
As far as I know, you need to use the i2c_t3 i2c library instead of the Wire library to access the 2nd i2c adapter (& 3rd/4th in terms of the forthcoming 3.5/3.6). Also, if you wanted to change many of the i2c paramters, the i2c_t3 library has more options.

However, while i2c_t3 is a functional replacement for Wire, you have to switch all of your code, including the library functions to use i2c_t3 instead of Wire. In particular, the Audio library uses Wire to talk to the SGTL5000 and WM8731 devices. So you would need to clone the Audio library to use i2c_t3

Like the standard i2c bus on the Teensy (pins 18/19), you need to provide pull-up resistors between both the SDA and SCL pins and 3.3v. Generally for Teensy 2.2K resistors are standard for just a few devices connected with a short connection distance, but you might need to adjust the resistors depending on your environment.

<edit>
Generally things can share an i2c bus, providing they have different addresses. The audio shield uses addresses 0x0A (10) for the SGTL5000 and address 0x1A (26) for the WM8731. The typical SSD1306 seems to use 0x3C or 0xeD as an address, so it should work.

<edit2>
There are various devices that can switch i2c buses that might be useful in this case. One that is perhaps overkill is the Switchdoc labs 4 channel i2c muxer: http://store.switchdoc.com/i2c-4-ch...ove-pin-headers-for-arduino-and-raspberry-pi/. Adafruit has a somewhat simpler one: https://www.adafruit.com/products/2717.

<edit3>
Finally, most Arduino libraries are written to only use one i2c interface. So in addition, to changing your SSD1306 library to use i2c_t3, you would have to change to use the Wire1 device instead of Wire1.
 
Last edited:
However, while i2c_t3 is a functional replacement for Wire, you have to switch all of your code, including the library functions to use i2c_t3 instead of Wire. In particular, the Audio library uses Wire to talk to the SGTL5000 and WM8731 devices. So you would need to clone the Audio library to use i2c_t3

Can you expand on what this requires?
If I want to keep the audio card with SGTL5000 on the default i2C buss, would anything really change here?

In my sketch I commented out Wire.h, and included i2c_t3.h:
#include <i2c_t3.h>
//#include <Wire.h>

In the SGTL5000.ccp file I commented out Wire.h, and included i2c_t3.h:
#include <i2c_t3.h>
//#include "Wire.h"

However in SGTL5000.ccp I did not change Wire. names such as the following as I want to talk to SGTL5000 on SCL0, and SDA0:
unsigned int val;
Wire.beginTransmission(i2c_addr);
Wire.write(reg >> 8);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) return 0;
if (Wire.requestFrom((int)i2c_addr, 2) < 2) return 0;
val = Wire.read() << 8;
val |= Wire.read();
return val;

There doesn't appear to be any instances of Wire. in SGTL5000.h, so no changes made there.

In the SSD1306.h file I changed the 2x following instances of Wire. to Wire1:
#define WIRE_WRITE Wire1.write
#else
#include "WProgram.h"
#define WIRE_WRITE Wire1.send
#endif

In the SSD1306.ccp file I removed include<Wire.h>, and replaced with #include <i2c_t3.h>
and also replaced instances of Wire. with Wire1. such as the following:
// I2C Init
Wire1.begin();
#ifdef __SAM3X8E__
// Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
TWI1->TWI_CWGR = 0;
TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
#endif
}

// I2C
uint8_t control = 0x00; // Co = 0, D/C = 0
Wire1.beginTransmission(_i2caddr);
Wire1.write(control);
Wire1.write(c);
Wire1.endTransmission();

// I2C
for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) {
// send a bunch of data in one xmission
Wire1.beginTransmission(_i2caddr);
WIRE_WRITE(0x40);
for (uint8_t x=0; x<16; x++) {
WIRE_WRITE(buffer);
i++;
}
i--;
Wire1.endTransmission();
}

After these changes have been made, I still get errors compiling:
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/bin/ld.exe: Warning: size of symbol `Wire' changed from 20 in C:\Users\Georg\AppData\Local\Temp\buildcbae753b9cdf2debfa3fc88d3a8bf251.tmp\libraries\i2c_t3\i2c_t3.cpp.o to 16 in C:\Users\Georg\AppData\Local\Temp\buildcbae753b9cdf2debfa3fc88d3a8bf251.tmp\libraries\Wire\Wire.cpp.o
 
UPDATE: I commented out all of my additional "audio" code from the sketch, and the OLED display is now working with SCL1, and SDA1 with the changes I noted in my previous post.

So now I get to fish through my "audio" code and see why there are conflicts and why the code doesn't compile with it included.

Thanks for all the help, and feel free to add more if you think of something else I may need to do to keep using the SGTL5000 working when using the i2c_t3.h to replace Wire.h
 
Note: I am not sure you can use Wire and I2c_t3 in the same sketch as I believe they try to define the same objects mainly Wire.

I am surprised that Wire1 is not defined elsewhere (like in Wire library). Probably not hard to create a version, but main question might be, is how hard is it for you to convert your audio code to i2c_t3 library. May not take much more than simply changing which file is included and maybe some creator and Init call change?
 
I'm not trying to use Wire.h and i2c_t3.h at the same time.

when using i2C_t3, functions still call wire like: Wire.beginTransmission(i2c_addr);

I was successful in getting the OLED display talking on Wire1 with i2C_t3.h. However with i2c_t3.h enabled and Wire.h dissabled, I'm not able to get the audio library working. Tried replacing Wire.h with i2c_t3.h in the control_SGTL5000.ccp, and I get compile errors.
I'm wondering if it has to do with control_SGTL5000.ccp calling Wire.begin(), and if this should not be moved to the main portion of the sketch.
 
Can you expand on what this requires?
If I want to keep the audio card with SGTL5000 on the default i2C buss, would anything really change here?

I know the theory, but I've never done it with something as complex as the Audio library.

Basically you have to track down every library that is called, and replace the Wire.h with i2c_t3.h, and iterate until you have no errors. It is probably best to copy each library to a new directory and rename them (that way when you update, it will update the original libraries, and you just have to merge in any changes.

I wish we didn't have this big compatibility issue, but it is there.

It does occur to me, that if you only want i2c_t3.h for the 2nd i2c bus, that it might be simpler to make a version of i2c_t3 that only defines Wire1, Wire2, etc. and does not define Wire. That way code that uses the traditional Wire in theory should continue to work, but the new users can use the i2c_t3.h.
 
Actually before you go to much farther with this, we should maybe take another look at your setup.

You say that you have the Audio adapter soldered on top of the T3.2.

The Audio library uses I2C to talk to the SGTL5000 on the Audio adapter.

So the problem is if you use both devices, you do not get any output on your display.

It might simply be that with Audio library the I2C speed is too high for the display to handle. I have a version of the library I hacked up awhile ago to have it set the Buss speed, which might help?
I have that version up on github: https://github.com/KurtE/Adafruit_SSD1306/tree/Wire.setClock-plus

The change was to set the clock speed...
Code:
    // I2C Init
    Wire.begin();
#ifdef __SAM3X8E__
    // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
    TWI1->TWI_CWGR = 0;
    TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
#elif ARDUINO >= 157
    Wire.setClock(400000UL); // Set I2C frequency to 400kHz
#endif
This is in Adafruit_SSD1306.cpp in the begin method around line 200. I added the WireSetclock and elif...

But not sure what this will do to Audio library.


But if you go the I2C_t3 route, then might help to see what your compile errors are. Also FYI, I hacked up my copy of the library and created a new branch i2c_t3, which converted over to using I2C_t3 and changed the constructor used for I2C, to take an optional parameter, that might be Wire or Wire1 or in my current beta board testing Wire2...
 
After moving the display to SDA/SCL1, I got it to work, but could not get the code to compile without errors for the SGTL5000 to work on SDA/SCL0 while using the i2c_t3. If I put Wire back in to replace i2c_t3, then the code compiled correctly, but then display does not work.

So I moved my display back to SDA/SCL0 (sharing the same buss as the audio shield's codec), and commented various portions of code out until the display would worked. It appears that while in this configuration, the display will work and get updates, even when I update certain audio parameters, great! However the portion of my code that causes the display to stop being updated is when I tell the audio library to playFlashRaw. In other words the processor is trying to play a sound stored on the EEPROM, and send it to the codec. The EEPROM is not on the i2C buss, only the codec. BTW, this is the eeprom chip that you solder onto the audio shield board.

The reason why I wanted the OLED display on one buss and the audio codec on another is to help throughput. As both are capable of sending lots of data.

Kurt E: I did post the compile error at the bottom of message #5 in this post. Something to do with the size of symbol 'Wire' changed. I have no clue what that means... I did not edit Wire.h, simply trying to use i2c_t3.h to replace Wire.h.
And from the discussions on the forum about i2c_t3, it appears that you simply remove Wire.h and put i2c_t3.h in it's place. Then change code to use Wire1 instead of Wire if needing to use the second I2C buss.
 
Kurt E: I did post the compile error at the bottom of message #5 in this post. Something to do with the size of symbol 'Wire' changed. I have no clue what that means... I did not edit Wire.h, simply trying to use i2c_t3.h to replace Wire.h.
That most likely means that some code was compiled with Wire.h and some other code that included i2c_t3.h. That won't work - you have to replace Wire.h everywhere it's used.
The reason why I wanted the OLED display on one buss and the audio codec on another is to help throughput. As both are capable of sending lots of data.
Really? For the SGTL5000 only control data (like configuration, volume, ...) goes over I2C. Audio data is using the I2S interface.
 
Kurt, that's good to know. I'll plan to keep both devices on the same i2C buss to simplify things.

Something I notice is in the sketch setup of parameters for audio and patch chord routing, it shows "AudioPlaySerialflashRaw" as black text, and "AudioPlaySdRaw" as orange text. (most functions are orange)

From my experience, it usually only blacks out text here when the audio library does not recognize this function. That's the same result I get when I edit and rename an existing library object to do some other function, even though I add #included "newfilename" in the Audio.h file.

Does that seem strange to you?

I just did a complete fresh reinstall of Arduino 1.6.9 and Teensy Audio library and get the same result with "AudioPlaySerialflashRaw" as black text.
 
Actually the color stuff, simply says that the one function has not been added to the keywords.txt file for the audio library.

Sorry I am not much of an expert on the Audio library. But Arduino reads in the keywords file to know that some words should be highlighted.
 
Status
Not open for further replies.
Back
Top