CircuitPython busio For Hardware Serial Communication
For my first nontrivial CircuitPython project, I thought I would try getting a microcontroller to communicate with control panel salvaged from a Canon MX340 multi-function inkjet. Like most microcontrollers, the RP2040 chip at the heart of my KB2040 board can handle asynchronous serial communication via its UART hardware peripheral. Under CircuitPython, this peripheral is exposed by an uart
class. It is under the umbrella of busio
library, which includes hardware-accelerated communication of popular serial buses I2C, SPI, and asynchronous serial. CircuitPython has several libraries with the io
suffix, and given their hardware-focused nature they appear to be a big chunk of the work required to port CircuitPython to a new microcontroller.
One aspects of CircuitPython (and MicroPython) I found enticing is the ideal that I could develop and debug code on my desktop computer and then copy it to run on a microcontroller. Unfortunately this goes out the window when I want to use hardware-accelerated features like busio.uart
. Its name clearly announces that it is not trying to act like PySerial on the desktop. If I want to write something that works on both desktop Python and microcontroller CircuitPython, I would have to write an abstraction layer restricted to the small subset of common features I need in my project. Learning how to write such adapter code is on my Python learning to-do list, but it is out of scope for my first CircuitPython project. I'll stick with busio.uart
and develop/debug strictly on microcontroller.
One Python skill area I want to improve is structuring my code to better handle non-sequential events. The relevant scenario today is sending serial data out the transmit pin while simultaneously responsive to serial data coming in over the receive pin. Plus handling when the two interact: for example waiting to receive an acknowledgement after sending data. My earlier serial data filtering tool handled reading from two serial ports by rapidly switching between polling the two ports, but in hindsight, that was not elegant code and it didn't handle interaction between the two streams. In the search for a better way, I recall Python supported the async/await pattern I've encountered earlier in JavaScript and C#. Furthermore, CircuitPython supports some form of the pattern as well, so I'm going to give it another go.