Important

The mw_dual_motor_torque_ctrl repository is not maintained anymore!

The CAN firmware has been integrated into the udriver_firmware repository and will be maintained there from now on. See the documentation of udriver_firmware for up-to-date installation and usage instructions.

CAN Communication Protocol

Each frame has an 11-bit identifier, which is used to distinguish different types of messages. In the following the protocol (which identifier is used for which data and how the data is stored inside the frame) that is used by the firmware is described.

Note that in the CAN protocol, the identifier is also used to define priorities. If two nodes try to send at the same time, the message with the lower ID comes first.

The 8 byte of data of a frame are split into a “lower” and a “higher” part of 4 bytes each. Following the names used in the CAN module they are referred to as MDL and MDH here.

Bit timing

The firmware is configured for communication at 1 Mbit/s using a sampling point of 86.7%.

Messages sent from the board

ID

Meaning

Size [Bytes]

Structure of the data

0x010

Status

1

see Status Message

0x020

Current \(I_q\) (both motors)

8

  • MDL: \(I_q\) of motor 1

  • MDH: \(I_q\) of motor 2

0x030

Encoder Position (both motors)

8

  • MDL: Position of motor 1

  • MDH: Position of motor 2

0x040

Velocity (both motors)

8

  • MDL: Velocity of motor 1

  • MDH: Velocity of motor 2

0x050

Additional ADC inputs (e.g. used for potentiometers or other sensors)

8

  • MDL: ADC reading of input A6

  • MDH: ADC reading of input B6

0x060

Encoder Index Position

This is not sent with a fixed rate but whenever the encoder index is detected.

5

  • MDL (4 Bytes): Motor position at the index tick

  • MDH (1 Byte): ID of the motor

Important

The motor data (current, position, velocity) is send as Q24 values. Divide by 224 to get the float representation.

Note

The IDs 0x100 and 0x101 are by default used by the OptoForce sensor. To keep things simple, we should not use these IDs for other data, so we don’t have to reconfigure the sensors.

Status Message

The status message contains one byte of data which is structured as follows:

Bit 5-7

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

Error Code

Flag motor 2 ready

Flag motor 2 enabled

Flag motor 1 ready

Flag motor 1 enabled

Flag system enabled

A motor is “ready” when the alignment process is finished.

Error Codes

Error Code

Meaning

0

No Error

1

Encoder Error

2

CAN Receive Timeout

3

Critical Motor Temperature (currently unused)

4

Some error in the Position Converter module

5

Position Rollover (position exceeded max value)

This error is by default disabled. To enable it, send a ENABLE_POS_ROLLOVER_ERROR=1 command.

7

Other Error (to be used if we run out of free error codes)

Note that the error code for critical motor temperature won’t be used for now, as we don’t have any temperature sensing. As this might be added in the future, I already reserve an error code for this, though. The “Other Error” code is also not used so far. It may be useful if we run out of error codes at some point.

Messages sent to the board

ID

Name

Meaning [Unit]

Structure of the data

0x000

CAN_ID_COMMANDS

Command

0x005

CAN_ID_IqRef

Current \(I_q\) Reference \([A]\)

  • MDL: IqRef for motor 1

  • MDH: IqRef for motor 2

0x006

CAN_ID_KP

Gains for P controller \([\frac{A}{mrev}]\)

  • MDL: P gain for motor 1

  • MDH: P gain for motor 2

0x007

CAN_ID_KD

Gains for D controller \([\frac{A}{kmrev / min}]\)

  • MDL: D gain for motor 1

  • MDH: D gain for motor 2

0x008

CAN_ID_POS_REF

Reference for P controller \([mrev]\)

  • MDL: Reference position for motor 1

  • MDH: Reference position for motor 2

0x009

CAN_ID_VEL_REF

Reference for D controller \([\frac{kmrev}{min}]\)

  • MDL: Reference velocity for motor 1

  • MDH: Reference velocity for motor 2

\(mrev\) = motor revolutions. E.g. 0.5 is half a revolution, 1.0 a full revolution, 2.0 two revolutions, etc.

Important

Please note that current reference values have to be send as Q24 values. To convert float to Q24 multiply by 224 and round to an integer.

Command Codes

A command message (ID = 0) consists of two parts. The high bytes (MDH) contain a code that is associated with a specific parameter (see table below) while the lower bytes (MDL) contain the value that is to be assigned to the parameter.

Code

Name

Meaning [Unit]

Value

Default

0x01

ENABLE_SYS

Enable the system.

0/1

1

0x02

ENABLE_MTR1

Enable Motor 1

0/1

0

0x03

ENABLE_MTR2

Enable Motor 2

0/1

0

0x04

ENABLE_VSPRING1

Enable virtual spring mode for motor 1

0/1

0

0x05

ENABLE_VSPRING2

Enable virtual spring mode for motor 2

0/1

0

0x0C

SEND_CURRENT

Send motor currents via CAN

0/1

0

0x0D

SEND_POSITION

Send encoder positions via CAN

0/1

0

0x0E

SEND_VELOCITY

Send motor velocities via CAN

0/1

0

0x0F

SEND_ADC6

Send ADC inputs A6/B6 via CAN

0/1

0

0x14

SEND_ALL

Disable/Enable all of the configurable CAN messages

0/1

0

0x1E

SET_CAN_RECV_TIMEOUT

Set CAN Receive Timeout in milliseconds. Set to zero to disable timeout.

uint32

0

0x1F

ENABLE_POS_ROLLOVER_ERROR

Enable the position rollover error

0/1

0

0x28

CAN_CMD_P_CONTROLLER_LIMIT_IQ_MTR1

Set the current limit for the P controller of motor 1 [A]

IQ24

0

0x29

CAN_CMD_P_CONTROLLER_LIMIT_IQ_MTR2

Set the current limit for the P controller of motor 2 [A]

IQ24

0

0x2A

CAN_CMD_D_CONTROLLER_LIMIT_IQ_MTR1

Set the current limit for the D controller of motor 1 [A]

IQ24

0

0x2B

CAN_CMD_D_CONTROLLER_LIMIT_IQ_MTR2

Set the current limit for the D controller of motor 2 [A]

IQ24

0

Example: To enable motor 1, set MDH = 2 and MDL = 1.

Nomenclature: When refering to sending commands in this documentation, the following nomenclature is used: NAME=value. Example: ENABLE_SYS=1 to enable the system.

CAN Receive Timeout

The embedded software on the board provides a security feature that disables the motors in case the CAN connection is interrupted or the controller on the PC exits without properly shutting down the system. This is done by simply checking the time since the last current \(I_q\) reference was received and raising an error if it exceeds a specified timeout.

Note that by default, this feature is disabled! If you want to use it, you have to enable it by specifying a timeout duration greater than zero (see Command Codes above). There are a few consequences that have to be kept in mind:

  • Before enabling the motors, set the current references to zero, otherwise the timeout may be trigger immediately when enabled. Note that this is good practice anyway as it clears potentially dangerous previous reference values.

  • Current references have to be sent in a loop, even if the values do not change.

The timeout is only checked when motors are enabled and current references are not zero. This means that, as long as the current reference is zero, it is okay to enable the timeout during intialization even if current commands are not send immediately.

When the timeout is triggered, an error is set and the system is disabled. You can simply reenable it by sending (in this order) enable system command, a current=0 command and enable motor commands.