One-inch OLED displays with an SSD1306 controller talk to microcontrollers over I2C. Several libraries are available that make interfacing to these modules straightforward. You need to provide a few pieces of information: the screen size and the I2C address. However, knowing that address is something that plagues 1" OLED modules--especially those bought from grey market suppliers.
Their Silk Screen is WRONG! These claim their I2C address is 0x78, when it is actually 0x3C. Or is it?
Side note. For information on decoding serial busses (and to see where I got the idea for this post), check out Workbench Wednesdays 34: Triggering And Decoding Serial Protocols On An Oscilloscope. I show how to decode UART and I2C with an oscilloscope.
I2C Addressing
I2C is a two-wire bus, sometimes called Two Wire Interface (TWI) to get around trademarks, that has a clock and data line. All devices on the bus share these two signals. For multiple devices to work, each needs a unique address. (Unique to the bus.)
7-bit vs. 8-bit Address
You might hear that I2C supports 7-bit or 8-bit addressing. The original specification for I2C was only 7-bit. An "8th bit" determines if the transaction is a read or write. So some manufacturers say their I2C device is 8-bit. When they are actually providing both the "read" and "write" addresses. (There are also 10-bit addressing methods, but I am ignoring those for this post.)
So how does this difference affect the 1" OLED? Well, take a look at the back of the one I have.
OLED Silk Screen Is Wrong?
On the back, there are two I2C addresses shown. 0x78 and 0x7A. Like many breakout modules, there are solder jumpers to change the device's address. This module has 0x78 selected. However, if I put that into some Arduino code, nothing happens.
#include <Wire.h> #include "SSD1306Ascii.h" #include "SSD1306AsciiWire.h" #define I2C_ADDRESS 0x78 SSD1306AsciiWire oled; //------------------------------------------------------------------------------ void setup() { Wire.begin(); Wire.setClock(400000L); oled.begin(&Adafruit128x64, 0x3c); oled.setFont(Verdana12_bold); oled.println("element14"); oled.println("Workbench"); oled.println("Wednesdays"); oled.println("@baldengineer"); delay(100); }
You might notice, most example code for these modules use 0x3C or 0x3D as the default address. And if you use one of those, the screens work great.
What gives?
Let's look at the I2C addresses, using an image from i2c-bus.org.
Notice the data pattern's sequence. There is a start condition followed by the 7-bit address and one bit for a read or write.
Why is it wrong?!
Let's combine everything we know now.
- I2C addresses are only 7-bit (except for a special 10-bit case)
- One bit in the serial sequence determines if there is a read or write
- 0x78 does not work
- 0x3C does work!
We need to compare the two addresses in binary:
0x78 = 0111 1000 // does not work 0x3C = 0011 1100 // does work
Broken out as nibbles may not make it obvious. So here are the 8-bits as one word.
0x78 = 01111000 // does not work 0x3C = 00111100 // does work
Can you see it yet? If 0x3C gets shifted one bit to the left, it would be the same address as 0x78! At first, when I looked at these addresses, I thought maybe the PCB designer was confused by the SSD1306's addresses. Since 0 = write and 1 = read. Maybe they just added a 0 to the 7-bit address from the datasheet.
One datasheet I found on the SSD1306 seems to confirm this idea. Here it is showing the 7-bit address with the first nibble as "0111" and the second nibble as "10XX." Where XX is the control signals Data/!Command and Read/!Write. So there you are, "0111 1000" = "0x78."
Whoops.
So in a way, both 0x78 and 0x3C are the correct addresses for these OLED devices. It depends on whether you include the SSD's internal Read/!Write flag as part of the I2C address. (I don't.)
In fairness, there could be some microcontroller registers that operate with the "8-bit" address scheme, so the 0x78 address may work correctly. However, I prefer to think in terms of the actual 7-bit address and let the software handle the read or write.
Related Workbench Wednesdays
The idea for this post came from an episode of Workbench Wednesdays. You can get the show notes from here: Workbench Wednesdays 34: Triggering And Decoding Serial Protocols On An Oscilloscope.
Top Comments