Skip to content

Please help me initialize my ILI9488 display with XPT2046 on ESP32S2 Lolin S2 Mini Board #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tetopik opened this issue Nov 30, 2024 · 25 comments

Comments

@tetopik
Copy link

tetopik commented Nov 30, 2024

I'm struggling to find any valid documentation on how to create a config to initialize my setup. I've been trying a couple code from this issues tab but nothing's really works. One yelled 'Bus' object has no attribute 'init'.

  File "display_driver_framework.py", line 212, in __init__
  File "display_driver_framework.py", line 217, in _init_bus
AttributeError: 'Bus' object has no attribute 'init'

Please help!

My code provided below

@tetopik
Copy link
Author

tetopik commented Nov 30, 2024

import lcd_bus
import machine 
from micropython import const 

spi_bus = machine.SPI.Bus(
    host=1,
    mosi=11,
    miso=9,
    sck=7
)

display_bus = lcd_bus.SPIBus(
    spi_bus=spi_bus,
    dc=5,
    cs=12,
    freq=40000000
)

import ili9488  
import lvgl as lv 

fb1 = display_bus.allocate_framebuffer(480*320*2/10, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)
fb2 = display_bus.allocate_framebuffer(480*320*2/10, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)

display = ili9488.ILI9488(
    data_bus=spi_bus,
    display_width=480,
    display_height=320,
    frame_buffer1 = fb1,
    frame_buffer2 = fb2,
    reset_pin=1,
    reset_state=ili9488.STATE_LOW,
    power_on_state=ili9488.STATE_HIGH,
    backlight_pin=3,
    offset_x=0,
    offset_y=0,
    color_space=lv.COLOR_FORMAT.RGB888,
    color_byte_order=ili9488.BYTE_ORDER_BGR,
    rgb565_byte_swap=True
)

display.set_power(True)
display.init()
display.set_backlight(100)

import task_handler
th = task_handler.TaskHandler()

@kdschlosser
Copy link
Collaborator

kdschlosser commented Nov 30, 2024

you are passing the wrong "Bus" to the display driver. You need to be passing the lcd_bus.SPIBus instance to the display driver not the SPI.Bus instance.

@tetopik
Copy link
Author

tetopik commented Nov 30, 2024

Working great now, thank you.

But now how to properly calibrate the display? Because calling the indev.calibrate() seems laggy and still invalid touch detected. I'm using the same SPI bus as the display.

import lcd_bus
import machine 
from micropython import const 
import ili9488  
import lvgl as lv 
import task_handler
import xpt2046

spi_bus = machine.SPI.Bus(host=1, mosi=11, miso=9, sck=7)
display_bus = lcd_bus.SPIBus(spi_bus=spi_bus, dc=5, cs=12, freq=40000000)

display = ili9488.ILI9488(
    data_bus=display_bus,
    display_width=320,
    display_height=480,
    reset_pin=1,
    reset_state=ili9488.STATE_LOW,
    backlight_pin=3,
    backlight_on_state=ili9488.STATE_PWM,
    color_space=lv.COLOR_FORMAT.RGB888,
    color_byte_order=ili9488.BYTE_ORDER_RGB,
    rgb565_byte_swap=True
)

display.init()
display.set_backlight(50)
display.set_rotation(lv.DISPLAY_ROTATION._90)

touch_dev = machine.SPI.Device(spi_bus=spi_bus, freq=10_000_000, cs=18)
indev = xpt2046.XPT2046(touch_dev, startup_rotation=lv.DISPLAY_ROTATION._90, debug=True)
    
th = task_handler.TaskHandler()

Same thing also happen using my ili9341 display, anything I missed?
I also noticed that by default the touch y point is mirrored, is there any way to just flip it away?

@kdschlosser
Copy link
Collaborator

reduce the color depth to 16 bit by changing color_space=lv.COLOR_FORMAT.RGB888 to color_space=lv.COLOR_FORMAT.RGB565 That will help with the speeds. I have some work I need to do with the touch calibration as it has some issues in it. I will be working on that today at some point.

@tetopik
Copy link
Author

tetopik commented Nov 30, 2024

What an effort you put on this repo.

Just a little suggestion if it's really possible to have a choice to attach the touch IRQ pin instead of just periodically polling the screen since we are using a very slow frameworks.

@kdschlosser
Copy link
Collaborator

kdschlosser commented Nov 30, 2024

LVGL is not written to be able to inject touch input. It is only able to poll for touch input. Well... Not easily anyway, I would have to code in a work around. The functions that process input in LVGL are not exposed in any header files, so they are not public, In order to make it work I would have to make a copy of the functions which would cause an increase in the program size. MCU's have very limited resources. I did provide a function that does allow the polling to work better.

indev.enable_input_priority()

This bypasses the normal mechanics of

task_handler -> update display if 33 milliseconds has passed -> read indev if 33 milliseconds has passed -> process input if any -> exit task handler -> user code main loop -> task_handler -> update display if 33 milliseconds has passed.

and turns it into

task_handler -> read indev if 33 milliseconds has passed -> if input then process -> update display -> read indev ->  if input then process -> update display -> continue this loop as long as there is input. once input stops then exit the loop and continue the normal task_handler cycle 

You can see where the problem is with the first one. You can end up with a really long time from when input occurs until it gets realized on the display. it can be at least 33 milliseconds later, usually it is longer and depending on how long it takes the user code in the main loop to run you could see a much higher latency.

That function bypassed the typical mechanics and keeps reading the indev in a continuous loop so long as there is active input. This places user interaction with the GUI above all other thing in terms of priority.

@tetopik
Copy link
Author

tetopik commented Dec 1, 2024

I think that indev.enable_input_priority() function should be the default setup, but in my case I feel noting's difference after I put it after indev init and before the task handler. At least for now.

And also, my board didn't update the display when I switched the setup to color_space=lv.COLOR_FORMAT.RGB565 as you mentioned above.

Anyway, what is the proper spi freq to use for this xpt2046 driver? I've used this driver before with vanilla micropython and the driver from https://github.com/rdagger/micropython-ili9341/blob/master/xpt2046.py and it working great on 1MHz freq, but on this one is it really need 10Mhz?

Oh ya, once more, is it possible to do the calibration using arduino eSPI touch calibrate function instead, and than just put the result into the cal-data in the indev init?

@kdschlosser
Copy link
Collaborator

, is it possible to do the calibration using arduino eSPI touch calibrate function instead

You cannot use the same calibration numbers from eSPI. They are calculated differently I believe.

and it working great on 1MHz freq, but on this one is it really need 10Mhz?

I believe that 1 mhz is the speed you need to use for the touch panel. You would need to read the datasheet to find out if that is the case.

but in my case I feel noting's difference after I put it after indev init and before the task handler. At least for now.

not sure what you mean by this.

And also, my board didn't update the display when I switched the setup to color_space=lv.COLOR_FORMAT.RGB565 as you mentioned above.

I would have to check and see if this color depth is supported by your display. It may not be. Give me a few minutes to check on that.

@kdschlosser
Copy link
Collaborator

OK so your display only supports RGB888 when using an SPI Bus. That is quite a bit of additional work that needs to be done with that added byte to not a huge amount of perceived color difference due to the size of the display.

@kdschlosser
Copy link
Collaborator

If you have a mess of widgets and some of those widgets are outside of the viewable area on the display that will activate scrolling. When you scroll the display is when you will really notice a difference with the touch set to high priority vs not having it set.

@tetopik
Copy link
Author

tetopik commented Dec 1, 2024

I noticed that calling this indev.enable_input_priority() function allow me to initialize the touch driver with 1Mhz freq instead of 10Mhz. But still didn't manage to finish the calibration.

@kdschlosser
Copy link
Collaborator

OK the touch calibration should now be fixed.

@tetopik
Copy link
Author

tetopik commented Dec 1, 2024

OK the touch calibration should now be fixed.

I can confirm that touch calibration is working pretty well right now, but the touch orientation seem flipped here and there.
On rotation._0 , the y is mirrored
On rotation._90, the x,y is flipped and than the x is mirrored, and y seems random.

Even after the calibration succeed, indev.is_calibrated keeps returning False.

display.init()
display.set_backlight(100)
display.set_rotation(lv.DISPLAY_ROTATION._90)

touch_dev = machine.SPI.Device(spi_bus=spi_bus, freq=1_000_000, cs=18)

indev = xpt2046.XPT2046(touch_dev, startup_rotation=lv.DISPLAY_ROTATION._90, debug=True)
indev.enable_input_priority()

th = task_handler.TaskHandler()

if not indev.is_calibrated: indev.calibrate()

I'll try using my ILI9341 board later to see if ithe touch also got messy, I'm a little bit busy right now, gotta post here after getting the test result.

@kdschlosser
Copy link
Collaborator

If you flash your ESP32 at all that is going to erase the stored calibration settings.

I will check to see what could be causing the values to not be saved. If the values are working after you calibrate the only way they could work is if they have been saved. The indev driver reads the calibration values from NV memory. the calibration saves the values to the NV memory.

I will look into it later on today. It is 4:00 am where I am at so I am going to lay down for a few hours.

@tetopik
Copy link
Author

tetopik commented Dec 2, 2024

Using ILI9341 my touch now working perfectly fine. Didn't tested on ILI9488 yet, will come back later.

Here is the catch:

  • The touch calibration must be done BEFORE changing the display rotation.
  • If planning to run on potrait lv.DISPLAY_ROTATION._0 or lv.DISPLAY_ROTATION._180 the calibration should be done as the display is on potrait 0°.
  • If planning to run on landscape lv.DISPLAY_ROTATION._90 or lv.DISPLAY_ROTATION._270 the calibration should be done as the display is on flipped-potrait 180°, don't follow the actual red square shown on the screen.
  • Restarting the board even after succesfully done the calibration do NOT saved the cal value into NV memory, indev.is_calibrated always returns False.
display.init(1)
indev = XPT2046(tch_bus)
indev.enable_input_priority()
th = TaskHandler()
if not indev.is_calibrated: indev.calibrate()
display.set_rotation(lv.DISPLAY_ROTATION._90)

Untitled

@tetopik
Copy link
Author

tetopik commented Dec 2, 2024

Didn't tested on ILI9488 yet, will come back later.

I can peacefully say that same thing happen with my ILI9488 display, it's fully working now. One thing left is the calibration data isn't automatically being saved after the calibration.

@kdschlosser
Copy link
Collaborator

ok so the touch calibration still needs some fine tuning. I am not sure as to why there is an issue with it needing to be rotated and not following the points. I suspect that possibly your touch panel is not connected to the IC properly thus causing a problem. If you can enable the debugging for the touch driver by passing debug=True to the driver when you start it and paste the output to me that would help. I have a feeling that one of the axis is mirrored. Do this when the display is at rotation 0. If the touch IC is connected properly then the low touch input will be at the upper left corner and the high will be at the lower right. The debugging output will show the unaltered data as it is coming from the IC. I am thinking that I am going to have to add a check for this and save a marker so that axis can be flip flopped before any calibration gets applied to the raw coordinates.

The XPT IC has the be the biggest pain to deal with. Most of the issue stems from it not being connected correctly to the touch panel and the touch panel not being attached to the display properly. I am not sure if I will be able to automatically handle all of the installation related issues that occur with it. I will do my best. I still need to come up with a way to adjust the sensitivity because the panel is resistive a threshold needs to be set for when to register touch, The issue there is it is not a constant level across the entire panel. Typically more pressure is needed as you get to the corners in order to register the same touch pressure. If the threshold is set to align with those corners false input can occur for the center of the display. It's those kinds of things that are the hard ones to deal with. I need to come up with some code that will alter the threshold level as the input gets closer to the center of the screen. Problem there is if the display IC is connected incorrectly or the orientation of the panel to the display is not correct that's going to make things more complicated.

@kdschlosser
Copy link
Collaborator

I do not have a display with one of these touch panels to test with either. So that makes it a bit more challenging. If you are willing to help with the testing end of things I am sure we can get it ironed out.

@tetopik
Copy link
Author

tetopik commented Dec 2, 2024

I actually own 3 of those ILI9341 and 2 ILI9488, and every single one of them works pretty much like I said before.
Either the touch calibration and the touch input after the calibration runs smoothly and on point. So I doubt that there is any issue about the IC connection or even the issue on touch pressure.

If the touch IC is connected properly then the low touch input will be at the upper left corner and the high will be at the lower right.

On rotation 0°, I can say YES indeed, the console returns the exact value as you said. The touch just flipped at some point on another rotation as I mentioned above.

It's a pleasure to help this development as I really need to use it as soon as possible. Let me know anything I need to put on test for further debugging.

@kdschlosser
Copy link
Collaborator

I just made a change to the RGB driver. If you want to test it. It might speed things up a tad depending on how long the copy was taking and if LVGL was bumping the flush ready marker not being set. If LVGL bumping that marker the change should keep it from stalling without yielding. This would make a considerable difference as it would allow another thread to run if threading is being used in MicroPython.

@tetopik
Copy link
Author

tetopik commented Dec 3, 2024

Recompiled the last update, with the exact same code, now the touch starts unresponsive. Can't say anything about the speed difference.

@kdschlosser
Copy link
Collaborator

I will look at it to see what is going on.... I might have missed removing the lock being acquired somewhere.

@tetopik
Copy link
Author

tetopik commented Dec 6, 2024

I will look at it to see what is going on.... I might have missed removing the lock being acquired somewhere.

Any update on this Kevin?

@kdschlosser
Copy link
Collaborator

i reverted the changes I made so it should be working again.

@kdschlosser
Copy link
Collaborator

I did leave the alterations I made to the touch driver so perhaps that will work now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants