Is this expected? It's a 240x240 ST7789-based OLED from AliX. I drew some bars on the display, left it on for about a minute, and then powered off and on. Nothing is written to the display in the attached image. And writing all black doesn't change it. Damn!
I've seen this happen when those magic number arrays and values you write into the registers at the initialization time are wrong. There is a lot of random code floating around and everyone copies all the values and sometimes they are not applicable to the specific panel or just straight up wrong. I would double check the values you use against the datasheet and some other code examples.
This will likely go away after a few hours.
Although if this happens just after a minute, it may be just a shitty panel, which would not be surprising for aliexpress. I'd get displays from more reputable sources, like buydisplay.com
That's lcd, not oled?? Ips is a lcd technology.
Yes, this is not an OLED at all, just a regular IPS LCD.
Here are initialization values I used in my code for the similar display.
static const uint8_t commands[] =
{
ST7789_CMD_MADCTL, 1, 0x00,
ST7789_CMD_COLMOD, 1, 0x05,
ST7789_CMD_PORCTRL, 5, 0x0c, 0x0c, 0x00, 0x33, 0x33,
ST7789_CMD_GCTRL, 1, 0x35,
ST7789_CMD_VCOMS, 1, 0x19,
ST7789_CMD_LCMCTRL, 1, 0x2c,
ST7789_CMD_VDVVRHEN, 1, 0x01,
ST7789_CMD_VRHS, 1, 0x12,
ST7789_CMD_VDVS, 1, 0x20,
ST7789_CMD_FRCTRL2, 1, 0x0f,
ST7789_CMD_PWCTRL1, 2, 0xa4, 0xa1,
ST7789_CMD_PVGAMCTRL, 14, 0xd0, 0x04, 0x0d, 0x11, 0x13, 0x2b, 0x3f, 0x54, 0x4c, 0x18, 0x0d, 0x0B, 0x1f, 0x23,
ST7789_CMD_NVGAMCTRL, 14, 0xd0, 0x04, 0x0c, 0x11, 0x13, 0x2c, 0x3f, 0x44, 0x51, 0x2f, 0x1f, 0x1f, 0x20, 0x23,
ST7789_CMD_INVON, 0,
ST7789_CMD_SLPOUT, 250,
};
With those settings and a known good display, I saw no artifacts or burn-in after running for hours.
The initialization code I'm using is the same as Adafruit and Raspberry Pi have in their repos. I powered up the display, after an hour or two break, and the artifacts are gone. But I'll try your code. Thanks.
I never experienced any burn-in either. Check the init code:
About the same as ataradov's, just different order.
const uint8_t init_cmd[] = {
0, CMD_SLPOUT,
1, CMD_COLMOD, CMD_COLOR_MODE_16bit,
5, CMD_PORCTRL, 0x0C, 0x0C, 0x00, 0x33, 0x33, // Standard porch
//5, CMD_PORCTRL, 0x01, 0x01, 0x00, 0x11, 0x11, // Minimum porch (7% faster screen refresh rate)
1, CMD_GCTRL, 0x35, // Gate Control, Default value
1, CMD_VCOMS, 0x19, // VCOM setting 0.725v (default 0.75v for 0x20)
1, CMD_LCMCTRL, 0X2C, // LCMCTRL, Default value
1, CMD_VDVVRHEN,0x01, // VDV and VRH command Enable, Default value
1, CMD_VRHS, 0x12, // VRH set, +-4.45v (default +-4.1v for 0x0B)
1, CMD_VDVS, 0x20, // VDV set, Default value
1, CMD_FRCTRL2, 0x0F, // Frame rate control in normal mode, Default refresh rate (60Hz)
//1, CMD_FRCTRL2, 0x01, // Frame rate control in normal mode, Max refresh rate (111Hz)
2, CMD_PWCTRL1, 0xA4, 0xA1,
1, CMD_MADCTL, LCD_ROTATION_CMD,
14, CMD_GMCTRP1, 0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23,
14, CMD_GMCTRN1, 0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23,
0, CMD_INVON,
0, CMD_NORON
};
https://github.com/deividAlfa/ST7789-STM32-uGUI/tree/master/Library/LCDThis is not a professional-grade code, just a big scratchpad, done during the pandemic, having some fun with DMA / tweaking the performance.
I will test your guys' code shortly. I just verified that if I run my code, with the bars, leave it for 5 minutes, and then cycle the power, it retains the artifacts for at least 15 minutes afterwards...that is powered up but no display code. This means I can duplicate the problem and test the better code.
I purchased a few 1.27" Color OLEDs from Adafruit.
The settings in their SSD1351 library are insanely bright.
I basically cut them in half and haven't seen any burn-in.
Here are my settings for those using a SSD1351 OLED Controller:
#define SSD1351_SETCOLUMN 0x15
#define SSD1351_WRITERAM 0x5C
#define SSD1351_READRAM 0x5D
#define SSD1351_SETROW 0x75
#define SSD1351_HORIZSCROLL 0x96
#define SSD1351_STOPSCROLL 0x9E
#define SSD1351_STARTSCROLL 0x9F
#define SSD1351_SETREMAP 0xA0
#define SSD1351_STARTLINE 0xA1
#define SSD1351_DISPLAYOFFSET 0xA2
#define SSD1351_DISPLAYALLOFF 0xA4
#define SSD1351_DISPLAYALLON 0xA5
#define SSD1351_NORMALDISPLAY 0xA6
#define SSD1351_INVERTDISPLAY 0xA7
#define SSD1351_FUNCTIONSELECT 0xAB
#define SSD1351_DISPLAYOFF 0xAE
#define SSD1351_DISPLAYON 0xAF
#define SSD1351_PRECHARGE 0xB1
#define SSD1351_DISPLAYENHANCE 0xB2
#define SSD1351_CLOCKDIV 0xB3
#define SSD1351_SETVSL 0xB4
#define SSD1351_SETGPIO 0xB5
#define SSD1351_PRECHARGE2 0xB6
#define SSD1351_SETGRAY 0xB8
#define SSD1351_USELUT 0xB9
#define SSD1351_PRECHARGELEVEL 0xBB
#define SSD1351_VCOMH 0xBE
#define SSD1351_CONTRASTABC 0xC1
#define SSD1351_CONTRASTMASTER 0xC7
#define SSD1351_MUXRATIO 0xCA
#define SSD1351_COMMANDLOCK 0xFD
// Command Lock #1 {reset=0x12}
SSD1351_Write2(SSD1351_COMMANDLOCK, 0x12);
// Command Lock #2 {reset=0xB0}
SSD1351_Write2(SSD1351_COMMANDLOCK, 0xb1);
// Sleep Mode On
SSD1351_Write(SSD1351_DISPLAYOFF);
// Re-map / Color Depth {Vertical flip}
//SSD1351_Write2(SSD1351_SETREMAP, 0x66);
SSD1351_Write2(SSD1351_SETREMAP, 0x74);
// Display Start Line {reset=0}
SSD1351_Write2(SSD1351_STARTLINE, 0);
// Display Offset {reset=60h}
SSD1351_Write2(SSD1351_DISPLAYOFFSET, 0);
// Display Mode
SSD1351_Write(SSD1351_NORMALDISPLAY);
// Internal Vdd Regulator and Interface Select {reset A[7:6]=00b, A[0]=1b}
SSD1351_Write2(SSD1351_FUNCTIONSELECT, 0x01);
// Reset/Pre-charge Periods {reset A[7:4]=1000b 8_DCLKs], A[3:0]=0010b 5_DCLKs}
SSD1351_Write2(SSD1351_PRECHARGE, 0x62);
// Display Enhancement
//SSD1351_Write4(SSD1351_DISPLAYENHANCE, 0xa4, 0x00, 0x00);
// Clock Divider and Oscillator Frequency {reset A[7:4]=1101b, A[3:0]=0001b}
SSD1351_Write2(SSD1351_CLOCKDIV, 0xf1);
// Segment Low Voltage
SSD1351_Write4(SSD1351_SETVSL, 0xa0, 0xb5, 0x55);
// GPIO {reset A[3:2]=10b, A[1:0]=10b}
SSD1351_Write2(SSD1351_SETGPIO, 0x00);
// Second Pre-charge Period {reset A[3:0]=1000b 8_DCLKS]}
SSD1351_Write2(SSD1351_PRECHARGE2, 0x01);
// Pre-charge Voltage {reset A[4:0]=17h}
SSD1351_Write2(SSD1351_PRECHARGELEVEL, 0x15);
// COM Deselect Voltage {reset A[2:0]=05h}
SSD1351_Write2(SSD1351_VCOMH, 0x03);
// Contrast Current {reset=8Ah, 51h, 8Ah}
SSD1351_Write4(SSD1351_CONTRASTABC, 0x60, 0x50, 0x60);
// Master Contrast Current {reset A[3:0]=1111b}
SSD1351_Write2(SSD1351_CONTRASTMASTER, 0x09);
// MUX Ratio {reset A[6:0]=127}
SSD1351_Write2(SSD1351_MUXRATIO, SSD1351_HEIGHT-1);
This is an IPS display, it is impossible to make it brighter than the backlight brightness.
I purchased a few 1.27" Color OLEDs from Adafruit.
The settings in their SSD1351 library are insanely bright.
I basically cut them in half and haven't seen any burn-in.
You will see OLED burn-in even at reduced intensity, if you let it run long enough. It just takes longer. I use low intensity, and (if it works for the application) a moving low-density screensaver pattern for slow, evenly-distributed pixel burn.
I tried Alex's code and...I think it's actually worse. Displayed the bars for 5 minutes, cycled power, and several minutes later I could still tell which bars were which colors (well, they were inverted). Maybe it's a factory reject (or China standard quality).
One big issue here is that ST7789 is just a controller. All those displays may be different in theory and may require different settings. With displays from buydisplay you get the actual datasheet. Not that this datasheet mentions any of the settings, but they do provide example code specifically for their displays, which has all those values.
In this case you can try different options, but ultimately, I'd assume that the panel is defective.
I thought it could be signs of DC bias damage (electrolysis), but if you say it goes away after a while, that sounds more like residual charge that's remaining due to some defect, or unbalanced driving. This is an active-matrix display, which is harder to manufacture than passive-matrix (CSTN). Try writing the inverted pattern and see if that causes the afterimage to disappear?
Another thing to try on the '7789 is to change the gate control voltages (command B7) and gate timing (B8) as well as VCOM (BB), VRH (C3), VDV (C4), and VCOM offset (C5). These are normally adjusted at the factory and programmed into the NVM but maybe they didn't do that on your unit.
Oh well. It was just a personal pet project; a Space Invaders game. I should use a larger display anyway.
Thanks.
Just another vote for buydisplay.com. (Just as a satisfied customer, no other relationship.) Their documentation is far better than what you get from eBay/aliexpress no-name stuff, and above all, the documentation (and sample code, etc) is actually guaranteed to match the product delivered…
ST7789 has power level control registers. The default value is 2.8V. However, the power control registers have a range of 2.5-3.6V stable operation, you just need to write before the high voltage is enabled.