梯形加减速算法梯形加减速算法
/*! \brief 以给定的步数移动步进电机
const
* 通过计算加速到最⼤速度,以给定的步数开始减速
* 如果加速度和减速度很⼩,步进电机会移动很慢,还没达到最⼤速度就要开始减速
* \param step 移动的步数 (正数为顺时针,负数为逆时针).
* \param accel 加速度,如果取值为10,实际值为10*0.1*rad/c^2=1rad/c^2
* \param decel 减速度,如果取值为10,实际值为10*0.1*rad/c^2=1rad/c^2
* \param speed 最⼤速度,如果取值为10,实际值为10*0.1*rad/c=1rad/c
*/
void stepper_move_T( int32_t step, uint32_t accel, uint32_t decel, uint32_t speed)
{
//达到最⼤速度时的步数.
unsigned int max_s_lim;you can let go
//必须开始减速的步数(如果还没加速到达最⼤速度时)。
unsigned int accel_lim;
/*根据步数和正负判断*/
if(step ==0)
{
return;
}
el if(step <0)//逆时针
{
srd.dir = CCW;
step =-step;
}
el//顺时针
noticeably{
srd.dir = CW;
}
// 输出电机⽅向
MOTOR_DIR(srd.dir);
// 如果只移动⼀步
if(step ==1)
{
// 只移动⼀步
srd.accel_count =-1;
// 减速状态
srd.run_state = DECEL;
/
/ 短延时
srd.step_delay =1000;
// 配置电机为运⾏状态
status.running = TRUE;
}
// 步数不为零才移动
el if(step !=0)
{
// 设置最⼤速度极限, 计算得到min_delay⽤于定时器的计数器的值。
// min_delay = (alpha / tt)/ w
srd.min_delay =(int32_t)(A_T_x10/speed);
/
/ 通过计算第⼀个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/c^2 // step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100 srd.step_delay =(int32_t)((T1_FREQ_148 *sqrt(A_SQ / accel))/10);
// 计算多少步之后达到最⼤速度的限制
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim =(uint32_t)(speed*speed/(A_x200*accel/10));
// 如果达到最⼤速度⼩于0.5步,我们将四舍五⼊为0
// 但实际我们必须移动⾄少⼀步才能达到想要的速度
if(max_s_lim ==0)
{
max_s_lim =1;
}
// 计算多少步之后我们必须开始减速
// n1 = (n1+n2)decel / (accel + decel)
accel_lim =(uint32_t)(step*decel/(accel+decel));
// 我们必须加速⾄少1步才能才能开始减速.
if(accel_lim ==0)
{
accel_lim =1;
}
// 使⽤限制条件我们可以计算出第⼀次开始减速的位置
//srd.decel_val为负数
if(accel_lim <= max_s_lim)buyren
{
srd.decel_val = accel_lim - step;
}
el{
srd.decel_val =-(max_s_lim*accel/decel);
}
// 当只剩下⼀步我们必须减速
if(srd.decel_val ==0)
{
srd.decel_val =-1;
}
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;
// 如果最⼤速度很慢,我们就不需要进⾏加速运动
if(srd.step_delay <= srd.min_delay)
{
srd.step_delay = srd.min_delay;
srd.run_state = RUN;
}
el
{
srd.run_state = ACCEL;
}
// 复位加速度计数值
srd.accel_count =0;
status.running = TRUE;
}
/*获取当前计数值*/
int tim_count=__HAL_TIM_GET_COUNTER(&TIM_TimeBaStructure);
/*在当前计数值基础上设置定时器⽐较值*/
__HAL_TIM_SET_COMPARE(&TIM_TimeBaStructure,MOTOR_PUL_CHANNEL_x,tim_count+srd.step_delay/2); /*使能定时器通道*/
TIM_CCxChannelCmd(MOTOR_PUL_TIM, MOTOR_PUL_CHANNEL_x, TIM_CCx_DISABLE);
__HAL_TIM_ENABLE_IT(&TIM_TimeBaStructure, TIM_IT_CC1);
__HAL_TIM_MOE_ENABLE(&TIM_TimeBaStructure);
__HAL_TIM_ENABLE(&TIM_TimeBaStructure);
}
/**
* @brief 速度决策
* @note 在中断中使⽤,每进⼀次中断,决策⼀次
* @retval ⽆
*/
void speed_decision()
{
uint32_t tim_count=0;
uint32_t tmp =0;
// 保存新(下)⼀个延时周期
uint16_t new_step_delay=0;
// 加速过程中最后⼀次延时(脉冲周期).
static uint16_t last_accel_delay=0;
// 总移动步数计数器
static uint32_t step_count =0;
static int32_t rest =0;
//定时器使⽤翻转模式,需要进⼊两次中断才输出⼀个完整脉冲
static uint8_t i=0;
if(__HAL_TIM_GET_IT_SOURCE(&TIM_TimeBaStructure, MOTOR_TIM_IT_CCx)!=RESET)
{
// 清楚定时器中断
districts__HAL_TIM_CLEAR_IT(&TIM_TimeBaStructure, MOTOR_TIM_IT_CCx);
// 设置⽐较值
tim_count=__HAL_TIM_GET_COUNTER(&TIM_TimeBaStructure);
tmp = tim_count+srd.step_delay/2;
__HAL_TIM_SET_COMPARE(&TIM_TimeBaStructure,MOTOR_PUL_CHANNEL_x,tmp);
navyi++;// 定时器中断次数计数值
if(i==2)// 2次,说明已经输出⼀个完整脉冲
{
i=0;// 清零定时器中断次数计数值
switch(srd.run_state)
{
/*步进电机停⽌状态*/
ca STOP:
switch什么意思step_count =0;// 清零步数计数器
rest =0;// 清零余值effort是什么意思
背单词软件
// 关闭通道
HAL_TIM_OC_Stop_IT(&TIM_TimeBaStructure,MOTOR_PUL_CHANNEL_x);
status.running = FALSE;
break;
/
*步进电机加速状态*/
ca ACCEL:
TIM_CCxChannelCmd(MOTOR_PUL_TIM, MOTOR_PUL_CHANNEL_x, TIM_CCx_ENABLE);
step_count++;
srd.accel_count++;
new_step_delay = srd.step_delay -(((2*srd.step_delay)+ rest)/(4* srd.accel_count +1));//计算新(下)⼀步脉冲周期(时间间隔) rest =((2* srd.step_delay)+rest)%(4* srd.accel_count +1);// 计算余数,下次计算补上余数,减少误差
//检查是够应该开始减速
if(step_count >= srd.decel_start){
srd.accel_count = srd.decel_val;
srd.run_state = DECEL;
}
//检查是否到达期望的最⼤速度
el if(new_step_delay <= srd.min_delay){
last_accel_delay = new_step_delay;
new_step_delay = srd.min_delay;
rest =0;
srd.run_state = RUN;
}
break;
/*步进电机最⼤速度运⾏状态*/
ca RUN:
step_count++;
new_step_delay = srd.min_delay;
//检查是否需要开始减速
if(step_count >= srd.decel_start)
{
srd.accel_count = srd.decel_val;
//以最后⼀次加速的延时作为开始减速的延时
new_step_delay = last_accel_delay;
srd.run_state = DECEL;
}
break;
/
*步进电机减速状态*/
ca DECEL:
step_count++;
srd.accel_count++;
new_step_delay = srd.step_delay -(((2* srd.step_delay)+ rest)/(4* srd.accel_count +1));//计算新(下)⼀步脉冲周期(时间间隔) rest =((2* srd.step_delay)+rest)%(4* srd.accel_count +1);// 计算余数,下次计算补上余数,减少误差//检查是否为最后⼀步
if(srd.accel_count >=0)
{
srd.run_state = STOP;
}
break;
}
babyboom}
/*求得下⼀次间隔时间*/
srd.step_delay = new_step_delay; }
}
}