moteus controller reference
The moteus controller is intended to drive 3 phase brushless motors using field oriented control. It has an integrated magnetic encoder for sensing the rotor position, 3 half-H bridges for switching power to each of the three phases, and current sense capability on each of the three phases.
The primary control mode, labeled as "position" mode in the rest of this document is a two stage cascaded controller, with both running at the switching frequency (by default 40kHz).
The outermost stage is an optional limited acceleration and velocity trajectory planner. Within that is an integrated position/velocity PID controller with optional feedforward torque. The output of that loop is a desired torque/current for the Q phase of the FOC controller.
The inner stage is a current mode PI controller. Its output is the desired voltage value for the Q phase. Then the magnetic encoder is used to map the D/Q phase voltage values to the 3 phases of the motor.
More precisely, the "Position Controller" implements the following control law:
acceleration = trajectory_follower(command_position, command_velocity)
control_velocity = command_velocity OR control_velocity + acceleration * dt OR 0.0
control_position = command_position OR control_position + control_velocity * dt
position_error = control_position - feedback_position
velocity_error = control_velocity - feedback_velocity
position_integrator = limit(position_integrator + ki * position_error * dt, ilimit)
torque = position_integrator +
kp * kp_scale * position_error +
kd * kd_scale * velocity_error +
command_torque
And the "Current Controller" implements the following control law:
current_error = command_current - feedback_current
current_integrator = limit(current_integrator + ki * current_error, ilimit)
voltage = current_integrator + kp * current_error
Since PID scaling for the position mode loop can be adjusted on a
cycle-by-cycle basis with the kp_scale
and kd_scale
terms, this
allows you to operate the controller with full
position/velocity/torque control, or velocity/torque, or just torque,
or any combination seamlessly throughout the control cycle.
The available knobs to the moteus controller allow it to implement a few different types of control schemes. From the factory, the control gains are selected for medium torque bandwidth. For other applications, here are suggestions for gains and control options to use.
To implement a velocity controller, each command should have the
"position" set to NaN (or equivalent integral encoding). It is
recommended to configure servo.max_position_slip
to a finite value
greater than 0 (reference). When it is
larger, more external disturbances will be rejected, but the
controller will also "catch up" when the magnitude of external
disturbances is decreased.
For either operation at very low speeds, or when precise positioning
performance is desired, it is recommended to configure a non-zero ki
and ilimit
term in the position controller
(reference). This will compensate for cogging
torque (at the expense of overall torque bandwidth). It may also be
beneficial to select a alternate values for moteus_tool --cal-bw-hz
during calibration (higher or lower).
Velocity and acceleration limits can be configured either globally, or on a per-command basis which will cause moteus to internally generate continuous acceleration limited trajectories to reach the given position and velocity. Once the trajectory is complete, the command velocity is continued indefinitely.
moteus only supports acceleration limited internal trajectories. To approximate a constant jerk trajectory, the host processor should send a sequence of piecewise linear constant velocity trajectories which approximate the desired one. This would be done by sending commands consisting of at least a position and velocity at some moderate to high rate while disabling the internal velocity and acceleration limits.
High torque bandwidth is desired for legged robots, or other
applications where it is necessary to respond to external disturbances
as rapidly as possible or accelerate the load maximally. For these
applications, it is recommended to have no integrative term in the
position controller (reference). When
calibrating the motor, you may use the moteus_tool --cal-bw-hz
option to select a bandwidth higher than the default of 100Hz (or
manually select servo.pid_dq.kp/ki after calibration).
For a pure torque control application, configure the position control loop kp, kd, and ki to 0 (reference). Alternately you can set the kp_scale and kd_scale to 0 in each command.
Note, however, that external torque control will be much lower bandwidth than using the internal position controller of moteus (~50x lower bandwidth if maximal CAN-FD update rate is achieved). Thus, a system will usually perform better if as much of the desired control law as possible is formulated in terms of the built in position controller.
The register command set is intended for use in real-time applications. It provides multiple levels of conciseness, and is possible to operate at over 1kHz on the provided FD-CAN communications bus.
Common definitions:
- endian-ness: All primitive types are in least significant byte first
- varuint: A sequence of one or more uint8 values, in least significant byte first order. For each value, the 7 LSBs contain data and if the MSB is set, it means there are more bytes remaining. At most, it may represent a single uint32 and thus 5 bytes is the maximum valid length.
- float: An IEEE 754 32-bit floating point number.
Communication with moteus is conducted via CAN-FD frames with a 1Mbit standard bitrate and a 5Mbit data bitrate.
The ID is structured as a 16 bit number, with the high 8 bits being the "source" and the low 8 bits being the "destination". The destination is the 7 bit servo ID with 0 as the highest bit. The source is an arbitrary 7 bit number, with the high bit being 1 if moteus should reply to the message.
The CAN frame must be an extended one if the ID would be greater than 0x7fff, but otherwise whether or not a frame is extended is not considered.
Example:
ID: 0x8001
- Send from source 0
- To destination 1
- 16th bit is set, so a reply is requested
ID: 0x100
- Send from source 1
- To destination 0
- No reply is requested
Each CAN-FD frame contains one or more "subframes". A short description of the allowable subframe types are described below. The canonical reference is located at multiplex/format.h
Any extra trailing padding bytes required in the CAN-FD frame should be set to NOP (0x50).
0x00, 0x04, 0x08, 0x0c - write (int8|int16|int32|float)
varuint
=> number of registers (may be optionally encoded as a non-zero 2 LSBS of the subframe type)varuint
=> start register number- N x (int8|int16|int32|float) => values
0x10, 0x14, 0x18, 0x1c - read (int8|int16|int32|float)
varuint
=> number of registers (may be optionally encoded as a non-zero 2 LSBs)varuint
=> start register number
0x20, 0x24, 0x28, 0x2c - reply (int8|int16|int32|float)
varuint
=> number of registers (may be optionally encoded as a non-zero 2 LSBs)varuint
=> start register number- N x (int8|int16|int32|float) => values
0x30, 0x31 - read/write error
varuint
=> register numbervaruint
=> error number
0x50 - no operation
Each register may be accessed as potentially multiple data types. This section describes the common mappings, and the semantics of each register.
When registers are accessed as integer types, the following mappings are used to encode the underlying floating point values into integer values.
- int8 => 1 LSB => 1A
- int16 => 1 LSB => 0.1A
- int32 => 1 LSB => 0.001A
- int8 => 1 LSB => 0.5 N*m
- int16 => 1 LSB => 0.01 N*m
- int32 => 1 LSB => 0.001 N*m
- int8 => 1 LSB => 0.5V
- int16 => 1 LSB => 0.1V
- int32 => 1 LSB => 0.001 V
- int8 => 1 LSB => 1 C
- int16 => 1 LSB => 0.1C
- int32 => 1 LSB => 0.001 C
- int8 => 1 LSB => 0.01s
- int16 => 1 LSB => 0.001s
- int32 => 1 LSB => 0.000001s
- int8 => 1 LSB => 0.01 rotation => 3.6 degrees (range of -1.27 to 1.27)
- int16 => 1 LSB => 0.0001 rotation => 0.036 degrees (range of -3.2767 to 3.2767)
- int32 => 1 LSB => 0.00001 rotation => 0.0036 degrees
- int8 => 1 LSB => 0.1Hz / 36 dps
- int16 => 1 LSB => 0.00025 Hz > 0.09 dps
- int32 => 1 LSB => 0.00001 Hz => 0.0036 dps
- int8 => 1 LSB => 0.05 l/s^2
- int16 => 1 LSB => 0.001 l/s^2
- int32 => 1 LSB => 0.00001 l/s^2
Mode: Read/write
The current operational mode of the servo. Not all values are valid to write.
- 0 => stopped = writeable, clears faults
- 1 => fault
- 2,3,4 => preparing to operate
- 5 => PWM mode
- 6 => voltage mode
- 7 => voltage FOC
- 8 => voltage DQ
- 9 => current
- 10 => position
- 11 => timeout
- 12 => zero velocity
- 13 => stay within
- 14 => measure inductance
- 15 => brake
Mode: Read only
The current position of the servo, measured in rotations of the output shaft. The maximum negative integer is reserved and will not be reported.
Mode: Read only
The current velocity of the servo, measured in Hz at the output shaft.
Mode: Read only
The current applied torque as measured at the output shaft.
Mode: Read only
The current in the Q phase measured in amperes.
Mode: Read only
The current in the D phase measured in amperes.
Mode: Read only
If an absolute encoder is configured on the ABS port, its value will be reported here in revolutions.
Mode: Read only
Non-zero if the current acceleration or velocity limited trajectory is complete, and the controller is following the final velocity.
Mode: Read only
Non-zero if the controller has been rezeroed since power on.
Mode: Read only
The current input voltage.
Mode: Read only
The current board temperature, measured in degrees celsius.
Mode: Read only
A fault code which will be set if the primary mode is 1 (Fault).
- 32 - calibration fault - the encoder was not able to sense a magnet during calibration
- 33 - motor driver fault - the most common reason for this is
undervoltage, moteus attempted to draw more current than the supply
could provide. Other electrical faults may also report this error,
the
drv8323
diagnostic tree has more information. - 34 - over voltage - the bus voltage exceeded
servo.max_voltage
. This can happen due to misconfiguration, or if the controller regenerated power with a supply that cannot sink power and no flux braking was configured. - 35 - encoder fault - the encoder readings are not consistent with a magnet being present.
- 36 - motor not configured - the
moteus_tool --calibrate
procedure has not been run on this motor. - 37 - pwm cycle overrun - an internal firmware error
- 38 - over temperature - the maximum configured temperature has been exceeded
- 39 - outside limit - an attempt was made to start position control
while outside the bounds configured by
servopos.position_min
andservopos.position_max
.
The full list can be found at: fw/error.h
Mode: Read/write
When in Pwm mode, this controls the raw PWM value for phase A, B, and C. If unspecified, 0.0 is used.
Mode: Read/write
When in Voltage mode, this controls the voltage applied to phase A, B, and C. If unspecified, 0.0 is used.
Mode: Read/write
When in Voltage Foc mode, this controls the desired electrical phase. Integral types use the PWM mapping. If unspecified, 0.0 is used.
Mode: Read/write
When in Voltage Foc mode, this controls the desired applied phase voltage. If unspecified, 0.0 is used.
Mode: Read/write
When in Voltage Dq mode, this controls the desired applied D voltage. If unspecified, 0.0 is used.
Mode: Read/write
When in kVoltageDq mode, this controls the desired applied Q voltage. If unspecified, 0.0 is used.
Mode: Read/write
When in Current mode, this controls the desired Q phase current. If unspecified, 0.0 is used.
Mode: Read/write
When in Current mode, this controls the desired D phase current. Unless you like burning power, with a BLDC motor you will typically want this set to 0. If unspecified, 0.0 is used.
Mode: Read/write
When in Position mode, this controls the desired position. The maximally negative integer, or NaN for float represents, "use the current position value". If unspecified, 0.0 is used. Note, the controller will attempt to achieve this position right now subject to the kp and kd constants.
Mode: Read/write
When in Position mode, advance the desired position at the given velocity in Hz.
As a special case, if the 0x020 position is unset, and 0x026 stop position is set, the sign of this is ignored, and is instead selected so that the motor will move towards the stop position. If unspecified, 0.0 is used.
Mode: Read/write
When in Position mode, add the given feedforward torque after applying all regular control loops. Note, this is torque at the output shaft. If unspecified, 0.0 is used.
Mode: Read/write
When in Position mode, shrink the proportional control term by the given factor. Integral types are applied as for PWM. If unspecified, 1.0 is used.
Mode: Read/write
When in Position mode, shrink the derivative control term by the given factor. Integral types are applied as for PWM. This is internally limited to be no more than the kp scale. If unspecified, 1.0 is used.
When in Position mode, the maximum torque to be applied. If unspecified, this defaults to the system-wide configured maximum torque.
When in Position mode, and a non-zero velocity is commanded, stop motion when reaching the given position. NaN / maximally negative means no limit is applied. If unspecified, NaN is used.
Note, if the controller is ever commanded to move away from the stop position, say with a velocity command that is inconsistent with the start and stop position, then it will act as if a 0 velocity has been commanded and the current command position equals the stop position.
Mode: Read/write
This determines the length of time for which this command is valid. If this timeout expires before another command is received, the controller will enter the Timeout state. The default is 0.0, which means to use the system-wide configured default. NaN / maximally negative means apply no enforced timeout.
Mode: Read/write
This can be used to override the global velocity limit for internally generated trajectories. If unspecified, it is NaN / maximally negative, which implies to use the global configurable default.
Mode: Read/write
This can be used to override the global acceleration limit for internally generated trajectories. If unspecified, it is NaN / maximally negative, which implies to use the global configurable default.
Mode: Read
This reports the torque contribution from the proportional term in the PID controller.
Mode: Read
This reports the torque contribution from the integral term in the PID controller.
Mode: Read
This reports the torque contribution from the derivative term in the PID controller.
Mode: Read
This reports the feedforward contribution in the PID controller.
Mode: Read
This reports the total commanded torque from the position mode controller.
Mode: Read/write
When in Stay Within mode, this controls the minimum allowable position. The maximally negative integer or NaN for float represents, "there is no lower bound". When special or the position is above this bound (and also respecting the optional upper bound), only a feedforward torque is applied. When outside this bound, the PID controller is used to force the position back to the bound. If unspecified, 0.0 is used.
Mode: Read/write
When in Stay Within mode, this controls the maximum allowable position. The maximally negative integer, or NaN for float represents, "there is no upper bound". When special or the position is below this bound (and also respecting the optional lower bound), only a feedforward torque is applied. When outside this bound, the PID controller is used to force the position back to the bound. If unspecified, 0.0 is used.
A shadow of the 0x022 register.
A shadow of the 0x023 register.
A shadow of the 0x024 register.
A shadow of the 0x025 register.
A shadow of the 0x027 register.
Name: Model Number Mode: Read only
This returns a 32 bit model number.
Mode: Read only
This returns a 32 bit firmware version, encoded bytewise as major.minor.micro. i.e. 0x010304 is version 1.3.4
Mode: Read only
This returns a number that indicates how to interpret all registers.
Name: Multiplex ID Mode: Configurable
This controls the primary ID used to access the device over the multiplex RS485 bus. It can only be between 1 and 127. (0 is reserved as the broadcast address).
Name: Serial Number Mode: Read only
This returns a 96 bit serial number, least significant word first.
Mode: Write only
When sent, this causes the servo to select a whole number of internal motor rotations so that the final position is as close to the given position as possible.
A single CAN-FD frame can be used to command the servo, and initiate a query of certain registers. An example frame might look like the following, encoded in hex with annotations.
01
- write a single int8 register (number of registers is encoded in the 2 LSBs)00
- start register number "Mode"0a
- "position" mode07
- write 3x int16 registers (number of registers is encoded in the 2 LSBs)20
- register 0x0206000
- position = 0x0060 = 96 = 3.456 degrees2001
- velocity = 0x0120 = 288 = 25.92 dps50ff
- feedforward torque = 0xff50 = -176 = 1.76 N*m14
- read int16 registers04
- read 4 registers00
- starting at 0x000 (so 0x000 Mode, 0x001 Position, 0x002 Velocity, 0x003 Torque)13
- read 3x int8 registers0d
- starting at 0x00d (so 0x00d Voltage, 0x00e Temperature, 0x00f Fault code)
Thus the whole CAN-FD message would be (in hex):
01000a07206000200150ff140400130d
To send this using the fdcanusb converter to a device configured at the default address of 1, you could write.
can send 8001 01000a07206000200150ff140400130d
The 80
in ID is used for two purposes. The high bit being set
forces the device to respond (otherwise it will not respond, even if
query commands are sent). The remaining bits are the "ID" to respond
to. In response to this command, a possible response from the servo
would look like:
rcv 100 2404000a005000000170ff230d181400
Decoded, that means:
-
100
from device "1" to device "0" -
24
reply with int16 values -
04
4 registers -
00
starting at register 0 -
0a00
in mode 10 - Position -
5000
position is 0x0050 = 80 = 2.88 degrees -
0001
velocity is 0x0100 = 256 = 23.04 dps -
70ff
torque is 0xff70 = -144 = -1.44 Nm -
23
reply with 3 int8 values -
0d
starting at register 0x00d -
18
voltage is 12V -
14
temperature is 20C -
00
no fault
The following command set is intended for debugging and diagnostics.
It can be entered from tview
or the --console
mode of
multiplex_tool
or moteus_tool
.
This causes the controller to enter the "stopped" state, which disables the motor driver.
This enters the "raw" PWM mode. Syntax:
d raw <pwm_a> <pwm_b> <pwm_c>
Where the pwm values are between 0.0 and 1.0. A command to the idle
state is thus: d raw 0.5 0.5 0.5
.
This enters voltage-FOC mode. Syntax:
d pwm <phase> <magnitude>
Where phase is in radians, and magnitude is in volts.
This enters the current controlled FOC mode. Syntax:
d dq <d_A> <q_A>
This enters the position control FOC mode. Syntax:
d pos <pos> <vel> <max_torque> [options...]
Each optional element consists of a prefix character followed by a value. Permissible options are:
p
- kp scale: the configured kp value is multiplied by this constant for the duration of this commandd
- kd scale: the configured kd value is multiplied by this constant for the duration of this commands
- stop position: when a non-zero velocity is given, motion stops when the control position reaches this value.f
- feedforward torque in Nmt
- timeout: If another command is not received in this many seconds, enter the timeout mode.v
- velocity limit: the given value will override the global velocity limit for the duration of this command.a
- acceleration limit: the given value will override the global acceleration limit for the duration of this command.
The position, velocity, maximum torque, and all optional fields have the same semantics as for the register protocol documented above.
Enter the timeout mode. This mode commands a zero velocity and can only be exited through the stopped state.
d tmt <pos> <vel> <max_torque> [options...]
Available options are identical to d pos
.
Enter the zero velocity state. A zero velocity is commanded regardless of position.
d zero <pos> <vel> <max_torque> [options...]
Available options are identical to d pos
. pos
and vel
are
ignored.
Enter the "stay within" state. When the position is contained within the given bounds, only the feedforward torque is applied. Otherwise, the position mode controller is used to hold the position at the violated boundary.
d within <lowbound> <highbound> <max_torque> [options...]
The fields have the same semantics as for the register protocol
documented above. The options are the same as for d pos
, with the
exception of stop position which is not supported.
Enter the "brake" state. In this mode, all motor phases are shorted to ground, resulting in a passive "braking" action.
Force the current recorded position to match exactly the given value.
d index <position>
Assuming that motor.position_offset
is configured correctly, update
the current position to the closest one which is consistent with a
given output position.
d rezero <position>
INTERNAL moteus_tool USE ONLY: Enter the encoder calibration mode. Upon starting this command, the controller will spin the motor in voltage-FOC mode until the encoder covers a full revolution, then repeat the process in the other direction. During the process, the current commanded phase and encoder value are periodically emitted to the console.
Syntax:
d cal <magnitude> [options...]
Each optional element consists of a prefix character followed by a value. Permissible options are:
s
- calibration speed in electrical revolutions per second
NOTE: This command is for internal moteus_tool use only. It performs only part of the calibration process, and saves nothing to the persistent storage.
Enter the bootloader.
NOTE: This is only intended for internal use. Users who want to flash new firmware should use moteus_tool
.
Retrieve the contents of a given channel. Text or binary mode is
determined via the tel fmt
or tel text
commands, and defaults to
binary mode.
tel get <channel>
List all available telemetry channels.
Report the binary schema associated with the given channel.
tel schema <channel>
The schema is reported as follows:
emit <channel>\r\n
<LE uint32 size><data>
Control the rate at which a given channel is emitted.
tel rate <channel> <rate_ms>
Select whether a given channel will be emitted in binary or text form.
tel fmt <channel> <format>
format
is an integer, non-zero signifies the data should be emitted
as text.
Stop emitting all periodic telemetry data.
Switch all channels to text mode.
NOTE: Any commands that change parameters, such as conf set
, conf load
, or conf default
, if executed manually in tview
will not
automatically update the UI. tview
must be restarted to display the
new parameters in the UI.
Print the current value of all configurable parameters.
Get the value of a single configurable parameter.
conf get <item>
Set the value of a single configurable parameter in RAM.
conf set <item> <value>
Load all configurable values from persistent storage. This will overwrite their current values in RAM.
Write the current value of all configurable parameters from RAM to persistent storage.
Update the RAM values of all configurable parameters to their firmware default.
NOTE: This only updates RAM, not the persistent storage. A conf write
will be necessary to save these to persistant storage.
This section describes the configurable values which are most likely to be modified for end-user applications. Changes to all values take effect immediately. This may mean, that for instance, it is wise to stop control loops before drastically changing control parameters. Or maybe not, it depends upon your goals.
The servo ID presented on the CAN bus. After this is modified, you need to immediately adjust which servo ID you communicate with in order to continue communication or save the parameters.
A 13 bit integer used as the upper 13 bits for the ID of all CAN
communication. As with id.id
this takes effect immediately, so
after changing it, communication must be restarted with the correct
prefix in order to do things like save the configuration.
This value is added to servo_stats.position
before reporting
unwrapped_position_raw
. It thus sets the 0
value for all position
control.
This sets the reduction of any integrated gearbox. Using this scales
all position, velocity, and torque commands and statuses accordingly.
A reducing gearbox will need a value between 0 and 1, so 0.25
for a
4x reduction gearbox.
The minimum allowed control position value, measured in rotations. If NaN, then no limit is applied.
The maximum allowed control position value, measured in rotations. If NaN, then no limit is applied.
These configure the position mode PID controller.
kp/ki/kd
- PID gains with units of:- kp - Nm per rotation
- ki - Nm/s per rotation
- kd - Nm per rotation/s
iratelimit
- The maximum rate at which the integral term can wind up, in N*m/s. <0 means "no limit"ilimit
- The total maximum I term, in Nmmax_desired_rate
- If non-zero, the commanded position is limited to change at this rate in Hz.
Note, these values are in physical units. Thus a kp
value of 1,
means that for 1 revolution of error at the output, 1 Nm of corrective
torque will be applied. Similarly, with a kd
value of 1, 1
revolution per second of error will result in 1 Nm of corrective
torque. Doubly note that these values are measured at the output,
thus after any scaling in position, velocity, and torque implied by
motor.unwrapped_position_scale
.
These have the same semantics as the position mode PID controller, and affect the current control loop.
Limits to be placed on trajectories generated within moteus. If
either is nan
, then that limit is unset. The limits may also be
overriden individually on a per command basis. The semantics of the
limits are as follows:
-
Neither set (both nan) In this case, position and velocity commands take immediate effect. The control position will be initialized to the command position, and the control velocity will be set to the command velocity. The control position will advance at the given velocity indefinitely, or until the command stop position is reached.
-
Only velocity limit set: In this case, until the desired position is reached, the control velocity will be set to either the positive or negative velocity limit. Once the desired position has been reached, then the velocity will continue indefinitely at the command velocity.
-
Both set: In this case, neither the command position nor the command velocity are immediately applied. Instead, the control velocity is advanced by the configured acceleration each timestep while being limited to the maximum configured velocity in order to achieve the desired position and velocity. Once the desired position and velocity have been achieved, then that final velocity is continued indefinitely. Note that this may require "back tracking" if the current and final velocities do not permit an approach in a single pass.
-
Only acceleration limit set: This behaves like the "both set" case, except that the control velocity is allowed to increase or decrease arbitrarily.
NOTE: This is limited internally to be no more than
servo.max_velocity
.
When set to non-zero, the current control loop is not closed, and all current commands in amperes are instead treated as voltage mode commands in volts related by the calibrated phase resistance. For high winding resistance motors, the default current sense resistors are too small for accurate current sensing, resulting in significant cogging torque and current sense noise. If replacing the current sense resistors is not an option, this flag can be used to achieve smooth control. The downside is that the actual torque will no longer follow the applied torque accurately at speed, or in the face of external disturbances.
When set, the servo.pid_dq
configuration values no longer affect
anything.
If non-zero, then no feedback based control of either position or current is done. Instead, a fixed voltage is applied to the phase terminals based on the current commanded position and the configured number of motor poles. In this mode, the encoder and current sense resistors are not used at all for control.
This is a similar control mode to inexpensive brushless gimbal controllers, and relies on burning a fixed amount of power in the motor windings continuously.
When this mode is active, the reported position and velocity will be 0 when the drive is disabled, and exactly equal to the control position when it is enabled.
Various derating limits are inoperative in this mode:
- torque derating for temperature
- torque derating when outside position bounds
- the maximum current limit
- the commanded maximum torque
A fault will still be triggered for over-temperature.
In the fixed voltage control mode, the voltage to apply to the output.
When finite, this enforces a limit on the difference between the control position and the current measured position measured in revolutions. It can be used to prevent "catching up" when the controller is used in velocity mode.
If the input voltage reaches this value, a fault is triggered and all torque is stopped.
The controller will limit the output power to this value. The value is defined relative to a PWM rate of 40kHz and is scaled linearly with respect to the PWM rate.
The PWM rate to use, defaulting to 40000. Allowable values are between 15000 and 60000. Lower values increase efficiency, but limit peak power and reduce the maximum speed and control bandwidth.
Torque begins to be limited when the temperature reaches this value.
If the temperature reaches this value, a fault is triggered and all torque is stopped.
When the input voltage is above this value, the controller causes the
motor to act as a "virtual resistor" with resistance
servo.flux_brake_resistance_ohm
. All extra energy is dumped into
the D phase of the motor. This can be used to handle excess
regenerative energy if the input DC link is incapable of accepting
sufficient energy.
Phase current will never be used more than this value. It can be decreased to limit the total power used by the controller. Increasing beyond the factory configured value can result in hardware damage.
Output power will be limited if the velocity exceeds this threshold.
Once velocity reaches the max_velocity plus this value, allowed output power is reduced to 0.
These values configure a higher order torque model for a motor.
servo.rotation_current_cutoff_A
if the phase current is less than this value, then the linear relationship implied bymotor.v_per_hz
is used.
Once above that cutoff, the following formula is used to determine torque from phase current:
torque = cutoff * tc + torque_scale * log2(1 + (I - cutoff) * current_scale)
Where tc
is the torque constant derived from motor.v_per_hz
.
This model is not automatically calibrated, and needs to be determined and configured manually.
When sending position mode commands over CAN, there is an optional
watchdog timeout. If commands are not received at a certain rate,
then the controller will latch into the "position timeout" state,
requiring a stop command to resume operation. This configuration
value controls the length of time that the controller will wait after
receiving a command before entering this state. If set to nan
then
the controller will never enter this timeout state.
It may be overidden on a per-command basis with the 0x027 register or
the t
optional flag of the d pos
command for the diagnostic
interface.
When in the "position timeout" mode the controller acts to damp the output. This parameter controls the maximum torque available for such damping.
Selects what behavior will take place in the position timeout mode. The allowable values are a subset of the top level modes.
- 0 - "stopped" - the driver is disengaged
- 12 - "zero velocity"
- 15 - "brake"
If set to one, then shortly after startup, the value of the position will be initialized to the closest one consistent with the position measured at the ABS port.
Configures the mode of operation of the ABS port:
- 0 - disabled
- 1 - AS5048B (I2C address is default 64)
- 2 - AS5600 (I2C address is default 54)
Configures what I2C mode will be used:
- 0 - standard <= 100kHz
- 1 - fast <= 400kHz
- 2 - fast+ <= 1Mhz (note the AS5048B encoder does not support fast+)
What rate to operate the I2C bus at.
The I2C address to communicate with the auxiliary encoder.
How often, in milliseconds to poll the auxiliary encoder. Must be no less than 5.
The reported position is calculated from the raw value as follows:
position = (raw + offset) / 65536 * scale
Selects whether the onboard magnetic encoder or an external magnetic encoder is used.
- 0 - onboard
- 1 - external AS5047 compatible SPI encoder
tview can monitor and control 1 or more devices simultaneously. It can be started with:
python3 -m moteus_gui.tview --target 1[,2,3]...
When running, the configuration for each can be modified in the left hand tab, and live telemetry values can be displayed or plotted from the right hand tab. diagnostic mode commands may be issued in the bottom terminal window.
A simple command and scripting language beyond the diagnostic protocol is available within the tview terminal window.
If more than one device is available, commands can be sent to a specific device by prefixing the command with ID>
. For instance, to send a stop command to ID #2, you can do:
2>d stop
The 'A' character can be used to send to all devices simultaneously.
A>d stop
The &&
token may be used to separate individual commands, which will be issued back to back. For instance:
1>d stop && 2>d stop
Will send the command to both devices.
A delay may be inserted into a sequence of commands by entering an integer number of milliseconds prefixed by the colon (':') character. For instance:
d pos nan 0.5 1 s0.5 && :1000 && d stop
Will command a position mode, wait 1s, then command a stop.
Assuming your controller has firmware installed already, you can calibrate the controller using the following procedure.
python3 -m moteus.moteus_tool --target 1 --calibrate
WARNING: Any attached motor must be able to spin freely. It will be spun in both directions and at high speed.
After calibrating for an entirely new type of motor, you may need to
adjust PID gains before the motor will perform acceptably, and/or
configure motor.unwrapped_position_scale
.
The moteus controller can locate positions within one revolution after being power cycled, and will start with the reported position being between -0.5 and 0.5. The physical zero position can be set using the following command:
python3 -m moteus.moteus_tool --target 1 --zero-offset
The latest firmware can be downloaded from: https://github.com/mjbots/moteus/releases
You need the file named YYYYMMDD-moteus-HASH.elf NOT the one named "bootloader".
Download that file and save it somewhere on your computer, then
substitute its path in place of path/to/file.elf
in the following
command.
python3 -m moteus.moteus_tool --target 1 --flash path/to/file.elf
The firmware can be built and flashed using:
tools/bazel build --config=target //fw:flash
Or, if already built, flashed using:
./fw/flash.py
openocd 0.11.0 or newer is required. You can find binaries for many platforms at: https://xpack.github.io/openocd/releases/
This will build, but not flash the firmware. Only curl
needs to be
installed.
tools/bazel test --config=target //:target
The current mechanical drawing for the controller can be found at: 20210124-moteus-controller-r45-mechanical.pdf
The current mechanical drawing for the qdd100 servo can be found at: 20200315-qdd100-mechanical.pdf
Looking at the pins of the connector with the bottom of the board up the pins are numbered 1 to 3 from left to right.
- 1 - CAN_H
- 2 - CAN_L
- 3 - GND
NOTE 1: CAN connections should be terminated by a 120 ohm resistor at both ends of a bus. Some mjbots products have built in termination resistors, such as the pi3hat. The fdcanusb has a software configurable termination resistor that is by default on. moteus controllers have no termination resistors. For very short runs, the system will work terminated only on one side. However, when runs become longer than 0.5m, you will likely need to terminate both ends. This can be done by crimping a 120 ohm resistor into a JST PH3 connector and connecting it to the open data connector.
NOTE 2: Ground may not be necessary, only one path through ground in a system should exist to avoid ground loops. In a typical robot application with a common ground, that role is filled by the power ground. However, in desktop applications, it may be appropriate to connect the CAN ground if the device power supply is otherwise isolated.
Looking at the pins of the connector with the top of the board up the pins are numbered 1 to 6 from left to right.
- 1 - NC
- 2 - NRST
- 3 - SWDIO
- 4 - GND
- 5 - SWCLK
- 6 - 3.3V
Pin 1 is closest to the ABS label. They are assigned as follows:
- 1 - 3.3V
- 2 - SCL
- 3 - SDA
- 4 - GND
Looking at the pins of the power connector with the top of the board up, the ground pin is to the left with the chamfered corner and the positive supply is to the right with the square corner.
Looking at the back of the board with the ENC connector at the top, pins are numbered 1 as the rightmost, and 6 as the leftmost.
- 1 - 3.3V
- 2 - CS
- 3 - GND
- 4 - SCLK
- 5 - MISO
- 6 - MOSI
These pads can be populated with a Molex Pico-SPOX 6 connector PN 0874380643, or as an alternate, TE 5-1775444-6.
moteus_tool
and tview
can be configured to communicate with a
moteus controller through a variety of transports. By default, it
will attempt to autodetect either a fdcanusb or socketcan interface.
To force usage of a particular fdcanusb, you can use:
python3 -m moteus.moteus_tool --fdcanusb /path/to/fdcanusb
To force a particular python-can method, you can use:
python3 -m moteus.moteus_tool --can-iface socketcan --can-chan can0
where --can-iface
specifies the "interface" for python-can and
--can-chan
specifies the "channel".
Note, these are in addition to any other moteus_tool
or tview
options that may be desired.
Linux in particular appears to select very poor bit-timings for CAN-FD when running at 5 MBps data rate. The primary symptom is that no communication is possible with a moteus controller or fdcanusb unless you clock them a few percent slower than the requisite 5Mbps. This can be resolved by specifying custom bit timings to the linux socketcan subsystem. The following timings are known to work for at least some systems:
Chips such as the MCP2517/8 often use a 40MHz system clock. The following timings have been observed to work:
ip link set can0 up type can \
tq 25 prop-seg 13 phase-seg1 12 phase-seg2 14 sjw 5 \
dtq 25 dprop-seg 3 dphase-seg1 1 dphase-seg2 3 dsjw 3 \
restart-ms 1000 fd on
Adapter such as the PEAK-CAN-FD use a 80MHz clock. The following timings have been observed to work:
ip link set can0 up type can \
tq 12 prop-seg 25 phase-seg1 25 phase-seg2 29 sjw 10 \
dtq 12 dprop-seg 6 dphase-seg1 2 dphase-seg2 7 dsjw 12 \
restart-ms 1000 fd on
The commanded position is limited to +-32767.0 revolutions before any
unwrapped_position_scale
has been applied. Reducers there will
further limit the range of the commandable revolutions. For instance,
a 1/10 reducer configured as unwrapped_position_scale=0.1
results in
a available position command range of +-3276.7 revolutions.
If either:
a. the position is commanded as the special value (NaN or maximally negative), or b. the kp term is zero either through configuration or the "kp scale"
Then it is safe for the controller to "wrap around" from the maximal possible position to the maximally negative position and vice versa. This is useful in velocity control applications.
The commanded position is internally treated as a 32 bit floating point value. Thus the position resolution is reduced when the magnitude of the position is large. Resolution equal to the full capabilities of the onboard encoder (~0.09degree) is maintained to positions of +-2048.0 revolutions. At the maximum possible position, this resolution is reduced to ~1.44degrees. Note, that this is only for the "commanded position". Velocity control and PID feedback on the position works in an integral space and performs identically throughout the available control envelope.
The smallest usable mechanical velocity which can be commanded is
0.0001 revolutions per second before any unwrapped_position_scale
has been applied. This corresponds to 0.036 degrees per second.
Reducers will decrease the minimum usable velocity.
The maximum mechanical velocity which can be commanded is 28000 rpm, or ~467 revolutions per second before any reducers. Note, most motors will be incapable of this speed either mechanically or electrically.
The maximum electrical frequency is 4kHz.
The connections between moteus and the motor under control must be high quality. Poor quality solder joints can cause intermittent changes in resistance, sparking, and high voltage transients. High quality solder joints require:
- Sufficient flux to clean oxides off of the wire and the via
- Sufficient temperature so that the entire wire and via is hot enough for the solder to wet all surfaces
For the former, it is often necessary to add copious amounts of additional flux in addition to the rosin core inside many solders. For the latter, a high power soldering iron, with a fat tip, and what seems like a long time may be necessary. The temperature is definitely insufficient if solder touched to any part of the via or wire does not melt and wick instantly. Usually a small amount of solder is placed between the tip and wire to act as a heat transfer agent. Then the iron rests on the via and wire for between 5-30s until it looks like the initial solder has wicked fully into the via. Then additional solder can be added until it forms a clean smooth fillet around the entire via wicking up to the wire.
When complete, the back side of the hole can be examined, and if successful, solder will have wicked partially down out of the via onto the other side forming a clean, smooth fillet there as well.
A demonstration of this can be found in the following video: https://www.youtube.com/watch?v=mZ9w_TaWmjQ
When constructing power cables using XT30 connectors, it is critical that solder joints be sound, otherwise intermittent connectivity can result. This can cause sparking and high voltage transients. The soldering principles are the same as in the phase wire soldering section above.
A demonstration of XT30 soldering can be found in the following video: https://www.youtube.com/watch?v=f6WtDFWuxuQ
For moteus to operate without damage, the XT30 connectors used to transmit power must make a solid connection that is non-intermittent. As with poor soldering, an intermittent connection can cause inductive spikes, which will destroy components on the controller.
When connectors are functional, moderate insertion force should be required and the connectors should not "wiggle" much after insertion.
The XT30 is not rated for any significant amount of mechanical force when mated. For any application where cables may flex, strain relief should be used such that no force is applied to the connector. The connector may be damaged if a system goes "out of control" even in one instance, although milder mechanical stress may cause accelerated fatigue and failure.
If sparks are observed, that is definitely a problem and the system should be powered off until the connectors can be replaced and mitigations made for what led to that event.
Genuine AMASS connectors are rated for 1000 insertions assuming no other mechanical damage, however off-brand connectors may have worse tolerances and may not make a reliable connection for even one insertion.
moteus can be commanded to sharply decelerate loads, either directly in response to commands, or due to external disturbances. When braking a load, moteus by default applies the generated power to the input DC bus.
If there is nowhere for this power to go, this can cause problems. The voltage can increase without bound, which in mild cases will cause the CAN transceiver on all devices connected to the bus to fail, and in severe cases can explode the main FETs or other components on the board.
Here's what you should know about the facilities moteus has to deal with this, and what you can do to make your design safer.
The feature within moteus itself to deal with this is "flux braking". The flux braking implementation will dissipate extra power in the windings of the motor when the bus voltage gets above a certain threshold. This is controlled by the servo.flux_brake_min_voltage
and servo.flux_brake_resistance_ohm
parameters documented above.
The following design considerations can be used to minimize the risk of damage to hardware in the event of overvoltage. These are not a substitute for validation in progressively more demanding situations, but they can help you start off in a good place.
-
Configure Flux Braking: To have optimal effect, the flux braking minimum voltage should be approximately only 1.5V above the maximum voltage you expect your supply to provide. Additionally, the resistance may need to be lowered. When adjusting the resistance, it is wise to test for stability by gradually increasing the voltage with the drivers engaged using a programmable supply and monitoring for instability in the voltage bus. This can be identified either with an oscilloscope or audibly. The default values are set to provide a baseline of protection without compromising the maximum voltage rating of the controller, but more aggressive parameters can be useful when your system voltage is lower and you are able to validate stability.
-
Power from a battery, not a PSU: When not charged, batteries are capable of sinking current to minimize over-voltage transients. However, if the battery is fully charged, most battery management systems drastically reduce the allowable charging current. Thus, a battery is only useful as a mitigation if it is never charged above say 75 or 80% state of charge.
-
Decrease overall system voltage: If you run the moteus controller with say a 10S battery, the peak input voltage can be as high as 42V. That does not leave very much margin for regenerative loads. For applications that experience sharp regenerative loads and do not have a battery capable of charging always attached, it is recommended not to exceed 8S (33.6V peak).
-
Lower the over-voltage fault: The configuration parameter
servo.max_voltage
can be lowered for all devices on the bus. If set above the highest expected transient, this can reduce the likelihood of severe transients causing damage. -
Use a supply which can sink as well as source: Powering from an inexpensive lab supply is the most dangerous, as they typically have no ability to sink current, only source it. A "two quadrant" supply is the necessary device.