Over CAN¶
CAN is the interface for running a machine: compact frames, a fixed cost per message, up to 14 drivers on one bus, and a host that can be a PC, a microcontroller or a robot control box. The driver answers a motion command with its position, speed and current in the same frame exchange, so a control loop on the host needs one frame out and one frame back per motor and cycle.
The frame¶
CAN 2.0 data frames with 11-bit identifiers at 1 Mbit/s. The identifier carries the node, the command and the error state:
- Node ID, bits 10 to 7: which driver, 0 to 15. A driver acts only on frames with its own node ID and sends
with it. Set it with
#CANIDor Send_CAN_ID and save; every driver ships as node 0. Use 0 to 13: the bootloader reserves 14 and 15, and a driver on one of those cannot be updated over CAN. - Command ID, bits 6 to 1: which message, 0 to 63. The CAN reference lists all of them.
- Error bit, bit 0: in a frame from the driver, 1 while any error is active. In a frame from the host it is ignored.
So a host sends Send_data_pack_1 (command 2) to node 3 with the identifier (3 << 7) | (2 << 1) = 0x184, and the
driver answers with command 3 under (3 << 7) | (3 << 1) | error. A lower node ID wins the bus arbitration.
Multi-byte values are big-endian: the most significant byte is in data[0] and goes first. Floats are IEEE 754 single precision. Flags inside a byte are numbered from the most significant bit.
Three kinds of message¶
- Send_…: the host sends data. Some of these are answered (a motion command with Respond_data_pack_1, the gripper command with Respond_Gripper_data_pack); most are not.
- Send_Respond_…: the host asks for data with a remote frame (the RTR bit set, no data) carrying the command ID; the driver answers with a data frame with the same command ID.
- Respond_…: frames only the driver sends: the answers above, and the heartbeat.
A control loop¶
Send Send_data_pack_1 at a fixed rate, 100 Hz to 1 kHz, with the setpoint for this cycle; read Respond_data_pack_1 for the position, speed and current of the last cycle. Every valid motion frame, and every status request the driver answers, resets the watchdog; the setting frames (gains, limits, Idle, Clear, Save) do not. So with Send_Watchdog set to a few cycle times the motor stops when the host stops. A watchdog kept with Send_Save_config runs from power-up: a host that does not start its loop within the watchdog time finds the driver in watchdog error, and clears it with Send_Clear_Error. The heartbeat is the other way round: Send_Heartbeat_Setup makes the driver send a frame on its own every N ms when it has nothing else to send, so the host can see it is alive.
sequenceDiagram
participant H as Host
participant D as Driver
H->>D: Send_Clear_Error
H->>D: Send_Watchdog: a few cycle times
H->>D: Send_Heartbeat_Setup: every N ms
loop every cycle, 100 Hz to 1 kHz
H->>D: Send_data_pack_1: the setpoint, with the feedforwards
D-->>H: Respond_data_pack_1: position, speed, current, the error bit
end
D-->>H: heartbeat, whenever nothing else was sent for N ms
Note over D: no motion frame or status request within the watchdog time: watchdog error, the motor stops
From a PC¶
The CANvas adapter shows up as a serial port and
speaks slcan; python-can opens it with bustype='slcan'. The Python library wraps the whole protocol, see
With Python. Any CAN adapter that python-can supports works the same way.
Several drivers¶
Give each driver its own node ID before you put them on one bus (a bus with two node 0s cannot tell them apart):
connect one driver at a time over UART, #CANID 3, #Save. Terminate the first and the last node, and wire the
daisy chain as in Power and the CAN daisy chain.
Comments
Found a mistake on this page? Edit it on GitHub · Report it · Get help · This page as Markdown · llms.txt · The whole manual as PDF