Files
5dof/can_test_motor/motor_control_can_all.py

175 lines
6.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# 不同模式can发送指令集成
# -*- coding: utf-8 -*-
'''
# @Time : 2025/7/21
# @Author : hx
# @File : motor_control_can_all.py
'''
import can
import time
import argparse
# 细分值映射表
MICROSTEP_MAP = {
2: 0x01,
4: 0x02,
8: 0x04,
16: 0x10,
32: 0x20
}
# ========================================
# CAN 发送函数(使用 socketcan
# ========================================
def send_can_frame(data, can_id=0x01, channel='can0', bustype='socketcan'):
"""
发送CAN帧
:param data: 7字节的列表
:param can_id: CAN ID
:param channel: CAN 通道
:param bustype: 总线类型
"""
try:
bus = can.interface.Bus(channel=channel, bustype=bustype)
msg = can.Message(arbitration_id=can_id, data=data, is_extended_id=False)
bus.send(msg)
print(f"[发送CAN帧] ID={can_id:02X} 数据=[{', '.join(f'0x{x:02X}' for x in data)}]")
bus.shutdown()
except Exception as e:
print(f"[发送失败] {e}")
# ========================================
# 模式1速度控制模式 (0x01)
# ========================================
def generate_speed_command(direction, microstep, speed):
"""
生成速度控制指令
:param direction: 方向 (0:逆时针, 1:顺时针)
:param microstep: 细分值 (2, 4, 8, 16, 32)
:param speed: 速度值 (单位: rad/s)
"""
direction_byte = 0x01 if direction == 1 else 0x00
microstep_byte = MICROSTEP_MAP.get(microstep, 0x20)
raw_speed = int(speed * 10)
speed_high = (raw_speed >> 8) & 0xFF
speed_low = raw_speed & 0xFF
return [0x01, direction_byte, microstep_byte, 0x00, 0x00, speed_high, speed_low]
# ========================================
# 模式2位置控制模式 (0x02)
# ========================================
def generate_position_command(direction, microstep, angle):
"""
生成位置控制指令
:param direction: 方向 (0:逆时针, 1:顺时针)
:param microstep: 细分值 (2, 4, 8, 16, 32)
:param angle: 角度值 (单位: 度)
"""
direction_byte = 0x01 if direction == 1 else 0x00
microstep_byte = MICROSTEP_MAP.get(microstep, 0x20)
raw_angle = int(angle * 10)
pos_high = (raw_angle >> 8) & 0xFF
pos_low = raw_angle & 0xFF
return [0x02, direction_byte, microstep_byte, pos_high, pos_low, 0x00, 0x64]
# ========================================
# 模式3力矩控制模式 (0x03)
# ========================================
def generate_torque_command(direction, microstep, current):
"""
生成力矩控制指令
:param direction: 方向 (0:逆时针, 1:顺时针)
:param microstep: 细分值 (2, 4, 8, 16, 32)
:param current: 电流值 (单位: mA)
"""
direction_byte = 0x01 if direction == 1 else 0x00
microstep_byte = MICROSTEP_MAP.get(microstep, 0x20)
raw_current = int(current)
current_high = (raw_current >> 8) & 0xFF
current_low = raw_current & 0xFF
return [0x03, direction_byte, microstep_byte, current_high, current_low, 0x00, 0x64]
# ========================================
# 模式4单圈绝对角度控制模式 (0x04)
# ========================================
def generate_absolute_angle_command(direction, microstep, angle, speed):
"""
生成单圈绝对角度控制指令
:param direction: 方向 (0:逆时针, 1:顺时针)
:param microstep: 细分值 (2, 4, 8, 16, 32)
:param angle: 目标角度 (单位: 度)
:param speed: 速度值 (单位: rad/s)
"""
direction_byte = 0x01 if direction == 1 else 0x00
microstep_byte = MICROSTEP_MAP.get(microstep, 0x20)
raw_angle = int(angle * 10)
pos_high = (raw_angle >> 8) & 0xFF
pos_low = raw_angle & 0xFF
raw_speed = int(speed * 10)
speed_high = (raw_speed >> 8) & 0xFF
speed_low = raw_speed & 0xFF
return [0x04, direction_byte, microstep_byte, pos_high, pos_low, speed_high, speed_low]
# ========================================
# 主函数(命令行调用)
# ========================================
def main():
parser = argparse.ArgumentParser(description="CAN电机控制程序支持4种模式")
parser.add_argument("--mode", type=int, choices=[1, 2, 3, 4],
help="控制模式: 1=速度, 2=位置, 3=力矩, 4=绝对角度")
parser.add_argument("--direction", type=int, choices=[0, 1], default=1,
help="方向: 0=逆时针, 1=顺时针")
parser.add_argument("--microstep", type=int, choices=[2, 4, 8, 16, 32], default=32,
help="细分值: 2, 4, 8, 16, 32")
parser.add_argument("--value", type=float, required=True,
help="控制值(速度: rad/s, 位置/角度: 度, 力矩: mA")
parser.add_argument("--speed_rad_per_sec", type=float,
help="速度值(仅用于绝对角度模式)")
args = parser.parse_args()
try:
if args.mode == 1:
cmd = generate_speed_command(args.direction, args.microstep, args.value)
elif args.mode == 2:
cmd = generate_position_command(args.direction, args.microstep, args.value)
elif args.mode == 3:
cmd = generate_torque_command(args.direction, args.microstep, args.value)
elif args.mode == 4:
if args.speed_rad_per_sec is None:
raise ValueError("绝对角度模式需要提供速度参数 (--speed_rad_per_sec)")
cmd = generate_absolute_angle_command(args.direction, args.microstep, args.value, args.speed_rad_per_sec)
print(f"生成CAN指令: [{', '.join(f'0x{x:02X}' for x in cmd)}]")
send_can_frame(cmd)
except Exception as e:
print(f"错误: {e}")
# ========================================
# 程序入口
# ========================================
if __name__ == "__main__":
main()
#python motor_control_can_all.py --mode 1 --direction 1 --microstep 32 --value 10
#python motor_control_can_all.py --mode 2 --direction 1 --microstep 32 --value 1000
#python motor_control_can_all.py --mode 3 --direction 1 --microstep 32 --value 1000