USB Devices In CircuitPython
I've done two projects in CircuitPython and decided I'm a fan. The second project was a USB keyboard which brought my attention to CircuitPython's USB capability advantage over classic Arduino setups. They look interesting, but having two projects also exposed some strange CircuitPython microcontroller behavior.
Scenario 1: Plug in second CircuitPython board
I can have a CircuitPython project up and running along attached to my computer with its console output shown on Mu's serial terminal. If I then plug in a second CircuitPython microcontroller, execution of the first one would halt with KeybardInterrupt
as if I had pressed Control+C. I was surprised to discover this interaction as I had expected them to operate independently.
Scenario 2: Unplug one of two CircuitPython boards
If I have two CircuitPython projects up and running attached to my computer, again with console output shown on Mu serial terminal, unplugging the one not connected to Mu would halt the not-unplugged unit with KeyboardInterrupt
. Why doesn't it just keep running?
Control+D To Resume
In both cases I could soft restart the board by pressing Control+D in Mu serial terminal, but this would obviously be a problem if that device was my keyboard running KMK firmware. I can't press Control+D if my keyboard's KMK firmware has been halted with KeyboardInterrupt
!
I thought maybe this was a KMK keyboard thing, but I quickly determined it's more general. Whichever CircuitPython device is plugged/unplugged, the other device halts. The good news is that this seems to only happen if Mu serial terminal was connected. Maybe this is a Mu issue? Either way, it appears a way to avoid this problem is to deactivate the serial terminal of a CircuitPython microcontroller after development is complete and it is "running in production". I went looking for instructions on how I might accomplish such a goal and found Adafruit's Customizing USB Devices in CircuitPython.
The good news is: yes, it is possible to deactivate the serial text terminal as well as the CIRCUITPY
USB storage volume. The magic has to happen in boot.py
, which runs before USB hardware configuration occurs. This document also explains that USB MIDI hardware is also part of CircuitPython default USB behavior, something I hadn't noticed because I hadn't played with MIDI.
The document also explains more about how CircuitPython's USB magic works behind the scenes. Valuable background to understand how microcontroller implementation can limit the number of USB devices that can be presented over a single cable. There's also a second USB serial port that is off by default. It can be turned on after turning off certain other hardware, if we ever need an asynchronous serial port separate from the Python REPL console. Good to know as I proceed to play with other CircuitPython devices.