Project Overview
The SO-101 is TheRobotStudio's open-source leader-follower robotic arm (Apache-2.0) — the current version of their SO-ARM100 design — built for the Hugging Face LeRobot ecosystem — you physically move the leader arm, and the follower mirrors it in real time, the standard way to collect teleoperation data for training robot learning policies. It was chosen over the pricier AM-ARM200 mainly on servo economics — full comparison in the sourcing section below.
Everything through this point is stock SO-101: the 12 Feetech STS3215 servos and both motor-controller boards were bought as parts, the arm links were 3D printed from TheRobotStudio's original files, and both arms were assembled and calibrated through LeRobot's Python tooling — homing offsets and safe position limits get burned straight into each servo's EEPROM. The one part that isn't stock: the desk clamps, custom-modelled from scratch — more on that below.
What isn't in the official repo is the wireless link. The arm pair worked over USB from day one; built on top of that are two ESP32-C3 Super Mini boards that read the leader's joints and mirror them to the follower over ESP-NOW, no PC in the loop. Full breakdown in the Wireless Upgrade section below.
Servos, Sourcing & Mechanical
The SO-101 has one real drop-in constraint: the Feetech STS3215 serial bus servo. It's a proprietary 45.2 × 24.7 × 35 mm form factor with position feedback over a single-wire half-duplex bus — no cheaper PWM servo (MG996R and similar) can substitute, because those have no feedback and can't support LeRobot's teleoperation or policy-learning pipeline. The correct variant is the C001: 7.4 V, 19.5 kg·cm torque, 1:345 gear ratio. The 12 V/30 kg C018 variant exists but is more expensive and isn't what the official BOM specifies.
Building a cheaper DIY equivalent — DC motor, gearbox, AS5048 magnetic encoder, custom driver PCB — was seriously considered and ruled out: at roughly $20–30 per joint plus hours of engineering per axis, it lands close to the STS3215's $13.89/unit Alibaba price without any of the reliability or drop-in compatibility.
| Alternative Considered | Why Ruled Out |
|---|---|
| AM-ARM200 | ~$380 full kit vs ~$230 — 3× STS3095 servos at ~$50 each drive the cost up |
| Moss Robot Arms | Same servos, same cost, and being deprecated in favour of SO-ARM100 |
| Koch v1.1 | Uses Dynamixel servos — notably more expensive per joint |
| MG996R-based arms | No position feedback — can't support LeRobot teleoperation or policy training |
| DIY servo (DC + encoder) | ~$20–30/joint plus hours of engineering per axis — lands at the STS3215 price anyway |
LeRobot Software & Calibration
Both arms are brought up and calibrated through Hugging Face's LeRobot Python library. A dedicated conda environment (lerobot) was set up with the Feetech servo backend, and both controller boards were found on /dev/ttyACM0 (one at a time, since both boards enumerate identically). Motor IDs were assigned 1–6 on each arm, followed by LeRobot's guided calibration routine, which walks each joint through its range and burns homing offsets directly into servo EEPROM — no recalibration is needed later on the ESP32 firmware, since the offsets travel with the hardware.
The Wireless Upgrade
USB teleoperation works, but tethers both arms to a PC and to each other's cable runs — awkward for anything beyond a desk demo. The goal was to cut the cable and mirror the leader arm's 6 joints to the follower wirelessly, with low enough latency that it still feels like direct control.
lerobot-teleoperate reading the leader's joint positions and writing them to the follower in a tight Python loop. This confirmed both arms, all 12 servos, and the calibration data were correct before touching any custom firmware.servo_test sketch reads and wiggles all 6 joints, confirming the ESP32 can talk to that arm's servos before any ESP-NOW code goes near it. First-time pairing: flash the follower sketch first, read its MAC address off the Serial Monitor, paste it into the leader sketch, then flash the leader. Confirmed working end-to-end — moving the leader arm by hand drives the follower in real time with no perceptible lag.Electronics & Wiring
Both boards are wired identically. The motor controller board is powered from an external 5 V supply, and the ESP32-C3 talks to it over the board's UART header rather than the raw servo data line.
| Signal | ESP32-C3 GPIO | Function |
|---|---|---|
| Board 5V | 5V pin | Motor controller board power (external 5V supply) |
| Board GND | GND | Common ground |
| Board RX (UART header) | GPIO 4 | ESP32 TX → board RX, jumper set to UART mode |
| Board TX (UART header) | GPIO 3 | Board TX → ESP32 RX |
0x02 — present position0x83 — sync write, all 6 in one packetBoth sketches are plain Arduino C++ using esp_now.h and the STS servo protocol implemented by hand over HardwareSerial — no external servo library. The follower's receive callback runs inside the FreeRTOS WiFi task, so it only copies the incoming packet into a buffer and flips a flag; the main loop does the actual servo write on its own schedule, avoiding any work inside the callback itself.