Display + touch not displaying anything on ESP32

Hello, sorry for the late response.

First of all, thank you for your previous responses. I still haven’t tried to use the ili9488 driver as @amirgon suggested, as when I tried it the first time I got a console error saying that I haven’t set LV_COLOR_DEPTH=32 (which I did when deploying), and haven’t tried ever since.

Also, thanks @saul for the recommendation with the logic analyzer, I didn’t know those existed, and I could resort to use one in the future, it seems really helpful.

Now, this is what I have:

These past weeks I’ve been having problems with my computer and also I’ve been trying to write some initialization code for the ili9486, first by checking the ili9341 config in lv_binding_micropython, looking in the ili9341 datasheet and taking note of what the commands were, then comparing with ili9486 datasheet (finding that the latter has some differences in quantity and use of commands and their parameters).

So what I first did, was to check (and copy) other people’s init code (like ustropo’s module or gfxlcd), which didn’t result/work when written in ili9XXX.py.

Then, I tried looking at the ili9341 config and both ili9486 and ili9341 datasheets, trying to copy the parameters passed to ili9341, and translate them into ili9486 commands. The latter had some commands missing, there are also parameters missing in some commands as well as parameters added. It also has a whole different set of commands called CABC Control (which I didn’t set in my config, as they weren’t set neither in ustropo’s code or in the gfxlcd library).

By the way, I tried my best to replicate the config of the ili9341, then I wrote that code again in ili9XXX.py, recompiled, flashed it in the ESP32, and I still have a white screen in the display.

As far as I understand, the ili9486 also uses 0x2A, 0x2B, and 0x2C for their flush function, so I don’t know if there could be a problem with the parameters there? I’ll check that this week.

I don’t know what to do now, really. I don’t want to give up with the ili9486 driver, but I think I will try buying an actual ili9341 just to make something work. I don’t know, maybe making a driver for this display is way over my current level.

I can paste my ili9486 class in another reply, if you want, or if it could be of help to anyone for an example of what not to do.

Anyway, sorry for the long response and maybe also some grammar errors. And thanks again for your help.

Hi @GianK128,
Have you tried using a different library just to check there are no issues with your hardware or wiring. Seems like some tried using similar hardware here:

When I was having issues it was also a little difficult because it compiled with no errors and was also just getting a blank screen. The reason I knew something was wrong was that when I toggled the back light nothing happened.

Have you tried connecting either the back light or power pin to the lcd power input and tried toggling it over lvgl.
Do you get different results when running:

import lvgl as lv
from ili9XXX import ili9488
lv.init()
ili9488(power=33, power_on=0)

VS

import lvgl as lv
from ili9XXX import ili9488
lv.init()
ili9488(power=33, power_on=1)

Yeah I think it wouldn’t be a bad idea to order a ILI9341 they seem to be easy to use and have a good refresh rate. Depending on where you get it, by the time you want to try it out it will be delivered :slight_smile:

First of all, sorry, this is going to be a long response.

Have you tried using a different library just to check there are no issues with your hardware or wiring.

Yes, after I posted my last reply I started testing with other libraries, actually just with Bodmer’s TFT_eSPI with Arduino IDE. I trusted this library since this is where I got the image of the display pinout (see my first post).

Well, the screen was still not working, so I decided to check again the connections, and in LCD Wiki I found that the display has two 5V pins instead of the one declared in the image mentioned. So I connected it, uploaded the graphics_test sketch and it works good as new.

So I thought that I could just copy the init sequence from Bodmer’s script (I also tried from other authors with different init sequences) into the ili9XXX.py script and it would work, since the flush method seems to be the same for ili9341 and ili9486. Turns out it did not, and I am again lost as to why, since this configuration works in TFT_eSPI.

In case anyone wants to see what I am doing, I’ll paste my ili9486 class:

class ili9486(ili9XXX):

    def __init__(self,
        miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0,
        spihost=esp.HSPI_HOST, mhz=40, factor=8, hybrid=True, width=320, height=480,
        colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True,
        asynchronous=False, initialize=True
    ):

        if lv.color_t.__SIZE__ != 2:
            raise RuntimeError('ili9486 micropython driver requires defining LV_COLOR_DEPTH=16')
        if colormode == COLOR_MODE_BGR and not hasattr(lv.color_t().ch, 'green_l'):
            raise RuntimeError('ili9486 BGR color mode requires defining LV_COLOR_16_SWAP=1')

        self.display_name = 'ILI9486'
        self.display_type = DISPLAY_TYPE_ILI9486

        self.init_cmds = [
            # ustropo's & gfxlcd config (not working)
            #{'cmd': 0xB0, 'data': bytes([0x00])},                       # Interface Mode Control
            #{'cmd': 0x11, 'data': bytes([0]), 'delay': 120},            # Sleep OUT
            #{'cmd': 0x3A, 'data': bytes([0x55])},                       # Interface Pixel Format (55 = 16 bits)
            #{'cmd': 0xB6, 'data': bytes([0x0A, 0x02, 0x3B])},           # Display Function Control
            #{'cmd': 0xC2, 'data': bytes([0x44])},                       # Power Control 3, Normal Mode
            #{'cmd': 0xC5, 'data': bytes([0x00, 0x00, 0x00, 0x00])},     # VCOM Control
            #{'cmd': 0xE0, 'data': bytes([0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x00, 0x00])},   # Positive Gamma Correction
            #{'cmd': 0xE1, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Negative Gamma Correction
            #{'cmd': 0xE2, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Digital Gamma Control
            #{'cmd': 0x36, 'data': bytes([rot | colormode])},            # Memory Access Control
            #{'cmd': 0x11, 'data': bytes([0]), 'delay': 120},            # Sleep OUT
            #{'cmd': 0x29, 'data': bytes([0]), 'delay': 120}             # Display ON
            
            # lvgl_esp32_drivers & Bodmer's config (not working)
            {'cmd': 0x11, 'data': bytes([0]), 'delay': 120},            # Sleep OUT
            {'cmd': 0x3A, 'data': bytes([0x55])},                       # Interface Pixel Format (55 = 16 bits)
            {'cmd': 0xC2, 'data': bytes([0x44])},                       # Memory Write
            {'cmd': 0xC5, 'data': bytes([0x00, 0x00, 0x00, 0x00])},     # VCOM Control
            {'cmd': 0xE0, 'data': bytes([0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x00, 0x00])},   # Positive Gamma Correction
            {'cmd': 0xE1, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Negative Gamma Correction
            {'cmd': 0x20, 'data': bytes([0])},                          # Inversion OFF
            {'cmd': 0x36, 'data': bytes([rot | colormode])},            # Memory Access Control
            {'cmd': 0x29, 'data': bytes([0]), 'delay': 150}             # Display ON
            
            # Waveshare_ILI9486 config (not working)
            #{'cmd': 0xC0, 'data': bytes([0x19, 0x1A])},                 # Power Control 1
            #{'cmd': 0xC1, 'data': bytes([0x45, 0x00])},                 # Power Control 2
            #{'cmd': 0xC2, 'data': bytes([0x33])},                       # Power Control 3, Normal Mode
            #{'cmd': 0xC5, 'data': bytes([0x00, 0x28])},                 # VCOM Control
            #{'cmd': 0xB1, 'data': bytes([0xA0, 0x11])},                 # Frame Rate Control
            #{'cmd': 0xB4, 'data': bytes([0x02])},                       # Display Inversion Control
            #{'cmd': 0xB6, 'data': bytes([0x00, 0x42, 0x3B])},           # Display Function Control
            #{'cmd': 0xE0, 'data': bytes([0x1F, 0x25, 0x22, 0x0B, 0x06, 0x0A, 0x4E, 0xC6, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])},   # Positive Gamma Correction
            #{'cmd': 0xE1, 'data': bytes([0x1F, 0x3F, 0x3F, 0x0F, 0x1F, 0x0F, 0x46, 0x49, 0x31, 0x05, 0x09, 0x03, 0x1C, 0x1A, 0x00])},   # Negative Gamma Correction
            #{'cmd': 0x3A, 'data': bytes([0x55])},                       # Interface Pixel Format (55 = 16 bits)
            #{'cmd': 0x11, 'data': bytes([0]), 'delay': 120},            # Sleep OUT
            #{'cmd': 0x20, 'data': bytes([0])},                          # Inversion OFF
            #{'cmd': 0x36, 'data': bytes([rot | colormode])},            # Memory Access Control
            #{'cmd': 0x29, 'data': bytes([0]), 'delay': 150} 

            # way5's stm32 config (not working)
            #{'cmd': 0xB0, 'data': bytes([0x00])},                       # Interface Mode Control
            #{'cmd': 0x3A, 'data': bytes([0x55])},                       # Interface Pixel Format (55 = 16 bits)
            #{'cmd': 0xE0, 'data': bytes([0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x00, 0x00])},   # Positive Gamma Correction
            #{'cmd': 0xE1, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Negative Gamma Correction
            #{'cmd': 0xE2, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Digital Gamma Control
            #{'cmd': 0x36, 'data': bytes([rot | colormode])},            # Memory Access Control
            #{'cmd': 0x38, 'data': bytes([0])},                          # Idle Mode OFF
            #{'cmd': 0xB1, 'data': bytes([0xB0, 0x11])},                 # Frame Rate Control     
            #{'cmd': 0xC2, 'data': bytes([0x55])},                       # Power Control 3, Normal Mode
            #{'cmd': 0xB4, 'data': bytes([0x02])},                       # Display Inversion Control
            #{'cmd': 0xB6, 'data': bytes([0x02, 0x22, 0x3B])},           # Display Function Control
            #{'cmd': 0x11, 'data': bytes([0]), 'delay': 150},            # Sleep OUT
            #{'cmd': 0x29, 'data': bytes([0]), 'delay': 150}             # Display ON
            
            # My own config (not working, too)
            #{'cmd': 0xB0, 'data': bytes([0x00])},                       # Interface Mode Control
            #{'cmd': 0xC0, 'data': bytes([0x13, 0x13])},                 # Power Control 1
            #{'cmd': 0xC1, 'data': bytes([0x42, 0x30])},                 # Power Control 2
            #{'cmd': 0xC2, 'data': bytes([0x44])},                       # Power Control 3, Normal Mode
            #{'cmd': 0xC5, 'data': bytes([0x00, 0x00, 0x00, 0x00])},     # VCOM Control
            #{'cmd': 0x36, 'data': bytes([rot | colormode])},            # Memory Access Control
            #{'cmd': 0x3A, 'data': bytes([0x55])},                       # Interface Pixel Format (55 = 16 bits)
            #{'cmd': 0xB1, 'data': bytes([0xB0, 0x17])},             
            #{'cmd': 0xE0, 'data': bytes([0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x00, 0x00])},   # Positive Gamma Correction
            #{'cmd': 0xE1, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Negative Gamma Correction
            #{'cmd': 0xE2, 'data': bytes([0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00])},   # Digital Gamma Control
            #{'cmd': 0x2A, 'data': bytes([0x00, 0x00, 0x01, 0x3F])},     # Column Address Set
            #{'cmd': 0x2B, 'data': bytes([0x00, 0x00, 0x01, 0xDF])},     # Page Address Set
            #{'cmd': 0x2C, 'data': bytes([0])},
            #{'cmd': 0xB7, 'data': bytes([0x07])},                       # Entry Mode Set
            #{'cmd': 0xB6, 'data': bytes([0x0A, 0x02, 0x3B])},           # Display Function Control
            #{'cmd': 0x11, 'data': bytes([0]), 'delay': 120},            # Sleep OUT
            #{'cmd': 0x29, 'data': bytes([0]), 'delay': 120}             # Display ON
        ]

        super().__init__(miso, mosi, clk, cs, dc, rst, power, backlight, backlight_on, power_on,
            spihost, mhz, factor, hybrid, width, height, colormode, rot, invert, double_buffer, half_duplex,
            asynchronous=asynchronous, initialize=initialize)

I think this should be either a problem of the flush function, or something in how lvgl handles SPI, but it is an uneducated guess.

Have you tried connecting either the back light or power pin to the lcd power input and tried toggling it over lvgl.

I did after you recommended it, the display has no backlight control, it is always on when powered, so I tried to connect a pin from the ESP32 to both 5V pins and turning it on with:

import lvgl as lv
from ili9XXX import ili9486

#lv.init gets called inside ili9XXX class
#Same mhz used in TFT_eSPI, and factor = 8 needed or else I get DMAerror
disp=ili9486(power=33, power_on=0, mhz=20, factor=8) # Also tried power_on=1

the display didn’t turn on. Then I tried connecting pin 33 to both 3.3V pins of the display and had the same results. Then I tried with backlight=33 instead of power, same results.

I’ll get an ili9341 for convenience, but I’ll keep an eye on this and update if I come up with something.

Hi @GianK128,
The driver stuff seems a little too complicated for me :slight_smile: But I think you might have to look in to getting some type of logic analyzer to see what the pins are actually doing.

Can you try connecting a resister and LED to the power pin and try initializing the driver from lvgl? If the power or back light pins are not able to initialize correctly then you probably want to figure out what is causing that issue before working too much on the LCD commands. You may even want to try initializing an unchanged ili9341 or ili9488 driver just to check the power pin toggles there.

Regards,
Saul

I’m having a very similar issue
Please click on Display MPI3501 + Ili9486 + XPT2046 [lvgl 7 + esp-idf] - Display not showing, but touch works (IDFGH-10617) · Issue #11852 · espressif/esp-idf · GitHub