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.
Here are the constructors I used. (one at a time of course )
//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.
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
}
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:
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.
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?
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.
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.
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:
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.
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.
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.