PRESTO - Polling touch prevents plasma updates

First off, thanks so much for the Presto, it’s so nicely made, and is exactly what I was looking for!

I’m working on a basic “window manager” for a project, to help manage multi-page apps (will share soon - if it is of interest). I added backlight timeout based on touch interactivity. I have all this working fine with the main screen brightness. I tried to add support for managing the glow LEDs (via plasma), and found half the time the LEDs weren’t updating.

I eventually figured out that repeatedly polling the touch screen immediately after updating the LEDs, causes the updates to fail. Inserting a small sleep seems to solve the issue.

Sorry I’m relatively new to the 2050 platform, not sure if this is expected or not. I’m probably doing something silly. The code below should demonstrate this issue. To repro, run this, wait for the screen to sleep and touch it to wake. After a few cycles, the glow LEDs will update intermittently or not at all.

Uncomment line 57 and it should then work as expected.

The additional timeout will work fine for my application. Wanted to post here in case it was any help for others, or it was unexpected behaviour.

Many thanks in advance,
Tom

import plasma
import time

from presto import Presto

presto = Presto()
ambient = plasma.WS2812(7, 0, 0, 33)
ambient.start()

last_touch_ms = None
current_brightness = 0.0

DIM_TIMEOUT = 3000
SLEEP_TIMEOUT = 6000
AMBIENT_COLOR = (255, 255, 255)

WHITE = presto.display.create_pen(255, 255, 255)
BLACK = presto.display.create_pen(0, 0, 0)

while True:

    presto.touch.poll()

    new_brightness = 1.0
    time_ms = time.ticks_ms()

    if presto.touch.state or not last_touch_ms:
        last_touch_ms = time_ms

    delta_ms = time.ticks_diff(time_ms, last_touch_ms)

    if delta_ms > SLEEP_TIMEOUT:
        new_brightness = 0.0
    elif delta_ms > DIM_TIMEOUT:
        new_brightness = 0.3

    presto.display.set_pen(WHITE)
    presto.display.clear()
    presto.display.set_pen(BLACK)
    presto.display.text(f"{new_brightness} @ {time_ms}", 10, 10)
    presto.update()

    if new_brightness != current_brightness:
        current_brightness = new_brightness

        presto.set_backlight(new_brightness)

        new_rgb = [int(v * new_brightness) for v in AMBIENT_COLOR]
        for i in range(7):
            ambient.set_rgb(i, *new_rgb)

        # Uncomment to fix
        # Without this sleep ambient LED updates often don't happen.
        # This seems to be the minimum sleep duration to be reliable.
        # |
        # v
        #time.sleep_ms(15)

        # Wait for the touch to end, so it is effectively swallowed by
        # the backlight wake mechanism.
        while presto.touch.state:
            time.sleep_ms(5)
            presto.touch.poll()

        # ... the rest of the application code

You should have a read about asyncio. This is a Python module for cooperative multitasking and usually is the tool of choice for this kind of parallel stuff. Basically, asyncio uses “co-routines” (co-operative routines) that give up processor time to other coros at a suitable point in time. Remember: we don’t have an operating system on a MCU so it can’t be the OS that gives programs a time-slice. Of course you could also go with threading, but I think asyncio is much more transparent.

Hey @bablokb - thanks - yeah that’s going to be useful for sure.

What’s interesting, is that whilst looking into this - I update the board to the 0.0.7, and now the above code no longer reproduces the issue! Looking at the diff, there’s nothing majorly obvious in any of the commits that might have changed this either!