SSD1306 Adjust Brightness?


New Member
Hi everyone,

Thanks to this forum I have had success working with the SSD1306 OLED driver. The issue I now face is with dimming the display.
I've looked over threads such as Thread, Thread and Thread but none specify dimming the display.

I have attempted to change the values for the init contrast (
hi2cout 0x81,(0x8F)
but with no luck.

I'll continue to modify the init parameters, (maybe the charge pump?) but I'm a little lost and would be very thankful for any help.

Cheers; Zander


New Member
I use a picaxe 20X2 and had a similar problem with another an LCD.
As I read the user manual I had the use the following method

hi2csetup i2cmaster, slaveaddress, mode, addresslen (opening a communication line?)
hi2cout location, (variable)

In my case this it would look like :

hi2csetup i2cmaster, $50, i2cslow, i2cbyte
($50 being the address of my LCD)
hi2cout $52, ($40)
($52 is the brightness register and $40 the brightness level)

However, this didn't work for me. Above all, since there are different circuits om my I2C-bus, I always had to use I2Csetup followed by hi2cout if I wanted to communicate between my MCP and LCD alternatively

Then I discovered that with the X2 serie it was less of a hassle to communicate with different devices

First I setup the communication line like usual

Hi2csetup i2cmaster, slaveaddres, i2cslow, i2cbyte
slave address was that of a MCP23017

To communicate with my LCD I didn't have to use Hi2csetup again but use

hi2cout [newslave], location, (variable)

In my case

hi2cout $50, $52, ($40)
$50; LCD address
$52; register address
$40; brightness level

Since then I had no troubles with the I2C-bus and I could communicate with all the register in my LCD and MCP23017

So try this commands if you use a X2-serie

Hi2csetup i2cmaster, $78, i2cslow, i2cbyte
$78 being the address of your OLED (don't shoot me if I am wrong)
Hi2cout $78, $81, ($8F)
$81 contrastregister and $8F as contrastvalue.
Last edited:


Technical Support
Staff member
My SSD1306 datasheet states -

"The SSD1306 embeds with contrast control, display RAM and oscillator, which reduces the number of external components and power consumption. It has 256-step brightness control".

Plus -

"256 step contrast brightness current control"

That would suggest contrast and brightness are synonymous, which makes sense, seeing as black (off) is fixed..

Contrast is set by sending $81 with 0 to 255. It appears the default at reset is 127 ($7F) -
HI2cOut $81, (   0 ) ; Off
HI2cOut $81, (  63 ) ; Dim
HI2cOut $81, ( 127 ) ; Normal
HI2cOut $81, ( 190 ) ; Brighter
HI2cOut $81, ( 255 ) ; Brightest
I would start with that and seeing if that works well enough, then consider other options.

Your previous effort may not have worked well simply because 0x8F isn't that far from the default, and you were increasing brightness rather than decreasing it.


New Member
I might be overlooking something, but when I looked at the threads that ZanderPIC had mentioned, I saw that they setup I2C with I2Cword instead of I2Cbyte. I always use bytes to communicate with an LCD. Even when I use the "conventional" way with 4 datalines and a few control lines.
Since the registers of this OLED are written with bytes, it seems to me a bit strange to write words to those registers.


Technical Support
Staff member
when I looked at the threads that ZanderPIC had mentioned, I saw that they setup I2C with I2Cword instead of I2Cbyte. ... Since the registers of this OLED are written with bytes, it seems to me a bit strange to write words to those registers.
It is strange. An I2CBYTE is what I would have expected.

The I2CWORD only affects the address size, not the data size, so it is still writing bytes to the registers, but the commands would be affected when they are being sent as if an address, sent as two bytes rather than one.

I would have guessed that using word addresses is sending a $00 command before the intended command which is being ignored, treated as a 'no operation', which allows things to work.

But looking at the SSD1306 datasheet, its I2C protocol is more complicated, because both data and commands can be sent. I cannot see how it would work with I2CWORD but from those threads I would guess it did - or it didn't, but that just happened not to matter !

The first linked thread does indicate I2CWORD, the second starts with I2CWORD but then reinitialises with I2CBYTE, the third does use I2CBYTE.

When the code uses "HI2cOut ( command, data )" rather than "HI2cOut command, ( data )" it shouldn't matter which it is.

Added : Just to add to the confusion - It appears the Grove 128x64 OLED which Blockly supports is an SSD1306. That uses I2CBYTE and "HI2cOut $80, ( command )" or "HI2cOut $40, ( data... )", which is what I would have expected from reading the datasheet.

That is also the same protocol and I2C format used with the 128x128 and 96x96 OLED which use similar chips. And we know all three worked because we tested them.

All those linked threads are quite old, and from a time before we had used the SSD1306 ourselves, so I am not sure if they are correct or not.

I would say that our Blockly code should be the 'reference design', so it would be interesting to see Zander's code if it is different from that, as it appears to be.
Last edited: