peterhinch / micropython-async

Application of uasyncio to hardware interfaces. Tutorial and code.
MIT License
739 stars 168 forks source link

"Interrupts" for awaitable #97

Closed AuHau closed 1 year ago

AuHau commented 1 year ago

First of all thanks for such a great repo with great resources about this topic! It is really life-saver!

I am using your AADC driver to sense some ADC values. I am currently running into a problem that the values might never reach the desired range, because of some other problem that happened. In my use case, I am driving a linear actuator and sensing its position. The ADC readings represent the extension of the actuator's shaft with using it for awaiting until the shaft is in the desired position. But at the same time, I am running obstacle detection and if an obstacle is detected then the shaft is stopped and hence will "never" reaches the desired target position. In this case, when the obstacle is detected, I would need to "cancel" the original awaited AADC range.

I know about task cancellation, but somehow I am not sure about what architecture I should really employ for this task.

I am planning to extend the AADC class with cancel() method, which will set an internal flag that once detected in the ioctl() call, will result in unblocking the awaited call. But maybe is there some other better approach?

peterhinch commented 1 year ago

I'm struggling to understand the problem here. Consider this example from the docs:

aadc = AADC(ADC('X1'))
async def foo():
    while True:
        aadc.sense(normal=False)
        value = await aadc(25_000, 39_000)  # Wait until in range
        print('In range:', value)
        aadc.sense(normal=True)
        value = await aadc()  # Wait until out of range
        print('Out of range:', value)

There is nothing to stop another task from cancelling the foo() task and creating another instance (possibly with different args) when necessary.

evt = asyncio.Event()  # Obstacle detected
async def bar():
    foo_task = asyncio.create_task(foo())
    await evt.wait()  # Obstacle occurs
    foo_task.cancel()
AuHau commented 1 year ago

You are right. It was just my problem to wrap my head around this and structure the code in a different way. I am closing this. Thanks anyway!