1Introduction

I saw a micro:bit demo at the school I work and picked one up for myself. Turns out it’s a neat little device for collecting sensor data — and you don’t need a browser, an IDE, or any Microsoft-flavored tooling to work with it, which I first was afraid of. I’ve been using Arduinos, since their inception. After Qualcomm acquired Arduino, they are not that fun anymore — not that BBC (the owner of micro:bit) is flawless.

This guide shows how to read microphone data from the micro:bit over USB serial and visualize it as a live bar in the terminal. You can generalize this into reading any sort of data over USB serial from the device.

2Prerequisites

  • pipx install uflash
  • pipx install pyserial

uflash handles flashing MicroPython scripts onto the device (this is where the no-browser achievement is acquired). pyserial handles reading from the serial interface.

3Step 1: Mount the micro:bit

The micro:bit shows up as a USB mass storage device (after connected). Mount it with your user (usually UID=1000) owning the mount point:

doas mount -ouid=1000 /dev/sda ~/mnt/strg01

The device path may vary — /dev/sda is what it showed up as here. Check dmesg och lsblk after plugging it in if you’re unsure. I use ~/mnt/strg01 as my mount point, but you can use whatever.

4Step 2: Write the Firmware

This is the script that runs on the micro:bit itself. It reads the microphone level and prints it over serial every 50 ms. Quite lean, if I do say so myself — and that is good on such a small device. Turns out, it’s easy to get the 405 :( memory error quite easy.

mic_sender.py
from microbit import microphone, sleep

while True:
 print(microphone.sound_level())
 sleep(50)

5Step 3: Write the Listener

This runs on your computer and reads from the serial port, drawing a live colored bar in the terminal.

mic_listener.py
#!/usr/bin/env python3

import serial
import sys
import glob

BAR_WIDTH = 40
MAX_VAL = 255


def find_microbit():
 candidates = glob.glob("/dev/ttyACM*") + glob.glob("/dev/ttyUSB*")
 if candidates:
 return candidates[0]
 return None


def draw_bar(value):
 filled = int((value / MAX_VAL) * BAR_WIDTH)
 bar = "█" * filled + "░" * (BAR_WIDTH - filled)

 if value < 80:
 colour = "\033[92m"
 elif value < 160:
 colour = "\033[93m"
 else:
 colour = "\033[91m"
 reset = "\033[0m"
 print(f"\r{colour}[{bar}]{reset} {value:>3}", end="", flush=True)


def main():
 port = sys.argv[1] if len(sys.argv) > 1 else find_microbit()
 if not port:
 print("Could not find micro:bit. Plug it in or pass port as argument:")
 print("  python3 mic_listener.py /dev/ttyACM0")
 sys.exit(1)

 print(f"Connecting to {port} at 115200 baud... (Ctrl+C to stop)\n")

 with serial.Serial(port, baudrate=115200, timeout=1) as ser:
 try:
 while True:
 line = ser.readline().decode("utf-8", errors="ignore").strip()
 if line.isdigit():
 draw_bar(int(line))
 except KeyboardInterrupt:
 print("\nStopped.")


if __name__ == "__main__":
 main()

The bar is green below 80, yellow below 160, and red above that. Values range from 0–255 (8bit resolution).

6Step 4: Flash the Firmware

uflash mic_sender.py ~/mnt/strg01

Replace ~/mnt/strg01 with wherever you mounted the device. The flashing process can take a few seconds.

7Step 5: Unmount

umount ~/mnt/strg01

8Step 6: Run the Listener

python mic_listener.py

Or if you’ve made it executable:

chmod +x mic_listener.py
./mic_listener.py

The script will auto-detect the micro:bit on /dev/ttyACM* or /dev/ttyUSB*. If you have other devices on those interfaces, pass the port explicitly:

./mic_listener.py /dev/ttyACM0