Skip to content
Ahmed Dabak edited this page Jul 24, 2026 · 4 revisions

Arms

Introduction

Arms drives the two optional arm servos of the Otto Humanoid build. It is a facade over the ArmServos module.

Arms::raiseBoth();
Arms::waveRight(3);
Arms::lowerBoth();

Arms are off by default, because the classic biped does not have them. While they are off, every Arms call is a silent no-op -- so the same sketch runs on both builds without #ifdefs.

Enabling arms

Either take the preset:

OttoFlow::start(Preset::Humanoid);   // arms on pins 6 (left) and 7 (right)

or enable them explicitly, which is also how you move them to different pins:

OttoConfig cfg = Preset::Humanoid;
cfg.arms.leftPin  = 10;
cfg.arms.rightPin = 7;
OttoFlow::start(cfg);

Check at runtime whether this build has working arms:

if (Arms::isActive()) Arms::waveRight();

Raising and lowering

Arms::raiseBoth();        // both arms to 160 degrees
Arms::lowerBoth();        // both arms to 20 degrees
Arms::raiseLeft();        // left arm only
Arms::raiseRight();

Each takes an explicit angle when the defaults do not suit your build:

Arms::raiseBoth(120);
Arms::raiseLeft(90);
Arms::lowerBoth(0);

Angles are 0 to 180 degrees and values above 180 are clamped. The movement is immediate -- the servo travels at its own speed and the call returns at once. To hold a pose, simply do not command a new angle.

Waving

Arms::waveRight();        // two waves
Arms::waveLeft(4);

A wave raises the arm to 160 degrees, drops it to 120, repeats that for the number of times you asked, and finally lowers the arm to 20. It blocks for about 600 ms per wave.

A greeting that reads well:

Mouth::show(Icon::Happy);
Voice::play(Sound::Hello);
Arms::waveRight(2);

Relaxing and holding

Arms::relax();            // detach: stop driving the servos
Arms::hold();             // drive them again
bool active = Arms::isActive();

A detached servo consumes no current and makes no noise, and you can move the arm by hand -- useful while you check clearances or judge a mounting angle. A held servo resists being moved and hums quietly.

Motion::disable() relaxes the arms along with the legs. Motion::enable() re-attaches them, but only if arms are enabled in the configuration.

Note Arms::hold() on a build with arms.enabled = false does nothing, and isActive() stays false. That is the check to use in the serial console or a sketch that must know whether the hardware really exists.

Mounting and angles

What "up" means depends entirely on how you pressed the servo horns onto the splines. If raiseBoth() lowers your arms, you have two options:

  • Pull the horn off, rotate it 180 degrees, and press it back on -- the mechanical fix, and the better one.
  • Or invert the angles in your sketch: Arms::raiseBoth(20), Arms::lowerBoth(160).

Before mounting the horns, centre the servos so you can align them with the arm at rest:

Arms::raiseBoth(90);

Going lower: the ArmServos module

ArmServos::attach();
ArmServos::detach();
bool attached = ArmServos::isAttached();

ArmServos::positionLeftDegrees(140);
ArmServos::positionRightDegrees(40);
ArmServos::positionBothDegrees(90);

ArmServos::waveRight(2);
ArmServos::waveLeft(2);

The module is driven by the standard Arduino Servo library, independently of OttoDIYLib -- which is why arm angles are plain servo angles with no trim applied. If you need arm calibration, add a constant offset in your own code.

Clone this wiki locally