MD80 FDCAN communication#
The easiest way to communicate with an MD80 controller is to use a CANdle device connected to a PC. Even though we are aware some customers want to integrate the MD80 controllers in their product with minimal setup to reduce the costs and the system’s complexity. This manual will guide you through the process of communicating with MD80 actuators from your custom FDCAN-capable master controller.
Hardware requirements#
The main requirement for the host system is to be equipped with an FDCAN peripheral (either a built-in one or an external one) and an FDCAN transceiver capable of speeds up to 8Mbps. Lower maximum speed transceivers can be used as well, however for the cost of limited update rates. Currently, the differential side of the transceiver (the CANH and CANL lines) is supplied with 5V. Depending on your custom setup you should be able to integrate a 120 ohm terminating resistor on both ends of your CAN bus (MD80 controllers from version 2.0 can be upgraded to software controlled termination. Please contact us for more information).
Communication Structure#
The communication stack is based on a register access using two frames - register read and register write. The list of available registers can be found at the end of this chapter. All fields are little-endian - least significant byte first, and all float fields are 4 bytes long encoded in IEEE-754 standard.
Default response#
The default response is sent by the drive in case a register write operation was successfull.
BYTE 0 | BYTE 1-2 | BYTE 3 | BYTE 4-7 | BYTE 8-11 | BYTE 12-15 | BYTE 16-19 | BYTE 20-23 | |
NAME | FRAME ID | QUICK STATUS | MOTOR TEMPERATURE | MAIN ENCODER POSITION | MAIN ENCODER VELOCITY | MOTOR TORQUE | OUTPUT ENCODER POSITION | OUTPUT ENCODER VELOCITY |
TYPE | uint8_t | uint16_t | uint8_t [*C] | float [rad] | float [rad/s] | float [Nm] | float [rad] | float [rad/s] |
VALUE | 0x0A | 0x0000 - 0xFFFF | 0 - 255 | - | - | - | - | - |
In case the operation initiated by a frame was unsuccessful the MD80 will not respond.
Write register frame#
Write register frame is used to modify values of the user-modifiable registers. Only registers with write access can be modified.
FRAME NAME | ID | LENGTH | BYTE 0 [ID] | BYTE 1 | BYTE 2-3 | BYTE 4-X | BYTE X+1-X+2 | BYTE X+4-X+Y |
WRITE_REGISTER | 0x40 | X (64 max) | 0x40 | 0x00 | reg ID | value | reg ID | value |
Params:
regID (uint16_t) - first register ID (please see the end of this section)
value (uint8_t/uint16_t/uint32_t/float/char[]) - first register value to be written
regID (uint16_t) - second register ID (please see the end of this section)
value (uint8_t/uint16_t/uint32_t/float/char[]) - second register value to be written
… (up to 64 bytes total)
When all registers write operations succeed the drive will respond with default response.
Read Register Frame#
Read register command is used to retrieve certain register values. The actuator will respond with a frame consisting of the addresses and values of the registers issued in the master request. The master request should have the following form:
FRAME NAME | ID | LENGTH | BYTE 0 [ID] | BYTE 1 | BYTE 2-3 | BYTE 4-X | BYTE X+1-X+2 | BYTE X+4-X+Y |
READ_REGISTER | 0x41 | X (64 max) | 0x41 | 0x00 | reg ID | 0x00 | reg ID | 0x00 |
When all read operations succeed the 0x00 fields will be filled with appropriate register data when transmitted back to master by the MD80 controller. Maximum payload should not exceed 64 bytes.
Available registers#
reg name | address | read/write | size | limits | description |
---|---|---|---|---|---|
canId | 0x001 | RW | uint32_t | [10-2000] | FDCAN bus id number |
canBaudrate | 0x002 | RW | uint32_t | [1e6;2e6;5e6;8e6] | FDCAN bus baudrate |
canWatchdog | 0x003 | RW | uint16_t | [0-2500] | FDCAN bus watchdog period in ms |
canTermination | 0x004 | RW | uint8_t | [0-1] | CAN termination (available upon request) |
motorName | 0x010 | RW | char[24] | - | motor name |
motorPolePairs | 0x011 | RW | uint32_t | [2;225] | motor pole pair count |
motorKt | 0x012 | RW | float | >0 | motor torque constant |
motorIMax | 0x016 | RW | float | [1 - peak controller current] | maximum phase current |
motorGearRatio | 0x017 | RW | float | - | actuator gear ratio (ex 2:1 should be 0.5) <1 - reductors >1 - multiplicators |
motorTorgueBandwidth | 0x018 | RW | uint16_t | [50-2500] | torque bandwidth in Hz |
motorResistance | 0x01B | RO | float | [5mOhm-20Ohm] | motor resistance in d axis |
motorInductance | 0x01C | RO | float | [5nH-100mH] | motor inductance in d axis |
motorKV | 0x01D | RW | uint16_t | - | motor KV rating [RPM/V] |
motorCalibrationMode | 0x01E | RW | uint8_t | [0;1] | FULL = 0, NOPPDET = 1 |
outputEncoder | 0x020 | RW | uint8_t | [0;1;2;3] | NONE = 0, AS5047_CENTER = 1, AS5047_OFFAXIS = 2, MB053SFA17BENT00 = 3, CM_OFFAXIS = 4, M24B_CENTER = 5, M24B_OFFAXIS = 6 |
outputEncoderDefaultBaud | 0x022 | RW | uint32_t | - | output encoder default baudrate |
outputEncoderVelocity | 0x023 | RO | float | - | output encoder velocity in rad/s (calculated in a 5kHz loop) |
outputEncoderPosition | 0x024 | RO | float | - | output encoder position in rad (read in 5kHz loop) |
outputEncoderMode | 0x025 | RW | uint8_t | [0;1;2;3;4] | NONE = 0, STARTUP = 1, MOTION = 2, REPORT = 3, MAIN = 4 |
outputEncoderCalibrationMode | 0x026 | RW | uint8_t | [0;1] | FULL = 0, DIRONLY = 1 |
motorPosPidKp | 0x030 | RW | float | - | position PID proportional gain |
motorPosPidKi | 0x031 | RW | float | - | position PID integral gain |
motorPosPidKd | 0x032 | RW | float | - | position PID derivative gain |
motorPosPidWindup | 0x034 | RW | float | - | position PID integral windup limit |
motorVelPidKp | 0x040 | RW | float | - | velocity PID proportional gain |
motorVelPidKi | 0x041 | RW | float | - | velocity PID integral gain |
motorVelPidKd | 0x042 | RW | float | - | velocity PID derivative gain |
motorVelPidWindup | 0x044 | RW | float | - | velocity PID integral windup limit |
motorImpPidKp | 0x050 | RW | float | - | impedance PD proportional gain |
motorImpPidKd | 0x051 | RW | float | - | impedance PD derivative gain |
mainEncoderVelocity | 0x062 | RO | float | - | main encoder velocity in rad/s (calculated in a 40kHz loop) |
mainEncoderPosition | 0x063 | RO | float | - | main encoder position in rad (read in 40kHz loop) |
motorTorque | 0x064 | RO | float | - | motor output shaft torque in Nm (read in 40kHz loop) |
homingMode | 0x070 | RW | uint8_t | [0;1] | 0 - OFF, 1 - SENSORLESS |
homingMaxTravel | 0x071 | RW | float | - | max allowable movmement in rad during homing |
homingVelocity | 0x072 | RW | float | - | velocity in rad/s during homing movement |
homingTorque | 0x073 | RW | float | - | maximum and threshold torque for sensorless homing in Nm |
runSaveCmd | 0x080 | WO | uint8_t | other than 0 to run | save non-volatle memory |
runTestMainEncoderCmd | 0x081 | WO | uint8_t | other than 0 to run | runs main encoder test routine |
runTestOutputEncoderCmd | 0x082 | WO | uint8_t | other than 0 to run | runs output encoder test routine |
runCalibrateCmd | 0x083 | WO | uint8_t | other than 0 to run | runs main calibration routine |
runCalibrateOutpuEncoderCmd | 0x084 | WO | uint8_t | other than 0 to run | runs output encoder calibration routine |
runCalibratePiGains | 0x085 | WO | uint8_t | other than 0 to run | runs current PI loop calibration routine |
runHoming | 0x086 | WO | uint8_t | other than 0 to run | runs homing |
runRestoreFactoryConfig | 0x087 | WO | uint8_t | other than 0 to run | reverts config to factory state |
runReset | 0x088 | WO | uint8_t | other than 0 to run | resets the controller |
runClearWarnings | 0x089 | WO | uint8_t | other than 0 to run | clears all warnings |
runClearErrors | 0x08A | WO | uint8_t | other than 0 to run | clears non-critical errors |
runBlink | 0x08B | WO | uint8_t | other than 0 to run | blinks onboard leds |
runZero | 0x08C | WO | uint8_t | other than 0 to run | sets new zero position |
runCanReinit | 0x08D | WO | uint8_t | other than 0 to run | reinits can peripheral |
calOutputEncoderStdDev | 0x100 | RO | float | - | output encoder test result (standard deviation) |
calOutputEncoderMinE | 0x101 | RO | float | - | output encoder test result (min error) |
calOutputEncoderMaxE | 0x102 | RO | float | - | output encoder test result (max error) |
calMainEncoderStdDev | 0x103 | RO | float | - | main encoder test result (standard deviation) |
calMainEncoderMinE | 0x104 | RO | float | - | main encoder test result (min error) |
calMainEncoderMaxE | 0x105 | RO | float | - | main encoder test result (max error) |
positionLimitMax | 0x110 | RW | float | - | minimum valid position |
positionLimitMin | 0x111 | RW | float | - | maximum valid position |
maxTorque | 0x112 | RW | float | - | maximum torque |
maxVelocity | 0x113 | RW | float | - | maximum velocity |
maxAcceleration | 0x114 | RW | float | - | maximum acceleration |
maxDeceleration | 0x115 | RW | float | - | maximum deceleration |
profileVelocity | 0x120 | RW | float | - | profile velocity |
profileAcceleration | 0x121 | RW | float | - | profile acceleration |
profileDeceleration | 0x122 | RW | float | - | profile deceleration |
quickStopDeceleration | 0x123 | RW | float | - | quick stop deceleration in case of a non-critical error |
positionWindow | 0x124 | RW | float | - | position window within position is considered to be reached |
velocityWindow | 0x125 | RW | float | - | velocity window within velocity is considered to be reached |
motionModeCommand | 0x140 | WO | uint8_t | - | commans a motion mode change: IDLE = 0x00, POSITION_PID = 0x01, VELOCITY_PID = 0x02, RAW_TORQUE = 0x03, IMPEDANCE = 0x04, POSITION_PROFILE = 0x07, VELOCITY_PROFILE = 0x08 |
motionModeStatus | 0x141 | RO | uint8_t | - | shows the currently set motion mode |
state | 0x142 | RW | uint16_t | - | returns the internal state machine state of the controller |
targetPosition | 0x150 | RW | float | - | sets target position in rad |
targetVelocity | 0x151 | RW | float | - | sets target velocity in rad/s |
targetTorque | 0x152 | RW | float | - | sets target torque in Nm |
reverseDirection | 0x600 | RW | uint8_t | - | used to change the direction of the main encoder when using other encoders than the onboard one. Always recalibrate after changing this setting |
shuntResistance | 0x700 | RO | float | [0.001 - 0.01] | Current sense resistor value. Setting this register to a value that is not coherent with the hardware may damage the controller. In this cases warranty is not respected. |
buildDate | 0x800 | RO | uint32_t | - | software build date |
commitHash | 0x801 | RO | char[8] | - | commit hash |
firmwareVersion | 0x802 | RO | uint32_t | - | - |
hardwareVersion | 0x803 | RO | uint8_t | - | - |
bridgeType | 0x804 | RO | uint8_t | - | type of the mosfet driver |
quickStatus | 0x805 | RO | uint16_t | - | quick status vector |
mosfetTemperature | 0x806 | RO | float | - | power stage temperature |
motorTemperature | 0x807 | RO | float | - | motor temperature (if thermistor is mounted) |
motorShutdownTemp | 0x808 | RW | uint8_t | - | temperature at which the md80 will enter IDLE mode |
mainEncoderErrors | 0x809 | RO | uint32_t | - | main encoder errors |
outputEncoderErrors | 0x80A | RO | uint32_t | - | output encoder errors |
calibrationErrors | 0x80B | RO | uint32_t | - | calibration errors |
bridgeErrors | 0x80C | RO | uint32_t | - | bridge errors |
hardwareErrors | 0x80D | RO | uint32_t | - | hardware errors |
communicationErrors | 0x80E | RO | uint32_t | - | communication errors |
homingErrors | 0x80F | RO | uint32_t | - | homing errors |
motionErrors | 0x810 | RO | uint32_t | - | motion errors |