Weird stripe on OLED I2C Display

I am modified the example code for the seed/OLED to make it work with a I2C OLED display, but there seems to be a weird white stripe on the right of the display I cannot get rid off (see picture).

The display works fine with DaisyDuino and adafruit display code, I tried most all of the workarounds described here without success.

The code I run looks like this:

#include <stdio.h>
#include <string.h>
#include "daisy_seed.h"
#include "dev/oled_ssd130x.h"

using namespace daisy;
using MyOledDisplay = OledDisplay<SSD130xI2c128x64Driver>;

DaisySeed     hw;
MyOledDisplay display;

int main(void)
{
    uint8_t message_idx;
    hw.Configure();
    hw.Init();

    /** Configure the Display */
    MyOledDisplay::Config disp_cfg;
    // disp_cfg.driver_config.transport_config.pin_config.dc    = hw.GetPin(9);
    // disp_cfg.driver_config.transport_config.pin_config.reset = hw.GetPin(30);
    /** And Initialize */
    display.Init(disp_cfg);

    message_idx = 0;
    char strbuff[128];
    while(1)
    {
        System::Delay(500);
        switch(message_idx)
        {
            case 0: sprintf(strbuff, "Testing. . ."); break;
            case 1: sprintf(strbuff, "Daisy. . ."); break;
            case 2: sprintf(strbuff, "1. . ."); break;
            case 3: sprintf(strbuff, "2. . ."); break;
            case 4: sprintf(strbuff, "3. . ."); break;
            default: break;
        }
        message_idx = (message_idx + 1) % 5;
        display.Fill(false);
        display.SetCursor(0, 0);
        display.WriteString(strbuff, Font_11x18, true);
        display.Update();
    }
}

My display is one of those typical 1.3" 128x64px I2C ones OLED displays you can get on Amazon, maybe the issue is that they use a SSH1106 instead of a SSD130x?

Another datapoint: if I draw a rect that should cover the screen it is cut off on the left and on the bottom.

display.DrawRect(0, 0, 127, 127, true, false);

All I see is the vertical line, and the glitch on the right, which is also present if I do not draw anything at all, just display.Update()

There may also be a problem related to ssd1306 vs ssh1106 , but coordinates in your rect example look wrong. Shouldn’t it be:

display.DrawRect(0, 0, 127, 63, true, false);

I’ll have to scrounge around to see if I have an OLED like that…

EDIT: I ran the code in the first post on an OLED I found here, it worked correctly, without any modification. I can’t tell if it’s got SSD1306 or the SSH1106, but I got it cheap on Amazon a few years ago.

1 Like

Thanks for the help. Indeed – you’re absolutely right, the height should have been 63 and not 127. I must have been ready for bed… I continued on working for some code for the sound part of my project and ignored the screen, today I ran the example again, without any changes and guess what:

I rule out hardware errors, as this was working fine for a month using DaisyDuino-code and the display is soldered in (and I know how to solder, I teach it at University).

One thing I needed to do tho if I wanted to see a full rectangle is to adjust the start coordinates:

display.DrawRect(2, 0, 127, 63, true, false);

This draws a full rectangle, everything smaller for x1 and y1 and everything bigger for x2 and y2 starts cutting off the rectangle. Now there is one question: Where have the two pixels in x direction gone?

My guess is that something between the two displays differs so the code updating drawing/updating the display has that offset in there. Knowing how a fully drawn screen looks on my device through the milled window, I would say there are two pixels missing on the right. Maybe two off by one errors in the drawing code?

2 Likes

If you Google :
ssd1306 vs sh1106

You’ll find the answer. The SH1106 controller has an internal RAM of 132x64 pixel. The SSD1306 only has 128x64 pixel.

Thanks for the hint, I went looking for a lot of code and while the SRAM seems to indeed support 132x64 pixels.

I made a change to the Update() method of SSD130xDriver that makes it work perfectly:

void Update()
    {
        uint8_t i;

        for(i = 0; i < (height / 8); i++)
        {
            transport_.SendCommand(0xB0 + i);
            transport_.SendCommand(2 & 0xf);
            transport_.SendCommand(0x10 | (2 >> 4));
            transport_.SendData(&buffer_[width * i], 132);
        }
    };

  private:
    Transport transport_;
    uint8_t   buffer_[height * 132 / 8];

Note: 132 is the hardcoded width of the buffer and the lines

transport_.SendCommand(2 & 0xf);
transport_.SendCommand(0x10 | (2 >> 4));

have been taken from another project, as this is apparently how the SSH1106 differs.

Did you make that change in libDaisy code? So, if you use SD1306, it won’t work correctly?

If YES, better would be to add a parameter to the display Init code to select which display type.

I copied seed/oled_ssd130x.hseed/oled_ssh1106.h and made my changes there for the time being.
Unfortunately I do not have a good overview on the SSH1106-based displays out there, so this only supports 128×64 and I2C now.

The question would be whether it would be better to have one oled.h that serves all (or the most common) displays or to split it up clearly by type. For my tinkering it was better to copy and leave ssd130x.h untouched, but If wanted I could do a PR that adds:

  • class SSH110xDriver with the Update() method
  • class SSH110xI2CTransport (although this is equivalent with SSD130xI2CTransport)
  • SSH110xI2c128x64Driver so it can be used with using Display = OledDisplay<SSH110xI2c128x64Driver>;

These are the changes I already made in seed/oled_ssh1106.h. If we were to go for a unified oled.h route, it would make sense to add clear documentation of which displays are supported and which are not (yet).

Alternatively I can just add a PR for my new header file after removing everything I could not test.

1 Like

This is exactly what is proposed in this PR: Add SH1106 OLED driver by nullobject · Pull Request #590 · electro-smith/libDaisy · GitHub

1 Like

Hi dreamer : )

Of course there is already a PR… Should have checked. Thanks for the hint, I will have a look at the proposed code.

1 Like

Okay, had the time to check it, and it seems to work as expected and is already merged in libDaisy.

1 Like