Files
FDR-Core/Core/Src/motor.c

332 lines
10 KiB
C
Raw Normal View History

2026-03-08 18:17:14 +08:00
#include "motor.h"
2026-03-14 17:17:17 +08:00
#include <stdbool.h>
#include <stdint.h>
#include "tim.h"
/*
*
* 1) LADRC H PWM
* 2) RPM CAN
*
*
* -
* -
*/
2026-03-08 18:17:14 +08:00
/* ================== 全局静态变量 ================== */
2026-03-14 17:17:17 +08:00
static uint16_t s_last_count[4] = {0U, 0U, 0U, 0U};
static volatile float s_current_rpm[4] = {0.0f, 0.0f, 0.0f, 0.0f};
static volatile int32_t s_odom_acc_ticks[4] = {0, 0, 0, 0};
/* ================== 内部辅助函数声明 ================== */
static inline void Motor_WriteBridge(TIM_HandleTypeDef *htim,
uint32_t channel_in1,
uint32_t channel_in2,
uint16_t pwm_in1,
uint16_t pwm_in2);
static void Motor_PrimeEncoderCounters(void);
static uint16_t Motor_ClampAbsToPwm(int32_t value);
static int16_t Motor_SaturateToI16(int32_t value);
/**
* @brief H PWM
* @note AT8236
* - IN1 = PWMIN2 = 0
* - IN1 = 0 IN2 = PWM
*/
static inline void Motor_WriteBridge(TIM_HandleTypeDef *htim,
uint32_t channel_in1,
uint32_t channel_in2,
uint16_t pwm_in1,
uint16_t pwm_in2)
{
__HAL_TIM_SET_COMPARE(htim, channel_in1, pwm_in1);
__HAL_TIM_SET_COMPARE(htim, channel_in2, pwm_in2);
}
/**
* @brief PWM
*/
static uint16_t Motor_ClampAbsToPwm(int32_t value)
{
if (value > PWM_LIMIT)
{
value = PWM_LIMIT;
}
else if (value < -PWM_LIMIT)
{
value = -PWM_LIMIT;
}
if (value < 0)
{
value = -value;
}
return (uint16_t)value;
}
/**
* @brief int32 int16 CAN
*/
static int16_t Motor_SaturateToI16(int32_t value)
{
if (value > 32767)
{
return 32767;
}
if (value < -32768)
{
return -32768;
}
return (int16_t)value;
}
/**
* @brief
* @note last_count 0
*/
static void Motor_PrimeEncoderCounters(void)
{
s_last_count[MOTOR_FL] = (uint16_t)__HAL_TIM_GET_COUNTER(&htim5);
s_last_count[MOTOR_RL] = (uint16_t)__HAL_TIM_GET_COUNTER(&htim3);
s_last_count[MOTOR_FR] = (uint16_t)__HAL_TIM_GET_COUNTER(&htim4);
s_last_count[MOTOR_RR] = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);
}
2026-03-08 18:17:14 +08:00
/**
2026-03-14 17:17:17 +08:00
* @brief PWM
2026-03-08 18:17:14 +08:00
*/
void Motor_Init(void)
{
2026-03-14 17:17:17 +08:00
uint32_t primask = __get_PRIMASK();
if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim9, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim9, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL) != HAL_OK) { Error_Handler(); }
/* 启动完成后,把输出和测速状态清零。 */
Motor_Brake_All();
Motor_PrimeEncoderCounters();
__disable_irq();
s_current_rpm[MOTOR_FL] = 0.0f;
s_current_rpm[MOTOR_RL] = 0.0f;
s_current_rpm[MOTOR_FR] = 0.0f;
s_current_rpm[MOTOR_RR] = 0.0f;
s_odom_acc_ticks[MOTOR_FL] = 0;
s_odom_acc_ticks[MOTOR_RL] = 0;
s_odom_acc_ticks[MOTOR_FR] = 0;
s_odom_acc_ticks[MOTOR_RR] = 0;
__set_PRIMASK(primask);
2026-03-08 18:17:14 +08:00
}
/**
2026-03-14 17:17:17 +08:00
* @brief
* @param id
* @param control_out
* @note
* 1) control_out
* 2)
* 3) forward
* true -> IN1 = PWM, IN2 = 0
* false -> IN1 = 0, IN2 = PWM
2026-03-08 18:17:14 +08:00
*/
void Set_Motor_Output(Motor_ID_t id, int16_t control_out)
{
2026-03-14 17:17:17 +08:00
int32_t hw_command = (int32_t)control_out;
bool forward;
uint16_t pwm_val;
2026-03-08 18:17:14 +08:00
2026-03-14 17:17:17 +08:00
/* 左侧硬件方向镜像:同样的“车体前进”命令,左轮需要反向转。 */
if ((id == MOTOR_FL) || (id == MOTOR_RL))
{
hw_command = -hw_command;
2026-03-08 18:17:14 +08:00
}
2026-03-27 23:32:15 +08:00
forward = (hw_command < 0);
2026-03-14 17:17:17 +08:00
pwm_val = Motor_ClampAbsToPwm(hw_command);
switch (id)
2026-03-08 18:17:14 +08:00
{
2026-03-14 17:17:17 +08:00
case MOTOR_FL:
if (forward)
{
Motor_WriteBridge(&htim2, TIM_CHANNEL_3, TIM_CHANNEL_4, pwm_val, 0U);
}
else
{
Motor_WriteBridge(&htim2, TIM_CHANNEL_3, TIM_CHANNEL_4, 0U, pwm_val);
2026-03-08 18:17:14 +08:00
}
break;
2026-03-14 17:17:17 +08:00
case MOTOR_RL:
if (forward)
{
Motor_WriteBridge(&htim9, TIM_CHANNEL_1, TIM_CHANNEL_2, pwm_val, 0U);
}
else
{
Motor_WriteBridge(&htim9, TIM_CHANNEL_1, TIM_CHANNEL_2, 0U, pwm_val);
2026-03-08 18:17:14 +08:00
}
break;
2026-03-14 17:17:17 +08:00
case MOTOR_FR:
if (forward)
{
Motor_WriteBridge(&htim8, TIM_CHANNEL_1, TIM_CHANNEL_2, pwm_val, 0U);
}
else
{
Motor_WriteBridge(&htim8, TIM_CHANNEL_1, TIM_CHANNEL_2, 0U, pwm_val);
2026-03-08 18:17:14 +08:00
}
break;
2026-03-14 17:17:17 +08:00
case MOTOR_RR:
if (forward)
{
Motor_WriteBridge(&htim8, TIM_CHANNEL_3, TIM_CHANNEL_4, pwm_val, 0U);
}
else
{
Motor_WriteBridge(&htim8, TIM_CHANNEL_3, TIM_CHANNEL_4, 0U, pwm_val);
2026-03-08 18:17:14 +08:00
}
break;
2026-03-14 17:17:17 +08:00
default:
break;
2026-03-08 18:17:14 +08:00
}
}
/**
2026-03-14 17:17:17 +08:00
* @brief
* @note 使 0
* 线
* Brake
2026-03-08 18:17:14 +08:00
*/
void Motor_Brake_All(void)
{
2026-03-14 17:17:17 +08:00
Motor_WriteBridge(&htim2, TIM_CHANNEL_3, TIM_CHANNEL_4, 0U, 0U);
Motor_WriteBridge(&htim9, TIM_CHANNEL_1, TIM_CHANNEL_2, 0U, 0U);
Motor_WriteBridge(&htim8, TIM_CHANNEL_1, TIM_CHANNEL_2, 0U, 0U);
Motor_WriteBridge(&htim8, TIM_CHANNEL_3, TIM_CHANNEL_4, 0U, 0U);
2026-03-08 18:17:14 +08:00
}
/**
2026-03-14 17:17:17 +08:00
* @brief
* @param dt_s 10ms 0.01f
* @note
* - int16_t 16
* - RPM
2026-03-08 18:17:14 +08:00
*/
void Motor_Update_RPM(float dt_s)
{
2026-03-14 17:17:17 +08:00
uint16_t curr_count_fl;
uint16_t curr_count_rl;
uint16_t curr_count_fr;
uint16_t curr_count_rr;
2026-03-08 18:17:14 +08:00
int16_t delta[4];
2026-03-14 17:17:17 +08:00
float rpm_scale;
if (dt_s <= 0.0f)
2026-03-08 18:17:14 +08:00
{
2026-03-14 17:17:17 +08:00
return;
2026-03-08 18:17:14 +08:00
}
2026-03-14 17:17:17 +08:00
curr_count_fl = (uint16_t)__HAL_TIM_GET_COUNTER(&htim5);
curr_count_rl = (uint16_t)__HAL_TIM_GET_COUNTER(&htim3);
curr_count_fr = (uint16_t)__HAL_TIM_GET_COUNTER(&htim4);
curr_count_rr = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);
delta[MOTOR_FL] = (int16_t)(curr_count_fl - s_last_count[MOTOR_FL]);
delta[MOTOR_RL] = (int16_t)(curr_count_rl - s_last_count[MOTOR_RL]);
delta[MOTOR_FR] = (int16_t)(curr_count_fr - s_last_count[MOTOR_FR]);
delta[MOTOR_RR] = (int16_t)(curr_count_rr - s_last_count[MOTOR_RR]);
s_last_count[MOTOR_FL] = curr_count_fl;
s_last_count[MOTOR_RL] = curr_count_rl;
s_last_count[MOTOR_FR] = curr_count_fr;
s_last_count[MOTOR_RR] = curr_count_rr;
/* 左侧输入镜像修正:让“车体前进”统一表现为正脉冲 / 正 RPM。 */
2026-03-27 23:32:15 +08:00
delta[MOTOR_FL] = (int16_t)(-delta[MOTOR_FL]);
delta[MOTOR_RL] = (int16_t)(-delta[MOTOR_RL]);
// delta[MOTOR_FR] = (int16_t)(-delta[MOTOR_FR]);
// delta[MOTOR_RR] = (int16_t)(-delta[MOTOR_RR]);
2026-03-14 17:17:17 +08:00
/* 用 32 位内部累加,避免偶发高速度时 16 位回绕。 */
s_odom_acc_ticks[MOTOR_FL] += delta[MOTOR_FL];
s_odom_acc_ticks[MOTOR_RL] += delta[MOTOR_RL];
s_odom_acc_ticks[MOTOR_FR] += delta[MOTOR_FR];
s_odom_acc_ticks[MOTOR_RR] += delta[MOTOR_RR];
rpm_scale = 60.0f / ((float)PULSES_PER_REV * dt_s);
s_current_rpm[MOTOR_FL] = (float)delta[MOTOR_FL] * rpm_scale;
s_current_rpm[MOTOR_RL] = (float)delta[MOTOR_RL] * rpm_scale;
s_current_rpm[MOTOR_FR] = (float)delta[MOTOR_FR] * rpm_scale;
s_current_rpm[MOTOR_RR] = (float)delta[MOTOR_RR] * rpm_scale;
2026-03-08 18:17:14 +08:00
}
/**
2026-03-14 17:17:17 +08:00
* @brief RPM
2026-03-08 18:17:14 +08:00
*/
float Get_Motor_RPM(Motor_ID_t id)
{
2026-03-14 17:17:17 +08:00
if ((id < MOTOR_FL) || (id > MOTOR_RR))
{
return 0.0f;
}
return s_current_rpm[id];
2026-03-08 18:17:14 +08:00
}
2026-03-14 17:17:17 +08:00
2026-03-08 18:17:14 +08:00
/**
2026-03-14 17:17:17 +08:00
* @brief CAN
* @note 10ms
* +
2026-03-08 18:17:14 +08:00
*/
2026-03-14 17:17:17 +08:00
void Motor_Get_And_Clear_Delta_Ticks(int16_t *d_fl, int16_t *d_rl, int16_t *d_fr, int16_t *d_rr)
2026-03-08 18:17:14 +08:00
{
2026-03-14 17:17:17 +08:00
int32_t fl;
int32_t rl;
int32_t fr;
int32_t rr;
uint32_t primask;
if ((d_fl == NULL) || (d_rl == NULL) || (d_fr == NULL) || (d_rr == NULL))
{
return;
}
primask = __get_PRIMASK();
__disable_irq();
fl = s_odom_acc_ticks[MOTOR_FL];
rl = s_odom_acc_ticks[MOTOR_RL];
fr = s_odom_acc_ticks[MOTOR_FR];
rr = s_odom_acc_ticks[MOTOR_RR];
s_odom_acc_ticks[MOTOR_FL] = 0;
s_odom_acc_ticks[MOTOR_RL] = 0;
s_odom_acc_ticks[MOTOR_FR] = 0;
s_odom_acc_ticks[MOTOR_RR] = 0;
__set_PRIMASK(primask);
*d_fl = Motor_SaturateToI16(fl);
*d_rl = Motor_SaturateToI16(rl);
*d_fr = Motor_SaturateToI16(fr);
*d_rr = Motor_SaturateToI16(rr);
}