1 Introduction

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.

2 Prerequisites

  • 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.

3 Step 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.

4 Step 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)

5 Step 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).

6 Step 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.

7 Step 5: Unmount

umount ~/mnt/strg01

8 Step 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