Skip to content

Commit 3cda4af

Browse files
committed
docs: update documentation for hardware setup workflow
Rewrite README with step-by-step hardware setup guide (servo ID assignment, calibration, running). Update AGENTS.md with correct joint ranges and mix task documentation.
1 parent 4b5ca1e commit 3cda4af

2 files changed

Lines changed: 117 additions & 110 deletions

File tree

AGENTS.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ mix test path:42 # Run single test at line
2020
mix check --no-retry # Run all checks (compile, format, credo, dialyzer)
2121
```
2222

23+
### Hardware Mix Tasks
24+
25+
```bash
26+
mix so101.setup_servos /dev/ttyUSB0 # Assign servo IDs (one at a time)
27+
mix so101.calibrate /dev/ttyUSB0 # Calibrate centre offsets
28+
mix so101.calibrate /dev/ttyUSB0 -n # Dry run (show offsets without writing)
29+
```
30+
2331
## Architecture
2432

2533
### Robot Definition (`lib/bb/example/so101/robot.ex`)
@@ -35,16 +43,21 @@ The robot starts as a supervised child in `application.ex` and exposes commands
3543

3644
### Kinematic Structure
3745

38-
Derived from the official SO-ARM100 URDF (new calibration - zeros at joint midpoints):
46+
Derived from the official SO-ARM100 URDF:
3947

4048
| Joint | Servo ID | Type | Range | Link Length |
4149
|-------|----------|------|-------|-------------|
4250
| shoulder_pan | 1 | revolute | ±110° | 62mm (base height) |
43-
| shoulder_lift | 2 | revolute | ±100° | 54mm |
44-
| elbow_flex | 3 | revolute | ±97° | 113mm (upper arm) |
51+
| shoulder_lift | 2 | revolute | -10° to 190° | 54mm |
52+
| elbow_flex | 3 | revolute | -187° to 7° | 113mm (upper arm) |
4553
| wrist_flex | 4 | revolute | ±95° | 135mm (forearm) |
4654
| wrist_roll | 5 | revolute | ±160° | 61mm (wrist) |
47-
| gripper | 6 | revolute | 10°-100° | ~98mm to EE |
55+
| gripper | 6 | revolute | -10° to 100° | ~98mm to EE |
56+
57+
### Mix Tasks (`lib/mix/tasks/`)
58+
59+
- **`so101.setup_servos`** - Interactive wizard for assigning servo IDs. Guides the user through connecting each servo one at a time and setting IDs 1-6.
60+
- **`so101.calibrate`** - Calibrates servo centre offsets. Disables torque, tracks min/max positions as the user moves each joint through its full range, then writes position offsets so the mechanical centre maps to 0 radians.
4861

4962
### Web Dashboard
5063

@@ -78,16 +91,8 @@ Set `SIMULATE=1` to run without hardware. In simulation mode:
7891

7992
## Hardware Configuration
8093

81-
Configure the serial port via environment or `config/runtime.exs`:
82-
83-
```elixir
84-
config :bb_example_so101, BB.Example.SO101.Robot,
85-
config: [
86-
feetech: [
87-
device: "/dev/ttyUSB0" # Your serial device
88-
]
89-
]
90-
```
94+
The serial port defaults to `/dev/ttyUSB0` at 1Mbaud. To change it, edit
95+
`lib/bb_example_so101/application.ex` in the `robot_opts/0` function.
9196

9297
## Dependencies
9398

README.md

Lines changed: 98 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -22,107 +22,104 @@ Example Phoenix application demonstrating the [Beam Bots](https://github.com/bea
2222

2323
- Elixir ~> 1.15
2424
- SO-101 robot arm with Feetech STS3215 servos (or run in simulation mode)
25-
- USB serial adapter connected to servo bus
25+
- Feetech URT-1 USB adapter or compatible TTL serial adapter
26+
- 6-7.4V DC power supply for the servos
2627

27-
## Quick Start
28+
## Quick Start (Simulation)
29+
30+
No hardware required:
2831

2932
```bash
30-
# Install dependencies and build assets
3133
mix setup
32-
33-
# Start in simulation mode (no hardware required)
3434
SIMULATE=1 mix phx.server
35-
36-
# Or start with real hardware
37-
mix phx.server
3835
```
3936

4037
Visit [localhost:4000](http://localhost:4000) to access the robot dashboard.
4138

4239
## Hardware Setup
4340

44-
### Servo Configuration
41+
### What You Need
4542

46-
The SO-101 uses 6 Feetech STS3215 servos with IDs 1-6:
43+
- **SO-101 arm** fully assembled with 6x Feetech STS3215 servos
44+
- **USB serial adapter** (Feetech URT-1 or any 5V TTL serial adapter)
45+
- **Power supply** 6-7.4V DC, connected to the servo bus
46+
- **USB cable** connecting the adapter to your computer
4747

48-
| Servo ID | Joint |
49-
|----------|-------|
50-
| 1 | Shoulder Pan |
51-
| 2 | Shoulder Lift |
52-
| 3 | Elbow Flex |
53-
| 4 | Wrist Flex |
54-
| 5 | Wrist Roll |
55-
| 6 | Gripper |
48+
The serial adapter connects to the servo bus (the same daisy-chain cable
49+
that connects all the servos). On Linux, it typically appears as
50+
`/dev/ttyUSB0` or `/dev/ttyACM0`.
5651

57-
### Serial Connection
52+
### Step 1: Assign Servo IDs
5853

59-
Configure your serial device in `config/runtime.exs`:
54+
STS3215 servos ship with a default ID of 1. Each servo in the arm needs
55+
a unique ID. The setup wizard walks you through connecting each servo
56+
one at a time and assigning the correct ID.
6057

61-
```elixir
62-
config :bb_example_so101, BB.Example.SO101.Robot,
63-
config: [
64-
feetech: [
65-
device: "/dev/ttyUSB0", # Adjust for your system
66-
baud_rate: 1_000_000
67-
]
68-
]
58+
```bash
59+
mix so101.setup_servos /dev/ttyUSB0
6960
```
7061

71-
## Robot Definition
62+
The wizard will prompt you to connect each servo individually:
7263

73-
The robot is defined in `lib/bb/example/so101/robot.ex` using the BB DSL:
64+
| Joint | Servo ID | Description |
65+
|----------------|----------|--------------------------|
66+
| shoulder_pan | 1 | Base rotation |
67+
| shoulder_lift | 2 | Shoulder up/down |
68+
| elbow_flex | 3 | Elbow bend |
69+
| wrist_flex | 4 | Wrist up/down |
70+
| wrist_roll | 5 | Wrist rotation |
71+
| gripper | 6 | Gripper open/close |
7472

75-
```elixir
76-
defmodule BB.Example.SO101.Robot do
77-
use BB
78-
79-
parameters do
80-
bridge(:feetech, {BB.Servo.Feetech.Bridge, controller: :feetech})
81-
end
82-
83-
commands do
84-
command :home do
85-
handler(BB.Example.SO101.Command.Home)
86-
allowed_states([:idle])
87-
end
88-
# ... additional commands
89-
end
90-
91-
controllers do
92-
controller(:feetech, {BB.Servo.Feetech.Controller,
93-
port: param([:config, :feetech, :device]),
94-
baud_rate: param([:config, :feetech, :baud_rate]),
95-
control_table: Feetech.ControlTable.STS3215
96-
})
97-
end
98-
99-
topology do
100-
link :base_link do
101-
joint :shoulder_pan do
102-
# ... joint definition with actuator
103-
link :shoulder_link do
104-
# ... nested kinematic chain
105-
end
106-
end
107-
end
108-
end
109-
end
73+
After assigning IDs, daisy-chain all servos together and reconnect to
74+
the controller board.
75+
76+
### Step 2: Calibrate
77+
78+
With all servos connected and powered, run the calibration task:
79+
80+
```bash
81+
mix so101.calibrate /dev/ttyUSB0
11082
```
11183

112-
## Kinematic Structure
84+
This will:
11385

114-
Derived from the official [SO-ARM100 URDF](https://github.com/TheRobotStudio/SO-ARM100/tree/main/Simulation/SO101):
86+
1. Disable torque on all servos so you can move the arm freely
87+
2. Prompt you to move **every joint** through its **full range of motion**
88+
(push each joint to both mechanical limits)
89+
3. Track the min/max positions for each joint in real time
90+
4. When you press Enter, calculate the mechanical centre of each joint
91+
5. Write a position offset to each servo so that the centre corresponds
92+
to 0 radians
11593

116-
| Joint | Range | Link Length |
117-
|-------|-------|-------------|
118-
| shoulder_pan | ±110° | 62mm (base) |
119-
| shoulder_lift | ±100° | 54mm |
120-
| elbow_flex | ±97° | 113mm (upper arm) |
121-
| wrist_flex | ±95° | 135mm (forearm) |
122-
| wrist_roll | ±160° | 61mm (wrist) |
123-
| gripper | 10°-100° | ~98mm to EE |
94+
You can preview the results without writing to the servos:
12495

125-
Total reach: ~350mm
96+
```bash
97+
mix so101.calibrate /dev/ttyUSB0 --dry-run
98+
```
99+
100+
Calibration only needs to be done once - the offsets are stored in the
101+
servo's EEPROM and persist across power cycles. Re-run it if you
102+
physically reposition a servo on its bracket.
103+
104+
### Step 3: Run
105+
106+
```bash
107+
mix phx.server
108+
```
109+
110+
Visit [localhost:4000](http://localhost:4000). Use the dashboard to arm
111+
the robot, then send commands.
112+
113+
### Serial Port Configuration
114+
115+
By default the application connects to `/dev/ttyUSB0` at 1Mbaud. To use
116+
a different port, edit `lib/bb_example_so101/application.ex`:
117+
118+
```elixir
119+
defp robot_opts do
120+
[params: [config: [feetech: [device: "/dev/ttyACM0"]]]]
121+
end
122+
```
126123

127124
## Commands
128125

@@ -132,25 +129,34 @@ Total reach: ~350mm
132129
| `disarm` | Disable torque safely | `[:idle]` |
133130
| `home` | Move all joints to zero position | `[:idle]` |
134131
| `demo_circle` | Execute circular motion demo | `[:idle]` |
135-
| `disable_torque` | Disable servo torque without state change | `[:idle, :disarmed]` |
132+
| `disable_torque` | Disable servo torque | `[:idle, :disarmed]` |
136133
| `move_to_pose` | Move end effector to target position | `[:idle]` |
137134

138135
Execute commands via the web dashboard or programmatically:
139136

140137
```elixir
141-
# Arm the robot first
142138
{:ok, cmd} = BB.Example.SO101.Robot.arm()
143139
{:ok, :armed} = BB.Command.await(cmd)
144140

145-
# Move to home position
146141
{:ok, cmd} = BB.Example.SO101.Robot.home()
147142
{:ok, :homed} = BB.Command.await(cmd)
148-
149-
# Run demo circle
150-
{:ok, cmd} = BB.Example.SO101.Robot.demo_circle()
151-
{:ok, :complete} = BB.Command.await(cmd, 30_000)
152143
```
153144

145+
## Kinematic Structure
146+
147+
Derived from the official [SO-ARM100 URDF](https://github.com/TheRobotStudio/SO-ARM100/tree/main/Simulation/SO101):
148+
149+
| Joint | Range | Link Length |
150+
|-------|-------|-------------|
151+
| shoulder_pan | ±110° | 62mm (base) |
152+
| shoulder_lift | -10° to 190° | 54mm |
153+
| elbow_flex | -187° to 7° | 113mm (upper arm) |
154+
| wrist_flex | ±95° | 135mm (forearm) |
155+
| wrist_roll | ±160° | 61mm (wrist) |
156+
| gripper | -10° to 100° | ~98mm to EE |
157+
158+
Total reach: ~350mm
159+
154160
## Project Structure
155161

156162
```
@@ -162,26 +168,22 @@ lib/
162168
│ ├── demo_circle.ex
163169
│ ├── move_to_pose.ex
164170
│ └── disable_torque.ex
165-
├── bb_example_so101.ex # Application context
166171
├── bb_example_so101/
167172
│ └── application.ex # Supervision tree
168-
└── bb_example_so101_web/ # Phoenix web layer
169-
├── router.ex # Mounts bb_dashboard
170-
└── ...
173+
├── bb_example_so101_web/ # Phoenix web layer
174+
│ ├── router.ex # Mounts bb_dashboard
175+
│ └── ...
176+
└── mix/tasks/
177+
├── so101.setup_servos.ex # Servo ID assignment wizard
178+
└── so101.calibrate.ex # Servo calibration
171179
```
172180

173181
## Development
174182

175183
```bash
176-
# Run in simulation mode
177-
SIMULATE=1 mix phx.server
178-
179-
# Run tests
180-
mix test
181-
mix test path/to/test.exs:42 # Single test at line
182-
183-
# Run all checks
184-
mix check --no-retry
184+
SIMULATE=1 mix phx.server # Run in simulation mode
185+
mix test # Run tests
186+
mix check --no-retry # Run all checks
185187
```
186188

187189
## Related Packages

0 commit comments

Comments
 (0)