Controlling microcontrollers over USB with the Web Serial API
Under Control
Upgrade your computer with LEDs, buttons, or sensors to control a microcontroller board over USB from your web browser.
Microcontroller boards such as Arduino, Raspberry Pi Pico, and ESP32 can be connected to various LEDs, buttons, and sensors. Many of these boards have a built-in WiFi chip, which allows for remote control. However, sometimes WiFi is not possible, too complicated, or simply unnecessary.
Fortunately, most microcontroller boards for makers are equipped with a universal serial bus (USB) connection, which can often be used to send commands to the microcontroller from your computer or to receive sensor data. In this article, I explore what you need to establish two-way communication over USB, and I guide you through writing the necessary code for both the microcontroller and the computer.
USB CDC
To enable communication between the microcontroller and computer, this project uses USB communications device class (CDC). When you connect a USB CDC device to your computer, this interface appears in your Linux system as a device, like /dev/ttyACM0
. With this device file, software on your computer can communicate with the microcontroller.
Therefore, you need to establish a serial connection over USB CDC on the microcontroller. In this article, I do this with CircuitPython [1], which supports hundreds of microcontroller boards. Make sure to choose a board with USB CDC support [2] (Figure 1). I have successfully tested this project with the Raspberry Pi Pico (W), Arduino Nano RP2040 Connect, Seeed Studio XIAO SAMD21, and Seeed Studio XIAO nRF52840. For other boards, you might need to modify the CircuitPython code slightly or install the firmware differently.
Installing CircuitPython
Note that you don't need a board with WiFi or Bluetooth Low Energy (BLE) connectivity for serial communication, so you can choose a more affordable board, such as the Raspberry Pi Pico (the version without WiFi), which I use for the examples in this article. To download the appropriate CircuitPython firmware, visit the CircuitPython Downloads page [3] and choose the link for your board.
At the time of writing, the Raspberry Pi Pico [4] version was 8.2.2. You can choose your language, but that doesn't matter much. On the device's download page (Figure 2), you'll see that the list of built-in modules includes usb_cdc
, which confirms that you can use USB CDC on this board.
For the Raspberry Pi Pico, the downloaded firmware file has the .uf2
extension. To install the firmware, press and hold the white BOOTSEL button on the Raspberry Pi Pico, connect the board to your computer with a micro-USB cable, and then release the button. The board's internal storage will now appear as a USB drive named RPI-RP2 on your computer. Drag and drop the .uf2
file onto that drive. After copying, the drive's name will change to CIRCUITPY.
Mu Editor
The easiest way to program your board in CircuitPython is with the code editor Mu [5]. You can download a TAR archive of an AppImage for Linux, currently at version 1.2.0. To untar the AppImage and make the file executable, run the following command:
tar xf MuEditor-Linux-1.2.0-x86_64.tar chmod + x Mu_Editor-1.2.0-x86_64.AppImage
On most Linux distributions, you can now simply double-click the AppImage file in your favorite graphical file manager to start Mu. Detailed installation instructions for Mu [6] for various distributions can be found on the website.
After launching Mu, click Mode at the top left, choose CircuitPython from the list, and click OK. If you connect your board to your computer with a USB cable, Mu should detect it, displaying the message Detected new CircuitPython device at the bottom.
Now you can type the code you want to run on your board in the large text field. To test the hardware to make sure it is working properly, enter the code in Listing 1, which makes the built-in LED blink.
Listing 1
Blink the LED
¡ì¡ìnonumber """Make the built-in LED blink.""" from board import LED from digitalio import DigitalInOut, Direction from time import sleep led = DigitalInOut(LED) led.direction = Direction.OUTPUT while True: led.value = True sleep(0.5) led.value = False sleep(0.5)
At the top, click Save, select code.py (Figure 3), and confirm that you want to overwrite it. You should now see the built-in LED on the Raspberry Pi Pico blinking, confirming that the board is working.
Buy this article as PDF
(incl. VAT)