Menlo

First Boot & Software Setup

Flash the motion control board, set up the Raspberry Pi, install the Asimov API.

The robot's software stack has three pieces:

  • the Motion Control Board (Radxa CM5 IO) running the Asimov MCB image
  • a Raspberry Pi running Raspberry Pi OS as the edge compute
  • the Asimov API on the Pi, connected to the MCB over wired Ethernet

1. Flash the Motion Control Board

You'll need:

  • Armbian-*-radxa-cm5-io-*.img.xz, the MCB image (provided to you)
  • rk3588_spl_loader_v1.22.114.bin, the Rockchip MaskROM loader from radxa/rkbin
  • A USB-C cable from your laptop to the MCB
  • A USB-to-serial adapter (FTDI or CH340) for the debug console

1.1. Install rkdeveloptool

Linux:

sudo apt install rkdeveloptool

macOS:

brew install libusb pkg-config autoconf automake
git clone https://github.com/rockchip-linux/rkdeveloptool /tmp/rkdt && cd /tmp/rkdt
autoreconf -i && ./configure
make CXXFLAGS="-O2 -Wno-error=vla-cxx-extension" && sudo cp rkdeveloptool /opt/homebrew/bin/

1.2. Set up the three connections

CableEndpoint on MCBWhenPurpose
Power12V DC barrel jackAlways connectedPowers the board
Serial adapterDBG header (UART2 TX/RX/GND)Always connectedConsole for boot logs and login
MaskROM USB-CU0 portOnly during flashingTalks to rkdeveloptool

1.3. Flash the image

  1. Hold the MaskROM button on the CM5 while turning on power. The blue LED confirms MaskROM mode.
  2. From the directory containing the two files, run:
    rkdeveloptool db rk3588_spl_loader_v1.22.114.bin
    xz -dk Armbian-*-radxa-cm5-io-*.img.xz
    rkdeveloptool wl 0 Armbian-*-radxa-cm5-io-*.img
    rkdeveloptool rd
  3. After rd, unplug USB-C from U0. Power and serial stay connected. The MCB reboots from eMMC into the new image.

1.4. Verify over serial

Open minicom at 1.5 Mbps (the kernel's console baud):

# macOS
ls /dev/cu.usb*
minicom -w -t xterm -l -R UTF-8 -b 1500000 -D /dev/cu.usbserial-XXXX

# Linux
sudo minicom -w -t xterm -l -R UTF-8 -b 1500000 -D /dev/ttyUSB0

Kernel boot logs appear, then a login prompt:

  • User: radxa
  • Password: asimov

The shell drops straight to a $ prompt. No setup wizard.


2. Flash the Raspberry Pi

The Pi runs the Asimov API and bridges applications to the MCB.

  1. Download Raspberry Pi Imager from raspberrypi.com/software.
  2. Insert a microSD card (16 GB or larger) into your laptop.
  3. In the Imager, choose:
    • Device: your Pi model (Pi 4 or Pi 5)
    • OS: Raspberry Pi OS (64-bit) Lite (no desktop)
    • Storage: your SD card
  4. Open the gear icon for Advanced Options and set:
    • Hostname (any value you want)
    • Username and password
    • Wi-Fi SSID and password
    • SSH: enabled. Paste your laptop's public key if you have one.
  5. Click Write, wait, then insert the SD card into the Pi and power it on.
  6. After about 30 seconds, SSH in from your laptop:
    ssh <username>@<hostname>.local

3. Network the Pi to the MCB

The MCB's wired Ethernet (end1) is pre-configured to 10.0.0.2/24. The Pi needs 10.0.0.1/24 on its eth0 to be on the same subnet.

Connect the Pi to the MCB with an Ethernet cable, then on the Pi:

sudo nmcli con add con-name asimov-mcb ifname eth0 type ethernet \
    ipv4.method manual ipv4.addresses 10.0.0.1/24
sudo nmcli con up asimov-mcb

# Test
ping -c 3 10.0.0.2
ssh [email protected]     # password: asimov

You land in the MCB shell. The Pi's Wi-Fi stays reachable from your laptop.


4. Install and run the Asimov API on the Pi

The Asimov API exposes LiveKit control and telemetry. Applications talk to the API; the API talks to the firmware on the MCB.

4.1. Prerequisites

  • Raspberry Pi OS Bookworm or newer.
  • Python 3.12 or newer. Bookworm ships 3.11. Install 3.12 with uv.
  • System libraries:
    sudo apt update
    sudo apt install -y portaudio19-dev libgl1 libglib2.0-0
  • A USB or CSI camera and a USB audio device (mic and speaker, same device or separate).

4.2. Install

git clone https://github.com/asimovinc/asimov-api ~/asimov-api
cd ~/asimov-api
make install               # creates .venv and installs the package

If python on $PATH is not 3.12:

uv venv --python 3.12 ~/asimov-api/.venv
~/asimov-api/.venv/bin/pip install -e .

Protobuf files are committed. Run make proto only if you edit proto/*.proto.

4.3. Find your camera

v4l2-ctl --list-devices

for N in $(ls /dev/video* | sed 's|/dev/video||'); do
    echo "=== /dev/video$N ==="
    v4l2-ctl -d /dev/video$N --list-formats 2>/dev/null | head -5
done

Note the index N of the device that lists at least one format (often MJPG or YUYV). Pass it as --camera-device N.

4.4. Find your audio devices

aplay -l       # speakers / playback
arecord -l     # microphones / capture

Note the human-readable name of your USB audio device (e.g. ReSpeaker, USB Audio). Pass that name, or a substring, to --mic-device and --speaker-device. ALSA's default device often does not work for USB capture; name the device explicitly.

Sample rate gotcha

Some cheap USB audio devices only accept 16 kHz output. If you see [Errno -9997] Invalid sample rate when the speaker starts, pass --speaker-sample-rate 16000.

Software volume (optional)

If your USB device has no hardware mixer (check amixer -c <card>), add a software volume plugin in ~/.asoundrc:

pcm.your_softvol {
    type softvol
    slave.pcm "hw:CARD=YourDevice,DEV=0"
    control.name "SoftMaster"
    control.card "YourDevice"
}

Replace YourDevice with your card's ID (from aplay -l). Then use --speaker-device your_softvol and adjust with:

amixer -D your_softvol sset SoftMaster 80%

4.5. Launch

On your laptop, start LiveKit and mint a viewer token. LIVEKIT_ENABLE_DATA_TRACKS=true is required for telemetry; --dev mode does not enable data tracks by default.

LIVEKIT_ENABLE_DATA_TRACKS=true livekit-server --dev --bind 0.0.0.0
lk token create --api-key devkey --api-secret secret \
    --identity viewer --room robot --join --valid-for 24h

Note your laptop's LAN IP. On the Pi:

env PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python PYTHONPATH=~/asimov-api/src \
    ~/asimov-api/.venv/bin/python -m edge.main \
        --firmware-host 10.0.0.2 \
        --livekit-url ws://<laptop-lan-ip>:7880 \
        --livekit-key devkey --livekit-secret secret \
        --serial MENLO-0001 --force-cloud \
        --mic-device <your-mic-name> \
        --speaker-device <your-speaker-name> \
        --camera-device <N>

--force-cloud is required. It bypasses BLE provisioning and starts LiveKit immediately. Use --firmware-host 127.0.0.1 if the motor firmware is not running yet; the media pipeline (camera, mic, speaker) still works.

4.6. Verify

Watch the logs in the terminal you launched it from, or journalctl -t edge -f if running as a systemd service. Look for:

  • [MAIN] startup banner
  • [CAMERA] opened /dev/videoN at a non-zero resolution
  • [MICROPHONE] and [SPEAKER] opened at their sample rates
  • [CLOUD] connected to your LiveKit URL and joined the room
  • [FW_LINK] first RobotState from the MCB (only if firmware is running)

In a viewer joined to the same LiveKit room, you see the camera feed, hear mic audio, and can send audio back to the speaker.

4.7. Stop

pkill -f "edge.main"

Next steps

  • Read the API manual to drive the robot from your application.
  • Read the Robot Control page for the command state machine and joint order.

How is this guide?

On this page