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 30kHz).
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 or equal to 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.
moteus includes an onboard on-axis magnetic encoder and supports a number of options for using external encoders. To understand how to use them, we first need to know the two things that moteus needs encoders for:
- Commutation: moteus needs to know the electrical relationship between the stator and the rotor in order to apply torque.
- Output: moteus needs to know the position and velocity of the output shaft in order to follow commanded trajectories.
By default, the onboard magnetic encoder is assumed to sense the rotor. It is also used as the source for position and velocity of the output constrained by a configurable reduction ratio.
Configuration is performed in 3 stages, first is the auxiliary port configuration, second is encoder source configuration, and finally is the output configuration.
There are two auxiliary ports on moteus, each with pins that can be used for various functions.
ELECTRICAL NOTES:
- The 3.3V supply pins can power external peripherals:
- r4.5: 50mA
- r4.8/11: 100mA
- Some pins are 5V tolerant. Those not marked as such in the pin option table are 3.3V only.
The following capabilities can be used. Some are supported on any pins, others only on select pins.
Pins: any
The software quadrature feature uses GPIO pins to read incremental quadrature encoders. It is capable of counting at 200,000 counts per second without error, but incurs processor overhead that increases with count rate. Higher overhead means the latency to respond to CAN messages increases.
Pins: any
3 hall sensor inputs are required. For many hall sensors, the pullup must be configured for the auxiliary port pin in question.
When using hall effect sensors as the commutation source, calibration
with moteus_tool requires the --cal-hall
option be passed.
Pins: any
This is a single pin that is high when the encoder is in a known location. It can be fed from the "I" signal of an ABI output, or a dedicated homing sensor.
Pins: any
Any pin may be designated as a GPIO input. Its value may be read over the diagnostic or register protocols.
Pins: select
Between 1 and 3 I2C devices may be periodically polled at rates up to 200Hz. The associated pins on moteus r4.5/8/11 have permanently configured 2kohm pullup resistors.
Pins: select
A variety of SPI based peripherals are supported. This mode is also used for the onboard encoder, which when enabled, claims the CLK, MOSI, and MISO pins on auxiliary port 1.
Pins: select
Hardware quadrature pins use microcontroller peripherals to process quadrature input at any speed with no processor overhead.
Pins: select
Analog sine/cosine inputs are supported with a configurable common mode voltage.
Pins: select
Arbitary analog inputs can be read either over the diagnostic or register protocol.
Pins: select
Currently supported are the RLS AksIM-2 encoder, and a transparent UART tunnel.
The following table shows which pins can be used for the unique capabilities:
moteus r4.5/8/11 | Con | Aux | SPI | ADC/Sin/Cos | I2C | HW Quad | UART | 5VT |
---|---|---|---|---|---|---|---|---|
3.3V (3) | 1 | |||||||
C | 2 | 0 | X | X | ||||
GND (G) | 3 | |||||||
K | 4 | 1 | CLK | X | ||||
I | 5 | 2 | MISO | X | ||||
O | 6 | 3 | MOSI | X |
moteus n1 | Con | AUX | SPI | ADC/Sin/Cos | I2C | HW Quad | UART | 5VT |
---|---|---|---|---|---|---|---|---|
5V (5) | 1 | |||||||
3.3V (3) | 2 | |||||||
A | 3 | 0 | CLK | X | ||||
B | 4 | 1 | MISO | 3.1 | RX | |||
C | 5 | 2 | MOSI | X | 3.2 | |||
D | 6 | 3 | SCL | 2.1 | RX | X | ||
E | 7 | 4 | SDA | 2.2 | TX | X | ||
GND (G) | 8 |
moteus r4.5/8/11 | Con | Aux | SPI | ADC/Sin/Cos | I2C | HW Quad | UART | 5VT |
---|---|---|---|---|---|---|---|---|
3.3V (3) | 1 | |||||||
2 | 0 | SCL | RX | X | ||||
3 | 1 | SDA | TX | X | ||||
GND (G) | 4 | |||||||
DBG 1 | 2 | X | ||||||
DBG 2 | 3 | X |
moteus n1 | Con | AUX | SPI | ADC/Sin/Cos | I2C | HW Quad | UART | 5VT |
---|---|---|---|---|---|---|---|---|
5V (5) | 1 | |||||||
3.3V (3) | 2 | |||||||
A | 3 | 0 | CLK | X | X | |||
B | 4 | 1 | MISO | X | SDA | RX | X | |
C | 5 | 2 | MOSI | X | SCL | 4.1 | TX | X |
D | 6 | 3 | 4.2 | RX | X | |||
GND (G) | 7 |
NOTE: For moteus r4.5/8/11, DBG 1/2 are not present on the ABS connector, but are exposed pads on the circuit board.
Auxiliary port configuration is achieved in two steps. First, the
aux[12].pins.X.mode
value is set to the proper capability for each
pin. aux[12].pins.X.pull
can be used to configure an optional
pullup or pulldown for some modes. Second, the corresponding
capabilities must be configured in one of the capability specific
sections of aux[12]
. For instance, for each auxiliary port, the SPI
configuration in aux[12].spi
has a mode
to select what the slave
device is and a rate_hz
to define the frequency of the SPI
peripheral.
For I2C ports, up to 3 different slave devices may be configured, in
each of aux[12].i2c.devices.[012]
.
The diagnostic values in aux[12]
can be used to monitor for errors
from mis-configuration or mis-operation.
Once the auxiliary ports have been configured, next encoder sources
should be configured in motor_position.sources
. Up to 3 sources may
be configured, with the available types roughly corresponding to the
categories available from the auxiliary ports. Typically, source 0 is
used for the sensor that is used for commutation.
For each source motor_position.sources.[012].aux_number
should be
either "1" or "2", to select which auxiliary port the sensor should be
read from. motor_position.sources.[012].type
selects the type of
sensor. For I2C based sources,
motor_position.sources.[012].i2c_device
selects which I2C device
on that auxiliary port is used.
For sources that are incremental only, like quadrature, a source level
index may be configured in
motor_position.sources.[012].incremental_index
. This should be used
if the incremental source is needed to provide position for
commutation.
Each source can be marked as measuring the rotor or the output in
motor_position.sources.[012].reference
.
Each source has configuration that determines how to map the raw value
provided by the device into a rotary angle. cpr
is the number of
counts per revolution, offset
provides an integral count offset, and
sign
can be used to invert the reading. The final reading is
(raw + offset) * sign / cpr
.
Finally, each source has a configurable low pass filter, with cutoff
frequency set by motor_position.sources.[012].pll_filter_hz
. It may
be set to 0 to disable the filter. If disabled no velocity will be
interpolated on sensors that do not provide it natively.
The third major stage controls how the sources are used by the motor controller. Some source selections may be left at -1, which disables that feature.
motor_position.commutation_source
selects which source is used to
provide rotor position for commutation purposes. It is typically left
at source 0 and is required.
motor_position.output.source
selects which source is used to provide
output position and velocity and is required.
motor_position.output.offset
and motor_position.output.sign
are
used to transform the output position to achieve a given zero point
and rotational direction.
motor_position.output.reference_source
optionally configures a
source that is used solely to disambiguate the output position at
startup. It could be a low-rate I2C based sensor for instance.
Finally, motor_position.rotor_to_output_ratio
defines the number of
turns of the output for one turn of the rotor. This is used to map
the readings from sensors that are defined relative to one into the
other.
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 - write/read 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
- int8 => 1 LSB => (1/127) - 0.007874
- int16 => 1 LSB => (1/32767) - 0.000030519
- int32 => 1 LSB => (1/2147483647) - 4.657e-10
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
When sending a command, this register must be written before any other registers in the command frame.
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
The current motor temperature, measured in degrees celsius. This will
only be valid if a 47k NTC thermistor is connected to the TEMP pads
and servo.enable_motor_temperature
is set to 1.
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 had its output position set since power on. This could have been from a source configured for multi-turn, as an index, or the "set output nearest" or "set output exact" commands.
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
. - 40 - under voltage - the voltage was too low
- 41 - config changed - a configuration value was changed during operation that requires a stop
- 42 - theta invalid - no valid commutation encoder is available
- 43 - position invalid - no valid output encoder is available
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 Voltage Foc mode, this controls the rate of change of electrical phase. Integral types use the velocity mapping.
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/write
If specified and not-NaN, then the control mode will temporarily be in
the "fixed voltage" mode, regardless of the current setting of
servo.fixed_voltage_mode
.
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. This is also reported in 0x03a.
Mode: Read
This reports the current trajectory control position, in modes where that is valid. When velocity or acceleration limiting is enabled, the control position will follow the desired limits to achieve the command position.
Mode: Read
This reports the current velocity control value, in modes where that is valid. When velocity or acceleration limiting is enabled, the control velocity will follow the desired limits to achieve the control position and velocity.
Mode: Read
The torque commanded by the control loop. This is the same as 0x034.
Mode: Read
The current sensed position minus the control position.
Mode: Read
The current sensed velocity minus the control velocity.
Mode: Read
The current sensed torque minus the control torque.
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.
Mode: Read only
Reports the current filtered position of the encoder configured in slot 0.
Mode: Read only
Reports the current filtered velocity of the encoder configured in slot 0.
Mode: Read only
Reports the current filtered position of the encoder configured in slot 1.
Mode: Read only
Reports the current filtered velocity of the encoder configured in slot 1.
Mode: Read only
Reports the current filtered position of the encoder configured in slot 2.
Mode: Read only
Reports the current filtered velocity of the encoder configured in slot 2.
Mode: Read only
Returns a bitfield, where bit 0 indicates whether encoder 0 is active, bit 1 indicates whether encoder 1 is active, etc.
Mode: Read/write
The current output command for any GPIOs configured as an output on aux1 as a bitfield. Not all bits may be used, as bit 0 is always for pin 1, whether or not it is configured as a GPIO output.
Mode: Read/write
The current output command for any GPIOs configured as an output on aux2 as a bitfield. Not all bits may be used, as bit 0 is always for pin 1, whether or not it is configured as a GPIO output.
Mode: Read only
The current input value of any GPIOs configured as an input on aux1 as a bitfield. Not all bits may be used, as bit 0 is always for pin 1, whether or not it is configured as a GPIO input.
Mode: Read only
The current input value of any GPIOs configured as an input on aux2 as a bitfield. Not all bits may be used, as bit 0 is always for pin 1, whether or not it is configured as a GPIO input.
Mode: Read only
The current input value of any analog inputs configured on aux1. The registers are associated with pins 1-5, regardless of whether they are configured as an analog input. Each value is scaled as a PWM from 0 to 1.
Mode: Read only
The current input value of any analog inputs configured on aux2. The registers are associated with pins 1-5, regardless of whether they are configured as an analog input. Each value is scaled as a PWM from 0 to 1.
Mode: Read only
Increments once per millisecond. It wraps at the maximum value for the queried type to the minimum value for that type. For floating point types, it counts integers from 0 to 8388608.
Mode: Read/write
An integer which can trim the clock rate of the microprocessor on the moteus controller. Positive values speed it up and negative values slow it down. Each integer step roughly corresponds to a 0.25% change in speed.
WARNING: Changing the speed affects all processes driven by the microcontroller, including CAN communication. Thus setting this to a non-zero value may prevent future CAN communications.
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.
Mode: Write only
When sent, the servo will force the output position to be the exact specified value.
Mode: Write only
When sent with any value, the servo will require that any index position be re-located before control can begin. Regardless, the position will reset to an arbitrary value consistent with the current encoder settings.
Mode: Read only
The exact bitfield reported by the motor driver in fault conditions for fault register 1. Up to 16 bits may be set. This will only be non-zero if the current mode is fault (1) and the fault code is 33 (motor driver fault).
Mode: Read only.
The exact bitfield reported by the motor driver in fault conditions for fault register 2. Up to 16 bits may be set. This will only be non-zero if the current mode is fault (1) and the fault code is 33 (motor driver fault).
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> [<phase_rate>]
Where phase is in radians, magnitude is in volts, and the optional phase rate is in radians per second.
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.o
- fixed voltage override: while in affect, treat the control as iffixed_voltage_mode
were enabled with the given voltage
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.
Update the current position to the closest one which is consistent with a given output position.
d rezero <position>
Update the current position to exactly the given value.
d exact <position>
Reset the homing state to relative based, requiring any homing procedure to be re-run.
d req-reindex
Modify the configuration as required so that the current observed position will be equal to the given value. Note, the configuration is not written to persistent storage.
d cfg-set-output <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
.
All commands are supported on both aux1
and aux2
.
aux1 out <data>
'data' is a single decimal integer. Only bits associated with pins configured as digital outputs are used, the remainder are ignored.
aux1 ic-cmd <HEXBYTE>
An example of entering analog mode calibration.
aux1 ic-cmd B0
aux1 ic-wr <reg> <data>
Register is one byte in hex, data is 1 or more bytes in hex.
Example of switching to memory page 0.
aux1 ic-wr 40 00
aux1 ic-rd <reg> <length>
The register is one byte in hex, length is a decimal value indicating the number of bytes to read.
Example of reading the temperature data:
aux1 ic-rd 4e 2
aux1 ic-extra <fields>
"fields" is a decimal bitmask of items to read at 1000Hz and display in the diagnostic stream.
bit 0 - the diagnosis command result bit 1 - the contents of the AI_PHASES registers
Example of enabling the AI_PHASES registers only:
aux1 ic-extra 2
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.
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_position.rotor_to_output_ratio
.
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.
If true, then the motor temperature will be sensed via the TEMP pads on the board.
Torque begins to be limited when the motor temperature reaches this value.
If the motor 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"
Selects what functionality will be used on the given pin.
- 0 - NC - Not connected (or used for onboard SPI)
- 1 - SPI - Used for one of CLK, MISO, or MOSI
- 2 - SPI CS - Used for SPI CS
- 3 - UART
- 4 - Software quadrature
- 5 - Hardware quadrature
- 6 - Hall
- 7 - Index
- 8 - Sine
- 9 - Cosine
- 10 - Step (not implemented)
- 11 - Dir (not implemented)
- 12 - RC PWM (not implemented)
- 13 - I2C
- 14 - Digital input
- 15 - Digital output (not implemented)
- 16 - Analog input
Configures optional pullup or pulldown on each pin. Not all pullup options will be used with every mode. Additionally, the 2 aux2 pins on moteus 4.5/8/11 have hard-installed 2k ohm pullups regardless of these settings.
- 0 - no pullup or pulldown
- 1 - pull up
- 2 - pull down
- 3 - open drain (not implemented)
The frequency to operate the I2C bus at. Between 50000 and 400000.
What I2C mode to use.
What I2C device to expect.
- 0 - disabled
- 1 - AS5048
- 2 - AS5600
The I2C address to use.
How often in milliseconds to poll the device for more data. Must no less than 5.
The type of SPI device.
- 0 - The onboard AS5047P. Only valid for aux1. If selected, the CLK, MOSI, and MISO lines must be either NC or selected as SPI.
- 1 - Disabled.
- 2 - AS5047P
- 3 - iC-PZ
NOTE: iC-PZ devices require significant configuration and calibration before use. Diagnostic mode commands are provided for low level access.
The frequency to operate the SPI bus at. The default is 12000000, which is required for AS5047P devices. Other devices may support lower rates.
The type of UART device.
- 0 - Disabled
- 1 - RLS AksIM-2
- 2 - Tunnel
- 3 - Per-control cycle debug information (undocumented)
When the tunnel mode is selected, data may be sent or received using the CAN diagnostic protocol. For aux1, use diagnostic channel 2. For aux2, use diagnostic channel 3.
The baud rate to use for the UART.
For encoder modes, the interval at which to poll the encoder for new position information.
True/non-zero if quadrature input should be read from this port.
The number of counts per revolution of the quadrature input. If used as a source, then this CPR must match the one configured in the source.
True/non-zero if hall effect sensors should be read from this port.
A bitmask to XOR with the 3 hall phases.
True/non-zero if an index input be read from this port.
True/non-zero if a sine/cosine input should be read from this port.
The common mode voltage to use for the sine cosine. The sampling is done with 12 bits, so 2048 would be exactly 0.5 * 3.3V. However, it is best to calibrate this with actual readings as observed over the diagnostic protocol for optimal performance.
1 for an aux1 device, or 2 for an aux2 device.
One of:
- 0 - disabled
- 1 - SPI
- 2 - UART
- 3 - Quadrature
- 4 - Hall
- 5 - Index
- 6 - Sine/Cosine
- 7 - I2C
- 8 - Sensorless (not implemented)
Note: The "Index" source type is only allowed for an output referenced encoder, and can be used as an alternate way to enter the "output" homed state.
If type
was "7/I2C", this is a 0 based index specifying which I2C
device on that port should be used.
If the specified auxiliary port has an incremental encoder, like a quadrature encoder, this can be set to either 1 or 2 in order to use an "index" pin to reference the data to a given position. It will allow the source to provide theta readings for commutation.
The CPR of the given input. In some cases this is automatically set, but in most it will need to be manually entered.
An integer offset and inversion to apply. The resulting value is:
(raw + offset) * sign / cpr
.
- 0 - this source is relative to the rotor
- 1 - this source is relative to the output
Selects the cutoff frequency of a low-pass filter used on this source. It should typically be less than 10X the update rate of the input and if used as the commutation or output sensor, should be higher than the mechanical bandwidth of the plant. Within that range, it can be tuned for audible noise versus performance.
If set to 0, then no filter is applied. In that case, sensors which do not natively measure velocity will produce no velocity readings (most of them).
A 0-based index into the source list that selects the source to use for commutation. This means it should have an accurate measure of the relationship between the rotor and stator.
A 0-based index into the source list that selects the source to use for the output position. The position and velocity from this source will be used for control in "position" mode.
The offset is a floating point value measured in output revolutions. Combined with the sign of -1/1, they can be used to position the 0 point of the output and control its direction of rotation.
If non-negative, this is a 0-based index into the source list. The selected source is used at power on to disambiguate the output position for multi-turn scenarios or when a reducer is configured.
The number of times the output turns for each revolution of the rotor.
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_position.rotor_to_output_ratio
.
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
To build the moteus firmware, an x86-64 Ubuntu 20.04 or 22.04 system is required.
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
This may require the appropriate binutils to be installed, on Ubuntu this can be accomplished with:
sudo apt install binutils-arm-none-eabi
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
RS422, configured by AUX1 D/E to USART and enabling RS422 on AUX1.
- 1 - 5V
- 2 - A
- 3 - B
- 4 - Y
- 5 - Z
- 6 - GND
- 1 - 5V
- 2 - 3.3V
- 3 - A
- 4 - B
- 5 - C
- 6 - D
- 7 - E
- 8 - GND
- 1 - 5V
- 2 - 3.3V
- 3 - A
- 4 - B
- 5 - C
- 6 - D
- 7 - 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
Adapters 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
rotor_to_output_ratio
has been applied. Reducers there will
further limit the range of the commandable revolutions. For instance,
a 1/10 reducer configured as rotor_to_output_ratio=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 rotor_to_output_ratio
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.