Files
linear-Slide/Interface/Int_TMC2209.c

243 lines
7.7 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 "Int_TMC2209.h"
/*
* TIM2 CH1 使用 TOGGLE 模式输出 STEP
* 每次中断只翻转一次电平,两个中断才构成一个完整 STEP 脉冲。
*/
// 静态变量,记录分频状态
static uint8_t double_flag = 0;
void Int_TMC2209_init(void)
{
}
static void Int_TMC2209_set_steps(Stepper_t *stepper)
{
/* 将目标运动参数换算为总步数和梯形/三角速度曲线参数 */
// --- 参数单位定义 ---
// stepper->distance -> 代表目标距离 (mm)
// stepper->speed -> 代表目标速度 (mm/s)
// stepper->acc -> 代表加速度 (mm/s^2)
// stepper->start_speed -> 代表启动速度 (mm/s)
// 1. 计算总步数
// 总步数 = 距离(mm) * 每毫米步数
stepper->total_step = (uint32_t)(stepper->distance * STEPS_PER_MM);
// 2. 物理运动学公式计算加速距离
// 公式: x = (v^2 - v0^2) / 2a
// 单位全部统一为 mm, mm/s, mm/s^2
float v_target = stepper->speed; // mm/s
float v_start = stepper->start_speed; // mm/s
float accel = stepper->acc; // mm/s^2
// 防止除0错误
if (accel == 0 || v_target == 0)
return;
// 计算加速所需的距离 (mm)
float acc_distance_mm = (v_target * v_target - v_start * v_start) / (2.0f * accel);
// 将加速距离转换为加速步数
stepper->acc_step = (uint32_t)(acc_distance_mm * STEPS_PER_MM);
// 3. 规划梯形/三角形速度曲线
if (stepper->total_step < stepper->acc_step * 2)
{
// 距离太短,跑不到目标速度 -> 三角形加减速
stepper->acc_step = stepper->total_step / 2;
stepper->constant_step = 0;
debug_printf("Model: Triangle, AccStep: %d", stepper->acc_step);
}
else
{
// 距离足够 -> 梯形加减速
stepper->constant_step = stepper->total_step - stepper->acc_step * 2;
debug_printf("Model: Trapezoid, Acc: %d, Const: %d", stepper->acc_step, stepper->constant_step);
}
// 4. 计算每一步的速度增量 (mm/s per step)
// 逻辑:(目标速度 - 启动速度) / 加速步数
// 含义:每走一步,速度增加多少 mm/s
if (stepper->acc_step > 0)
{
stepper->speed_inc = (float)(v_target - v_start) / stepper->acc_step;
}
else
{
stepper->speed_inc = 0;
}
// 5. 初始化状态
stepper->step_count = 0;
stepper->current_speed = stepper->start_speed;
stepper->state = ACCELERATE;
}
void Int_stepper_run(void)
{
/* 仅用于调试的固定步进函数,不参与正式运行逻辑 */
// 此函数用于测试,硬编码了步数,建议根据新的 STEPS_PER_MM 修改这里
// 例如走 10mm:
// uint32_t steps = 10 * STEPS_PER_MM * 2; // *2 是因为 toggle
HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(STEPPER1_DIR_GPIO_Port, STEPPER1_DIR_Pin, GPIO_PIN_SET);
// 这里的3200原来是转一圈现在如果导程是8mm3200次toggle (1600步) = 8mm
for (uint16_t i = 0; i < 3200; i++)
{
HAL_GPIO_TogglePin(STEPPER_1_STEP_GPIO_Port, STEPPER_1_STEP_Pin);
HAL_Delay(1);
}
}
void Int_TMC2209_start(Stepper_t *stepper, Encoder_t *encoder)
{
/* 启动流程:
* 1) 清零编码器基准
* 2) 使能驱动并配置方向
* 3) 计算速度曲线参数
* 4) 配置并启动 TIM2 输出中断
*/
// 清零编码器值
encoder->pulses = 0;
encoder->overflow = 0;
__HAL_TIM_SET_COUNTER(&htim1, 0);
encoder->z = 0;
HAL_GPIO_WritePin(ENCODER_MODE_GPIO_Port, ENCODER_MODE_Pin, GPIO_PIN_RESET);
HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
// 使能驱动
HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(STEPPER1_DIR_GPIO_Port, STEPPER1_DIR_Pin, stepper->dir);
// 复位分频标志位
double_flag = 0;
// 设置步数参数
Int_TMC2209_set_steps(stepper);
// [修改] 计算初始ARR (基于 mm/s)
// 最小速度保护防止ARR计算溢出
if (stepper->start_speed < 0.1f)
stepper->start_speed = 0.1f;
// 这里传入的是 mm/s
uint32_t arr = CALC_ARR(stepper->start_speed);
debug_printf("Start Speed: %.2f mm/s, ARR: %d", stepper->start_speed, arr);
__HAL_TIM_SET_COUNTER(&htim2, 0);
__HAL_TIM_SET_AUTORELOAD(&htim2, arr);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, arr / 2);
HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1);
}
void Int_TMC2209_stop(void)
{
/* 停止流程停止STEP输出 -> 关闭驱动 -> 停止编码器计数 */
HAL_TIM_OC_Stop_IT(&htim2, TIM_CHANNEL_1);
HAL_GPIO_WritePin(STEPPER123_EN_GPIO_Port, STEPPER123_EN_Pin, GPIO_PIN_RESET);
HAL_TIM_Encoder_Stop(&htim1, TIM_CHANNEL_ALL);
}
uint8_t Int_TMC2209_CheckHomeStop(Stepper_t *stepper)
{
// 检测当前是否在零点,如果是,则禁止向零点方向移动
if (HAL_GPIO_ReadPin(X_ZERO_GPIO_Port, X_ZERO_Pin) == GPIO_PIN_RESET)
{
// 只有当方向是朝着零点移动时 (dir == 1),才强制停止
if (stepper->dir == GPIO_PIN_SET)
{
stepper->state = STOP;
stepper->current_speed = 0;
Int_TMC2209_stop(); // 停止定时器脉冲输出
// 标记:如果正在执行回零操作,这里可以清零坐标
stepper->step_count = 0;
return 1; // 直接退出中断,不再生成这个脉冲
}
// 如果 s->dir == 0 (远离零点),代码会继续往下走,从而允许电机退出限位区
}
return 0;
}
void Int_TMC2209_SpeedUpadte(Stepper_t *stepper)
{
// 根据加减速算法更新速度(当前采用梯形算法)
double_flag++;
// 必须满2次中断1个完整脉冲才进行计算
if (double_flag < 2)
return;
stepper->step_count++;
double_flag = 0;
// --- 状态机管理 ---
switch (stepper->state)
{
case ACCELERATE:
// 加速阶段
stepper->current_speed += stepper->speed_inc; // 这里的 speed_inc 单位是 mm/s per step
if (stepper->step_count >= stepper->acc_step || stepper->current_speed >= stepper->speed)
{
stepper->current_speed = stepper->speed;
stepper->state = CONSTANT;
}
break;
case CONSTANT:
// 匀速阶段
if (stepper->step_count >= (stepper->total_step - stepper->acc_step))
stepper->state = DECELERATE;
break;
case DECELERATE:
// 减速阶段
stepper->current_speed -= stepper->speed_inc;
if (stepper->current_speed < stepper->start_speed)
stepper->current_speed = stepper->start_speed;
if (stepper->step_count >= stepper->total_step)
{
stepper->state = STOP;
Int_TMC2209_stop(); // 内部会关闭中断所以这里直接return即可
return;
}
break;
case STOP:
Int_TMC2209_stop();
return;
}
// --- 更新硬件 ---
if (stepper->state != STOP)
{
// 传入 mm/s计算新的 ARR
uint32_t new_arr = CALC_ARR(stepper->current_speed);
__HAL_TIM_SET_AUTORELOAD(&htim2, new_arr);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, new_arr / 2);
}
}
extern Stepper_t stepper_1;
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
/* TIM2中断中完成步进脉冲计数、速度状态机更新和ARR重装载 */
if (htim->Instance == TIM2)
{
Stepper_t *s = &stepper_1;
// --- 1. 实时限位保护拦截 ---
if (Int_TMC2209_CheckHomeStop(s))
return;
// --- 2. 定时更新步进电机速度 ---
Int_TMC2209_SpeedUpadte(s);
}
}