JC3248W535EN event problem

Hi all.
I buy this board : JC3248W535EN
Compile source code and flash . I use Thonny IDE .
IF reset then show me this :

LVGL (9.2.2) MicroPython (1.25.0) Binding compiled on 2025-06-27; Generic ESP32S3 module with Octal-SPIRAM with ESP32S3
Type "help()" for more information.
>>> 

and if try my easy program to detect corect event still have problem .
sthis is my program:


import lv_config
import lvgl as lv

HEIGHT  = 480#lv_config.HEIGHT
WIDTH   = 320#lv_config.WIDTH

import task_handler
th = task_handler.TaskHandler()


scr = lv.screen_active()
lv.screen_load(scr)

scr.set_style_bg_color(lv.color_hex(0x000000), 0)

def Button1_event(event):
	#print(event.get_code())
	kod = event.get_code()
	if kod == 1:
		print('1 Tlacidlo 1')
	if kod == 2:
		print('2 Tlacidlo 1')
	if kod == 3:
		print('3 Tlacidlo 1')
	if kod == 4:
		print('4 Tlacidlo 1')
	if kod == 5:
		print('5 Tlacidlo 1')
	if kod == 6:
		print('6 Tlacidlo 1')
	if kod == 7:
		print('7 Tlacidlo 1')
#def Button2_event_handler(event):

#Definicia tlacidile s textom
Button1 = lv.button(scr)
Button1.align(lv.ALIGN.CENTER,0,0)
#Vytvorime text v strede tlacidla
L_Button1 = lv.label(Button1)
L_Button1.set_text('Tlacidlo 1')
#Priradenie udalosti pre Tlacidlo1
Button1.add_event_cb(Button1_event,lv.EVENT.ALL, None)

During testing, regardless of the button press duration, it consistently returns 1, 2, 4, 7.
Yes I cahnge lv.EVENT.ALL to CLICKED… then still receive 7 …

Where is problem ???
Is problem in my cmpilation ? Source code … etc ??? You have same issue ??

regards.

btn.add_event_cb(on_click, lv.EVENT.CLICKED, None)

def on_click(e):
    # get obj button
    target = e.get_current_target_obj()

Hi.
I change fom ALL to CLICKED
and still same problem :

  1. objekt =event.get_current_target_obj() - return objekt and what ?
  2. event still return 7 , It doesn’t matter how long I press, how long I hold or how short I press, it still cyclically creates an event with code 7.

You have same display , same firmware , I use your code - try it …

regards.

I want to say that this…

    target = e.get_current_target_obj()

should be this

    target = e.get_current_target_obj().__cast__()
1 Like

Yes… and what ? Sorry but what I will do with object ?? give here small example how solve my problem … Ok , I know what object is it …

For example if use widget slider , then work good … if touch blob and not move then not generate event , if move then generate 32 … value are change … work perfect .

If use widget button … if touch button … receive 7 very fast …

Hi all,

Today, I finally found a solution to a problem I was having with touch events in my code.

I’m using:

LVGL (9.2.2) MicroPython (1.25.0) Binding compiled on 2025-06-29; Generic ESP32S3 module with Octal-SPIRAM with ESP32S3

Here’s what was happening: When I set up events for a button, like CLICKED, it wasn’t generating a single event per push. Instead, it would generate multiple events such as PRESSED, RELEASE, CLICKED, LONG_PRESS, and then repeat these as long as my finger stayed on the LCD. This wasn’t logical, as a single press should ideally result in one CLICKED event.

I started investigating and pinpointed the issue.

LVGL calls my _get_coords function in the background to get coordinates, and _get_coords in turn calls _read_data. Inside my _read_data function, I have this:

            self._device.write(self._tx_mv)
            self._device.read(buf=self._rx_mv)
            ...
            data = self._rx_mv
            ...

When reading data from the LCD touch IC via I2C, I can get a result where all 14 bytes are the same (e.g., 0xAF or 0x14), which signifies no touch. Alternatively, I get touch data where the first byte is 0x00 (touch detected), the second byte indicates 0x01 or 0x02 (one or two touches), and the remaining bytes contain position, region ID, press/release state, etc.

The core problem was that when I pressed my finger on the LCD, LVGL immediately called my _get_coords function again, which then triggered a re-read of the touch display data. This happened too quickly (the time between calls was around 2ms), and the AXS15231 sensor couldn’t provide real, stable data so quickly. As a result, the buffer would get filled with unexpected data, often all the same bytes. My _read_data function, unaware of this, would parse these invalid data. This would lead to my system incorrectly interpreting “no touch” and sending a RELEASE event to the LVGL core.

Then, after the time defined in lv_config.py (e.g., task_handler.TaskHandler(duration=33) for every 33ms), LVGL would call _get_coords again. By this time, the sensor had enough time (a safe time is around 18ms; I use 20ms) to read real data, and _read_data would return correct position data, etc. This cycle of fast, invalid reads followed by slower, valid reads was causing the flood of unwanted events.

So, I understood the problem, but I wasn’t sure about LVGL’s internal workings regarding input device polling. I decided to solve it based on what I knew.

I modified the _read_data function in AXS15231.py as follows:

# Init
        self._sensor_data_buffer = bytearray(14) # Tento buffer bude uchovávat posledne nacitane data
        for i in range(14):
            self._sensor_data_buffer[i] = 0xAF # Alebo 0x14, podÄľa toho, ktorĂ˝ je "predvolenĂ˝"
        self._rx_mv[:] = self._sensor_data_buffer[:]
        self._last_sensor_read_time = utime.ticks_ms()
# Init end 

    def _read_data(self):
        current_time = utime.ticks_ms()
        if utime.ticks_diff(current_time, self._last_sensor_read_time) > 20: # minimum time is 20ms 
            self._device.write(self._tx_mv)
            self._device.read(buf=self._sensor_data_buffer) # Načíta dáta do buffera
            self._rx_mv[:] = self._sensor_data_buffer[:]
            self._last_sensor_read_time = current_time # Aktualizuj čas posledného čítania

By adding a time check (if utime.ticks_diff(...) > 20:) before performing the I2C read, I ensure that new data is fetched from the touch sensor only if enough time has passed. If less than 20ms has elapsed, the function simply returns the previously read and stored data.

While this might not be the “ideal” solution from a purely theoretical standpoint (as LVGL still requests data more often than the sensor is physically read), it is a working solution! Now, when I set events for a button as CLICKED, it generates only one event as expected.


My main question (for a deeper understanding): Why does LVGL immediately call my _get_coords function again after a touch is detected, causing an immediate re-read of the touch display coordinates, even when LV_INDEV_DEF_READ_PERIOD is set to 33ms? Is LV_INDEV_DEF_READ_PERIOD merely a recommended period for LVGL’s internal processing, or should it strictly control the frequency of _read_data() calls?

regards.

“CLICKED” show up when there is a press and then a release. It doesn’t matter how long you have held the button for. The “CLICKED” event only gets triggered when the release happens. It’s normal to see something like this happening…

PRESSED
LONG_PRESS
LONG_PRESS
LONG_PRESS
LONG_PRESS
CLICKED
RELEASED

the CLICKED even should show up only a single time for a single press and then release of the touchscreen. If it is not then we need to look at why it’s not and see if there is an issue with the driver, lvgl or if it is a PEBKAC issue.

Just so you know Python is a very dynamic programming language and it allows you to do all kinds of nifty things. One of those things is called “monkey patching”. Monkey patching allows you to override the default behavior of code from an external library. External being not something that you have written. as an example…

import axs15231
import time

class AXS15231(axs15231.AXS15231):

    def __init__(self, device, touch_cal=None,
                        startup_rotation=lv.DISPLAY_ROTATION._0,  # NOQA
                        debug=False):

        super().__init__(device, touch_cal, startup_rotation, debug)
        self.__last_x = -1
        self.__last_y = -1
        self.__last_state = self.RELEASED

    def _get_coords(self):
        touch_data = self._read_data()

        if touch_data:
            self.__last_x = touch_data[0].x
            self.__last_y = touch_data[0].y

            if touch_data[0].event == 1:
                self.__last_state = self.RELEASED
                
            else:
                self.__last_state = self.PRESSED

        return self.__last_state, self.__last_x, self.__last_y


indev = AXS15231(...)

And that code abose is what you would add to your main.py file. No need to alter the code directly in the axs15231.py file. You can patch the code in the python source code files that you write.

Either way the problem you are encountering is an issue with the driver and it reporting some kind of a state change in an odd manner. I would need to add some debugging code to the driver to see what is actually going on. I am thinking that maybe I am reading something from the touch IC incorrectly and it is saying that there is input but the state is released for some reason. This is why you end up with the button being released.

If I am correct in what I am saying then the code above will also fail. It will behave the same way. If that is the case then I will do some debugging.

Also the way you have gone about dealing with the data buffers is wrong. You are going to cause a lot of memory fragmentation doing what you are doing.

…original code … not generate what you write … generate :
PRESSED,CLICKED,RELEASE,PRESSED,CLICKED,RELEASE … around … in cycle …

Yeah that’s because there is an issue in the driver that needs to be sorted out. I don’t have access to all of thew hardware that I have written drivers for. It takes someone willing to spend the time to help me work through bugs like this one. If you are will to do that I am more than happy to fix the issue. What your did may work but there is a better way to correct the problem without needing to consume additional resources.

If you are interested in helping out with debugging it lemme know.