Files
Gimbal/modules/motor/step_motor/X_V2.c
T
2026-05-29 17:36:34 +08:00

1775 lines
68 KiB
C
Raw 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.
#include "X_V2.h"
#include "step_motor.h"
/**********************************************************
*** X_V2步进闭环控制例程
*** 编写作者:ZHANGDATOU
*** 技术支持:张大头闭环伺服
*** 淘宝店铺:https://zhangdatou.taobao.com
*** CSDN博客:http s://blog.csdn.net/zhangdatou666
*** qq交流群:262438510
**********************************************************/
uint16_t MMCL_count = 0, MMCL_cmd[MMCL_LEN] = {0};
/**********************************************************
*** 触发动作命令
**********************************************************/
/**
* @brief 触发编码器校准
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Trig_Encoder_Cal(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x06; // 功能码
cmd[2] = 0x45; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr, cmd, 4);
}
/**
* @brief 重启电机(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Reset_Motor(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x08; // 功能码
cmd[2] = 0x97; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr, cmd, 4);
}
/**
* @brief 将当前位置清零
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Reset_CurPos_To_Zero(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0A; // 功能码
cmd[2] = 0x6D; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr, cmd, 4);
}
/**
* @brief 解除堵转保护
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Reset_Clog_Pro(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0E; // 功能码
cmd[2] = 0x52; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr, cmd, 4);
}
/**
* @brief 恢复出厂设置
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Restore_Motor(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0F; // 功能码
cmd[2] = 0x5F; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr, cmd, 4);
}
/**********************************************************
*** 运动控制命令
**********************************************************/
/**
* @brief 多电机命令(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Multi_Motor_Cmd(uint8_t addr)
{
uint16_t i = 0, j = 0, len = 0; static uint8_t cmd[MMCL_LEN] = {0};
// 多电机命令长度大于0
if(MMCL_count > 0)
{
// 多电机命令的总字节数
len = MMCL_count + 5;
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xAA; // 功能码
cmd[2] = (uint8_t)(len >> 8); // 总字节数高8位
cmd[3] = (uint8_t)(len); // 总字节数低8位
for(i=0,j=4; i < MMCL_count; i++,j++) { cmd[j] = MMCL_cmd[i]; }
cmd[j] = 0x6B; ++j; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, j); MMCL_count = 0;
}
else
{
MMCL_count = 0;
}
}
/**
* @brief 使能信号控制
* @param addr :电机地址
* @param state :使能状态 ,true为使能电机,false为关闭电机
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_En_Control(uint8_t addr, bool state, bool snF)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xF3; // 功能码
cmd[2] = 0xAB; // 辅助码
cmd[3] = (uint8_t)state; // 使能状态
cmd[4] = snF; // 多机同步运动标志
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 力矩模式
* @param addr :电机地址
* @param sign :符号(方向) ,0为正,1为负
* @param t_ramp :电流斜率(Ma/s) ,范围0 - 65535Ma/s
* @param torque :力矩电流(Ma) ,范围0 - 6000Ma
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Torque_Control(uint8_t addr, uint8_t sign, uint16_t t_ramp, uint16_t torque, bool snF)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xF5; // 功能码
cmd[2] = sign; // 符号(方向)
cmd[3] = (uint8_t)(t_ramp >> 8); // 电流斜率(Ma/s)
cmd[4] = (uint8_t)(t_ramp >> 0);
cmd[5] = (uint8_t)(torque >> 8); // 力矩电流(Ma)
cmd[6] = (uint8_t)(torque >> 0);
cmd[7] = snF; // 多机同步标志
cmd[8] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 9);
}
/**
* @brief 力矩模式限速控制(Y42)
* @param addr :电机地址
* @param sign :符号(方向) ,0为正,1为负
* @param t_ramp :电流斜率(Ma/s) ,范围0 - 65535Ma/s
* @param torque :力矩电流(Ma) ,范围0 - 6000Ma
* @param snF :多机同步标志 ,false为不启用,true为启用
* @param maxVel :最大速度(RPM) ,范围0.0 - 3000.0RPM
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Torque_LV_Control(uint8_t addr, uint8_t sign, uint16_t t_ramp, uint16_t torque, bool snF, float maxVel)
{
static uint8_t cmd[16] = {0}; uint16_t v = 0;
// 将速度放大10倍发送过去
v = (uint16_t)ABS(maxVel * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xC5; // 功能码
cmd[2] = sign; // 符号(方向)
cmd[3] = (uint8_t)(t_ramp >> 8); // 电流斜率(Ma/s)
cmd[4] = (uint8_t)(t_ramp >> 0);
cmd[5] = (uint8_t)(torque >> 8); // 力矩电流(Ma)
cmd[6] = (uint8_t)(torque >> 0);
cmd[7] = snF; // 多机同步标志
cmd[8] = (uint8_t)(v >> 8); // 最大速度(RPM)
cmd[9] = (uint8_t)(v >> 0);
cmd[10] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 11);
}
/**
* @brief 速度模式
* @param addr :电机地址
* @param dir :方向 ,0为CW,1为CCW
* @param acc :加速度(RPM/s) ,范围0 - 65535RPM/s
* @param vel :速度(RPM) ,范围0.0 - 3000.0RPM
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Vel_Control(uint8_t addr, uint8_t dir, uint16_t acc, float vel, bool snF)
{
static uint8_t cmd[16] = {0}; uint16_t v = 0;
// 将速度放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xF6; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(acc >> 8); // 加速度(RPM/s)
cmd[4] = (uint8_t)(acc >> 0);
cmd[5] = (uint8_t)(v >> 8); // 速度(RPM)
cmd[6] = (uint8_t)(v >> 0);
cmd[7] = snF; // 多机同步运动标志
cmd[8] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 9);
}
/**
* @brief 速度模式限电流控制(Y42)
* @param addr :电机地址
* @param dir :方向 ,0为CW,1为CCW
* @param acc :加速度(RPM/s) ,范围0 - 65535RPM/s
* @param vel :速度(RPM) ,范围0.0 - 3000.0RPM
* @param snF :多机同步标志 ,false为不启用,true为启用
* @param maxCur:最大电流(mA) ,范围0 - 6000mA
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Vel_LC_Control(uint8_t addr, uint8_t dir, uint16_t acc, float vel, bool snF, uint16_t maxCur)
{
static uint8_t cmd[16] = {0}; uint16_t v = 0;
// 将速度放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xC6; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(acc >> 8); // 加速度(RPM/s)
cmd[4] = (uint8_t)(acc >> 0);
cmd[5] = (uint8_t)(v >> 8); // 速度(RPM)
cmd[6] = (uint8_t)(v >> 0);
cmd[7] = snF; // 多机同步运动标志
cmd[8] = (uint8_t)(maxCur >> 8); // 最大电流(mA)
cmd[9] = (uint8_t)(maxCur >> 0);
cmd[10] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 11);
}
/**
* @brief 直通限速位置模式
* @param addr :电机地址
* @param dir :方向 ,0为CW,1为CCW
* @param vel :运动速度(RPM) ,范围0.0 - 3000.0RPM
* @param pos :位置角度(°) ,范围0.0°- (2^32 - 1) / 10°
* @param raf :相位/绝对运动标志 ,0为相对上一次输入目标位置,1为绝对位置,2为相对当前实时位置
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Bypass_Pos_LV_Control(uint8_t addr, uint8_t dir, float vel, float pos, uint8_t raf, bool snF)
{
uint8_t cmd[16] = {0}; uint16_t v = 0; uint32_t p = 0;
// 将速度和位置放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f); p = (uint32_t)ABS(pos * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFB; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(v >> 8); // 运动速度(RPM)
cmd[4] = (uint8_t)(v >> 0);
cmd[5] = (uint8_t)(p >> 24); // 位置角度
cmd[6] = (uint8_t)(p >> 16);
cmd[7] = (uint8_t)(p >> 8);
cmd[8] = (uint8_t)(p >> 0);
cmd[9] = raf; // 相位/绝对运动标志
cmd[10] = snF; // 多机同步运动标志
cmd[11] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 12);
}
/**
* @brief 直通限速位置模式限电流控制
* @param addr :电机地址
* @param dir :方向 ,0为CW,1为CCW
* @param vel :运动速度(RPM) ,范围0.0 - 3000.0RPM
* @param pos :位置角度(°) ,范围0.0°- (2^32 - 1) / 10°
* @param raf :相位/绝对运动标志 ,0为相对上一次输入目标位置,1为绝对位置,2为相对当前实时位置
* @param snF :多机同步标志 ,false为不启用,true为启用
* @param maxCur:最大电流(mA) ,范围0 - 6000mA
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Bypass_Pos_LV_LC_Control(uint8_t addr, uint8_t dir, float vel, float pos, uint8_t raf, bool snF, uint16_t maxCur)
{
uint8_t cmd[16] = {0}; uint16_t v = 0; uint32_t p = 0;
// 将速度和位置放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f); p = (uint32_t)ABS(pos * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xCB; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(v >> 8); // 运动速度(RPM)
cmd[4] = (uint8_t)(v >> 0);
cmd[5] = (uint8_t)(p >> 24); // 位置角度
cmd[6] = (uint8_t)(p >> 16);
cmd[7] = (uint8_t)(p >> 8);
cmd[8] = (uint8_t)(p >> 0);
cmd[9] = raf; // 相位/绝对运动标志
cmd[10] = snF; // 多机同步运动标志
cmd[11] = (uint8_t)(maxCur >> 8); // 最大电流(mA)
cmd[12] = (uint8_t)(maxCur >> 0);
cmd[13] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 14);
}
/**
* @brief 梯形曲线加减速位置模式控制
* @param addr :电机地址
* @param dir :方向 ,0为CW,其余值为CCW
* @param acc :加速加速度(RPM/s) ,0为CW,其余值为CCW
* @param dec :减速加速度(RPM/s) ,0为CW,其余值为CCW
* @param vel :最大速度(RPM) ,范围0.0 - 3000.0RPM
* @param pos :位置(°) ,范围0.0°- (2^32 - 1)°
* @param raf :相位/绝对运动标志 ,0为相对上一次输入目标位置,1为绝对位置,2为相对当前实时位置
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Traj_Pos_Control(uint8_t addr, uint8_t dir, uint16_t acc, uint16_t dec, float vel, float pos, uint8_t raf, bool snF)
{
uint8_t cmd[32] = {0}; uint16_t v = 0; uint32_t p = 0;
// 将速度和位置放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f); p = (uint32_t)ABS(pos * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFD; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(acc >> 8); // 加速加速度(RPM/s)
cmd[4] = (uint8_t)(acc >> 0);
cmd[5] = (uint8_t)(dec >> 8); // 减速加速度(RPM/s)
cmd[6] = (uint8_t)(dec >> 0);
cmd[7] = (uint8_t)(v >> 8); // 最大速度(RPM)
cmd[8] = (uint8_t)(v >> 0);
cmd[9] = (uint8_t)(p >> 24); // 位置角度
cmd[10] = (uint8_t)(p >> 16);
cmd[11] = (uint8_t)(p >> 8);
cmd[12] = (uint8_t)(p >> 0);
cmd[13] = raf; // 相位/绝对运动标志
cmd[14] = snF; // 多机同步运动标志
cmd[15] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 16);
}
/**
* @brief 梯形曲线加减速位置模式限电流控制(Y42)
* @param addr :电机地址
* @param dir :方向 ,0为CW,其余值为CCW
* @param acc :加速加速度(RPM/s) ,0为CW,其余值为CCW
* @param dec :减速加速度(RPM/s) ,0为CW,其余值为CCW
* @param vel :最大速度(RPM) ,范围0.0 - 3000.0RPM
* @param pos :位置(°) ,范围0.0°- (2^32 - 1)°
* @param raf :相位/绝对运动标志 ,0为相对上一次输入目标位置,1为绝对位置,2为相对当前实时位置
* @param snF :多机同步标志 ,false为不启用,true为启用
* @param maxCur:最大电流(mA) ,范围0 - 6000mA
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Traj_Pos_LC_Control(uint8_t addr, uint8_t dir, uint16_t acc, uint16_t dec, float vel, float pos, uint8_t raf, bool snF, uint16_t maxCur)
{
uint8_t cmd[32] = {0}; uint16_t v = 0; uint32_t p = 0;
// 将速度和位置放大10倍发送过去
v = (uint16_t)ABS(vel * 10.0f); p = (uint32_t)ABS(pos * 10.0f);
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xCD; // 功能码
cmd[2] = dir; // 符号(方向)
cmd[3] = (uint8_t)(acc >> 8); // 加速加速度(RPM/s)
cmd[4] = (uint8_t)(acc >> 0);
cmd[5] = (uint8_t)(dec >> 8); // 减速加速度(RPM/s)
cmd[6] = (uint8_t)(dec >> 0);
cmd[7] = (uint8_t)(v >> 8); // 最大速度(RPM)
cmd[8] = (uint8_t)(v >> 0);
cmd[9] = (uint8_t)(p >> 24); // 位置角度
cmd[10] = (uint8_t)(p >> 16);
cmd[11] = (uint8_t)(p >> 8);
cmd[12] = (uint8_t)(p >> 0);
cmd[13] = raf; // 相位/绝对运动标志
cmd[14] = snF; // 多机同步运动标志
cmd[15] = (uint8_t)(maxCur >> 8); // 最大电流(mA)
cmd[16] = (uint8_t)(maxCur >> 0);
cmd[17] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 18);
}
/**
* @brief 立即停止
* @param addr :电机地址
* @param snF :多机同步标志,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Stop_Now(uint8_t addr, bool snF)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFE; // 功能码
cmd[2] = 0x98; // 辅助码
cmd[3] = snF; // 多机同步运动标志
cmd[4] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 5);
}
/**
* @brief 多机同步运动
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Synchronous_motion(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFF; // 功能码
cmd[2] = 0x66; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**********************************************************
*** 原点回零命令
**********************************************************/
/**
* @brief 设置单圈回零的零点位置
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Origin_Set_O(uint8_t addr, bool svF)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x93; // 功能码
cmd[2] = 0x88; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 5);
}
/**
* @brief 触发回零
* @param addr :电机地址
* @param o_mode :回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
* @param snF :多机同步标志,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Origin_Trigger_Return(uint8_t addr, uint8_t o_mode, bool snF)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x9A; // 功能码
cmd[2] = o_mode; // 回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
cmd[3] = snF; // 多机同步运动标志,false为不启用,true为启用
cmd[4] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 5);
}
/**
* @brief 强制中断并退出回零
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Origin_Interrupt(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x9C; // 功能码
cmd[2] = 0x48; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**
* @brief 读取回零参数
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Origin_Read_Params(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x22; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改回零参数
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param o_mode :回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
* @param o_dir :回零方向,0为CW,其余值为CCW
* @param o_vel :回零速度,单位:RPM(转/分钟)
* @param o_tm :回零超时时间,单位:毫秒
* @param sl_vel :无限位碰撞回零检测转速,单位:RPM(转/分钟)
* @param sl_ma :无限位碰撞回零检测电流,单位:Ma(毫安)
* @param sl_ms :无限位碰撞回零检测时间,单位:Ms(毫秒)
* @param potF :上电自动触发回零,false为不使能,true为使能
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Origin_Modify_Params(uint8_t addr, bool svF, uint8_t o_mode, uint8_t o_dir, uint16_t o_vel, uint32_t o_tm, uint16_t sl_vel, uint16_t sl_ma, uint16_t sl_ms, bool potF)
{
static uint8_t cmd[32] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x4C; // 功能码
cmd[2] = 0xAE; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = o_mode; // 回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
cmd[5] = o_dir; // 回零方向
cmd[6] = (uint8_t)(o_vel >> 8); // 回零速度(RPM)高8位字节
cmd[7] = (uint8_t)(o_vel >> 0); // 回零速度(RPM)低8位字节
cmd[8] = (uint8_t)(o_tm >> 24); // 回零超时时间(bit24 - bit31)
cmd[9] = (uint8_t)(o_tm >> 16); // 回零超时时间(bit16 - bit23)
cmd[10] = (uint8_t)(o_tm >> 8); // 回零超时时间(bit8 - bit15)
cmd[11] = (uint8_t)(o_tm >> 0); // 回零超时时间(bit0 - bit7 )
cmd[12] = (uint8_t)(sl_vel >> 8); // 无限位碰撞回零检测转速(RPM)高8位字节
cmd[13] = (uint8_t)(sl_vel >> 0); // 无限位碰撞回零检测转速(RPM)低8位字节
cmd[14] = (uint8_t)(sl_ma >> 8); // 无限位碰撞回零检测电流(Ma)高8位字节
cmd[15] = (uint8_t)(sl_ma >> 0); // 无限位碰撞回零检测电流(Ma)低8位字节
cmd[16] = (uint8_t)(sl_ms >> 8); // 无限位碰撞回零检测时间(Ms)高8位字节
cmd[17] = (uint8_t)(sl_ms >> 0); // 无限位碰撞回零检测时间(Ms)低8位字节
cmd[18] = potF; // 上电自动触发回零,false为不使能,true为使能
cmd[19] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 20);
}
/**********************************************************
*** 读取系统参数命令
**********************************************************/
/**
* @brief 定时返回信息命令(Y42)
* @param addr :电机地址
* @param s :系统参数类型
* @param time_ms :定时时间
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Auto_Return_Sys_Params_Timed(uint8_t addr, SysParams_t s, uint16_t time_ms)
{
uint8_t i = 0; static uint8_t cmd[16] = {0};
// 装载命令
cmd[i] = addr; ++i; // 地址
cmd[i] = 0x11; ++i; // 功能码
cmd[i] = 0x18; ++i; // 辅助码
switch(s) // 信息功能码
{
case S_VBUS : cmd[i] = 0x24; ++i; break; // 读取总线电压
case S_CBUS : cmd[i] = 0x26; ++i; break; // 读取总线电流
case S_CPHA : cmd[i] = 0x27; ++i; break; // 读取相电流
case S_ENCO : cmd[i] = 0x29; ++i; break; // 读取编码器原始值
case S_CLKC : cmd[i] = 0x30; ++i; break; // 读取实时脉冲数
case S_ENCL : cmd[i] = 0x31; ++i; break; // 读取经过线性化校准后的编码器值
case S_CLKI : cmd[i] = 0x32; ++i; break; // 读取输入脉冲数
case S_TPOS : cmd[i] = 0x33; ++i; break; // 读取电机目标位置
case S_SPOS : cmd[i] = 0x34; ++i; break; // 读取电机实时设定的目标位置
case S_VEL : cmd[i] = 0x35; ++i; break; // 读取电机实时转速
case S_CPOS : cmd[i] = 0x36; ++i; break; // 读取电机实时位置
case S_PERR : cmd[i] = 0x37; ++i; break; // 读取电机位置误差
case S_VBAT : cmd[i] = 0x38; ++i; break; // 读取多圈编码器电池电压(Y42)
case S_TEMP : cmd[i] = 0x39; ++i; break; // 读取电机实时温度(Y42)
case S_FLAG : cmd[i] = 0x3A; ++i; break; // 读取电机状态标志位
case S_OFLAG: cmd[i] = 0x3B; ++i; break; // 读取回零状态标志位
case S_OAF : cmd[i] = 0x3C; ++i; break; // 读取电机状态标志位 + 回零状态标志位(Y42)
case S_PIN : cmd[i] = 0x3D; ++i; break; // 读取引脚状态(Y42)
default: break;
}
cmd[i] = (uint8_t)(time_ms >> 8); ++i; // 定时时间
cmd[i] = (uint8_t)(time_ms >> 0); ++i;
cmd[i] = 0x6B; ++i; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, i);
}
/**
* @brief 读取系统参数
* @param addr :电机地址
* @param s :系统参数类型
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Sys_Params(uint8_t addr, SysParams_t s)
{
uint8_t i = 0; static uint8_t cmd[16] = {0};
// 装载命令
cmd[i] = addr; ++i; // 地址
switch(s) // 功能码
{
case S_VBUS : cmd[i] = 0x24; ++i; break; // 读取总线电压
case S_CBUS : cmd[i] = 0x26; ++i; break; // 读取总线电流
case S_CPHA : cmd[i] = 0x27; ++i; break; // 读取相电流
case S_ENCO : cmd[i] = 0x29; ++i; break; // 读取编码器原始值
case S_CLKC : cmd[i] = 0x30; ++i; break; // 读取实时脉冲数
case S_ENCL : cmd[i] = 0x31; ++i; break; // 读取经过线性化校准后的编码器值
case S_CLKI : cmd[i] = 0x32; ++i; break; // 读取输入脉冲数
case S_TPOS : cmd[i] = 0x33; ++i; break; // 读取电机目标位置
case S_SPOS : cmd[i] = 0x34; ++i; break; // 读取电机实时设定的目标位置
case S_VEL : cmd[i] = 0x35; ++i; break; // 读取电机实时转速
case S_CPOS : cmd[i] = 0x36; ++i; break; // 读取电机实时位置
case S_PERR : cmd[i] = 0x37; ++i; break; // 读取电机位置误差
case S_VBAT : cmd[i] = 0x38; ++i; break; // 读取多圈编码器电池电压(Y42)
case S_TEMP : cmd[i] = 0x39; ++i; break; // 读取电机实时温度(Y42)
case S_FLAG : cmd[i] = 0x3A; ++i; break; // 读取电机状态标志位
case S_OFLAG: cmd[i] = 0x3B; ++i; break; // 读取回零状态标志位
case S_OAF : cmd[i] = 0x3C; ++i; break; // 读取电机状态标志位 + 回零状态标志位(Y42)
case S_PIN : cmd[i] = 0x3D; ++i; break; // 读取引脚状态(Y42)
default: break;
}
cmd[i] = 0x6B; ++i; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, i);
}
/**********************************************************
*** 读写驱动参数命令
**********************************************************/
/**
* @brief 修改电机ID地址
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param id :默认电机ID为1,可修改为1-255,0为广播地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Motor_ID(uint8_t addr, bool svF, uint8_t id)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xAE; // 功能码
cmd[2] = 0x4B; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = id; // 默认电机ID为1,可修改为1-255,0为广播地址
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改细分值
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param mstep :默认细分为16,可修改为1-2556,0为256细分
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_MicroStep(uint8_t addr, bool svF, uint8_t mstep)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x84; // 功能码
cmd[2] = 0x8A; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = mstep; // 默认细分为16,可修改为1-2556,0为256细分
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改掉电标志
* @param addr :电机地址
* @param pdf :掉电标志
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_PDFlag(uint8_t addr, bool pdf)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x50; // 功能码
cmd[2] = pdf; // 掉电标志
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**
* @brief 读取选项参数状态(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Opt_Param_Sta(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x1A; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改电机类型(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param mottype :电机类型,默认为0,0表示1.8°步进电机,1表示0.9°步进电机
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Motor_Type(uint8_t addr, bool svF, bool mottype)
{
static uint8_t cmd[16] = {0}; uint8_t MotType = 0;
if(mottype) { MotType = 25; } else { MotType = 50; }
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD7; // 功能码
cmd[2] = 0x35; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = MotType; // 电机类型,0表示0.9°步进电机,1表示1.8°步进电机
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改固件类型(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param fwtype :固件类型,默认为0,0为X固件,1为Emm固件
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Firmware_Type(uint8_t addr, bool svF, bool fwtype)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD5; // 功能码
cmd[2] = 0x69; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = fwtype; // 电机类型,25表示0.9°步进电机,50表示1.8°步进电机
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改开环/闭环控制模式(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param ctrl_mode:控制模式,默认为1,0为开环模式,1为闭环FOC模式
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Ctrl_Mode(uint8_t addr, bool svF, bool ctrl_mode)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x46; // 功能码
cmd[2] = 0x69; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = ctrl_mode; // 控制模式,默认为1,0为开环模式,1为闭环FOC模式
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改电机运动正方向(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param dir :电机运动正方向,默认为CW,0为CW(顺时针方向),1为CCW
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Motor_Dir(uint8_t addr, bool svF, bool dir)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD4; // 功能码
cmd[2] = 0x60; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = dir; // 电机运动正方向,默认为CW,0为CW(顺时针方向),1为CCW
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改锁定按键功能(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param lock :锁定按键功能,默认为Disable,0为Disable,1为Enable
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Lock_Btn(uint8_t addr, bool svF, bool lock)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD0; // 功能码
cmd[2] = 0xB3; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = lock; // 锁定按键功能,默认为Disable,0为Disable),1为Enable
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改命令位置角度是否继续缩小10倍输入(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param s_vel :命令位置角度是否继续缩小10倍输入,默认为Disable,0为Disable,1为Enable
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_S_Vel(uint8_t addr, bool svF, bool s_vel)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x4F; // 功能码
cmd[2] = 0x71; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = s_vel; // 命令位置角度是否继续缩小10倍输入,默认为Disable,0为Disable,1为Enable
cmd[5] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 6);
}
/**
* @brief 修改开环模式工作电流
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param om_ma :开环模式工作电流,单位mA
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_OM_mA(uint8_t addr, bool svF, uint16_t om_ma)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x44; // 功能码
cmd[2] = 0x33; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(om_ma >> 8); // 开环模式工作电流,单位mA
cmd[5] = (uint8_t)(om_ma >> 0);
cmd[6] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 7);
}
/**
* @brief 修改闭环模式最大电流
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param foc_mA :闭环模式最大电流,单位mA
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_FOC_mA(uint8_t addr, bool svF, uint16_t foc_mA)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x45; // 功能码
cmd[2] = 0x66; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(foc_mA >> 8); // 闭环模式最大电流,单位mA
cmd[5] = (uint8_t)(foc_mA >> 0);
cmd[6] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 7);
}
/**
* @brief 读取PID参数
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_PID_Params(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x21; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改PID参数
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param kp :比例系数,默认为Y42/18000
* @param ki :积分系数,默认为Y42/10
* @param kd :微分系数,默认为Y42/18000
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_PID_Params(uint8_t addr, bool svF, uint32_t kp, uint32_t ki, uint32_t kd)
{
static uint8_t cmd[20] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x4A; // 功能码
cmd[2] = 0xC3; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(kp >> 24); // kp
cmd[5] = (uint8_t)(kp >> 16);
cmd[6] = (uint8_t)(kp >> 8);
cmd[7] = (uint8_t)(kp >> 0);
cmd[8] = (uint8_t)(ki >> 24); // ki
cmd[9] = (uint8_t)(ki >> 16);
cmd[10] = (uint8_t)(ki >> 8);
cmd[11] = (uint8_t)(ki >> 0);
cmd[12] = (uint8_t)(kd >> 24); // kd
cmd[13] = (uint8_t)(kd >> 16);
cmd[14] = (uint8_t)(kd >> 8);
cmd[15] = (uint8_t)(kd >> 0);
cmd[16] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 17);
}
/**
* @brief 读取DMX512协议参数(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_DMX512_Params(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x49; // 功能码
cmd[2] = 0x78; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**
* @brief 读取DMX512协议参数(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param tch :总通道数,默认为192,该值要与自身 DMX512 控制器的总通道数一样
* @param nch :每个电机占用的通道数,默认为1,1为单通道模式,2为双通道模式
* @param mode :运动模式,默认为1,0表示相对位置模式运动,1表示绝对坐标式位置运动
* @param vel :单通道模式的运动速度,默认值为1000, 单位RPM, 即1000RPM;
* @param acc :加速度,acc=加速数值/8=125,加速时间见说明书“5.3.12 位置模式控制(Emm)”
* @param vel_step :双通道模式速度步长,默认值为 10, 即电机运动速度为(通道值 * 10)RPM
* @param pos_step :双通道模式运动步长,默认值为 100, 即电机转动角度为(通道值 * 10.0)°
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_DMX512_Params(uint8_t addr, bool svF, uint16_t tch, uint8_t nch, uint8_t mode, uint16_t vel, uint16_t acc, uint16_t vel_step, uint32_t pos_step)
{
static uint8_t cmd[32] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD9; // 功能码
cmd[2] = 0x90; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(tch >> 8); // 总通道数
cmd[5] = (uint8_t)(tch >> 0);
cmd[6] = nch; // 每个电机占用的通道数
cmd[7] = mode; // 运动模式
cmd[8] = (uint8_t)(vel >> 8); // 单通道模式的运动速度
cmd[9] = (uint8_t)(vel >> 0);
cmd[10] = (uint8_t)(acc >> 8); // 双通道模式速度步长
cmd[11] = (uint8_t)(acc >> 0);
cmd[12] = (uint8_t)(vel_step >> 8); // 双通道模式速度步长
cmd[13] = (uint8_t)(vel_step >> 0);
cmd[14] = (uint8_t)(pos_step >> 24); // 双通道模式运动步长
cmd[15] = (uint8_t)(pos_step >> 16);
cmd[16] = (uint8_t)(pos_step >> 8);
cmd[17] = (uint8_t)(pos_step >> 0);
cmd[18] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 19);
}
/**
* @brief 读取位置到达窗口(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Pos_Window(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x41; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改位置到达窗口(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param prw :位置到达窗口,默认值为8,即0.8°
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Pos_Window(uint8_t addr, bool svF, uint16_t prw)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD1; // 功能码
cmd[2] = 0x07; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(prw >> 8); // 位置到达窗口,默认值为8,即0.8°
cmd[5] = (uint8_t)(prw >> 0);
cmd[6] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 7);
}
/**
* @brief 读取过热过流保护检测阈值(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Otocp(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x13; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改过热过流保护检测阈值(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param otp :过热保护检测阈值,默认100℃
* @param ocp :过流保护检测阈值,默认6600mA
* @param time_ms :过热过流检测时间,默认1000ms
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Otocp(uint8_t addr, bool svF, uint16_t otp, uint16_t ocp, uint16_t time_ms)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xD3; // 功能码
cmd[2] = 0x56; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(otp >> 8); // 过热保护检测阈值
cmd[5] = (uint8_t)(otp >> 0);
cmd[6] = (uint8_t)(ocp >> 8); // 过流保护检测阈值
cmd[7] = (uint8_t)(ocp >> 0);
cmd[8] = (uint8_t)(time_ms >> 8); // 过热过流检测时间
cmd[9] = (uint8_t)(time_ms >> 0);
cmd[10] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 11);
}
/**
* @brief 读取心跳保护功能时间(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Heart_Protect(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x16; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改心跳保护功能时间(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param hp :心跳保护时间,单位:ms
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Heart_Protect(uint8_t addr, bool svF, uint32_t hp)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x68; // 功能码
cmd[2] = 0x38; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(hp >> 24); // 心跳保护时间,单位:ms
cmd[5] = (uint8_t)(hp >> 16);
cmd[6] = (uint8_t)(hp >> 8);
cmd[7] = (uint8_t)(hp >> 0);
cmd[8] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 9);
}
/**
* @brief 读取积分限幅/刚性系数(Y42)
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Integral_Limit(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x23; // 功能码
cmd[2] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 3);
}
/**
* @brief 修改积分限幅/刚性系数(Y42)
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param il :刚性系数,X 固件默认为Y42/388、Y57/512
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Modify_Integral_Limit(uint8_t addr, bool svF, uint32_t il)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x4B; // 功能码
cmd[2] = 0x57; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = (uint8_t)(il >> 24); // 刚性系数,X 固件默认为Y42/388、Y57/512
cmd[5] = (uint8_t)(il >> 16);
cmd[6] = (uint8_t)(il >> 8);
cmd[7] = (uint8_t)(il >> 0);
cmd[8] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 9);
}
/**********************************************************
*** 读取所有驱动参数命令
**********************************************************/
/**
* @brief 读取系统状态参数
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_System_State_Params(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x43; // 功能码
cmd[2] = 0x7A; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**
* @brief 读取驱动配置参数
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_Read_Motor_Conf_Params(uint8_t addr)
{
static uint8_t cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x42; // 功能码
cmd[2] = 0x6C; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 发送命令
step_sendcmd(addr,cmd, 4);
}
/**
***********************************************************
***********************************************************
***
***
*** @brief 以下是把相应命令加载到Y42多电机命令上的函数(Y42)
***
***
***********************************************************
***********************************************************
***/
/**********************************************************
*** 触发动作命令
**********************************************************/
/**
* @brief 触发编码器校准 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Trig_Encoder_Cal(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x06; // 功能码
cmd[2] = 0x45; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 重启电机(Y42) - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Reset_Motor(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x08; // 功能码
cmd[2] = 0x97; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 将当前位置清零 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Reset_CurPos_To_Zero(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0A; // 功能码
cmd[2] = 0x6D; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 解除堵转保护 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Reset_Clog_Pro(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0E; // 功能码
cmd[2] = 0x52; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 恢复出厂设置 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Restore_Motor(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x0F; // 功能码
cmd[2] = 0x5F; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**********************************************************
*** 运动控制命令
**********************************************************/
/**
* @brief 使能信号控制 - 加载到多电机指令上
* @param addr :电机地址
* @param state :使能状态 ,true为使能电机,false为关闭电机
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_En_Control(uint8_t addr, bool state, bool snF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xF3; // 功能码
cmd[2] = 0xAB; // 辅助码
cmd[3] = (uint8_t)state; // 使能状态
cmd[4] = snF; // 多机同步运动标志
cmd[5] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 6; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 速度模式 - 加载到多电机指令上
* @param addr:电机地址
* @param dir :方向 ,0为CW,其余值为CCW
* @param vel :速度 ,范围0 - 5000RPM
* @param acc :加速度 ,范围0 - 255,注意:0是直接启动
* @param snF :多机同步标志,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Vel_Control(uint8_t addr, uint8_t dir, uint16_t vel, uint8_t acc, bool snF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xF6; // 功能码
cmd[2] = dir; // 方向
cmd[3] = (uint8_t)(vel >> 8); // 速度(RPM)高8位字节
cmd[4] = (uint8_t)(vel >> 0); // 速度(RPM)低8位字节
cmd[5] = acc; // 加速度,注意:0是直接启动
cmd[6] = snF; // 多机同步运动标志
cmd[7] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 8; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 位置模式 - 加载到多电机指令上
* @param addr:电机地址
* @param dir :方向 ,0为CW,其余值为CCW
* @param vel :速度(RPM) ,范围0 - 5000RPM
* @param acc :加速度 ,范围0 - 255,注意:0是直接启动
* @param clk :脉冲数 ,范围0- (2^32 - 1)个
* @param raF :相位/绝对标志,false为相对运动,true为绝对值运动
* @param snF :多机同步标志 ,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Pos_Control(uint8_t addr, uint8_t dir, uint16_t vel, uint8_t acc, uint32_t clk, bool raF, bool snF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFD; // 功能码
cmd[2] = dir; // 方向
cmd[3] = (uint8_t)(vel >> 8); // 速度(RPM)高8位字节
cmd[4] = (uint8_t)(vel >> 0); // 速度(RPM)低8位字节
cmd[5] = acc; // 加速度,注意:0是直接启动
cmd[6] = (uint8_t)(clk >> 24); // 脉冲数(bit24 - bit31)
cmd[7] = (uint8_t)(clk >> 16); // 脉冲数(bit16 - bit23)
cmd[8] = (uint8_t)(clk >> 8); // 脉冲数(bit8 - bit15)
cmd[9] = (uint8_t)(clk >> 0); // 脉冲数(bit0 - bit7 )
cmd[10] = raF; // 相位/绝对标志,false为相对运动,true为绝对值运动
cmd[11] = snF; // 多机同步运动标志,false为不启用,true为启用
cmd[12] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 13; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 立即停止 - 加载到多电机指令上
* @param addr :电机地址
* @param snF :多机同步标志,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Stop_Now(uint8_t addr, bool snF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFE; // 功能码
cmd[2] = 0x98; // 辅助码
cmd[3] = snF; // 多机同步运动标志
cmd[4] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 5; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 多机同步运动 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Synchronous_motion(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0xFF; // 功能码
cmd[2] = 0x66; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**********************************************************
*** 原点回零命令
**********************************************************/
/**
* @brief 设置单圈回零的零点位置 - 加载到多电机指令上
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Origin_Set_O(uint8_t addr, bool svF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x93; // 功能码
cmd[2] = 0x88; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 5; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 触发回零 - 加载到多电机指令上
* @param addr :电机地址
* @param o_mode :回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
* @param snF :多机同步标志,false为不启用,true为启用
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Origin_Trigger_Return(uint8_t addr, uint8_t o_mode, bool snF)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x9A; // 功能码
cmd[2] = o_mode; // 回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
cmd[3] = snF; // 多机同步运动标志,false为不启用,true为启用
cmd[4] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 5; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 强制中断并退出回零 - 加载到多电机指令上
* @param addr :电机地址
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Origin_Interrupt(uint8_t addr)
{
uint8_t j = 0, cmd[16] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x9C; // 功能码
cmd[2] = 0x48; // 辅助码
cmd[3] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 4; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 修改回零参数 - 加载到多电机指令上
* @param addr :电机地址
* @param svF :是否存储标志,false为不存储,true为存储
* @param o_mode :回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
* @param o_dir :回零方向,0为CW,其余值为CCW
* @param o_vel :回零速度,单位:RPM(转/分钟)
* @param o_tm :回零超时时间,单位:毫秒
* @param sl_vel :无限位碰撞回零检测转速,单位:RPM(转/分钟)
* @param sl_ma :无限位碰撞回零检测电流,单位:Ma(毫安)
* @param sl_ms :无限位碰撞回零检测时间,单位:Ms(毫秒)
* @param potF :上电自动触发回零,false为不使能,true为使能
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Origin_Modify_Params(uint8_t addr, bool svF, uint8_t o_mode, uint8_t o_dir, uint16_t o_vel, uint32_t o_tm, uint16_t sl_vel, uint16_t sl_ma, uint16_t sl_ms, bool potF)
{
uint8_t j = 0, cmd[32] = {0};
// 装载命令
cmd[0] = addr; // 地址
cmd[1] = 0x4C; // 功能码
cmd[2] = 0xAE; // 辅助码
cmd[3] = svF; // 是否存储标志,false为不存储,true为存储
cmd[4] = o_mode; // 回零模式,0为单圈就近回零,1为单圈方向回零,2为多圈无限位碰撞回零,3为多圈有限位开关回零
cmd[5] = o_dir; // 回零方向
cmd[6] = (uint8_t)(o_vel >> 8); // 回零速度(RPM)高8位字节
cmd[7] = (uint8_t)(o_vel >> 0); // 回零速度(RPM)低8位字节
cmd[8] = (uint8_t)(o_tm >> 24); // 回零超时时间(bit24 - bit31)
cmd[9] = (uint8_t)(o_tm >> 16); // 回零超时时间(bit16 - bit23)
cmd[10] = (uint8_t)(o_tm >> 8); // 回零超时时间(bit8 - bit15)
cmd[11] = (uint8_t)(o_tm >> 0); // 回零超时时间(bit0 - bit7 )
cmd[12] = (uint8_t)(sl_vel >> 8); // 无限位碰撞回零检测转速(RPM)高8位字节
cmd[13] = (uint8_t)(sl_vel >> 0); // 无限位碰撞回零检测转速(RPM)低8位字节
cmd[14] = (uint8_t)(sl_ma >> 8); // 无限位碰撞回零检测电流(Ma)高8位字节
cmd[15] = (uint8_t)(sl_ma >> 0); // 无限位碰撞回零检测电流(Ma)低8位字节
cmd[16] = (uint8_t)(sl_ms >> 8); // 无限位碰撞回零检测时间(Ms)高8位字节
cmd[17] = (uint8_t)(sl_ms >> 0); // 无限位碰撞回零检测时间(Ms)低8位字节
cmd[18] = potF; // 上电自动触发回零,false为不使能,true为使能
cmd[19] = 0x6B; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < 20; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**********************************************************
*** 读取系统参数命令
**********************************************************/
/**********************************************************
*** 读取系统参数命令
**********************************************************/
/**
* @brief 定时返回信息命令(Y42)
* @param addr :电机地址
* @param s :系统参数类型
* @param time_ms :定时时间
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Auto_Return_Sys_Params_Timed(uint8_t addr, SysParams_t s, uint16_t time_ms)
{
uint8_t i = 0, j = 0; uint8_t cmd[16] = {0};
// 装载命令
cmd[i] = addr; ++i; // 地址
cmd[i] = 0x11; ++i; // 功能码
cmd[i] = 0x18; ++i; // 辅助码
switch(s) // 信息功能码
{
case S_VBUS : cmd[i] = 0x24; ++i; break; // 读取总线电压
case S_CBUS : cmd[i] = 0x26; ++i; break; // 读取总线电流
case S_CPHA : cmd[i] = 0x27; ++i; break; // 读取相电流
case S_ENCO : cmd[i] = 0x29; ++i; break; // 读取编码器原始值
case S_CLKC : cmd[i] = 0x30; ++i; break; // 读取实时脉冲数
case S_ENCL : cmd[i] = 0x31; ++i; break; // 读取经过线性化校准后的编码器值
case S_CLKI : cmd[i] = 0x32; ++i; break; // 读取输入脉冲数
case S_TPOS : cmd[i] = 0x33; ++i; break; // 读取电机目标位置
case S_SPOS : cmd[i] = 0x34; ++i; break; // 读取电机实时设定的目标位置
case S_VEL : cmd[i] = 0x35; ++i; break; // 读取电机实时转速
case S_CPOS : cmd[i] = 0x36; ++i; break; // 读取电机实时位置
case S_PERR : cmd[i] = 0x37; ++i; break; // 读取电机位置误差
case S_VBAT : cmd[i] = 0x38; ++i; break; // 读取多圈编码器电池电压(Y42)
case S_TEMP : cmd[i] = 0x39; ++i; break; // 读取电机实时温度(Y42)
case S_FLAG : cmd[i] = 0x3A; ++i; break; // 读取电机状态标志位
case S_OFLAG: cmd[i] = 0x3B; ++i; break; // 读取回零状态标志位
case S_OAF : cmd[i] = 0x3C; ++i; break; // 读取电机状态标志位 + 回零状态标志位(Y42)
case S_PIN : cmd[i] = 0x3D; ++i; break; // 读取引脚状态(Y42)
default: break;
}
cmd[i] = (uint8_t)(time_ms >> 8); ++i; // 定时时间
cmd[i] = (uint8_t)(time_ms >> 0); ++i;
cmd[i] = 0x6B; ++i; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < i; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**
* @brief 读取系统参数 - 加载到多电机指令上
* @param addr :电机地址
* @param s :系统参数类型
* @retval 地址 + 功能码 + 命令状态 + 校验字节
*/
void X_V2_MMCL_Read_Sys_Params(uint8_t addr, SysParams_t s)
{
uint8_t i = 0, j = 0; uint8_t cmd[16] = {0};
// 装载命令
cmd[i] = addr; ++i; // 地址
switch(s) // 功能码
{
case S_VBUS : cmd[i] = 0x24; ++i; break; // 读取总线电压
case S_CBUS : cmd[i] = 0x26; ++i; break; // 读取总线电流
case S_CPHA : cmd[i] = 0x27; ++i; break; // 读取相电流
case S_ENCO : cmd[i] = 0x29; ++i; break; // 读取编码器原始值
case S_CLKC : cmd[i] = 0x30; ++i; break; // 读取实时脉冲数
case S_ENCL : cmd[i] = 0x31; ++i; break; // 读取经过线性化校准后的编码器值
case S_CLKI : cmd[i] = 0x32; ++i; break; // 读取输入脉冲数
case S_TPOS : cmd[i] = 0x33; ++i; break; // 读取电机目标位置
case S_SPOS : cmd[i] = 0x34; ++i; break; // 读取电机实时设定的目标位置
case S_VEL : cmd[i] = 0x35; ++i; break; // 读取电机实时转速
case S_CPOS : cmd[i] = 0x36; ++i; break; // 读取电机实时位置
case S_PERR : cmd[i] = 0x37; ++i; break; // 读取电机位置误差
case S_VBAT : cmd[i] = 0x38; ++i; break; // 读取多圈编码器电池电压(Y42)
case S_TEMP : cmd[i] = 0x39; ++i; break; // 读取电机实时温度(Y42)
case S_FLAG : cmd[i] = 0x3A; ++i; break; // 读取电机状态标志位
case S_OFLAG: cmd[i] = 0x3B; ++i; break; // 读取回零状态标志位
case S_OAF : cmd[i] = 0x3C; ++i; break; // 读取电机状态标志位 + 回零状态标志位(Y42)
case S_PIN : cmd[i] = 0x3D; ++i; break; // 读取引脚状态(Y42)
default: break;
}
cmd[i] = 0x6B; ++i; // 校验字节
// 加载当前命令到多电机命令中
for(j=0; j < i; j++) { MMCL_cmd[MMCL_count] = cmd[j]; ++MMCL_count; }
}
/**********************************************************
*** 读写驱动参数命令
**********************************************************/