Here are the full details for how to enable and disable the CIRCUITPY, MIDI, and serial USB devices. HID devices are more complicated, and we'll cover them on their own page.
USB Setup and Configuration is Done in boot.py
All the code examples on this page must be put in boot.py. If you try to use them in code.py, you'll get an error, because by the time code.py runs, the USB devices are already set up.
Hard Reset Required After Changing boot.py
boot.py runs only after a hard reset. So if you change boot.py, you'll need to reset the board to have it re-run. Just editing boot.py or typing ctrl-D in the REPL will not cause it to re-run again. Make sure your changes are completely written out before you reset, to avoid confusion and filesystem corruption.
All the code examples in the page go in boot.py. boot.py only runs after a hard reset. So reset the board or power-cycle the board after you've changed boot.py and waited for your changes to be written to the board.
CIRCUITPY Mass Storage Device
The CIRCUITPY drive is normally visible on the host computer. To disable it showing up as a USB device, you can disable the drive in boot.py, as shown below. But note that if you add only the lines below, you'll lock yourself out (see below) from editing files! So don't put just this in your boot.py without realizing the consequences.
# Don't do just this! You'll lock yourself out from editing files. import storage storage.disable_usb_drive()
Note that disabling the USB device does not make the drive not work. It's still available for use by your program. In CircuitPython 9.0.0 and later, CIRCUITPY also becomes read-write to your program if it is not visible over USB. In earlier versions of CIrcuitPython, if you need to write to CIRCUITPY in your program, you need to use storage.remount("/", readonly=False)
to remount it as read/write. See this guide page for more details.
There is also a storage.enable_usb_drive()
function, but you normally don't need to use it, unless your build has CIRCUITPY disabled by default or you want to re-enable it after disabling it in boot.py.
import storage storage.disable_usb_drive() storage.enable_usb_drive() # Changed my mind :)
import usb_midi usb_midi.disable()
Some microcontrollers, such as the STM32F4, ESP32-S2, and ESP32-S3 do not provide enough USB endpoints (details here) to allow MIDI to be enabled all the time. On those boards, MIDI is disabled by default, but is available. If you want to enable it, you'll need to disable some other USB device to free up a pair of endpoints to accommodate MIDI. For example, you could do this:
import usb_hid, usb_midi # On some boards, we need to give up HID to accomodate MIDI. usb_hid.disable() usb_midi.enable()
USB Serial: Console (REPL) and Data
CircuitPython normally provides a USB serial device which lets you talk to the CircuitPython console, where you can use the Python REPL. On Windows, this device shows up as a numbered COM port, such as COM5. On Linux, it shows up as /dev/tty device, often /dev/ttyACM0. On MacOS, it shows up with a name starting with /dev/cu, such as /dev/cu.usbmodem14301.
The serial device is called a CDC device, which stands for "Communications Device Class". The CircuitPython module that controls serial devices is called usb_cdc
.
CircuitPython can also optionally provide a second serial device, which is not connected to the console. It's called the data
serial device. You can send and receive arbitrary binary data on this device, so it's very useful if you want to exchange data or commands without worrying about the REPL interfering or a ctrl-C character stopping your program. The second serial channel will appear as a second COM port or /dev/tty or /dev/cu device, with a different name.
For details about how to use the second serial device, see the usb_cdc
documentation.
Note that some microcontrollers have hardware limitations which can make using the second serial device awkward or impossible. See this page for more information.
You can enable and disable the console
device and the data
device independently. The console
device is enabled by default, but the data
device is not.
import usb_cdc usb_cdc.disable() # Disable both serial devices. usb_cdc.enable(console=True, data=False) # Enable just console # (the default setting) usb_cdc.enable(console=True, data=True) # Enable console and data usb_cdc.enable(console=False, data=False) # Disable both # Same as usb_cdc.disable()
Which Serial Port on the Host?
Since turning on the data
device presents another serial port to the host, you want to be able to determine which serial ports correspond to which CircuitPython devices. You can use the Adafruit_Board_Toolkit Python library, which is available for installation via pip3 install adafruit-board-toolkit
.
You can list the available usb_cdc.data
serial ports using adafruit_board_toolkit.circuitpython_serial.data_comports()
. Similarly, to get a list of the usb_cdc.console
(REPL) serial ports, use adafruit_board_toolkit.circuitpython.repl_comports()
. Full documentation is here.
Don't Lock Yourself Out!
If you turn off both CIRCUITPY and the REPL in boot.py, and don't provide a way to turn them back on, you will lock yourself out of your board: you won't have any way to edit files anymore. You can recover by forcing the board to start in safe mode, which skips running boot.py. But it's easier and better to provide yourself an out: for instance, allow button push to skip disabling the devices.
This kind of code will lock you out:
import storage, usb_cdc # DON'T DO THIS! storage.disable_usb_drive() usb_cdc.disable()
The code below is safer. It skips turning off both devices if a button is pushed. The first vesion of the code is for buttons that are grounded when pressed.
# This example is for the MacroPad, # or any board with buttons that are connected to ground when pressed. import storage import board, digitalio # On the Macropad, pressing a key grounds it. You need to set a pull-up. # If not pressed, the key will be at +V (due to the pull-up). button = digitalio.DigitalInOut(board.KEY12) button.pull = digitalio.Pull.UP # Disable devices only if button is not pressed. if button.value: storage.disable_usb_drive()
The second version is for buttons that are connected to +V when pressed.
# This example is for a Circuit Playground, # or any board with buttons that are connected to +V when pressed. import storage, usb_cdc import board, digitalio # On the Circuit Playground, pressing an on-board button # connects the button to +V. button = digitalio.DigitalInOut(board.BUTTON_A) button.pull = digitalio.Pull.DOWN # Disable devices only if button is not pressed. if not button.value: storage.disable_usb_drive() usb_cdc.disable()
Text editor powered by tinymce.