Actuators

Motors, servos, and output devices

Actuators

Reference for OctoMY™ actuator types, configuration, and control.

Pro Tip

Always configure the motor safety timeout (setSafetyTimeout(500)) for your actuators. If the Agent loses connection to the Remote, motors will automatically stop after the timeout period instead of continuing at the last commanded speed - this prevents runaways and protects both the robot and its surroundings.


Actuator overview

Actuators are output devices that convert commands into physical action:

Actuator System


Actuator classification

From a usability perspective, actuators are classified in the following ways:

Motion type

Type Description Example
Rotary Actuators that produce rotational motion DC motors, servo motors, stepper motors
Linear Actuators that produce linear motion (straight line) Linear actuators, solenoids, lead screw actuators

Movement range

Type Description Example
Continuous Capable of continuous 360-degree or infinite motion DC motors, stepper motors
Ranged Limited to a specific range of motion (e.g., 0 to 180 degrees) Servo motors, piezoelectric actuators

Feedback type

Type Description Example
Position Feedback Provides feedback on the position of the actuator Servo motors with potentiometers
Speed Feedback Provides feedback on the speed of movement Rotary encoders, tachometers
Force Feedback Provides feedback on the force or load applied Actuators with built-in load cells

Control method

Type Description Example
Open-loop Operates without feedback; performs predefined actions Basic DC motors, solenoids
Closed-loop Uses feedback mechanisms to adjust and control accurately Servo motors, stepper motors with feedback

Power source

Type Description Example
Electric Actuators powered by electrical energy DC motors, AC motors, stepper motors
Pneumatic Actuators that use compressed air to generate motion Pneumatic cylinders, pneumatic valves
Hydraulic Actuators that use fluid pressure for movement Hydraulic rams, hydraulic motors

Actuation mechanism

Type Description Example
Electromagnetic Uses magnetic fields for motion generation DC motors, stepper motors
Piezoelectric Uses electrical charge in piezoelectric materials Precise positioning devices
Electrostatic Uses electrostatic force, typically in micro-scale devices MEMS actuators, electrostatic relays

Actuator types

DC Motor

Standard brushed DC motors with PWM speed control:

Property Value
Type ID 0
Control PWM (0-255) or signed (-100 to 100)
Direction Forward/Reverse
Common Uses Wheels, tracks, propellers
struct DCMotorConfig {
    quint8 pwmPin;           // PWM output pin
    quint8 directionPin;     // Direction control pin (optional)
    quint8 enablePin;        // Enable pin (optional)
    bool invertDirection;    // Reverse direction polarity
    quint16 maxPWM;          // Maximum PWM value (default 255)
};

Servo motor

Standard hobby servos with angular position control:

Property Value
Type ID 1
Control Angle (0-180 degrees)
Range Configurable min/max angle
Common Uses Steering, arms, pan/tilt
struct ServoConfig {
    quint8 pin;              // Servo signal pin
    quint16 minPulse;        // Minimum pulse width (us)
    quint16 maxPulse;        // Maximum pulse width (us)
    quint8 minAngle;         // Minimum angle (degrees)
    quint8 maxAngle;         // Maximum angle (degrees)
    quint8 defaultAngle;     // Default/home position
};

Continuous servo

Servos modified for continuous rotation:

Property Value
Type ID 2
Control Speed (-100 to 100)
Direction Forward/Reverse
Common Uses Wheels, rotating platforms
struct ContinuousServoConfig {
    quint8 pin;              // Servo signal pin
    quint16 stopPulse;       // Pulse width for stop (typically 1500)
    quint16 minPulse;        // Minimum pulse (full reverse)
    quint16 maxPulse;        // Maximum pulse (full forward)
};

Stepper motor

Stepper motors with position and speed control:

Property Value
Type ID 3
Control Steps or degrees
Modes Full step, half step, microstepping
Common Uses Precise positioning, CNC
struct StepperConfig {
    quint8 stepPin;          // Step pulse pin
    quint8 dirPin;           // Direction pin
    quint8 enablePin;        // Enable pin (optional)
    quint16 stepsPerRev;     // Steps per revolution
    quint8 microstepping;    // Microstepping mode (1, 2, 4, 8, 16)
    quint16 maxSpeed;        // Maximum speed (steps/sec)
    quint16 acceleration;    // Acceleration (steps/sec^2)
};

Relay

On/off switching for high-power devices:

Property Value
Type ID 4
Control On (1) / Off (0)
Common Uses Lights, pumps, heaters
struct RelayConfig {
    quint8 pin;              // Control pin
    bool activeHigh;         // True if HIGH = ON
    bool defaultState;       // Default state on startup
};

PWM output

Raw PWM signal for custom applications:

Property Value
Type ID 5
Control Duty cycle (0-255)
Common Uses LEDs, fans, custom control
struct PWMConfig {
    quint8 pin;              // PWM output pin
    quint16 frequency;       // PWM frequency (Hz)
    quint8 defaultValue;     // Default duty cycle
};

Actuator configuration

ArduMYActuator structure

struct ArduMYActuator {
    quint8 id;               // Unique actuator ID
    ActuatorType type;       // Type enum
    QString name;            // Human-readable name
    quint8 flags;            // Enable bits and options
    ActuatorConfig config;   // Type-specific config
    ActuatorState state;     // Current state
};

Enable flags

enum ActuatorFlags {
    ACTUATOR_ENABLED  = 0x01,  // Actuator is enabled
    ACTUATOR_INVERTED = 0x02,  // Invert direction/value
    ACTUATOR_HOMED    = 0x04,  // Has been homed
    ACTUATOR_MOVING   = 0x08,  // Currently in motion
    ACTUATOR_ERROR    = 0x10,  // Error condition
};

Actuator sets

ArduMYActuatorSet

Collection of actuators managed together:

class ArduMYActuatorSet {
public:
    // Actuator management
    void addActuator(const ArduMYActuator& actuator);
    void removeActuator(quint8 id);
    ArduMYActuator* actuator(quint8 id);

    // Bulk operations
    void enableAll();
    void disableAll();
    void homeAll();

    // Serialization
    QByteArray serialize() const;
    bool deserialize(const QByteArray& data);

    // Iteration
    int count() const;
    ArduMYActuator& operator[](int index);
};

Configuration file format

Actuator sets can be saved/loaded from JSON:

{
  "actuators": [
    {
      "id": 0,
      "type": "DC_MOTOR",
      "name": "Left Motor",
      "config": {
        "pwmPin": 3,
        "directionPin": 4,
        "invertDirection": false
      }
    },
    {
      "id": 1,
      "type": "DC_MOTOR",
      "name": "Right Motor",
      "config": {
        "pwmPin": 5,
        "directionPin": 6,
        "invertDirection": true
      }
    },
    {
      "id": 2,
      "type": "SERVO",
      "name": "Pan Servo",
      "config": {
        "pin": 9,
        "minAngle": 0,
        "maxAngle": 180,
        "defaultAngle": 90
      }
    }
  ]
}

Actuator commands

Command structure

struct ActuatorCommand {
    quint8 actuatorId;       // Target actuator
    quint8 type;             // Command type
    qint16 value;            // Target value
    quint8 flags;            // Command flags
};

Command types

Type Description Value Range
SET_VALUE Set actuator value Type-dependent
SET_SPEED Set movement speed 0-100%
HOME Move to home position N/A
STOP Immediate stop N/A
ENABLE Enable actuator 0/1
DISABLE Disable actuator N/A

Sending commands

// From OPAL Plan
actuators.set(0, 75);      // Motor 0 to 75%
actuators.set(1, -50);     // Motor 1 to -50% (reverse)
actuators.set(2, 90);      // Servo to 90 degrees

// Multiple commands
actuators.setAll([75, 75, 90, 45]);

// Stop all
actuators.stopAll();

Value representations

ArduMYActuatorValue

Actuators use a union type for values:

union ActuatorValue {
    qint8 byte;              // 8-bit signed
    quint8 ubyte;            // 8-bit unsigned
    qint16 word;             // 16-bit signed
    quint16 uword;           // 16-bit unsigned
    qint32 dword;            // 32-bit signed
    quint32 udword;          // 32-bit unsigned
    float real;              // 32-bit float
};

Value types by actuator

Actuator Type Value Type Range Unit
DC Motor byte -100 to 100 % speed
Servo uword 0 to 180 degrees
Continuous Servo byte -100 to 100 % speed
Stepper dword varies steps
Relay ubyte 0 or 1 on/off
PWM ubyte 0 to 255 duty

Safety features

Motor safety timeout

Motors automatically stop if no command received:

struct SafetyConfig {
    quint16 timeoutMs;       // Timeout in milliseconds
    bool emergencyStop;      // Stop immediately on timeout
    bool coastStop;          // Coast to stop vs brake
};

// Configuration
actuators.setSafetyTimeout(500);  // 500ms timeout
actuators.setEmergencyStop(true);

Current limiting

struct CurrentLimit {
    quint16 maxCurrent;      // Maximum current (mA)
    quint16 warnCurrent;     // Warning threshold (mA)
    bool autoLimit;          // Auto-reduce on overcurrent
};

Position limits

For servos and steppers:

struct PositionLimits {
    qint32 minPosition;      // Minimum position
    qint32 maxPosition;      // Maximum position
    bool softLimits;         // Enable software limits
    bool hardLimits;         // Enable hardware limit switches
};

Actuator widgets

ActuatorWidget

UI component for individual actuator control:

class ActuatorWidget : public QWidget {
public:
    void setActuator(ArduMYActuator* actuator);
    void setValue(qint16 value);
    qint16 value() const;

signals:
    void valueChanged(qint16 value);
    void enabled(bool state);
};

ActuatorSetWidget

UI for managing multiple actuators:

class ActuatorSetWidget : public QWidget {
public:
    void setActuatorSet(ArduMYActuatorSet* set);
    void refresh();

public slots:
    void enableAll();
    void disableAll();
    void homeAll();
    void stopAll();
};

Common configurations

Differential drive robot

Two-wheel robot with tank steering:

{
  "actuators": [
    {"id": 0, "type": "DC_MOTOR", "name": "Left", "config": {"pwmPin": 3, "directionPin": 4}},
    {"id": 1, "type": "DC_MOTOR", "name": "Right", "config": {"pwmPin": 5, "directionPin": 6}}
  ]
}

Pan-tilt camera

Two-axis camera mount:

{
  "actuators": [
    {"id": 0, "type": "SERVO", "name": "Pan", "config": {"pin": 9, "minAngle": 0, "maxAngle": 180}},
    {"id": 1, "type": "SERVO", "name": "Tilt", "config": {"pin": 10, "minAngle": 30, "maxAngle": 150}}
  ]
}

Robot arm

Multi-joint arm with gripper:

{
  "actuators": [
    {"id": 0, "type": "SERVO", "name": "Base", "config": {"pin": 3}},
    {"id": 1, "type": "SERVO", "name": "Shoulder", "config": {"pin": 5}},
    {"id": 2, "type": "SERVO", "name": "Elbow", "config": {"pin": 6}},
    {"id": 3, "type": "SERVO", "name": "Wrist", "config": {"pin": 9}},
    {"id": 4, "type": "SERVO", "name": "Gripper", "config": {"pin": 10}}
  ]
}

Troubleshooting

Common issues

Issue Cause Solution
Motor doesn't move Wrong pin Verify pin configuration
Motor runs wrong direction Wiring Set invertDirection or swap wires
Servo jitters Power issues Use separate servo power supply
Stepper skips steps Speed too high Reduce maxSpeed
Timeout stops motor Safety feature Increase timeout or send commands faster

Debugging

// Enable actuator debugging
qSetMessagePattern("[%{type}] %{message}");
QLoggingCategory::setFilterRules("octomy.actuator.debug=true");

// Check actuator state
for (int i = 0; i < actuatorSet.count(); i++) {
    auto& a = actuatorSet[i];
    qDebug() << "Actuator" << a.id << a.name
             << "enabled:" << (a.flags & ACTUATOR_ENABLED)
             << "value:" << a.state.currentValue;
}

In this section
Topics
reference hardware actuators motors servos
See also