olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
4.91k stars 1.02k forks source link

2.42-inch Waveshare OLED SSD1309 and contrast problem #2408

Open JG24 opened 3 months ago

JG24 commented 3 months ago

Hi there! Thanks a lot for your work. I managed to get the 2.42-inch Waveshare OLED display up and running. Everything would be fine if it weren't for the lack of ability to adjust the contrast of this display. According to the manufacturer, the display supports contrast control. Unfortunately, I can't seem to achieve it. Has anyone had a similar issue?

Additionally, I'll mention that I have the display connected via SPI to an ESP32.

Here's datasheet: https://files.waveshare.com/wiki/2.42inch-OLED-Module/SSD1309Datasheet.pdf

olikraus commented 3 months ago

which exact constructor did you use?

JG24 commented 3 months ago

which exact constructor did you use?

U8G2_SSD1309_128X64_NONAME0_F_4W_HW_SPI u8g2(U8G2_R0, / cs=/13, / dc=/16, / reset=/17);

It works very well, except for the ability to change the contrast.

olikraus commented 3 months ago

I checked the code, but the setContrast() command should work. You can also use

u8g2.sendF("ca", 0x81, contrast); // 'contrast' is the desired contrast value

to manually set the contrast (see also https://github.com/olikraus/u8g2/wiki/u8g2reference#sendf)

Sometimes the contrast command for the display (0x81) does not have the desired effect. In such cases could play around with the 0xd9 or 0xdb command of your display.

olikraus commented 3 months ago

See also here: https://github.com/olikraus/u8g2/issues/1504

ntzb commented 1 month ago

hi Oli @olikraus, I'm facing similar issue. 2.42" OLED I2C, SSD1309, constructor U8G2_SSD1309_128X64_NONAME0_F_HW_I2C I tried the following contrast commands:

        u8g2.setContrast(0);
        u8g2.sendF("ca", 0x81, 0);
        u8g2.sendF("ca", 0x0db, 0);
        u8g2.sendF("ca", 0x0d9, 15);

none of them works. any clues?

the only thing that works for me is setPowerSave(1) to turn display completely off. is there a disadvantage to using this? will it shorten the lifespan of the oled?

olikraus commented 1 month ago

There should be some more related questions. Did you check the issues for more information? Life shouldn't be affected unless you increase brightness a lot.

ntzb commented 1 month ago

I've dug through all of the other related issues I could find. it seems that the solution that always worked eventually, was using u8g2.sendF("ca", 0x81, contrast_value); after carefully examining from very close, I did notice that the above command very slightly reduces the brightness. still it looks like it's almost all the way up, so I must be missing something. is there anything else I could try?

olikraus commented 1 month ago

For OLEDs the 0x81 command indeed doesn't change much by itself. Usually a combination of multiple commands is required to reduce brightness to zero. I have cellphone access only at the moment and searching in the GitHub issues with the app is a pain, but there should be issues regarding this. Also look out for ssd1306 , which should have the same commands.

olikraus commented 1 month ago

I think the above mentioned issue should contain all required information.

ntzb commented 1 month ago

I forgot to mention that my code already had:

// value from 0 to 7, higher values more brighter
void setSSD1309VcomDeselect(uint8_t v)
{   
  u8g2.sendF("ca", 0x0db, v << 4);
}

// p1: 1..15, higher values, more darker, however almost no difference with 3 or more
// p2: 1..15, higher values, more brighter
void setSSD1309PreChargePeriod(uint8_t p1, uint8_t p2)
{   
  u8g2.sendF("ca", 0x0d9, (p2 << 4) | p1 );
}

and it was called with:

setSSD1309VcomDeselect(2);
setSSD1309PreChargePeriod(15,1);

I'm working with https://github.com/Pako2/esp-oledproc and the web interface didn't have convenient way to change these values, so I had to rewrite flash all the time, and it wasn't really doing anything.

after adding the VcomDeselect and PreChargePeriod inputs via the web interface, I was now able to test it much faster. as per your post , I set p1 in the precharge period to 15, and can play with p2, contrast, and vcomdeselect. contrast and vcomdeselect show very big impact from small changes, so I decided to fix them on 0 (contrast) and 1 (vcomdeselect), which leaves only p2 of precharge period.

does this makes sense?

btw, setting low p2 to achieve low brightness, causes the display to look very bad (almost not understandable), it seems the minimal acceptable value is 2, and I've set it to 3.

all in all the brightness (contrast...) control is very flimsy and obfuscate, at least on my ssd1309... I wonder if it's because of the controller, the fact that it's i2c, or just like this in general.

olikraus commented 1 month ago

LED dimming is done via pulse wide modulation in all the displays. This approach however has issues and shows artefacts with very low brightness values, so this is a general problem. It might be influenced by the display if the vendor didn't add sufficient capacity at the power supply lines and as part of the charge pump ( your OLED probably requires 15V which is generated on the PCB itself). You might improve the situation by adding a 0.1uF, a 1uF and a 2.2uF ceramic cap close the the power supply of your OLED.