U8glib and SSD1306 I2C

So here's my problem

I have the v2.1 adafruit 128x64 SSD1306 OLED and I can not for the life of me get it to work with the U8glib library.
I'm using an Arduino UNO R2, Arduino IDE 1.5.6 r2, and the U8glib 1.16pre-release. I am trying to use the I2c setup, I have the SDA pin set to A4 and the SCL pin set to A5. 5V and Gnd are in the right place as well. I know the wiring is right and the display is functional because I can run the display with the adafruit library. I have tried every U8glib constructor involving SSD1306 and I2C, still only darkness. I have the adafruit 128x32 I2C OLED, I hooked it up, same as the 128x64, change the constructor and it works instantly. I don't understand why I can't get this to work.

Any help would be appreciated!! :slight_smile:

Can you provide the exact constructor calls? Maybe you could also repeat the test with Arduino IDE 1.0.5.

Oliver

Have you tried another library to rule out a hardware issue? I have different code that is working on that display.

olikraus:

Here are the constructors I used. (one at a time of course :wink: )
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK); // Display which does not send ACK

I have tried both 5V and 3.3V with each one of these. Neither works. I also tried each combination in Arduino IDE 1.0.5 like you suggested. Still nothing.

0miker0:

Every time I think it might be broken I switch to the adafruit library and fire it up, works every time, so I'm assuming that there's nothing wrong with the display itself.

It seems that you made everything right and U8glib is just not working. This is bad, but possible. I do not have any of the Adafruit OLED displays here. I have tested this controller with one of the cheap far east devices, which works fine. I know that the Adafruit had some special things in their setup code regarding an external charge pump. This might be missing in the U8glib code.

Locate file u8g_dev_ssd1306_128x64.c in your libreries folder (subfolder u8glib/utility)
In lines
172 to 176 you will find this code:

/* select one init sequence here */
//#define u8g_dev_ssd1306_128x64_init_seq u8g_dev_ssd1306_128x64_univision_init_seq
//#define u8g_dev_ssd1306_128x64_init_seq u8g_dev_ssd1306_128x64_adafruit1_init_seq
//#define u8g_dev_ssd1306_128x64_init_seq u8g_dev_ssd1306_128x64_adafruit2_init_seq
#define u8g_dev_ssd1306_128x64_init_seq u8g_dev_ssd1306_128x64_adafruit3_init_seq

Maybe you can uncomment one of the other init sequences and add a comment to the last define statement (only one define statement must be uncommented).Maybe one of the other sequences works better.

I am sorry of not beeing more helpful here. I once was told, that the adafruit3 sequence works.

Oliver

olikraus:

I had high hopes for what you suggested, alas it did not work. I looked into the adafruit I2C initialization code and found the following code. The interesting thing is that when I use the adafruit library it makes me use a reset pin (usually set to D5 or something) u8glib does not. Could there be something to that?

    // 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;
#endif
  }
  // Setup reset pin direction (used by both SPI and I2C)  
  pinMode(rst, OUTPUT);
  digitalWrite(rst, HIGH);
  // VDD (3.3V) goes high at start, lets just chill for a ms
  delay(1);
  // bring reset low
  digitalWrite(rst, LOW);
  // wait 10ms
  delay(10);
  // bring out of reset
  digitalWrite(rst, HIGH);
  // turn on VCC (9V?)[/glow][/glow]

  #if defined SSD1306_128_64
    // Init sequence for 128x64 OLED module
    ssd1306_command(SSD1306_DISPLAYOFF);                    // 0xAE
    ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV);            // 0xD5
    ssd1306_command(0x80);                                  // the suggested ratio 0x80
    ssd1306_command(SSD1306_SETMULTIPLEX);                  // 0xA8
    ssd1306_command(0x3F);
    ssd1306_command(SSD1306_SETDISPLAYOFFSET);              // 0xD3
    ssd1306_command(0x0);                                   // no offset
    ssd1306_command(SSD1306_SETSTARTLINE | 0x0);            // line #0
    ssd1306_command(SSD1306_CHARGEPUMP);                    // 0x8D
    if (vccstate == SSD1306_EXTERNALVCC) 
      { ssd1306_command(0x10); }
    else 
      { ssd1306_command(0x14); }
    ssd1306_command(SSD1306_MEMORYMODE);                    // 0x20
    ssd1306_command(0x00);                                  // 0x0 act like ks0108
    ssd1306_command(SSD1306_SEGREMAP | 0x1);
    ssd1306_command(SSD1306_COMSCANDEC);
    ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
    ssd1306_command(0x12);
    ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
    if (vccstate == SSD1306_EXTERNALVCC) 
      { ssd1306_command(0x9F); }
    else 
      { ssd1306_command(0xCF); }
    ssd1306_command(SSD1306_SETPRECHARGE);                  // 0xd9
    if (vccstate == SSD1306_EXTERNALVCC) 
      { ssd1306_command(0x22); }
    else 
      { ssd1306_command(0xF1); }
    ssd1306_command(SSD1306_SETVCOMDETECT);                 // 0xDB
    ssd1306_command(0x40);
    ssd1306_command(SSD1306_DISPLAYALLON_RESUME);           // 0xA4
    ssd1306_command(SSD1306_NORMALDISPLAY);                 // 0xA6
  #endif
  
  ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
}

hmm... you could manually reset the device by calling displayWrite(). After that, resent the init code with Google Code Archive - Long-term storage for Google Code Project Hosting. this work?

Oliver

So I tried to do what you posted and I couldn't get it to work, I don't believe that it's because of your idea, I DO beleive that it could work, I just don't think I have the techical know how to make it work.

Frustrated with I2C, I rewired it to SPI. For a brief moment I got it to work. Unfortunately I had to run errands and unplugged everything, when I came back it wouldn't start again. I really beleive that the reset/initialization is to blame. Check out this post:

http://forum.arduino.cc/index.php/topic,186792.0.html

I'm going to try implementing this guys start up for my display and see if I can get it running. Thoughts?

While re-reading through the thread the only though i had, was that i have too less knowledge on the OLED you are using. I fact i wonder that the OLED displays allows to use both, I2C and SPI. Maybe you could post a link to the display or datasheet.

Oliver

Sure thing!

Here's the board:
layout.GitHub - adafruit/Adafruit-128x64-Monochrome-OLED-PCB: OLED boards!

And the product page:

Under technical details there's a few datasheets on SSD1306 and the actual display module they are using.

Another idea: Because the reset seems to be an issue. If you use SPI, then u8glib allows to add the pin which is connected to the reset input of the display (last argument). So if the jumper is set to SPI on the display and you connect all 5 lines (SCLK/Clk, MOSI/Data, CS (SA0?), A0/DC, Rst), will this work?

Oliver

Ok I got it to turn on!!

I uncommented this initialization:
#define u8g_dev_ssd1306_128x64_init_seq u8g_dev_ssd1306_128x64_adafruit2_init_seq

and I added a reset pin to D6 while using this constructor: U8GLIB_SSD1306_128X64 u8g(10, 9, 6);

I have messed around with using the- u8g.drawStr( 0, 22, "Text"); command, and I can write all over the display. My new problem (and I don't know if I should start another thread for this?) is that I have a sketch that writes to the serial monitor and I was hoping to translate that to the u8glib.

Serial.print(now.hour(), DEC); would now become -> u8g.print(now.hour(), DEC);

so instead of appearing in the serial monitor it would be displayed on the OLED, at least that's what my intentions are.

I made a note that for you the adafruit2_init_seq works. Maybe i should change the default in U8glib to this sequence.

The ".print" in U8glib is identical. It is the same code as used for the serial interface. However, the fact that U8glib needs the draw command inside a "picture loop" usually requires some redesign.

Oliver

Download and run the i2c_scanner and find your device address. Mine was 0x3D.

Find the u8g_com_arduino_ssd_i2c.c file in the u8glib library

Change the following:

//#define I2C_SLA (0x3c2)
#define I2C_SLA (0x3d
2)

I know I'm a bit late on this, but did you ever get this display working through I2C rather than SPI? I'm attempting to do the same thing and have had a similar experience. Unfortunately (because of my own design) I need to stick with I2C. I've been trying to understand the reset, but with no luck thus far.

Clearly I wasn't trying hard enough... Simply adding the reset functionality from Adafruit's library in the setup function (setting the reset line high momentarily, then low for 10ms, and high again) did the trick. Dang. Wish I would've tried that a long time ago.

In any case, thanks for the excellent library!

aaronpbrooks:
I know I'm a bit late on this, but did you ever get this display working through I2C rather than SPI? I'm attempting to do the same thing and have had a similar experience. Unfortunately (because of my own design) I need to stick with I2C. I've been trying to understand the reset, but with no luck thus far.

I can't speak for the Adafruit OLED however I am using a very similar display from dfRobot and I can confirm that the I2C address should be 0x3D when the DC line is pulled HIGH. I could never get the device to appear at 0x3C.

Should that be the case for you then I suggest the hack posted just above your post. There may be a way that does not involve changing a component of u8glib but I'm not confident enough to work it out.

For Oli, and reference, the device I am using is DFRTOY0007 OLED 2864:

... their site appears to be done but you can find some technical info here:
http://www.swbee.com/wiki/index.php/OLED_2864_Display_module_(SKU:TOY0007)

Hi

So far all of my SSD1306 and SSH1106 OLEDs from Ebay (SPI and I2C variants) did work with u8glib. Should be about 10 different displays so far. I never had to change the I2C address.

Oliver

olikraus:
Hi

So far all of my SSD1306 and SSH1106 OLEDs from Ebay (SPI and I2C variants) did work with u8glib. Should be about 10 different displays so far. I never had to change the I2C address.

Oliver

I picked up one of these displays: White 3-5V 0.96" SPI Serial 128X64 OLED LCD LED Display Module for Arduino | eBay

It says it can be Spi or I2c. I set it up as I2C but when using the i2c scanner on a nano I do not see it.
It uses the ssd1306 also.

Has anybody used one of these.?? I am not sure if I have it hooked up correctly.

My info is: D0=SCL, D1=SDA, Res pulled high, DC pulled high, CS pulled low.

Tnx for any info. Mike.

Hi

To be visible for a I2C scanner the device must sent the ACK response. However some SSD1306 based OLEDs do not sent this response. U8glib can handle this with a special option to the I2C constructor, however the OLED will be invisible for the scanner.

Oliver