BLE issue with xpt2046.py touch driver

The touch driver is affecting the BLE scan function.
I have a recurring interrupt set to 20 seconds and a scan length of 5 seconds.
I calculate the time to start the interrupt and print “'seconds to start:”
It is here that a mysterious delay is injected of 10 seconds
that causes the BLE irq to become unresponsive.

I have set the… “timer period in ticks” to 10 in the modlvesp32.c file which worked for display issue.
And also set ili9341 mhz=25 for running in full duplex and factor=8) to minimize memory.

import ubluetooth, utime
import lvgl as lv
from machine import Timer
from micropython import const, schedule
from ili9341 import ili9341
from xpt2046 import xpt2046

lv.init()
disp = ili9341(mhz=25, factor=8) # and 10 // The timer period in ticks.
touch = xpt2046()
_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_COMPLETE = const(6)
bt=ubluetooth.BLE()
bt.active(True)

def ble(tm):
    start = utime.time()
    def bt_irq(event, data):
        if event == _IRQ_SCAN_RESULT:
            pass
        elif event == _IRQ_SCAN_COMPLETE:
            schedule(print, 'scan done... runtime {}sec' .format(utime.time()))
    bt.gap_scan(5000)   # Scan for 5s
    bt.irq(handler = bt_irq)
    print('seconds to start: {}' .format(utime.time() - start))

tm = Timer(-1)
tm.init(period=20000, mode=Timer.PERIODIC, callback=ble) # ble scan every 20 sec

Note **

If I schedule the print line ie: schedule(print,‘seconds to start: {}’ .format(utime.time() - start))
I will get an exception at that approximate delay point…
image
I believe that the queue is full due to touch interrupts.

If I comment out the line… touch = xpt2046() and only run with the display driver… no issue !!!
image

Do touch interrupts get sent even when the screen is not pressed? That seems a bit wasteful in terms of energy consumption. Possibly something to look into.

Actually there are no interrupts.
Every time lvgl calls read_cb of the indev driver, the driver queries the touch panel and obtains coordinates and touch status.
It’s possible to improve the driver so it would query the touch panel only upon touch interrupt.

Added GitHub issue to track this:

So that means that merely initializing the XPT2046 stops the Timer from working? That’s strange. There aren’t any references to schedule in the driver, so I don’t see how it is filling up the queue.

probably from here…

lv_task_handler gets scheduled every portTICK_RATE_MS milliseconds. Can you find what that value is on your platform?

stated at beginning…

I think that’s a better approach.

The issue with the BLE bt_irq function (dropping-out, stalling, disabled, halting, freezing, crashing) is the conflict it has with the “xTimer = xTimerCreate”
or routines spawned of it in the modlvesp32.c file.

see post in “https://forum.micropython.org/viewtopic.php?f=18&t=8068
In that post I have a small sketch for others to see if it exhibits it for them.

If I import… “lvgl” BLE runs with no issue.
If I import… “lvgl” and “lvesp32” with…
// timer period in ticks… set to 1… BLE stops almost immediately.
// timer period in ticks… set to 10… BLE will run for ~ 1 hour.
// timer period in ticks… set to 100… BLE will run for ~ 5 hour.

The more ticks I add the less responsive the display becomes.
There are applications where the screen can be unchanged for hours,
not a single pixel change yet the…

I don’t require high screen refresh rates.
Is it possible to refresh the display only when needed… with a manual call,
and query the touch panel only upon a touch interrupt?

Instead of importing the lvesp32 module you could call lv.task_handler() yourself manually whenever you need. Only when lv.task_handler() is called the display is refreshed.

The current xpt2046 touch driver implementation doesn’t use interrupts, so the touch panel is queried as an indirect result of lv.task_handler() call, which itself is called periodically by lvesp32.

I imagine the touch driver can be improved, by responding to a touch interrupt by -

  • Querying the touch panel and storing the coordinates and touch status
  • Scheduling a call to lv.task_handler() such that the display could be updated as a result of the touch.

Keep in mind that this breaks animations.

True.
But could be useful when screen updates rarely and power consumption is very important. An example use-case could be e-ink displays where animations are not very practical anyway.

lvesp32 module seems to have been the absolute culprit for all the BLE problems.
Removing lvesp32 and using the modILI9341.c module and lv.task_handler() when needed, the BLE scan routine has now run uninterrupted for over 44 hours.
Another benefit of using the modILI9341.c module is the ability to share the SPI bus with an SD card.

Implementing this would be greatly appreciated !!!

I’m sure there are quite a few projects out there that would benefit from this!