Application of uasyncio to hardware interfaces. Tutorial and code.
Switch branches/tags
Nothing to show
Clone or download
Permalink
Failed to load latest commit information.
HD44780 gps/README.md Add timing notes and wiring. May 13, 2018
benchmarks Doc improvements. Jul 27, 2018
fast_io run_until_complete returns coro return value. Jul 29, 2018
gps iotest4.py added. Jun 8, 2018
htu21d Adjust docs for uasyncio V2.0. Feb 24, 2018
i2c I2C: Add flow control. Reduce allocation. Oct 19, 2018
lowpower Tidy up lowpower README. Jul 28, 2018
nec_ir NEC IR driver and demos now run on ESP32. Jul 30, 2018
syncom_as syncom.py fix bug where verbose was false. Aug 17, 2017
.gitignore Initial commit Dec 6, 2016
DRIVERS.md iotest4.py added. Jun 8, 2018
FASTPOLL.md run_until_complete returns coro return value. Jul 29, 2018
LICENSE Initial commit Dec 6, 2016
PRIMITIVES.md Tutorial: expand beginner section 7. Jan 29, 2018
README.md I2C library added. Oct 15, 2018
TUTORIAL.md Docs: minor fixes. Jul 26, 2018
UNDER_THE_HOOD.md UNDER_THE_HOOD.md: ran the spoiling chuckler. Jul 7, 2018
aledflash.py Tutorial: update stream I/O information. Jun 19, 2018
apoll.py Tutorial: update stream I/O information. Jun 19, 2018
aqtest.py Tutorial: update stream I/O information. Jun 19, 2018
astests.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
aswitch.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
asyn.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
asyn_demos.py Cancellable tasks no longer get task_id as an arg. Jan 11, 2018
asyntest.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
auart.py Adjust docs for uasyncio V2.0. Feb 24, 2018
auart_hd.py auart_hd.py added. Tutorial amended to suit. Apr 5, 2018
awaitable.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
cantest.py Uasyncio V2.0 code changes. Feb 27, 2018
chain.py HD44780 LCD driver added. May 13, 2017
check_async_code.py check_async_code.py warns of more possible issues. Dec 14, 2017
io.py HD44780 LCD driver added. May 13, 2017
iorw.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
roundrobin.py Major update: asyncio_priority is replaced by a modified version of u… Jul 5, 2018
sock_nonblock.py Tutorial adds notes on nonblocking sockets. Feb 20, 2018

README.md

1. The MicroPython uasyncio library

This repository comprises the following parts.

  1. A modified fast_io version of uasyncio. This is a "drop in" replacement for the official version providing additional functionality.
  2. A module enabling the fast_io version to run with very low power draw.
  3. Resources for users of official or fast_io versions:
  • A tutorial An introductory tutorial on asynchronous programming and the use of the uasyncio library (asyncio subset).
  • Asynchronous device drivers. A module providing drivers for devices such as switches and pushbuttons.
  • Synchronisation primitives. Provides commonly used synchronisation primitives plus an API for task cancellation and monitoring.
  • A driver for an IR remote control This is intended as an example of an asynchronous device driver. It decodes signals received from infra red remote controls using the popular NEC protocol.
  • A driver for the HTU21D temperature and humidity sensor. This is intended to be portable across platforms and is another example of an asynchronous device driver.
  • A driver for character LCD displays. A simple asynchronous interface to displays based on the Hitachi HD44780 chip.
  • A driver for GPS modules Runs a background task to read and decode NMEA sentences, providing constantly updated position, course, altitude and time/date information.
  • Communication using I2C slave mode. Enables a Pyboard to to communicate with another MicroPython device using stream I/O. The Pyboard achieves bidirectional communication with targets such as an ESP8266.
  • Communication between devices Enables MicroPython boards to communicate without using a UART. This is hardware agnostic but slower than the I2C version.
  • Under the hood A guide to help understand the uasyncio code. For scheduler geeks and those wishing to modify uasyncio.

2. Version and installation of uasyncio

The documentation and code in this repository assume uasyncio version 2.0.x, which is the version on PyPi and in the official micropython-lib. This requires firmware dated 22nd Feb 2018 or later. Use of the stream I/O mechanism requires firmware after 17th June 2018.

See tutorial for installation instructions.

3. uasyncio development state

These notes are intended for users familiar with asyncio under CPython.

The MicroPython language is based on CPython 3.4. The uasyncio library supports a subset of the CPython 3.4 asyncio library with some V3.5 extensions. In addition there are non-standard extensions to optimise services such as millisecond level timing and task cancellation. Its design focus is on high performance and scheduling is performed without RAM allocation.

The uasyncio library supports the following Python 3.5 features:

  • async def and await syntax.
  • Awaitable classes (using __iter__ rather than __await__).
  • Asynchronous context managers.
  • Asynchronous iterators.
  • Event loop methods call_soon and call_later.
  • sleep(seconds).

It supports millisecond level timing with the following:

  • Event loop method call_later_ms
  • uasyncio sleep_ms(time)

uasyncio V2 supports coroutine timeouts and cancellation.

  • wait_for(coro, t_secs) runs coro with a timeout.
  • cancel(coro) tags coro for cancellation when it is next scheduled.

Classes Task and Future are not supported.

3.1 Asynchronous I/O

Asynchronous I/O (StreamReader and StreamWriter classes) support devices with streaming drivers, such as UARTs and sockets. It is now possible to write streaming device drivers in Python.

3.2 Time values

For timing asyncio uses floating point values of seconds. The uasyncio.sleep method accepts floats (including sub-second values) or integers. Note that in MicroPython the use of floats implies RAM allocation which incurs a performance penalty. The design of uasyncio enables allocation-free scheduling. In applications where performance is an issue, integers should be used and the millisecond level functions (with integer arguments) employed where necessary.

The loop.time method returns an integer number of milliseconds whereas CPython returns a floating point number of seconds. call_at follows the same convention.

4. The "fast_io" version.

Official uasyncio suffers from high levels of latency when scheduling I/O in typical applications. It also has an issue which can cause bidirectional devices such as UART's to block. The fast_io version fixes the bug. It also provides a facility for reducing I/O latency which can substantially improve the performance of stream I/O drivers. It provides other features aimed at providing greater control over scheduling behaviour.

To take advantage of the reduced latency device drivers should be written to employ stream I/O. To operate at low latency they are simply run under the fast_io version. The tutorial has details of how to write streaming drivers.

4.1 A Pyboard-only low power module

This is documented here. In essence a Python file is placed on the device which configures the fast_io version of uasyncio to reduce power consumption at times when it is not busy. This provides a means of using uasyncio in battery powered projects.

4.2 Historical note

This repo formerly included asyncio_priority.py which is obsolete. Its main purpose was to provide a means of servicing fast hardware devices by means of coroutines running at a high priority. This was essentially a workround.

The official firmware now includes this major improvement which offers a much more efficient way of achieving the same end using stream I/O and efficient polling using select.poll.

5. The asyn.py library

This library (docs) provides 'micro' implementations of the asyncio synchronisation primitives. CPython docs

It also supports a Barrier class to facilitate coroutine synchronisation.

Coroutine cancellation is performed in an efficient manner in uasyncio. The asyn library uses this, further enabling the cancelling coro to pause until cancellation is complete. It also provides a means of checking the 'running' status of individual coroutines.

A lightweight implementation of asyncio.gather is provided.