ESP32 In MicroPython: Asyncio |
Written by Harry Fairhead & Mike James | ||||||
Monday, 09 September 2024 | ||||||
Page 5 of 5
Using uasyncioWhen you first meet uasyncio, or its full Python equivalent asyncio, it is all too easy to see it as a total solution. The idea that you can structure a program as a collection of tasks which get to run when they are needed seems to be a simplification. However, the MicroPython implementation of uasyncio provides only two coroutines that free the thread – uasyncio.sleep() and uasyncio.sleep_ms(). There are also has some network classes and methods which make uasyncio much more useful, but it is still worth looking at its more basic use.
The only sort of task you can write that actually gives up the thread, and hence take advantage of asynchronous implementation, are of the form: async task1(): while True: do something await uasyncio.sleep(t) do something The call to sleep releases the thread and allows other tasks to run for at least t seconds. What this means is that all of the tasks you create have to be able to be suspended for a given amount of time to allow other tasks to run. Notice that there is no indication of how often any of the tasks will run. For example, if one of the tasks is designed to read a sensor every few seconds then there is no way that you can use an asynchronous approach to guarantee that this is the case unless you handcraft all of the other tasks to ensure that the sensor task gets its turn at the right time. This is just as difficult, if not more so, than writing a simple polling loop that calls the tasks in a fixed order. Consider the following program modeled on the example in the documentation: import uasyncio from machine import Pin async def blink(led, period_ms): while True: led.on() await uasyncio.sleep_ms(5) led.off() await uasyncio.sleep_ms(period_ms) async def main(led1, led2): uasyncio.create_task(blink(led1, 700)) uasyncio.create_task(blink(led2, 400)) await uasyncio.sleep_ms(10_000) uasyncio.run(main(Pin(22,Pin.OUT), Pin(23,Pin.OUT))) This flashes two LEDs connected to GPIO22 and GPIO23. The blink coroutine turns the LED on and then sleeps for 5ms, giving other tasks a chance to run. It then switches the LED off and sleeps for a specified period. If you try this out you will find that you do get 5ms pulses spaced at 700ms and 400ms. However, none of the periods are guaranteed. All it takes is another task, or a set of tasks, that take longer to process than 5ms to disrupt the intended timing. For example, we can introduce a task that simply wastes some time: import uasyncio from machine import Pin from time import sleep_ms async def blink(led, period_ms): while True: led.on() await uasyncio.sleep_ms(5) led.off() await uasyncio.sleep_ms(period_ms) async def timewaste(): while True: sleep_ms(10) await uasyncio.sleep_ms(0) async def main(led1, led2): uasyncio.create_task(blink(led1, 700)) uasyncio.create_task(blink(led2, 400)) uasyncio.create_task(timewaste()) await uasyncio.sleep_ms(10_000) uasyncio.run(main(Pin(22,Pin.OUT), Pin(23,Pin.OUT))) Now if you run the program you will discover that the pulses are now 10ms in size. The timewaste coroutine now hogs the only thread of execution, only giving it up every 10ms, which means that the blink coroutine only gets the thread back after at least 10ms whenever it gives it up. Even if you find this difficult to understand, an additional negative point for the approach is that the timing of blink depends on the timing of the other tasks it finds itself running with. Asynchronous approaches generally only work well when each task keeps the thread for a time that is much shorter than the time that each task needs to run – and this implies that the thread has to be idle for most of the time. You can convert any polling interaction into an uasyncio task by using the sleep_ms method. All you have to do is write a small infinite pooling loop: async def checkReady(): while True: if read hardware state: process hardware await uasyncio.sleep_ms(10) This can be run along with similar tasks and as long as none of them take longer to process the hardware than the sleep time they should all work together. In chapter but not in this extract
Summary
Programming the ESP32in MicroPythonBy Harry Fairhead & Mike JamesBuy from Amazon. ContentsPreface
<ASIN:187196282X>
Comments
or email your comment to: comments@i-programmer.info To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin. |
||||||
Last Updated ( Tuesday, 10 September 2024 ) |