A DREAM Robotics Agent · 6-DOF Arm

ARM

6-DOF Robot Arm

Six servos on a PCA9685, driven by an Arduino Uno. Steer her with a joystick, the keyboard, sliders, inverse kinematics or your phone, record macros, and join the RIFT fleet. Every controller shares one set of angles, so they all move together.

Python C++ C# Go Rust Julia Arduino MIT License
ARM's avatar: a human representation of the robot
ARM · avatar

Overview

Six joints, one shared state

Modes

Four ways to steer

Joystick, sliders, inverse kinematics (IK) and Fleet mode, in every controller.

Macros

Record & replay

Record a sequence of moves, save it to scripts/macros/*.json and replay it from any controller.

Sync

Live everywhere

The desktop window, the phone page and RIFT all read and write the same angles. Last writer wins.

Safe

Rest pose

On start-up, on Home, and whenever no controller has been heard from for 2 s, she eases back to rest.

Find

No COM ports to set

arm.ino answers WHO with I am Arm, so controllers find her on any port.

Theme

One colour file

Every UI takes its colours from colour_scheme.xml. Edit it and restart, with no rebuild.

Think

Mind mode

Her LLM mind moves her one joint at a time, thinking out loud and talking in her own dry, patient voice.

See

She watches herself

A webcam and a vision model. When she can’t see her own arm she’s very hesitant: one 3° nudge at a time.

Pick

Pick things up

A colour button, a click on the live camera, or type what it is: she finds it and works out how to grab it.

Hardware

What she's built from

  1. 01 Arduino Uno (scripts/arm/arm.ino, 115200 baud)
  2. 02 PCA9685 16-channel PWM servo driver (I2C 0x40, 50 Hz)
  3. 03 6× 270° servos (claw limited to 40–145°)
  4. 04 External 5–6 V servo supply (to the PCA9685’s V+)
  5. 05 Passive buzzer (her voice in the fleet’s conversations)
  6. 06 USB webcam pointed at the arm (Mind mode)

Wiring

SignalConnection
PCA9685 SDA / SCLUno A4 / A5
PCA9685 VCC / GNDUno 5 V / GND
PCA9685 V+External servo supply (share GND with the Uno)
Buzzer + / −Uno D8 / GND
Base / shoulder / elbowPCA9685 ch 0 / 1 / 2
Wrist pitch / wrist roll / clawPCA9685 ch 3 / 4 / 5

Channels, limits, rest angles and directions live in config.json. Power the servos from their own supply, not the Uno’s 5 V pin.

Controls

Joystick, keyboard or phone

Rest pose

Motor1 base2 shoulder3 elbow4 wrist pitch5 wrist roll6 claw
Rest angle1355510023013540 (open)

Change it in two places: rest in config.json for the controllers, and REST_ANGLE in scripts/arm/arm.ino (reflash afterwards).

Joystick

InputMotorWhat it does
Stick left / right1 baseFollows the stick, centred = rest
Stick forward / back2 shoulderFollows the stick, centred = rest
Twist5 wrist rollFollows the stick, centred = rest
Hat up / down3 elbow5° per press
Button 3 / button 24 wrist pitch5° per press
Trigger6 clawHeld = closed, released = open

Keyboard

KeysMotorPer press
A / D1 base−5° / +5°
W / S2 shoulderUp / down 5°
R / F3 elbowUp / down 5°
T / G4 wrist pitchUp / down 5°
Q / E5 wrist roll−5° / +5°
Space6 clawHeld = closed, released = open
Shift + any of the above1° steps for fine positioning
Home / 1–9 / EscRest pose / pick a macro / quit

Keyboard control is in the Python controller (controller.py) so far. Every motor stays inside its min/max from config.json, and invert flips its direction.

Controllers

Same arm, your language

Every controller has the same four modes and macros, and reads the same config.json. Launchers live at the repo root.

LanguageUILaunchPlatforms
Pythonpygamerun.bat (sets up its venv) / controller.shWindows, Linux
C++Win32build_cpp_controller.bat, then cpp_controller.batWindows
C#Avalonia (.NET 8)csharp_controller.bat / .shWindows, Linux
GoFynego_controller.bat / .shWindows, Linux
Rusteguirust_controller.bat / .shWindows, Linux
JuliaSDL2julia_controller.bat / .shWindows, Linux
> cpp_controller.bat --list-ports              # see what's connected
> cpp_controller.bat --port COM6 --serve        # drive her and share the angles
$ python scripts/controller.py --connect http://192.168.0.10:5011   # a second window

Leave out --port and the controller asks each port WHO and uses the one that answers I am Arm. That takes about 3 s, so --port is faster if you know it. Joystick support in Rust and Go needs the SDL2 shared library.

Fleet

Join RIFT, or use your phone

Whenever the Python or C++ controller runs, in any mode, it bridges RIFT's HTTP protocol to the Arduino: it serves /status, /cmd?motor=&angle=, /reset and /chirp, and heartbeats /register so ARM shows up in the dashboard on port 5011 (--no-serve keeps her to yourself). run.bat is the entry point: it sets up its own venv and installs the requirements the first time.

> run.bat --list-ports
> run.bat --port COM6 --mode fleet

The same server hosts a per-motor slider page: open http://<this machine>:5011/ on any phone or browser on the network, and it stays in sync with the desktop window.

Talking, in Brainfuck

Every phrase is a Brainfuck program that prints its words — hello is ++++++++[>+++++++++++++<-]>.+. → hi — and a robot says it by beeping the program on its buzzer, one tone per symbol, in its own voice. RIFT runs the conversations and asks each robot to speak with GET /chirp?u=<0-13> (phrases 0–6, replies 7–13). ARM’s voice is a passive buzzer on D8 (the other leg to GND), a little lower than the others; the controller passes TALK:<u> to arm.ino.

Inverse kinematics

ARM is the YFROBOT / Makerfabs 6-DOF disc-arm frame. Its link lengths in config.json come from the kit’s dimension drawing: 72 mm from the table to the shoulder pivot, then 104 (upper arm), 143 (forearm) and 173 mm (wrist to closed fingertips). IK measures each joint from an optional per-motor kinematicZero — the raw angle with the base forward, upper arm level and forearm and wrist in line — and falls back to the rest pose until that’s been calibrated.

Several controllers on one arm

Run one controller as the hub (the one with the Arduino plugged in and --serve on), and connect others with --connect http://<hub>:5011. They mirror the hub's angles ten times a second and send changes back, across languages. Connecting never moves the arm.

Sharing a PC with DREAM? Her sensor board answers WHO with I am Dream, so both projects find their own boards whatever COM numbers Windows hands out. Only one program can hold a serial port, so run one controller per arm.

Screens

The controllers

Captured without the arm plugged in, so the controllers are in display-only mode at the rest pose.

ARM's Python controller with motor sliders and macros
Python controller (pygame)
ARM's C++ controller with motor sliders and macros
C++ controller (Win32)
ARM's web control page with a slider per motor
Web control page
The DREAM Robotics ecosystem
Minds — DREAM companion · TINA engineer · NINA caretaker · RIFT fleet hub · LYCEA training school
Robots — NORA · MILA · WHIP · KIDA-00 · KIDA-01 · IDA · ARM · NIKA
Remotes — RITA handheld remote