Futures and Coroutines and Loops! Oh my!
I have just published an updated version of esp4s, the project that uses Scratch to interface to an Arduino Esplora microcontroller board. This latest version uses Python 3.4.3 and its associated asyncio library. The new program is called esp4s-aio and is available on Github.
Going from proof of concept to a finished project was not as simple as I had originally thought. The Python documentation for asyncio is really great for reference once you understand how to use the library, but at least for me, was not very instructive for a first time user.
But once I figured out how to convert Pyserial's readline() and write() to "futures", and was able to instantiate and communicate with an aiohttp HTTP server, I was well on my way to finishing the task at hand.
But those weren't my only educational challenges. I also needed to learn how to unit test the code and came upon pytest-asyncio. After asking the package authors several rookie questions, and receiving quick and accurate answers (without any snark I might add) the last pieces of the educational puzzle were in place.
Now on to the code. I started with the same architectural design I used for the original esp4s. However, working through the code, I quickly realized that I could take a simpler, more sequential code flow approach than I used for the original multi-threaded esp4s project. This not only simplified the design, but the testing and debugging, as well.
One very major design departure from the original project, was to go from having the Esplora pushing out all sensor data every 25 ms. to a polled approach.I was concerned that performance would suffer but that turned out not to be the case.
Now on to the results. I used a common Scratch script called test.sb2, ( which is provided in the esp4s-aio distribution) to compare esp4s and esp4s-aio. The Scratch script toggles an LED on the Esplora while concurrently displaying status for all 16 Esplora sensors. Scratch polls for status data at a rate of approximately 30 times per second.
It was interesting to find that the esp4s-aio version shows no display lag as sensor data varies, but the original version does (which means that the design of the original was sub-optimal).
However, more dramatic was the difference in CPU utilization. First, here is CPU utilization for the original:
And now the CPU utilization for esp4s-aio:
In this graph, the first 20 seconds are before Scratch was started and esp4s-aio is running idle. The increase begins when the Scratch script starts polling for data.
So overall, I am very pleased with the results, and plan to use asyncio coroutines for several future projects. Since my projects tend to be more I/O intensive than CPU intensive, asyncio and coroutines are definitely in my future.