添加均值滤波,修改HT电机控制方式,添加了一些文档
This commit is contained in:
parent
7403943814
commit
ff5028036a
|
@ -32,6 +32,7 @@
|
||||||
#include "master_process.h"
|
#include "master_process.h"
|
||||||
#include "daemon.h"
|
#include "daemon.h"
|
||||||
#include "robot.h"
|
#include "robot.h"
|
||||||
|
#include "HT04.h"
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
/* Private typedef -----------------------------------------------------------*/
|
||||||
|
@ -99,7 +100,8 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackTyp
|
||||||
* @param None
|
* @param None
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void MX_FREERTOS_Init(void) {
|
void MX_FREERTOS_Init(void)
|
||||||
|
{
|
||||||
/* USER CODE BEGIN Init */
|
/* USER CODE BEGIN Init */
|
||||||
|
|
||||||
/* USER CODE END Init */
|
/* USER CODE END Init */
|
||||||
|
@ -127,8 +129,9 @@ void MX_FREERTOS_Init(void) {
|
||||||
|
|
||||||
/* USER CODE BEGIN RTOS_THREADS */
|
/* USER CODE BEGIN RTOS_THREADS */
|
||||||
/* add threads, ... */
|
/* add threads, ... */
|
||||||
osThreadDef(instask, StartINSTASK, osPriorityNormal, 0, 1024);
|
osThreadDef(instask, StartINSTASK, osPriorityAboveNormal, 0, 1024);
|
||||||
insTaskHandle = osThreadCreate(osThread(instask), NULL);
|
insTaskHandle = osThreadCreate(osThread(instask), NULL); // 由于是阻塞读取传感器,为姿态解算设置较高优先级,确保以1khz的频率执行
|
||||||
|
// 后续修改为读取传感器数据准备好的中断处理,
|
||||||
|
|
||||||
osThreadDef(motortask, StartMOTORTASK, osPriorityNormal, 0, 256);
|
osThreadDef(motortask, StartMOTORTASK, osPriorityNormal, 0, 256);
|
||||||
motorTaskHandle = osThreadCreate(osThread(motortask), NULL);
|
motorTaskHandle = osThreadCreate(osThread(motortask), NULL);
|
||||||
|
@ -143,7 +146,6 @@ void MX_FREERTOS_Init(void) {
|
||||||
defaultTaskHandle = osThreadCreate(osThread(uitask), NULL);
|
defaultTaskHandle = osThreadCreate(osThread(uitask), NULL);
|
||||||
|
|
||||||
/* USER CODE END RTOS_THREADS */
|
/* USER CODE END RTOS_THREADS */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE BEGIN Header_StartDefaultTask */
|
/* USER CODE BEGIN Header_StartDefaultTask */
|
||||||
|
@ -170,13 +172,15 @@ void StartINSTASK(void const *argument)
|
||||||
{
|
{
|
||||||
// 1kHz
|
// 1kHz
|
||||||
INS_Task();
|
INS_Task();
|
||||||
VisionSend(); // 解算完æˆ<EFBFBD>å<EFBFBD>Žå<EFBFBD>‘é€<EFBFBD>视觉数æ<EFBFBD>?
|
VisionSend(); // 解算完成后发送视觉数<EFBFBD>?
|
||||||
osDelay(1);
|
osDelay(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartMOTORTASK(void const *argument)
|
void StartMOTORTASK(void const *argument)
|
||||||
{
|
{
|
||||||
|
// 若使用HT电机则取消本行注释
|
||||||
|
HTMotorControlInit();
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
// 500Hz
|
// 500Hz
|
||||||
|
|
|
@ -22,10 +22,13 @@ static osMutexId DWT_MUTEX;
|
||||||
* @brief 私有函数,用于检查DWT CYCCNT寄存器是否溢出,并更新CYCCNT_RountCount
|
* @brief 私有函数,用于检查DWT CYCCNT寄存器是否溢出,并更新CYCCNT_RountCount
|
||||||
* @attention 此函数假设两次调用之间的时间间隔不超过一次溢出
|
* @attention 此函数假设两次调用之间的时间间隔不超过一次溢出
|
||||||
*
|
*
|
||||||
|
* @todo 更好的方案是为dwt的时间更新单独设置一个任务
|
||||||
|
* 不过,使用dwt的初衷是定时不被中断/任务等因素影响,因此该实现仍然有其存在的意义
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
static void DWT_CNT_Update(void)
|
static void DWT_CNT_Update(void)
|
||||||
{
|
{
|
||||||
if (__get_CONTROL()) // 不在中断中,使用互斥锁;在中断则直接执行即可
|
if (__get_CONTROL()) // 不在中断中,使用互斥锁;在中断则直接执行即可,本框架将所有中断优先级设置为相同,故不会被其他中断重入
|
||||||
if (osOK != osMutexWait(DWT_MUTEX, 0))
|
if (osOK != osMutexWait(DWT_MUTEX, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -193,3 +193,17 @@ float Dot3d(float *v1, float *v2)
|
||||||
{
|
{
|
||||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 均值滤波,删除buffer中的最后一个元素,填入新的元素并求平均值
|
||||||
|
float AverageFilter(float new_data, float *buf, uint8_t len)
|
||||||
|
{
|
||||||
|
float sum = 0;
|
||||||
|
for (uint8_t i = 0; i < len - 1; i++)
|
||||||
|
{
|
||||||
|
buf[i] = buf[i + 1];
|
||||||
|
sum += buf[i];
|
||||||
|
}
|
||||||
|
buf[len - 1] = new_data;
|
||||||
|
sum += new_data;
|
||||||
|
return sum / len;
|
||||||
|
}
|
||||||
|
|
|
@ -12,20 +12,16 @@
|
||||||
*/
|
*/
|
||||||
#ifndef _USER_LIB_H
|
#ifndef _USER_LIB_H
|
||||||
#define _USER_LIB_H
|
#define _USER_LIB_H
|
||||||
|
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "cmsis_os.h"
|
#include "cmsis_os.h"
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
#define msin(x) (arm_sin_f32(x))
|
||||||
CHASSIS_DEBUG = 1,
|
#define mcos(x) (arm_cos_f32(x))
|
||||||
GIMBAL_DEBUG,
|
|
||||||
INS_DEBUG,
|
|
||||||
RC_DEBUG,
|
|
||||||
IMU_HEAT_DEBUG,
|
|
||||||
SHOOT_DEBUG,
|
|
||||||
AIMASSIST_DEBUG,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern uint8_t GlobalDebugMode;
|
extern uint8_t GlobalDebugMode;
|
||||||
|
|
||||||
|
@ -122,7 +118,8 @@ void Cross3d(float* v1, float* v2, float* res);
|
||||||
|
|
||||||
float Dot3d(float *v1, float *v2);
|
float Dot3d(float *v1, float *v2);
|
||||||
|
|
||||||
//<2F><><EFBFBD>ȸ<EFBFBD>ʽ<EFBFBD><CABD>Ϊ-PI~PI
|
float AverageFilter(float new_data, float *buf, uint8_t len);
|
||||||
|
|
||||||
#define rad_format(Ang) loop_float_constrain((Ang), -PI, PI)
|
#define rad_format(Ang) loop_float_constrain((Ang), -PI, PI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -99,7 +99,7 @@ attitude_t *INS_Init(void)
|
||||||
|
|
||||||
// noise of accel is relatively big and of high freq,thus lpf is used
|
// noise of accel is relatively big and of high freq,thus lpf is used
|
||||||
INS.AccelLPF = 0.0085;
|
INS.AccelLPF = 0.0085;
|
||||||
DWT_GetDeltaT64(&INS_DWT_Count);
|
DWT_GetDeltaT(&INS_DWT_Count);
|
||||||
return (attitude_t *)&INS.Gyro; // @todo: 这里偷懒了,不要这样做! 修改INT_t结构体可能会导致异常,待修复.
|
return (attitude_t *)&INS.Gyro; // @todo: 这里偷懒了,不要这样做! 修改INT_t结构体可能会导致异常,待修复.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ typedef struct
|
||||||
uint8_t led_alpha; // 透明度,通过pwm频率改变
|
uint8_t led_alpha; // 透明度,通过pwm频率改变
|
||||||
uint8_t led_brightness; // 亮度,通过电压改变(如果可以,使用dac)
|
uint8_t led_brightness; // 亮度,通过电压改变(如果可以,使用dac)
|
||||||
uint8_t led_color; // rgb value,0-255
|
uint8_t led_color; // rgb value,0-255
|
||||||
uint8_t led_switch // 开关,on1 off0
|
uint8_t led_switch; // 开关,on1 off0
|
||||||
// void (*action_callback)(void); // led动作回调函数
|
// void (*action_callback)(void); // led动作回调函数
|
||||||
} LEDInstance;
|
} LEDInstance;
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ static void DecodeDJIMotor(CANInstance *_instance)
|
||||||
RPM_2_ANGLE_PER_SEC * SPEED_SMOOTH_COEF * (float)((int16_t)(rxbuff[2] << 8 | rxbuff[3]));
|
RPM_2_ANGLE_PER_SEC * SPEED_SMOOTH_COEF * (float)((int16_t)(rxbuff[2] << 8 | rxbuff[3]));
|
||||||
measure->real_current = (1.0f - CURRENT_SMOOTH_COEF) * measure->real_current +
|
measure->real_current = (1.0f - CURRENT_SMOOTH_COEF) * measure->real_current +
|
||||||
CURRENT_SMOOTH_COEF * (float)((int16_t)(rxbuff[4] << 8 | rxbuff[5]));
|
CURRENT_SMOOTH_COEF * (float)((int16_t)(rxbuff[4] << 8 | rxbuff[5]));
|
||||||
measure->temperate = rxbuff[6];
|
measure->temperature = rxbuff[6];
|
||||||
|
|
||||||
// 多圈角度计算,前提是假设两次采样间电机转过的角度小于180°,自己画个图就清楚计算过程了
|
// 多圈角度计算,前提是假设两次采样间电机转过的角度小于180°,自己画个图就清楚计算过程了
|
||||||
if (measure->ecd - measure->last_ecd > 4096)
|
if (measure->ecd - measure->last_ecd > 4096)
|
||||||
|
@ -238,6 +238,7 @@ void DJIMotorControl()
|
||||||
pid_ref = motor_controller->pid_ref; // 保存设定值,防止motor_controller->pid_ref在计算过程中被修改
|
pid_ref = motor_controller->pid_ref; // 保存设定值,防止motor_controller->pid_ref在计算过程中被修改
|
||||||
if (motor_setting->motor_reverse_flag == MOTOR_DIRECTION_REVERSE)
|
if (motor_setting->motor_reverse_flag == MOTOR_DIRECTION_REVERSE)
|
||||||
pid_ref *= -1; // 设置反转
|
pid_ref *= -1; // 设置反转
|
||||||
|
|
||||||
// pid_ref会顺次通过被启用的闭环充当数据的载体
|
// pid_ref会顺次通过被启用的闭环充当数据的载体
|
||||||
// 计算位置环,只有启用位置环且外层闭环为位置时会计算速度环输出
|
// 计算位置环,只有启用位置环且外层闭环为位置时会计算速度环输出
|
||||||
if ((motor_setting->close_loop_type & ANGLE_LOOP) && motor_setting->outer_loop_type == ANGLE_LOOP)
|
if ((motor_setting->close_loop_type & ANGLE_LOOP) && motor_setting->outer_loop_type == ANGLE_LOOP)
|
||||||
|
@ -272,6 +273,9 @@ void DJIMotorControl()
|
||||||
pid_ref = PIDCalculate(&motor_controller->current_PID, measure->real_current, pid_ref);
|
pid_ref = PIDCalculate(&motor_controller->current_PID, measure->real_current, pid_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (motor_setting->feedback_reverse_flag == FEEDBACK_DIRECTION_REVERSE)
|
||||||
|
pid_ref *= -1;
|
||||||
|
|
||||||
// 获取最终输出
|
// 获取最终输出
|
||||||
set = (int16_t)pid_ref;
|
set = (int16_t)pid_ref;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef struct
|
||||||
float angle_single_round; // 单圈角度
|
float angle_single_round; // 单圈角度
|
||||||
float speed_aps; // 角速度,单位为:度/秒
|
float speed_aps; // 角速度,单位为:度/秒
|
||||||
int16_t real_current; // 实际电流
|
int16_t real_current; // 实际电流
|
||||||
uint8_t temperate; // 温度 Celsius
|
uint8_t temperature; // 温度 Celsius
|
||||||
|
|
||||||
float total_angle; // 总角度,注意方向
|
float total_angle; // 总角度,注意方向
|
||||||
int32_t total_round; // 总圈数,注意方向
|
int32_t total_round; // 总圈数,注意方向
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
#include "HT04.h"
|
#include "HT04.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "general_def.h"
|
#include "general_def.h"
|
||||||
#include "bsp_dwt.h"
|
#include "user_lib.h"
|
||||||
|
#include "cmsis_os.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "daemon.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
static uint8_t idx;
|
static uint8_t idx;
|
||||||
HTMotorInstance *ht_motor_instance[HT_MOTOR_CNT];
|
static HTMotorInstance *ht_motor_instance[HT_MOTOR_CNT];
|
||||||
|
static osThreadId ht_task_handle[HT_MOTOR_CNT];
|
||||||
|
static uint8_t zero_buff[6] = {0};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置电机模式,报文内容[0xff,0xff,0xff,0xff,0xff,0xff,0xff,cmd]
|
* @brief 设置电机模式,报文内容[0xff,0xff,0xff,0xff,0xff,0xff,0xff,cmd]
|
||||||
|
@ -17,9 +23,8 @@ static void HTMotorSetMode(HTMotor_Mode_t cmd, HTMotorInstance *motor)
|
||||||
memset(motor->motor_can_instace->tx_buff, 0xff, 7); // 发送电机指令的时候前面7bytes都是0xff
|
memset(motor->motor_can_instace->tx_buff, 0xff, 7); // 发送电机指令的时候前面7bytes都是0xff
|
||||||
motor->motor_can_instace->tx_buff[7] = (uint8_t)cmd; // 最后一位是命令id
|
motor->motor_can_instace->tx_buff[7] = (uint8_t)cmd; // 最后一位是命令id
|
||||||
CANTransmit(motor->motor_can_instace, 1);
|
CANTransmit(motor->motor_can_instace, 1);
|
||||||
memset(motor->motor_can_instace->tx_buff, 0, 6); // 发送控制指令的时候前面6bytes都是0
|
memcpy(motor->motor_can_instace->tx_buff, zero_buff, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 两个用于将uint值和float值进行映射的函数,在设定发送值和解析反馈值时使用 */
|
/* 两个用于将uint值和float值进行映射的函数,在设定发送值和解析反馈值时使用 */
|
||||||
static uint16_t float_to_uint(float x, float x_min, float x_max, uint8_t bits)
|
static uint16_t float_to_uint(float x, float x_min, float x_max, uint8_t bits)
|
||||||
{
|
{
|
||||||
|
@ -43,28 +48,60 @@ static void HTMotorDecode(CANInstance *motor_can)
|
||||||
{
|
{
|
||||||
uint16_t tmp; // 用于暂存解析值,稍后转换成float数据,避免多次创建临时变量
|
uint16_t tmp; // 用于暂存解析值,稍后转换成float数据,避免多次创建临时变量
|
||||||
uint8_t *rxbuff = motor_can->rx_buff;
|
uint8_t *rxbuff = motor_can->rx_buff;
|
||||||
HTMotor_Measure_t *measure = &((HTMotorInstance *)motor_can->id)->measure; // 将can实例中保存的id转换成电机实例的指针
|
HTMotorInstance *motor = (HTMotorInstance *)motor_can->id;
|
||||||
measure->feedback_dt = DWT_GetDeltaT(&measure->count);
|
HTMotor_Measure_t *measure = &(motor->measure); // 将can实例中保存的id转换成电机实例的指针
|
||||||
|
|
||||||
|
DaemonReload(motor->motor_daemon);
|
||||||
|
measure->feed_dt = DWT_GetDeltaT(&measure->feed_cnt);
|
||||||
|
|
||||||
measure->last_angle = measure->total_angle;
|
measure->last_angle = measure->total_angle;
|
||||||
tmp = (uint16_t)((rxbuff[1] << 8) | rxbuff[2]);
|
tmp = (uint16_t)((rxbuff[1] << 8) | rxbuff[2]);
|
||||||
measure->total_angle = uint_to_float(tmp, P_MIN, P_MAX, 16) - measure->angle_bias;
|
measure->total_angle = uint_to_float(tmp, P_MIN, P_MAX, 16);
|
||||||
|
|
||||||
measure->speed_rads = // SPEED_SMOOTH_COEF * measure->speed_rads + (1 - SPEED_SMOOTH_COEF) *
|
tmp = (uint16_t)(rxbuff[3] << 4) | (rxbuff[4] >> 4);
|
||||||
(measure->total_angle - measure->last_angle) / measure->feedback_dt;
|
measure->speed_rads = AverageFilter((uint_to_float(tmp, V_MIN, V_MAX, 12) - HT_SPEED_BIAS), measure->speed_buff, SPEED_BUFFER_SIZE);
|
||||||
|
|
||||||
|
tmp = (uint16_t)(((rxbuff[4] & 0x0f) << 8) | rxbuff[5]);
|
||||||
|
measure->real_current = CURRENT_SMOOTH_COEF * uint_to_float(tmp, T_MIN, T_MAX, 12) +
|
||||||
|
(1 - CURRENT_SMOOTH_COEF) * measure->real_current;
|
||||||
|
|
||||||
measure->real_current = uint_to_float(((uint16_t)(rxbuff[3] << 4) | (uint16_t)(rxbuff[4] >> 4)), V_MIN, V_MAX, 12);
|
|
||||||
|
|
||||||
if (!measure->first_feedback_flag) // 初始化的时候设置偏置
|
|
||||||
{
|
|
||||||
measure->first_feedback_flag = 1;
|
|
||||||
measure->angle_bias = measure->total_angle;
|
|
||||||
measure->total_angle = 0;
|
|
||||||
measure->speed_rads = 0;
|
|
||||||
DWT_GetDeltaT(&measure->count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// measure->real_current = uint_to_float((rxbuff[3] << 8) | rxbuff[4], I_MIN, I_MAX, 16);
|
static void HTMotorLostCallback(void *motor_ptr)
|
||||||
|
{
|
||||||
|
HTMotorInstance *motor = (HTMotorInstance *)motor_ptr;
|
||||||
|
if (motor->stop_flag == MOTOR_STOP)
|
||||||
|
return;
|
||||||
|
if (++motor->lost_cnt % 10 != 0)
|
||||||
|
HTMotorSetMode(CMD_MOTOR_MODE, motor); // 若不在停止模式,尝试重新让电机进入控制模式
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 海泰电机一生黑,什么垃圾协议! */
|
||||||
|
void HTMotorCalibEncoder(HTMotorInstance *motor)
|
||||||
|
{
|
||||||
|
uint16_t p, v, kp, kd, t;
|
||||||
|
p = float_to_uint(0, P_MIN, P_MAX, 16);
|
||||||
|
v = float_to_uint(0, V_MIN, V_MAX, 12);
|
||||||
|
kp = float_to_uint(0, KP_MIN, KP_MAX, 12);
|
||||||
|
kd = float_to_uint(0, KD_MIN, KD_MAX, 12);
|
||||||
|
t = float_to_uint(0, T_MIN, T_MAX, 12);
|
||||||
|
|
||||||
|
uint8_t *buf = motor->motor_can_instace->tx_buff;
|
||||||
|
buf[0] = p >> 8;
|
||||||
|
buf[1] = p & 0xFF;
|
||||||
|
buf[2] = v >> 4;
|
||||||
|
buf[3] = ((v & 0xF) << 4) | (kp >> 8);
|
||||||
|
buf[4] = kp & 0xFF;
|
||||||
|
buf[5] = kd >> 4;
|
||||||
|
buf[6] = ((kd & 0xF) << 4) | (t >> 8);
|
||||||
|
buf[7] = t & 0xff;
|
||||||
|
memcpy(zero_buff, buf, 6); // 初始化的时候至少调用一次,故将其他指令为0时发送的报文保存一下,详见ht04电机说明
|
||||||
|
CANTransmit(motor->motor_can_instace, 1);
|
||||||
|
DWT_Delay(0.005);
|
||||||
|
HTMotorSetMode(CMD_ZERO_POSITION, motor);
|
||||||
|
DWT_Delay(0.005);
|
||||||
|
// HTMotorSetMode(CMD_MOTOR_MODE, motor);
|
||||||
}
|
}
|
||||||
|
|
||||||
HTMotorInstance *HTMotorInit(Motor_Init_Config_s *config)
|
HTMotorInstance *HTMotorInit(Motor_Init_Config_s *config)
|
||||||
|
@ -83,34 +120,43 @@ HTMotorInstance *HTMotorInit(Motor_Init_Config_s *config)
|
||||||
config->can_init_config.id = motor;
|
config->can_init_config.id = motor;
|
||||||
motor->motor_can_instace = CANRegister(&config->can_init_config);
|
motor->motor_can_instace = CANRegister(&config->can_init_config);
|
||||||
|
|
||||||
|
Daemon_Init_Config_s conf = {
|
||||||
|
.callback = HTMotorLostCallback,
|
||||||
|
.owner_id = motor,
|
||||||
|
.reload_count = 5, // 20ms
|
||||||
|
};
|
||||||
|
motor->motor_daemon = DaemonRegister(&conf);
|
||||||
|
|
||||||
HTMotorEnable(motor);
|
HTMotorEnable(motor);
|
||||||
|
HTMotorSetMode(CMD_MOTOR_MODE, motor); // 确保电机已经上电并执行电机模式
|
||||||
|
DWT_Delay(0.05);
|
||||||
|
HTMotorCalibEncoder(motor); // 将当前编码器位置作为零位
|
||||||
|
DWT_Delay(0.05); // 保证下一个电机发送时CAN是空闲的,注意应用在初始化模块的时候不应该进入中断
|
||||||
ht_motor_instance[idx++] = motor;
|
ht_motor_instance[idx++] = motor;
|
||||||
return motor;
|
return motor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMotorSetRef(HTMotorInstance *motor, float ref)
|
void HTMotorSetRef(HTMotorInstance *motor, float ref)
|
||||||
{
|
{
|
||||||
motor->pid_ref = ref * 0.285f;
|
motor->pid_ref = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMotorControl()
|
/**
|
||||||
|
* @brief 为了避免总线堵塞,为每个电机创建一个发送任务
|
||||||
|
* @param argument 传入的电机指针
|
||||||
|
*/
|
||||||
|
void HTMotorTask(void const *argument)
|
||||||
{
|
{
|
||||||
float set, pid_measure, pid_ref;
|
float set, pid_measure, pid_ref;
|
||||||
|
HTMotorInstance *motor = (HTMotorInstance *)argument;
|
||||||
|
HTMotor_Measure_t *measure = &motor->measure;
|
||||||
|
Motor_Control_Setting_s *setting = &motor->motor_settings;
|
||||||
|
CANInstance *motor_can = motor->motor_can_instace;
|
||||||
uint16_t tmp;
|
uint16_t tmp;
|
||||||
HTMotorInstance *motor;
|
|
||||||
HTMotor_Measure_t *measure;
|
|
||||||
Motor_Control_Setting_s *setting;
|
|
||||||
CANInstance *motor_can;
|
|
||||||
|
|
||||||
// 遍历所有电机实例,计算PID
|
while (1)
|
||||||
for (size_t i = 0; i < idx; i++)
|
{
|
||||||
{ // 先获取地址避免反复寻址
|
|
||||||
motor = ht_motor_instance[i];
|
|
||||||
measure = &motor->measure;
|
|
||||||
setting = &motor->motor_settings;
|
|
||||||
motor_can = motor->motor_can_instace;
|
|
||||||
pid_ref = motor->pid_ref;
|
pid_ref = motor->pid_ref;
|
||||||
|
|
||||||
if ((setting->close_loop_type & ANGLE_LOOP) && setting->outer_loop_type == ANGLE_LOOP)
|
if ((setting->close_loop_type & ANGLE_LOOP) && setting->outer_loop_type == ANGLE_LOOP)
|
||||||
{
|
{
|
||||||
if (setting->angle_feedback_source == OTHER_FEED)
|
if (setting->angle_feedback_source == OTHER_FEED)
|
||||||
|
@ -145,36 +191,47 @@ void HTMotorControl()
|
||||||
if (setting->motor_reverse_flag == MOTOR_DIRECTION_REVERSE)
|
if (setting->motor_reverse_flag == MOTOR_DIRECTION_REVERSE)
|
||||||
set *= -1;
|
set *= -1;
|
||||||
|
|
||||||
LIMIT_MIN_MAX(set, T_MIN, T_MAX); // 限幅,实际上这似乎和pid输出限幅重复了
|
LIMIT_MIN_MAX(set, T_MIN, T_MAX);
|
||||||
tmp = float_to_uint(set, T_MIN, T_MAX, 12); // 数值最后在 -12~+12之间
|
tmp = float_to_uint(set, T_MIN, T_MAX, 12);
|
||||||
if (motor->stop_flag == MOTOR_STOP)
|
if (motor->stop_flag == MOTOR_STOP)
|
||||||
tmp = float_to_uint(0, T_MIN, T_MAX, 12);
|
tmp = float_to_uint(0, T_MIN, T_MAX, 12);
|
||||||
motor_can->tx_buff[6] = (tmp >> 8);
|
motor_can->tx_buff[6] = (tmp >> 8);
|
||||||
motor_can->tx_buff[7] = tmp & 0xff;
|
motor_can->tx_buff[7] = tmp & 0xff;
|
||||||
|
|
||||||
CANTransmit(motor_can, 1);
|
CANTransmit(motor_can, 0.5);
|
||||||
|
|
||||||
|
osDelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTMotorControlInit()
|
||||||
|
{
|
||||||
|
char ht_task_name[5] = "ht";
|
||||||
|
// 遍历所有电机实例,创建任务
|
||||||
|
if (!idx)
|
||||||
|
return;
|
||||||
|
for (size_t i = 0; i < idx; i++)
|
||||||
|
{
|
||||||
|
char ht_id_buff[2] = {0};
|
||||||
|
__itoa(i, ht_id_buff, 10);
|
||||||
|
strcat(ht_task_name, ht_id_buff); // 似乎没什么吊用,osthreaddef会把第一个变量当作宏字符串传入,作为任务名
|
||||||
|
// todo 还需要一个更优雅的方案来区分不同的电机任务
|
||||||
|
osThreadDef(ht_task_name, HTMotorTask, osPriorityNormal, 0, 128);
|
||||||
|
ht_task_handle[i] = osThreadCreate(osThread(ht_task_name), ht_motor_instance[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMotorStop(HTMotorInstance *motor)
|
void HTMotorStop(HTMotorInstance *motor)
|
||||||
{
|
{
|
||||||
if (motor->stop_flag == MOTOR_STOP)
|
|
||||||
return;
|
|
||||||
HTMotorSetMode(CMD_RESET_MODE, motor);
|
|
||||||
HTMotorSetMode(CMD_RESET_MODE, motor); // 发两次,确保电机停止
|
|
||||||
motor->stop_flag = MOTOR_STOP;
|
motor->stop_flag = MOTOR_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMotorEnable(HTMotorInstance *motor)
|
void HTMotorEnable(HTMotorInstance *motor)
|
||||||
{
|
{
|
||||||
if (motor->stop_flag == MOTOR_ENALBED)
|
|
||||||
return;
|
|
||||||
HTMotorSetMode(CMD_MOTOR_MODE, motor);
|
|
||||||
HTMotorSetMode(CMD_MOTOR_MODE, motor);
|
|
||||||
motor->stop_flag = MOTOR_ENALBED;
|
motor->stop_flag = MOTOR_ENALBED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// void HTMotorCalibEncoder(HTMotorInstance *motor)
|
void HTMotorOuterLoop(HTMotorInstance *motor, Closeloop_Type_e type)
|
||||||
// {
|
{
|
||||||
// HTMotorSetMode(CMD_ZERO_POSITION, motor);
|
motor->motor_settings.outer_loop_type = type;
|
||||||
// }
|
}
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
#include "bsp_can.h"
|
#include "bsp_can.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "motor_def.h"
|
#include "motor_def.h"
|
||||||
|
#include "daemon.h"
|
||||||
|
|
||||||
#define HT_MOTOR_CNT 4
|
#define HT_MOTOR_CNT 4
|
||||||
#define CURRENT_SMOOTH_COEF 0.9f
|
#define CURRENT_SMOOTH_COEF 0.9f
|
||||||
#define SPEED_SMOOTH_COEF 0.85f
|
#define SPEED_BUFFER_SIZE 5
|
||||||
|
#define HT_SPEED_BIAS -0.0109901428f // 电机速度偏差,单位rad/s
|
||||||
|
|
||||||
#define P_MIN -95.5f // Radians
|
#define P_MIN -95.5f // Radians
|
||||||
#define P_MAX 95.5f
|
#define P_MAX 95.5f
|
||||||
|
@ -16,18 +18,23 @@
|
||||||
#define V_MAX 45.0f
|
#define V_MAX 45.0f
|
||||||
#define T_MIN -18.0f // N·m
|
#define T_MIN -18.0f // N·m
|
||||||
#define T_MAX 18.0f
|
#define T_MAX 18.0f
|
||||||
|
#define KP_MIN 0.0f // N-m/rad
|
||||||
|
#define KP_MAX 500.0f
|
||||||
|
#define KD_MIN 0.0f // N-m/rad/s
|
||||||
|
#define KD_MAX 5.0f
|
||||||
|
|
||||||
typedef struct // HT04
|
typedef struct // HT04
|
||||||
{
|
{
|
||||||
float total_angle; // 角度为多圈角度,范围是-95.5~95.5,单位为rad
|
float total_angle; // 角度为多圈角度,范围是-95.5~95.5,单位为rad
|
||||||
float last_angle;
|
float last_angle;
|
||||||
float speed_rads;
|
|
||||||
float real_current;
|
|
||||||
float angle_bias;
|
|
||||||
uint8_t first_feedback_flag;
|
|
||||||
|
|
||||||
float feedback_dt;
|
float speed_rads;
|
||||||
uint32_t count;
|
float speed_buff[SPEED_BUFFER_SIZE];
|
||||||
|
|
||||||
|
float real_current;
|
||||||
|
|
||||||
|
float feed_dt;
|
||||||
|
uint32_t feed_cnt;
|
||||||
} HTMotor_Measure_t;
|
} HTMotor_Measure_t;
|
||||||
|
|
||||||
/* HT电机类型定义*/
|
/* HT电机类型定义*/
|
||||||
|
@ -49,6 +56,9 @@ typedef struct
|
||||||
Motor_Working_Type_e stop_flag; // 启停标志
|
Motor_Working_Type_e stop_flag; // 启停标志
|
||||||
|
|
||||||
CANInstance *motor_can_instace;
|
CANInstance *motor_can_instace;
|
||||||
|
|
||||||
|
DaemonInstance *motor_daemon;
|
||||||
|
uint32_t lost_cnt;
|
||||||
} HTMotorInstance;
|
} HTMotorInstance;
|
||||||
|
|
||||||
/* HT电机模式,初始化时自动进入CMD_MOTOR_MODE*/
|
/* HT电机模式,初始化时自动进入CMD_MOTOR_MODE*/
|
||||||
|
@ -76,10 +86,10 @@ HTMotorInstance *HTMotorInit(Motor_Init_Config_s *config);
|
||||||
void HTMotorSetRef(HTMotorInstance *motor, float ref);
|
void HTMotorSetRef(HTMotorInstance *motor, float ref);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 给所有的HT电机发送控制指令
|
* @brief 初始化电机任务,若要使用,需要在motortask的死循环前调用
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void HTMotorControl();
|
void HTMotorControlInit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 停止电机,之后电机不会响应HTMotorSetRef设定的值
|
* @brief 停止电机,之后电机不会响应HTMotorSetRef设定的值
|
||||||
|
@ -96,7 +106,15 @@ void HTMotorStop(HTMotorInstance *motor);
|
||||||
void HTMotorEnable(HTMotorInstance *motor);
|
void HTMotorEnable(HTMotorInstance *motor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 校准电机编码器,设置的当前位置为0
|
* @brief 修改电机闭环对象
|
||||||
|
*
|
||||||
|
* @param motor
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
void HTMotorOuterLoop(HTMotorInstance *motor, Closeloop_Type_e type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将当前编码器位置置零
|
||||||
*
|
*
|
||||||
* @param motor
|
* @param motor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,8 +9,34 @@
|
||||||
|
|
||||||
请注意发送和反馈数据的**单位**。
|
请注意发送和反馈数据的**单位**。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> ~~HT的电机协议做的真不行,纯纯直接抄mit还抄不明白,之后全部换成LK!~~
|
> ~~HT的电机协议做的真不行,纯纯直接抄mit还抄不明白,之后全部换成LK!~~
|
||||||
|
|
||||||
|
另一种上电时校准编码器的方法:
|
||||||
|
|
||||||
|
```c
|
||||||
|
static void HTMotorDecode(CANInstance *motor_can)
|
||||||
|
{
|
||||||
|
uint16_t tmp; // 用于暂存解析值,稍后转换成float数据,避免多次创建临时变量
|
||||||
|
uint8_t *rxbuff = motor_can->rx_buff;
|
||||||
|
HTMotor_Measure_t *measure = &((HTMotorInstance *)motor_can->id)->measure; // 将can实例中保存的id转换成电机实例的指针
|
||||||
|
|
||||||
|
measure->last_angle = measure->total_angle;
|
||||||
|
tmp = (uint16_t)((rxbuff[1] << 8) | rxbuff[2]);
|
||||||
|
measure->total_angle = uint_to_float(tmp, P_MIN, P_MAX, 16) - measure->angle_bias;
|
||||||
|
|
||||||
|
tmp = (uint16_t)(rxbuff[3] << 4) | (rxbuff[4] >> 4);
|
||||||
|
measure->speed_rads = AverageFilter((uint_to_float(tmp, V_MIN, V_MAX, 12) - HT_SPEED_BIAS), measure->speed_buff, SPEED_BUFFER_SIZE);
|
||||||
|
|
||||||
|
tmp = (uint16_t)(((rxbuff[4] & 0x0f) << 8) | rxbuff[5]);
|
||||||
|
measure->real_current = CURRENT_SMOOTH_COEF * uint_to_float(tmp, T_MIN, T_MAX, 12) +
|
||||||
|
(1 - CURRENT_SMOOTH_COEF) * measure->real_current;
|
||||||
|
|
||||||
|
if (!measure->first_feedback_flag) // 初始化的时候设置偏置
|
||||||
|
{
|
||||||
|
measure->first_feedback_flag = 1;
|
||||||
|
measure->angle_bias = measure->total_angle;
|
||||||
|
measure->total_angle = 0;
|
||||||
|
measure->speed_rads = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "LK9025.h"
|
#include "LK9025.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "general_def.h"
|
#include "general_def.h"
|
||||||
|
#include "daemon.h"
|
||||||
|
#include "bsp_dwt.h"
|
||||||
|
|
||||||
static uint8_t idx;
|
static uint8_t idx;
|
||||||
static LKMotorInstance *lkmotor_instance[LK_MOTOR_MX_CNT] = {NULL};
|
static LKMotorInstance *lkmotor_instance[LK_MOTOR_MX_CNT] = {NULL};
|
||||||
|
@ -14,10 +16,12 @@ static CANInstance *sender_instance; // 多电机发送时使用的caninstance(
|
||||||
*/
|
*/
|
||||||
static void LKMotorDecode(CANInstance *_instance)
|
static void LKMotorDecode(CANInstance *_instance)
|
||||||
{
|
{
|
||||||
LKMotor_Measure_t *measure;
|
LKMotorInstance *motor = (LKMotorInstance *)_instance->id; // 通过caninstance保存的father id获取对应的motorinstance
|
||||||
uint8_t *rx_buff;
|
LKMotor_Measure_t *measure = &motor->measure;
|
||||||
rx_buff = _instance->rx_buff;
|
uint8_t *rx_buff = _instance->rx_buff;
|
||||||
measure = &(((LKMotorInstance *)_instance->id)->measure); // 通过caninstance保存的id获取对应的motorinstance
|
|
||||||
|
DaemonReload(motor->daemon); // 喂狗
|
||||||
|
measure->feed_dt = DWT_GetDeltaT(&measure->feed_dwt_cnt);
|
||||||
|
|
||||||
measure->last_ecd = measure->ecd;
|
measure->last_ecd = measure->ecd;
|
||||||
measure->ecd = (uint16_t)((rx_buff[7] << 8) | rx_buff[6]);
|
measure->ecd = (uint16_t)((rx_buff[7] << 8) | rx_buff[6]);
|
||||||
|
@ -30,12 +34,11 @@ static void LKMotorDecode(CANInstance *_instance)
|
||||||
measure->real_current = (1 - CURRENT_SMOOTH_COEF) * measure->real_current +
|
measure->real_current = (1 - CURRENT_SMOOTH_COEF) * measure->real_current +
|
||||||
CURRENT_SMOOTH_COEF * (float)((int16_t)(rx_buff[3] << 8 | rx_buff[2]));
|
CURRENT_SMOOTH_COEF * (float)((int16_t)(rx_buff[3] << 8 | rx_buff[2]));
|
||||||
|
|
||||||
measure->temperate = rx_buff[1];
|
measure->temperature = rx_buff[1];
|
||||||
|
|
||||||
// 计算多圈角度
|
if (measure->ecd - measure->last_ecd > 32768)
|
||||||
if (measure->ecd - measure->last_ecd > 32678)
|
|
||||||
measure->total_round--;
|
measure->total_round--;
|
||||||
else if (measure->ecd - measure->last_ecd < -32678)
|
else if (measure->ecd - measure->last_ecd < -32768)
|
||||||
measure->total_round++;
|
measure->total_round++;
|
||||||
measure->total_angle = measure->total_round * 360 + measure->angle_single_round;
|
measure->total_angle = measure->total_round * 360 + measure->angle_single_round;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +69,16 @@ LKMotorInstance *LKMotorInit(Motor_Init_Config_s *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
LKMotorEnable(motor);
|
LKMotorEnable(motor);
|
||||||
|
DWT_GetDeltaT(&motor->measure.feed_dwt_cnt);
|
||||||
lkmotor_instance[idx++] = motor;
|
lkmotor_instance[idx++] = motor;
|
||||||
|
|
||||||
|
Daemon_Init_Config_s daemon_config = {
|
||||||
|
.callback = NULL,
|
||||||
|
.owner_id = motor,
|
||||||
|
.reload_count = 5, // 0.05秒
|
||||||
|
};
|
||||||
|
motor->daemon = DaemonRegister(&daemon_config);
|
||||||
|
|
||||||
return motor;
|
return motor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +103,7 @@ void LKMotorControl()
|
||||||
if (setting->angle_feedback_source == OTHER_FEED)
|
if (setting->angle_feedback_source == OTHER_FEED)
|
||||||
pid_measure = *motor->other_angle_feedback_ptr;
|
pid_measure = *motor->other_angle_feedback_ptr;
|
||||||
else
|
else
|
||||||
pid_measure = measure->total_angle;
|
pid_measure = measure->real_current;
|
||||||
pid_ref = PIDCalculate(&motor->angle_PID, pid_measure, pid_ref);
|
pid_ref = PIDCalculate(&motor->angle_PID, pid_measure, pid_ref);
|
||||||
if (setting->feedforward_flag & SPEED_FEEDFORWARD)
|
if (setting->feedforward_flag & SPEED_FEEDFORWARD)
|
||||||
pid_ref += *motor->speed_feedforward_ptr;
|
pid_ref += *motor->speed_feedforward_ptr;
|
||||||
|
@ -104,10 +116,10 @@ void LKMotorControl()
|
||||||
else
|
else
|
||||||
pid_measure = measure->speed_rads;
|
pid_measure = measure->speed_rads;
|
||||||
pid_ref = PIDCalculate(&motor->angle_PID, pid_measure, pid_ref);
|
pid_ref = PIDCalculate(&motor->angle_PID, pid_measure, pid_ref);
|
||||||
}
|
|
||||||
|
|
||||||
if (setting->feedforward_flag & CURRENT_FEEDFORWARD)
|
if (setting->feedforward_flag & CURRENT_FEEDFORWARD)
|
||||||
pid_ref += *motor->current_feedforward_ptr;
|
pid_ref += *motor->current_feedforward_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (setting->close_loop_type & CURRENT_LOOP)
|
if (setting->close_loop_type & CURRENT_LOOP)
|
||||||
{
|
{
|
||||||
pid_ref = PIDCalculate(&motor->current_PID, measure->real_current, pid_ref);
|
pid_ref = PIDCalculate(&motor->current_PID, measure->real_current, pid_ref);
|
||||||
|
@ -126,9 +138,7 @@ void LKMotorControl()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx) // 如果有电机注册了
|
if (idx) // 如果有电机注册了
|
||||||
{
|
CANTransmit(sender_instance, 0.2);
|
||||||
CANTransmit(sender_instance, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LKMotorStop(LKMotorInstance *motor)
|
void LKMotorStop(LKMotorInstance *motor)
|
||||||
|
@ -145,3 +155,8 @@ void LKMotorSetRef(LKMotorInstance *motor, float ref)
|
||||||
{
|
{
|
||||||
motor->pid_ref = ref;
|
motor->pid_ref = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t LKMotorIsOnline(LKMotorInstance *motor)
|
||||||
|
{
|
||||||
|
return DaemonIsOnline(motor->daemon);
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "bsp_can.h"
|
#include "bsp_can.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "motor_def.h"
|
#include "motor_def.h"
|
||||||
|
#include "daemon.h"
|
||||||
|
|
||||||
#define LK_MOTOR_MX_CNT 4 // 最多允许4个LK电机使用多电机指令,挂载在一条总线上
|
#define LK_MOTOR_MX_CNT 4 // 最多允许4个LK电机使用多电机指令,挂载在一条总线上
|
||||||
|
|
||||||
|
@ -23,11 +24,13 @@ typedef struct // 9025
|
||||||
float angle_single_round; // 单圈角度
|
float angle_single_round; // 单圈角度
|
||||||
float speed_rads; // speed rad/s
|
float speed_rads; // speed rad/s
|
||||||
int16_t real_current; // 实际电流
|
int16_t real_current; // 实际电流
|
||||||
uint8_t temperate; // 温度,C°
|
uint8_t temperature; // 温度,C°
|
||||||
|
|
||||||
float total_angle; // 总角度
|
float total_angle; // 总角度
|
||||||
int32_t total_round; // 总圈数
|
int32_t total_round; // 总圈数
|
||||||
|
|
||||||
|
float feed_dt;
|
||||||
|
uint32_t feed_dwt_cnt;
|
||||||
} LKMotor_Measure_t;
|
} LKMotor_Measure_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -49,6 +52,8 @@ typedef struct
|
||||||
|
|
||||||
CANInstance *motor_can_ins;
|
CANInstance *motor_can_ins;
|
||||||
|
|
||||||
|
DaemonInstance *daemon;
|
||||||
|
|
||||||
} LKMotorInstance;
|
} LKMotorInstance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,4 +93,6 @@ void LKMotorStop(LKMotorInstance *motor);
|
||||||
*/
|
*/
|
||||||
void LKMotorEnable(LKMotorInstance *motor);
|
void LKMotorEnable(LKMotorInstance *motor);
|
||||||
|
|
||||||
|
uint8_t LKMotorIsOnline(LKMotorInstance *motor);
|
||||||
|
|
||||||
#endif // LK9025_H
|
#endif // LK9025_H
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
#include "step_motor.h"
|
#include "step_motor.h"
|
||||||
#include "servo_motor.h"
|
#include "servo_motor.h"
|
||||||
|
|
||||||
|
|
||||||
void MotorControlTask()
|
void MotorControlTask()
|
||||||
{
|
{
|
||||||
// static uint8_t cnt = 0; 设定任务频率
|
// static uint8_t cnt = 0; 设定不同电机的任务频率
|
||||||
// if(cnt%5==0) //200hz
|
// if(cnt%5==0) //200hz
|
||||||
// if(cnt%10==0) //100hz
|
// if(cnt%10==0) //100hz
|
||||||
DJIMotorControl();
|
DJIMotorControl();
|
||||||
|
@ -16,10 +15,13 @@ void MotorControlTask()
|
||||||
/* 如果有对应的电机则取消注释,可以加入条件编译或者register对应的idx判断是否注册了电机 */
|
/* 如果有对应的电机则取消注释,可以加入条件编译或者register对应的idx判断是否注册了电机 */
|
||||||
LKMotorControl();
|
LKMotorControl();
|
||||||
|
|
||||||
HTMotorControl();
|
// legacy support
|
||||||
|
// 由于ht04电机的反馈方式为接收到一帧消息后立刻回传,以此方式连续发送可能导致总线拥塞
|
||||||
|
// 为了保证高频率控制,HTMotor中提供了以任务方式启动控制的接口,可通过宏定义切换
|
||||||
|
// HTMotorControl();
|
||||||
|
// 将所有的CAN设备集中在一处发送,最高反馈频率仅能达到500Hz,为了更好的控制效果,应使用新的HTMotorControlInit()接口
|
||||||
|
|
||||||
ServeoMotorControl();
|
ServeoMotorControl();
|
||||||
|
|
||||||
// StepMotorControl();
|
// StepMotorControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue