1
\$\begingroup\$

I bought one of these cheap 0.91" OLED displays and hooked it up according to a datasheet that was sent to me by the seller. I tried several drivers for it after I thought there are compatibility problems, but all of them give the same problem. Only the top of the display shows any characters, the rest seems like random pixels and it flickers while lines are running up and down on it. VBAT + VDD are connected to ~3.3V.

Perhaps someone can spot the issue just by looking at the display picture?

Wiring, the 1uF caps are ceramics, the 4.7uF electro Here is the initiation sequence:

void oled_init() {
    L(PORTE, SS1306_OLED_RST);
    _delay_ms(10);
    H(PORTE, SS1306_OLED_RST);
    _delay_ms(10);

    oled_write(0, 0xAE); // display off
    oled_write(0, 0xD5); // clock
    oled_write(0, 0x81); // upper nibble is rate, lower nibble is divisor
    oled_write(0, 0xA8); // mux ratio
    oled_write(0, 0x3F); // rtfm
    oled_write(0, 0xD3); // display offset
    oled_write(0, 0x00); // rtfm
    oled_write(0, 0x00);
    oled_write(0, 0x8D); // charge pump
    oled_write(0, 0x14); // enable
    oled_write(0, 0x20); // memory addr mode
    oled_write(0, 0x00); // horizontal
    oled_write(0, 0xA1); // segment remap
    oled_write(0, 0xA5); // display on
    oled_write(0, 0xC8); // com scan direction
    oled_write(0, 0xDA); // com hardware cfg
    oled_write(0, 0x12); // alt com cfg
    oled_write(0, 0x81); // contrast aka current
    oled_write(0, 0x7F); // 128 is midpoint
    oled_write(0, 0xD9); // precharge
    oled_write(0, 0x11); // rtfm
    oled_write(0, 0xDB); // vcomh deselect level
    oled_write(0, 0x20); // rtfm
    oled_write(0, 0xA6); // non-inverted
    oled_write(0, 0xA4); // display scan on
    oled_write(0, 0xAF); // drivers on
}

And what the LCD shows after I sent some characters to it. enter image description here

\$\endgroup\$
  • 2
    \$\begingroup\$ Looks like some kind of RAM buffer overflow in your code. \$\endgroup\$ – jippie Apr 25 '14 at 5:34
  • \$\begingroup\$ What is the host platform? \$\endgroup\$ – Zuofu Apr 25 '14 at 5:54
  • \$\begingroup\$ @Zuofu - ATmega128A \$\endgroup\$ – user34920 Apr 25 '14 at 6:00
  • 1
    \$\begingroup\$ Hmm, the ATmega128A only has 4KBytes of memory, exactly the size you need for a frame buffer assuming monochrome 8 bpp (128 * 32). However, that is assuming there is absolutely no overhead - which is never true if you are using a compiler (stack space, etc..) How are you drawing the characters? \$\endgroup\$ – Zuofu Apr 25 '14 at 7:02
  • \$\begingroup\$ Please also describe what you thought you were writing to the screen (some message, or ???), and also show a much better resolution picture (of just the display) for comparison. \$\endgroup\$ – gwideman Apr 25 '14 at 10:59
3
\$\begingroup\$

Taking a guess in lieu of more information (see my comments above). It does look suspiciously like what is drawn is 1/8th of the screen. The controller says that it operates at 8 bits per pixel (256 monochrome levels). Are you drawing into the screen as if it was a 1 bit per pixel screen instead of 8? As I noted in the comment above, you will not be able to hold a frame buffer at 8 bpp and still have any RAM left to do anything else.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ It seems that the driver for the display defined a frame buffer which is just as big as the RAM I have on the device... I'm moving to an ATmega328. Thanks! \$\endgroup\$ – user34920 Apr 25 '14 at 19:27
  • \$\begingroup\$ Cool, but the ATmega328 has even less SRAM (2KB). The issue is not flash memory (or program memory) it is SRAM. There are some MegaAVR controllers which have 8KB, which should be enough for this application: atmel.com/Images/8491E_MegaAVR_E_US_110112_LoRes.pdf \$\endgroup\$ – Zuofu Apr 25 '14 at 21:20
2
\$\begingroup\$

Responding in case anyone actually needs the issue solved,

If you aren't familiar with the SSD1306, it would be a good idea to read the documentation.

Each byte is vertical, with the LSB at the top and the MSB at the bottom. The screen is separated into several pages, each of which stores 1 byte by N columns. For a 128 by 32 pixel screen, that's 4 pages tall (8*4=32) and 128 columns wide. This can all be remapped, but if you follow the guides from the manufacturer, the default setup is the way I am describing.

When you write a data byte, by any method, it will increment the column pointer by one. So, if you set the column and page to zero, you are at the top left of the screen. If you write 10 bytes all 0xff, you would have a 10x8 pixel square at the top left of the screen. If you keep going, and write 128, the entire top page would be filled.

However, if you set the address mode incorrectly, it will not auto-increment the page. So, you might have a full buffer (which is only 512 bytes), but you are only writing the first 128 of those bytes, after which i don't know what will happen. It looks like it goes off the page, rather than re-writing over it.

So, tl;dr, change the address mode to horizontal so that it auto-increments the page. Alternatively, write 128 bytes at a time, then increment the page after each chunk.

For reference, the SSD1306 specs.

http://www.buydisplay.com/download/ic/SSD1306.pdf

In particular look up the documentation under the "Set Addressing Mode" command, it has lots of pictures to clarify what exactly is going on.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Well, I had the same issue and found an answer. All you have to change is

this line: oled_write(0, 0x3F); to this: oled_write(0, 0x1F);

and this line: oled_write(0, 0x12); to this line: oled_write(0, 0x02);

Your code above works for the 128x64 OLED displays. The changes in code make it working for 128x32 OLED displays.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.