81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
import time
|
||
import struct
|
||
import can
|
||
|
||
|
||
def arb_id_single(motor_id: int) -> int:
|
||
# 单电机命令:0x140 + ID(1~32)
|
||
return 0x140 + motor_id
|
||
|
||
|
||
def send_cmd(bus, motor_id: int, data8: bytes):
|
||
msg = can.Message(
|
||
arbitration_id=arb_id_single(motor_id),
|
||
data=data8,
|
||
is_extended_id=False,
|
||
)
|
||
bus.send(msg)
|
||
|
||
|
||
def motor_run(bus, motor_id: int):
|
||
# 电机运行命令:DATA[0]=0x88,其余 0
|
||
send_cmd(bus, motor_id, bytes([0x88, 0, 0, 0, 0, 0, 0, 0]))
|
||
|
||
|
||
def motor_stop(bus, motor_id: int):
|
||
# 电机停止命令:DATA[0]=0x81,其余 0
|
||
send_cmd(bus, motor_id, bytes([0x81, 0, 0, 0, 0, 0, 0, 0]))
|
||
|
||
|
||
def torque_iq_cmd_a1(bus, motor_id: int, iq_control: int):
|
||
"""
|
||
转矩闭环控制命令 0xA1:
|
||
DATA[0] = 0xA1
|
||
DATA[4..5] = iqControl (int16, little-endian), 范围 -2048~2048
|
||
其余字节 0
|
||
【协议:0xA1,iqControl:int16,DATA[4]=低字节,DATA[5]=高字节】
|
||
"""
|
||
if not (-2048 <= iq_control <= 2048):
|
||
raise ValueError("iq_control must be in [-2048, 2048]")
|
||
|
||
data = bytearray(8)
|
||
data[0] = 0xA1
|
||
data[4:6] = struct.pack("<h", int(iq_control)) # little-endian int16
|
||
send_cmd(bus, motor_id, bytes(data))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
# 前提:你已在系统里把 can0 配置并拉起,例如:
|
||
# sudo ip link set can0 type can bitrate 1000000 restart-ms 100
|
||
# sudo ip link set can0 up
|
||
bus = can.Bus(interface="canalystii", channel=0, bitrate=1000000)
|
||
|
||
motor_id = 2
|
||
iq = 40 # 示例:给一个正向转矩电流指令(注意范围 -2048~2048)
|
||
|
||
try:
|
||
motor_run(bus, motor_id)
|
||
time.sleep(0.05)
|
||
|
||
# 建议周期性刷新(例如 100~500 Hz),并在“零力矩”时及时归零
|
||
dt = 0.01 # 100 Hz
|
||
while True:
|
||
torque_iq_cmd_a1(bus, 1, iq)
|
||
torque_iq_cmd_a1(bus, 2, iq)
|
||
torque_iq_cmd_a1(bus, 3, iq)
|
||
# torque_iq_cmd_a1(bus, 4, iq)
|
||
time.sleep(dt)
|
||
|
||
except KeyboardInterrupt:
|
||
# 松手/退出时,建议先发 0 力矩,再 stop
|
||
try:
|
||
torque_iq_cmd_a1(bus, 1, 0)
|
||
torque_iq_cmd_a1(bus, 2, 0)
|
||
torque_iq_cmd_a1(bus, 3, 0)
|
||
# torque_iq_cmd_a1(bus, 4, 0)
|
||
time.sleep(0.05)
|
||
except Exception:
|
||
pass
|
||
motor_stop(bus, motor_id)
|
||
bus.shutdown()
|