Skip to content

M3 Wrist Control

The M3 extends the M2 kinematic chain with a 2-DOF articulated wrist between the elbow and gripper. This adds two independently controlled axes — pitch (vertical tilt) and rotation (axial spin) — enabling the gripper to approach objects from arbitrary orientations rather than being locked to the arm’s plane of motion.

M3 wrist close-up with angle annotations Image: Waveshare

The M3 wrist consists of two additional servos mounted at the end of the forearm link (L4 = 171.67mm):

JointServo IDFirmware ConstantRangeDefault
Wrist pitch15WRIST_JOINT (4)±90° (±π/2 rad)0 rad (horizontal)
Wrist rotation16ROLL_JOINT (5)±180° (±π rad)0 rad (neutral)
Gripper17EOAT_JOINT (6)~135° (3.14 → 1.08 rad)3.14 rad (fully open)

The pitch servo tilts the gripper in the vertical plane — positive values tilt downward. The rotation servo spins the gripper around its longitudinal axis — positive values rotate clockwise when viewed from the arm.

Every M2 motion command that accepted joint parameters has been extended with additional fields for the M3 wrist. The T-code numbers are identical — the M3 firmware simply recognizes extra JSON keys.

Control any individual joint by number. The M3 adds joints 4 (wrist), 5 (roll), and 6 (gripper):

{"T":101,"joint":4,"rad":0.5,"spd":0,"acc":10}
Joint NumberNameDirection
1Base+ = left
2Shoulder+ = down
3Elbow+ = down
4Wrist pitch+ = down
5Wrist rotation+ = CW
6Gripper(see gripper section)

Move all joints simultaneously using radian values:

{"T":102,"base":0,"shoulder":0,"elbow":1.57,"wrist":0,"roll":0,"hand":1.57,"spd":0,"acc":10}
ParameterJointUnitM3 Range
baseBase rotationradians±π
shoulderShoulderradians±π/2
elbowElbowradians(constrained by servo)
wristWrist pitchradians±π/2
rollWrist rotationradians±π
handGripperradians~1.08 to 3.14
spdSpeedservo steps/s0 = max
accAccelerationservo steps/s²1–254

Same as T:102 but using degrees. Shorthand parameter names:

{"T":122,"b":0,"s":0,"e":90,"t":0,"r":0,"h":180,"spd":10,"acc":10}
ParameterJointUnit
bBasedegrees
sShoulderdegrees
eElbowdegrees
tWrist pitchdegrees
rWrist rotationdegrees
hGripperdegrees

The M3 inverse kinematics solver extends XYZ positioning with wrist orientation parameters. The key insight is that the t parameter represents the desired tilt angle relative to the world frame, not a raw wrist joint angle — the firmware automatically compensates for the shoulder and elbow configuration to maintain the requested tilt.

Moves to a target position with smooth interpolation:

{"T":104,"x":235,"y":0,"z":234,"t":0,"r":0,"g":3.14,"spd":0.25}

Moves to a target position immediately (no interpolation):

{"T":1041,"x":235,"y":0,"z":234,"t":0,"r":0,"g":3.14}
ParameterDescriptionUnitDefault
xForward distancemm346.16 (l2B + l3A + L4A)
yLateral distancemm0
zVertical distancemm223.13 (l2A − L4B)
tWrist tilt (world frame)radians0 (horizontal)
rWrist rotationradians0 (neutral)
gGripper angleradians3.14 (fully open)
spdInterpolation speed(T:104 only)0.25

Limit the torque on individual joints for compliant/force-sensitive behavior. The M3 version adds per-joint torque limits for the wrist and roll:

{"T":112,"mode":1,"b":60,"s":110,"e":50,"t":50,"r":50,"h":50}
ParameterJointRange
bBase50–1000
sShoulder50–1000
eElbow50–1000
tWrist pitch50–1000
rWrist rotation50–1000
hGripper50–1000

Set mode to 0 to restore full torque on all joints. Lower values make joints more compliant (easier to push by hand).

The gripper commands work the same on M3 as M2:

{"T":106,"cmd":3.14,"spd":0,"acc":0}
  • cmd: 3.14 — fully open
  • cmd: 1.57 — approximately half closed
  • cmd: 1.08 — fully closed (minimum from firmware constraint)

For torque-limited gripping (grasp until resistance):

{"T":107,"tor":200}

The M3 forward kinematics compute end-effector position by chaining four link segments. The wrist adds a fourth link (L4) that the M2 doesn’t have:

graph LR
    A["Base<br/>L1 = 126.06mm"] --> B["Shoulder<br/>L2 = 238.71mm"]
    B --> C["Elbow<br/>L3 = 144.49mm"]
    C --> D["Wrist<br/>L4 = 172.21mm"]
    D --> E["Gripper"]

The firmware computes the effective L4 length as √(L4A² + L4B²) = √(171.67² + 13.69²) ≈ 172.21mm. The small L4B offset (13.69mm) accounts for the mechanical offset between the wrist pitch axis and the gripper centerline.

When using Cartesian control (T:104/T:1041), the IK solver:

  1. Computes the wrist pitch compensation from the t (tilt) parameter
  2. Projects the target point back along the L4 vector to find the elbow-wrist intersection
  3. Solves the 2-link (L2 + L3) planar IK for shoulder and elbow angles
  4. Sets the wrist joint angle to maintain the requested world-frame tilt
  5. Passes r (roll) and g (gripper) directly to their servos

Query the current state of all joints with T:105:

{"T":105}

The M3 response includes wrist and roll data:

{
"T": 1051,
"x": 346.16, "y": 0, "z": 223.13, "tit": 0,
"b": 0, "s": 0, "e": 1.57, "t": 0, "r": 0, "g": 3.14,
"tB": 0, "tS": 0, "tE": 0, "tT": 0, "tR": 0, "tG": 0,
"v": 1200
}
FieldDescription
x, y, zCartesian end-effector position (mm)
titComputed world-frame tilt
b, s, eBase, shoulder, elbow joint angles (rad)
t, r, gWrist pitch, roll, gripper angles (rad)
tBtGPer-joint torque load readings
vSupply voltage (×100, so 1200 = 12.00V)

The ESP-NOW group and single control commands also extend with wrist parameters:

{"T":305,"dev":0,"b":0,"s":0,"e":1.57,"t":0,"r":0,"h":1.57,"cmd":0,"megs":"hello!"}
{"T":306,"mac":"FF:FF:FF:FF:FF:FF","dev":0,"b":0,"s":0,"e":1.57,"t":0,"r":0,"h":1.57,"cmd":0,"megs":"hello!"}

The t, r, and h fields map to wrist pitch, roll, and gripper respectively — matching the T:122 degree-mode naming convention.

Point the gripper straight down, open it, lower to target, close, lift:

{"T":104,"x":200,"y":0,"z":150,"t":-1.57,"r":0,"g":3.14,"spd":0.25}
{"T":104,"x":200,"y":0,"z":50,"t":-1.57,"r":0,"g":3.14,"spd":0.15}
{"T":107,"tor":200}
{"T":104,"x":200,"y":0,"z":150,"t":-1.57,"r":0,"g":3.14,"spd":0.25}

Pick an object and rotate it 90° before placing:

{"T":104,"x":200,"y":0,"z":100,"t":0,"r":0,"g":3.14,"spd":0.25}
{"T":107,"tor":200}
{"T":104,"x":200,"y":100,"z":100,"t":0,"r":1.57,"g":3.14,"spd":0.25}
{"T":106,"cmd":3.14,"spd":0,"acc":0}

Lower the wrist torque limits so a human can physically guide the arm, then record the position:

{"T":112,"mode":1,"b":60,"s":110,"e":50,"t":30,"r":30,"h":50}
{"T":105}
{"T":112,"mode":0,"b":1000,"s":1000,"e":1000,"t":1000,"r":1000,"h":1000}

Firmware reference from RoArm-M3_config.h, RoArm-M3_module.h, and json_cmd.h in the RoArm-M3 example firmware. Images: Waveshare.