Before you start · Chapter 03 · Time: 45 minutes to read · Level: Beginner · Status: Reference
Every part of the robot with the identifiers the software matches on, the USB map, the battery and charging rules, the three machines and the network, and what came in the kit against what was bought later.
The robot is a Hiwonder ROSOrin Pro, bought as the "Ultimate" kit, with two parts added since: a microphone array
with a speaker, and a Bluetooth bike light. This chapter lists each part with the identifiers you will see in
commands, udev rules and scripts: USB IDs, USB paths, device nodes, serial numbers and firmware versions. Scripts
match parts by these identifiers, so a part that changes port or firmware can break a step without any error on the
part itself.
All values come from docs/hardware.md, the kit inventory (inventory/, 2026-08-15), and a read-only look at the
running robot on 2026-10-07 for this guide.
| Part | Source | State on 2026-10-07 |
|---|---|---|
| Chassis with four mecanum wheels and motors | kit (Standard) | in use |
| Jetson Orin NX 16 GB "Super" with NVMe SSD | kit (controller option) | in use, rebuilt from stock NVIDIA software |
| STM32 controller board with MPU6050 IMU | kit (Standard) | in use |
| COIN-D6 LiDAR | kit (Standard) | in use |
| Deptrum Aurora 930 depth camera, bracket and 550 mm cable | kit (Standard) | in use, on the arm |
| 6-joint arm with HX-12H bus servos | kit (Standard) | in use |
| 11.1 V 6000 mAh battery, 12.6 V 2 A charger (DC 5.5 × 2.5 mm) | kit (Standard) | in use |
| Wireless gamepad and receiver | kit (Standard) | in use: driving by hand, emergency stop |
| WonderEcho Pro voice box (mic + speaker) | kit (Advanced) | unplugged; replaced by the reSpeaker array |
| 7-inch touchscreen, panel, HDMI and USB cables | kit (Ultimate) | not attached; the robot runs headless |
| Colour blocks, card reader, hex key, screwdriver, screws, manual | kit (Standard) | not used by the software |
| reSpeaker XVF3800 USB 4-mic array | bought 2026-10-01; first unit faulty, replacement installed 2026-10-07 | in use: the robot's ears and mouth |
| Speaker on the array's JST connector | added 2026-10-06 with the array (model not recorded) | in use |
| Magicshine HORI 900 bike light | ordered 2026-10-06, arrived 2026-10-07 | the robot can switch it on, not off |
To rebuild the robot as it runs today you need the kit, the reSpeaker XVF3800 USB array and a speaker for its JST
connector. The array's amplifier drives up to 5 W into 4 Ω (docs/decisions.md 2026-10-06); which speaker was used
is not in the record.
Do not buy a part on a guess
The HORI 900 was bought on an estimate that its Bluetooth commands could be decoded after it arrived. The robot
can switch it on but not off, and the project's objective needs a light that is off by default. The project rule
since 2026-10-07: no part is bought until every operation the robot needs (at least on and off) is confirmed
on that exact model, by a published capture or a test. This guide names no light to buy; none is verified yet.
| Item | Identifier | Notes |
|---|---|---|
| Module | Jetson Orin NX 16 GB, part p3767-0000, EEPROM 699-13767-0000-303 D.1 |
8 CPU cores, Ampere GPU, 16 GB shared by CPU and GPU |
| Carrier board | p3768-0000, NVIDIA's own Orin Nano developer-kit carrier (not a Hiwonder board) | /proc/device-tree/compatible = nvidia,p3768-0000+p3767-0000-super |
| Factory flash configuration | jetson-orin-nano-devkit-super, DTB tegra234-p3768-0000+p3767-0000-nv-super.dtb |
stock NVIDIA |
| Software | L4T R36.4.3 (JetPack 6.2), Ubuntu 22.04, kernel 5.15.148-tegra |
the factory had the same versions |
| SSD | Micron 2400 512 GB (Micron_2400_MTFDKBK512QFM), nvme0n1, 1,000,215,216 sectors |
Hiwonder's documentation says 128 GB; this unit has 512 GB |
| Partitions | p1 APP_old (the factory system, kept), p2-p15 the rest of NVIDIA's layout (p10 is the EFI partition, UUID 4747-914F), p16 APP (this build, PARTUUID ef01d088-5975-4263-b620-2d0f5137dfe1) |
the boot loader starts the partition named exactly APP |
| Boot | UEFI (edk2-nvidia) | efibootmgr works from Linux |
| Power mode | 40 W, nvpmodel mode 4 (the default) | MAXN_SUPER is not used (your decision, recorded in docs/status.md); fan profile is NVIDIA's default "quiet" |
| Flash port | USB-C J5 on the carrier | when running, the robot shows up on a PC connected there as 0955:7020 |
| Recovery mode | header J14, pin 9 (GND) and pin 10 (FORCE_RECOVERY*), shorted during power-on | needs the robot taken apart; sudo reboot --force forced-recovery failed twice on this unit |
Why the carrier matters
Because the carrier is NVIDIA's reference design, NVIDIA's stock board support package boots this robot
unchanged. That is what made a rebuild with no Hiwonder software possible (chapters 4 and 5).
Controller board. STM32F407 microcontroller with an MPU6050 IMU. It connects to the Jetson by USB as
1a86:55d4 ("USB Single Serial") and appears as /dev/ttyACM0 through the stock cdc_acm driver at
1,000,000 baud. The factory system created a /dev/rrc name for it with its own udev rule; this build does not, and
the code opens /dev/ttyACM0 directly. The board's firmware version is not recorded. Access needs the dialout
group.
Wheels. Four mecanum wheels, 0.08 m in diameter, wheelbase 0.17706 m, track 0.17165 m (factory chassis code).
Mecanum wheels have rollers set at an angle, so the robot can drive sideways as well as forwards and turn on the
spot. The motors have no encoders. The footprint the navigation uses is 0.305 m long and 0.235 m wide.
Arm. Six bus servos (HX-12H, per the kit inventory) on the board's servo bus, not on USB: ids 1 to 5 are the
joints, id 10 is the claw. Positions are pulses from 0 to 1000. The camera is mounted on the arm. Recorded facts:
Gamepad. The wireless gamepad's receiver does not appear on the Jetson's USB (it is absent from lsusb); the
controller board reads it and reports buttons and sticks in its own frames (function 8, about 20 Hz). Which socket
the receiver sits in is not recorded. A gamepad that is switched off reports all zeros, so the software cannot tell
"off" from "nobody touching it".
LiDAR: COIN-D6. A 360° time-of-flight distance scanner.
| Fact | Value |
|---|---|
| USB | CH340 serial adapter 1a86:7523 at USB path 1-2.2.4, 12 Mb/s |
| Device node | /dev/ttyUSB0, with the stable name /dev/lidar from this build's udev rule (matches the USB path) |
| Driver | ch341, which the stock R36.4.3 kernel does not include; chapter 7 builds it |
| Serial link | 230400 baud; streams as soon as it has power, no start command |
| Output | about 10 turns per second, about 400 readings per turn (0.9° apart), up to about 7.94 m |
| Blind spots | a sector about 65° wide at the rear; the robot's own body at 50-106 mm |
| Mounting | 0.048 m in front of and 0.107 m above base_link, turned 180°; native angles run clockwise |
| Firmware | not recorded; no datasheet was found, the packet format was decoded from captured data |
The LiDAR can change its device number
When the robot is handled, the LiDAR can drop off USB and come back as a differentttyUSBnumber. That is why
/dev/lidarfollows the USB path, not the number, and why the reader reopens the port on errors
(docs/lessons.md).
Depth camera: Deptrum Aurora 930. Mounted on the arm, on the link that the wrist joint tilts (link4).
| Fact | Value |
|---|---|
| USB | 3251:1930 at USB path 1-2.2.1, 480 Mb/s (through the USB 2 hub) |
| Interface | one vendor-specific interface (class 0xff): no UVC, no /dev/video*; only the vendor driver can read it |
| Serial number | HY400586001016515G00505 |
| Firmware | 2.0.8 |
| Driver | deptrum-ros-driver-aurora930 0.2.11 (source) plus the closed library libdeptrum_stream_aurora900.so 1.1.22, copied from the factory partition (chapter 15) |
| Modes | 320x200, 480x300, 640x400; 640x400 in use, no larger colour mode |
| Measured rates | colour 9.3 Hz, depth 14.0 Hz, point cloud 12.9 Hz; the driver uses 35 % of one CPU core |
| Range seen | 1.27-3.78 m in the living room, 34 % valid depth pixels (holes on black or shiny surfaces) |
IMU: MPU6050 on the controller board, about 110 Hz. The accelerometer was calibrated on 2026-09-27 (offsets
X +0.0460, Y −0.0635, Z −0.0501 g; scales 1.0058, 0.9964, 1.0076). The gyro's zero point differs at every boot, so
the driver measures it for 3 s at each start.
Battery voltage. The board reports voltage only. Current, charge state and percentage are not available.
The array is the robot's microphone and, through its own amplifier, its speaker. Buddy on bigbuddy hears and speaks
through it over Wi-Fi (chapter 27).
| Fact | Value |
|---|---|
| USB | 2886:001a "reSpeaker XVF3800 4-Mic Array" at USB path 1-2.3, must run at 480 Mb/s |
| Sound card | ALSA card named Array, driver snd-usb-audio, 16 kHz, 2 channels (the card number changes between boots; use the name) |
| Unit in use | #2, serial 101991441262500220, installed 2026-10-07; arrived with firmware 2.0.6, flashed to 2.1.1 |
| First unit | #1, serial 114993701262800721: heard voices from its right side only and half of its 12-LED ring stayed dark; replaced |
| Output | codec TLV320AIC3104; amplifier for the JST speaker, enabled by pin GPO X0D31 (low = enabled) |
| Controls | Mute button (held while plugging in, it boots a factory safe-mode image with no sound card); 12 WS2812 LEDs |
| Host tools | Seeed's repo clone in ~/tools/reSpeaker_XVF3800_USB_4MIC_ARRAY (@ 4b49bfd) and a Python venv ~/tools/xvfenv |
Known array faults
- After a firmware flash the array came back at USB full speed (12 Mb/s): playback broke up and capture ran at
half rate. A physical re-plug brought it back to 480 Mb/s. On #2 a software unbind/rebind did not help.- The flash stopped at 25 % while PulseAudio held the array; it completed with PulseAudio stopped.
- After a reboot, playback once stalled until a physical re-plug. Do not unbind the array to fix it.
WonderEcho Pro (kit, unplugged). A small box with its own USB hub (1a86:8091), a CH340 serial line
(1a86:7523, an offline voice chip, never used) and a JMTek USB sound device (0c76:161f). A loopback test on
2026-09-28 showed it has no echo cancellation: the robot could not listen while it spoke. It sat on USB path 1-2.3,
where the array is now.
| Part | Identifier | Interface and MAC | Driver |
|---|---|---|---|
| Wi-Fi: Realtek RTL8852CE | PCI 10ec:c852 |
wlP1p1s0, <robot-wifi-MAC> |
rtw89 from github.com/a5a5aa555oo/rtw89, branch 6.6-lts @ 2310939e, built here (chapter 7); firmware 0.27.56.14 |
| Bluetooth: the same Realtek chip | USB 0bda:0852 at USB path 1-3, 12 Mb/s |
hci0 |
NVIDIA's rtk_btusb, with the stock btusb blacklisted (chapter 7) |
| Ethernet: Realtek | - | enP8p1s0, <robot-ethernet-MAC> |
r8168 8.053.00-NAPI, already in the stock system |
Wi-Fi firmware resets
Thertw89firmware resets itself about twice an hour ("SER catches error: 0x1000"; 23 times on 2026-10-05/06)
and recovers on its own. On 2026-10-07 at 17:44 UTC it hung leaving power save and did not recover: the robot
was off the network until it was rebooted by hand. Power save is now off (chapter 7). Whether that stops the hangs
is not yet shown.
| Fact | Value |
|---|---|
| Bluetooth name and address | M1-B0 HORI_900, <light-BLE-address> |
| Bluetooth services | GAP name "Simple BLE MultiRole" (a TI sample firmware); service FFE1, characteristic FFE0 carries Magicshine's frames |
| USB-C port | charging only (5 V / 2 A); it does not appear on USB |
| What works | the robot switches it on (buddy_link/light_hori.py on) and reads its state |
| What does not | switching it off: every known "off" frame is acknowledged and ignored; off is the lamp's own button |
| Heat | 59 °C after minutes at 50-99 % brightness with no airflow |
| Leftover | slot 1 of the lamp's modes holds a test mode from 2026-10-07, to be deleted only when you decide to |
Where the light is mounted on the robot is not recorded. Chapter 30 covers it.
7-inch, 1024x600, HDMI into the carrier's HDMI port (Linux names it card1-DP-1), touch over USB 1a86:e5e3
("wch.cn USB2IIC_CTP_CONTROL"). Plugging it in while running was not detected without a manual probe. Since
2026-10-07 the robot runs with no screen (chapter 28 keeps the face code as an option).
Everything plugs into the USB 2 bus through one 4-port hub. The USB 3 bus has nothing attached.
Which physical socket on the robot each path belongs to is not recorded. If you move a cable, check the path again:
the LiDAR's udev rule matches 1-2.2.4:1.0, and a LiDAR on another port gets no /dev/lidar.
To see the tree yourself, run this on the robot at any time; it changes nothing:
On the robot:
lsusb -t
On 2026-10-07 it printed:
On the robot:
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=tegra-xusb/4p, 10000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=tegra-xusb/4p, 480M
|__ Port 2: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 4, If 1, Class=CDC Data, Driver=cdc_acm, 12M
|__ Port 1: Dev 4, If 0, Class=Communications, Driver=cdc_acm, 12M
|__ Port 2: Dev 5, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 4: Dev 8, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
|__ Port 1: Dev 7, If 0, Class=Vendor Specific Class, Driver=usbfs, 480M
|__ Port 3: Dev 9, If 4, Class=Application Specific Interface, Driver=, 480M
|__ Port 3: Dev 9, If 2, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 3: Dev 9, If 0, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 3: Dev 9, If 5, Class=Human Interface Device, Driver=usbhid, 480M
|__ Port 3: Dev 9, If 3, Class=Vendor Specific Class, Driver=, 480M
|__ Port 3: Dev 9, If 1, Class=Audio, Driver=snd-usb-audio, 480M
|__ Port 3: Dev 3, If 0, Class=Wireless, Driver=rtk_btusb, 12M
|__ Port 3: Dev 3, If 1, Class=Wireless, Driver=rtk_btusb, 12M
Check
Your tree has the same ports in the same places: hub on port 2, the board on 2.1, the second hub on 2.2 with the
camera on its port 1 and the LiDAR adapter on its port 4, the array on 2.3, Bluetooth on port 3. The device
numbers (Dev 4,Dev 8) change at every plug-in; the port numbers do not. On a fresh install, before
chapter 7, the LiDAR line shows no driver and the Bluetooth lines showbtusb. The array's lines must end in
480M;12Mmeans it needs a physical re-plug.
| Fact | Value |
|---|---|
| Battery | 11.1 V, 6000 mAh lithium pack with over-charge, over-current, over-discharge and short-circuit protection; maximum discharge 10 A (maker) |
| Charger | 12.6 V 2 A, barrel plug 5.5 × 2.5 mm; the robot's charging socket is at the back right |
| Charger light | red = charging; green = done, or not connected to mains |
| Charge time | 10 V to about 12.3 V takes about three hours (maker). Here, 70 min from 10.71 V reached only 11.26 V; a full charge has never been logged |
| Drain | about 1.1 V in 45 min while running navigation (2026-10-05) |
| Readings | about 12.67 V on the charger; 11.13 V after about 2 h unplugged (2026-09-30) |
Charging rules
- Charge only with the included 12.6 V charger, and only into the robot's charging socket. Never plug the
charger into the Jetson's DC jack.- The maker says: turn the robot off while charging, do not run it and charge at the same time, and unplug the
charger when charging is done. This robot has been run on the charger for hours (stand tests, idle days),
against that instruction. Why the maker forbids it is not stated; the decision is yours and still open.- Recharge before the voltage falls below 10 V. The maker's manual says the buzzer warns with three beeps below
10 V; that warning has not been observed on this robot.- Never let the robot update its map while it is plugged in (chapter 17).
The voltage alone does not show whether the charger is in: plugged in, the robot read 12.30-12.32 V; unplugged
earlier the same day, 12.40 V. A plug or unplug shows as a jump of about +249 mV or −226 mV with the wheels off. The
board driver treats a jump of 190 mV or more as a plug event and stores the result in ~/battery/plugged.json. It
also logs the voltage every 10 s to ~/battery/YYYYMMDD.csv.
The software's battery thresholds:
| Voltage | What happens | Where |
|---|---|---|
| 10.9 V | self-care asks to be charged | selfcare/expected.json battery_ask_v |
| 10.6 V | the mind starts no more wheel skills | vision/mind.py BODY_MIN_V |
| 10.4 V | self-care's request becomes urgent | selfcare/expected.json battery_urgent_v |
| 10.0 V | exploration stops (20 s average); the maker's low-voltage limit | behavior/explore_auto.py LOW_BATTERY_V |
The robot's power switch is the last way to stop the wheels: the controller board has no stop watchdog of its own
(chapter 2).
| Robot | bigbuddy | server | |
|---|---|---|---|
| Hardware | Jetson Orin NX 16 GB (above) | PC with NVIDIA RTX 5070 Ti 16 GB, 32 GB RAM, 929 GB internal disk (btrfs); CPU not recorded | Mac mini, Apple M4 Pro (12 cores), 24 GB |
| System | Ubuntu 22.04, L4T R36.4.3, ROS 2 Humble | Fedora 44, KDE Plasma 6.7.5 (Wayland), kernel 7.2.5, NVIDIA driver 615.71.09 | macOS 26.7.1 |
| User | burgerbarn, passwordless sudo (robot only) |
burgerbarn (uid 1001), login shell fish, sudo asks for a password |
matty |
| Hostname | rosorin |
bigbuddy |
Server.local |
| Role | drives, maps, sees, keeps itself healthy; needs neither other machine to drive | Buddy's wake word, Whisper, Kokoro voice; LM Studio with google/gemma-4-12b on port 1234 |
Open WebUI (buddy.matttesch.com), SearXNG (mattysearch.matttesch.com), Home Assistant, Plex, Ollama; always on |
| Chapters | 4-24, 27, 30 | 25-28 | 28 |
bigbuddy also has: a Samsung TV over HDMI (3840x2160), a WingCool touchscreen, a Cambridge Audio Evo 150 amplifier
(USB sound, and network control at 192.168.1.11), a Logitech C910 webcam (046d:0821, used on the robot as a test
camera on 2026-09-27), and your external SABRENT 477 GB SSD.
Your other machines
- The SABRENT SSD holds your personal files: never reformat it, and keep robot data and models off it
(decision 2026-10-01). Robot data goes to~/rosorin-dataon bigbuddy's internal disk.- Nothing is copied to or installed on
serverwithout your explicit OK (AGENTS.mdrule 6).- bigbuddy suspends when idle unless its power settings say otherwise (chapter 25); an ssh session does not
keep it awake.
Your laptop is the Mac (matty@MacBook-Air); its key matty@MacBook-Air-20260808 is the one authorized on the robot.
All machines are on the home LAN 192.168.1.0/24; the router is 192.168.1.1. The router hands out the robot's two
addresses as fixed DHCP reservations, set on the router on 2026-09-29 and matched by MAC address:
| Machine | Interface | MAC | Address | How it stays fixed |
|---|---|---|---|---|
| robot | wired enP8p1s0 |
<robot-ethernet-MAC> |
192.168.1.109 | router reservation |
| robot | Wi-Fi wlP1p1s0 |
<robot-wifi-MAC> |
192.168.1.108 | router reservation |
| bigbuddy | wired enp8s0 |
<bigbuddy-ethernet-MAC> |
192.168.1.111 | not recorded |
| bigbuddy | Wi-Fi wlp7s0 |
not recorded | 192.168.1.59 | not recorded |
| server | en0 |
not recorded | 192.168.1.122 | not recorded |
The robot's Wi-Fi joins the network saved as the NetworkManager connection <your-wifi-name> (5300 MHz, −44 dBm when
it was set up on 2026-09-27). Neither robot interface randomizes its MAC address (checked 2026-09-29), which is what
keeps the reservations working. When both robot links are up, the default route is the wired one. On 2026-10-07 the
cable was out and the robot ran on Wi-Fi only; Buddy's code on bigbuddy talks to the Wi-Fi address, 192.168.1.108.
~/.config/rosorin/api_token (mode 0600); bigbuddy keeps a copy in ~/.config/rosorin/api_token and~/voice/robot_api_token. Never paste the token into a command line or a document.Every @mac command in this guide uses these aliases. Chapter 6 sets them up; this is the record of what they are,
from ~/.ssh/config on the Mac:
On your laptop:
Host rosorin-wifi
HostName 192.168.1.108
User burgerbarn
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
HostKeyAlias 192.168.1.22
Host rosorin
HostName 192.168.1.109
HostKeyAlias 192.168.1.22
User burgerbarn
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 4
Host server
HostName 192.168.1.122
User matty
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 4
Host bigbuddy fedora
HostName 192.168.1.111
User burgerbarn
IdentityFile ~/.ssh/id_ed25519
Why both robot aliases say HostKeyAlias 192.168.1.22
ssh remembers each server's host key under the address it connected to. The rebuilt system first came up on the
wired network as 192.168.1.22, so its new host key was stored under that address. 192.168.1.108 was the factory
system's Wi-Fi address, and the Mac'sknown_hostsstill held the factory system's keys for it; connecting there
would have failed with a changed-key warning.HostKeyAlias 192.168.1.22tells ssh to check both addresses
against the key stored for .22, which is the rebuilt system's key.
bigbuddy's login shell is fish, which does not understand bash syntax. Send multi-line commands like this:
On your laptop:
ssh bigbuddy 'bash -s' <<'EOF'
hostname
EOF
Once chapter 6 is done, test the alias from the laptop:
On your laptop:
ssh rosorin-wifi hostname
Check
It printsrosorin. On the robot,ip -br addrlistswlP1p1s0with192.168.1.108/24(andenP8p1s0with
192.168.1.109/24when the cable is in).
/dev/ttyACM0, /dev/lidar, cardArray).HostKeyAlias 192.168.1.22.Where this comes from
docs/hardware.md(compute, boot, recovery mode, controller board, LiDAR, WonderEcho, Aurora 930, power, network,
MAC reservations 2026-09-29, bigbuddy voice host, reSpeaker entries 2026-10-06/07, Wi-Fi 2026-10-07, Bluetooth,
HORI 900),inventory/rosorin-pro-inventory.csvandinventory/live-scan-2026-08-15.txt(kit tiers),
docs/decisions.md2026-09-26 (no Hiwonder software), 2026-10-01 (reSpeaker bought; SABRENT rule),
2026-10-06 (array amplifier, headless),docs/status.md2026-10-06/07 (light ordered and tested, array #2),
docs/lessons.md2026-10-07 (light bought on a guess),AGENTS.mdrules 6 and 10,
docs/research/power_and_charging_reference.md(maker's charging rules),docs/research/jetson_platform.md
(power modes, fan),docs/motion_safety.md(wheel geometry, power switch),selfcare/expected.json,
vision/mind.py,behavior/explore_auto.py,ros2/rosorin_base/config/nav2.yaml(footprint),
voice/60-buddy-echo-cancel.conf(array #1 serial),voice/buddy_voice.py,vision/think.py(addresses),
the Mac's~/.ssh/config,sources/survey_bigbuddy.md,sources/cmdlog_server.md(server hardware,
2026-09-15). Live, read-only on the robot 2026-10-07:lsusb,lsusb -t, USB sysfs paths,/proc/asound/cards,
ip -br addr,nvpmodel -q.
← Robotics in one sitting · Contents · Prepare the build host →