Hello, I’m using the ODrive S1 and M8325s Motor Kit, powered by a 24V 4.5A power supply. The system is configured via the GUI for position control (filtered). I’m controlling the motor using the CAN bus protocol with a Python script (code provided below). The issue I’m encountering is that the motor always starts with a very high velocity and then enters an error state, regardless of the velocity or torque limits I attempt to set. When the target position is close, the motor reaches it without error—but the set velocity is still ignored. I would appreciate guidance on how to properly set velocity or torque limits when using position control via CAN bus to avoid this overshoot and error. For your reference, I’ve included both the Python code and the ODrive configuration. Thank you!
Python Code:
import can
import struct
node_id = 0 # must match <odrv>.axis0.config.can.node_id
. The default is 0.
bus = can.interface.Bus(“can0”, interface=“socketcan”)
while not (bus.recv(timeout=0) is None): pass
bus.send(can.Message(
arbitration_id=(node_id << 5 | 0x07), # 0x07: Set_Axis_State
data=struct.pack(‘<I’, 8), # 8: AxisState.CLOSED_LOOP_CONTROL
is_extended_id=False
))
for msg in bus:
if msg.arbitration_id == (node_id << 5 | 0x01): # 0x01: Heartbeat
error, state, result, traj_done = struct.unpack(‘<IBBB’, bytes(msg.data[:7]))
if state == 8: # 8: AxisState.CLOSED_LOOP_CONTROL
break
bus.send(can.Message(
arbitration_id=(node_id << 5 | 0x0B),
data=struct.pack(‘<II’, 3, 3),
is_extended_id=False
))
desPos = 0.0 #0 5
velo = 0 # 10 100 1000
torque = 0 # 10 100 1000
bus.send(can.Message(
arbitration_id=(node_id << 5 | 0x0C),
data=struct.pack(‘<fhh’, desPos, velo, torque),
is_extended_id=False
))
Config:
odrv = odrv0
odrv.config.dc_bus_overvoltage_trip_level = 30
odrv.config.dc_bus_undervoltage_trip_level = 10.5
odrv.config.dc_max_positive_current = math.inf
odrv.config.dc_max_negative_current = -math.inf
odrv.config.brake_resistor0.enable = False
odrv.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
odrv.axis0.config.motor.pole_pairs = 20
odrv.axis0.config.motor.torque_constant = 0.0827
odrv.axis0.config.motor.current_soft_max = 50
odrv.axis0.config.motor.current_hard_max = 70
odrv.axis0.config.motor.calibration_current = 10
odrv.axis0.config.motor.resistance_calib_max_voltage = 2
odrv.axis0.config.calibration_lockin.current = 10
odrv.axis0.motor.motor_thermistor.config.enabled = True
odrv.axis0.motor.motor_thermistor.config.r_ref = 10000
odrv.axis0.motor.motor_thermistor.config.beta = 3435
odrv.axis0.motor.motor_thermistor.config.temp_limit_lower = 110
odrv.axis0.motor.motor_thermistor.config.temp_limit_upper = 130
odrv.axis0.controller.config.control_mode = ControlMode.POSITION_CONTROL
odrv.axis0.controller.config.input_mode = InputMode.POS_FILTER
odrv.axis0.controller.config.vel_limit = 10
odrv.axis0.controller.config.vel_limit_tolerance = 1.2
odrv.axis0.config.torque_soft_min = -math.inf
odrv.axis0.config.torque_soft_max = math.inf
odrv.axis0.controller.config.input_filter_bandwidth = 20
odrv.can.config.protocol = Protocol.SIMPLE
odrv.can.config.baud_rate = 250000
odrv.axis0.config.can.node_id = 0
odrv.axis0.config.can.heartbeat_msg_rate_ms = 100
odrv.axis0.config.can.encoder_msg_rate_ms = 10
odrv.axis0.config.can.iq_msg_rate_ms = 10
odrv.axis0.config.can.torques_msg_rate_ms = 10
odrv.axis0.config.can.error_msg_rate_ms = 10
odrv.axis0.config.can.temperature_msg_rate_ms = 10
odrv.axis0.config.can.bus_voltage_msg_rate_ms = 10
odrv.axis0.config.enable_watchdog = False
odrv.axis0.config.load_encoder = EncoderId.ONBOARD_ENCODER0
odrv.axis0.config.commutation_encoder = EncoderId.ONBOARD_ENCODER0
odrv.config.enable_uart_a = False