STM32 步进电机T型加速

般PLC 运动控制卡都有实现电机的T型 S型加减速算法,我们只需要设置起始最小速度(Pulse/S),最终最大速度(Pulse/s),加速时间(ms)即可,这样使用起来很方便和直观。但有些控制场合不是使用PLC或运动控制卡,而是我们自己做的STM32控制板时,这些加速算法就需我们自己来实现了。
步进电机加速一般有S型加速和T型加速,T型由于电机的运动状态包含匀加速 匀速 匀减速三种状态,运动轨迹看起来像个等腰梯形,所以叫T型加速.

加速数据生成

T型加速
加减速部分速度与时间的关系为:
V = a ∗ t + V 0 V=a*t+V_0 V=at+V0
V 0 V_0 V0就是起始速度SpeedMin
以下生成的数据,是以定时器频率为12M为基准:

/***************************************************************************************************************
  * 函数名称: GetTData
  * 函数描述:  根据y=a*x+b线性加速,斜率a=(SpeedMax-SpeedMin)/nAccTime,b=SpeedMin,nAccTime单位为ms
  * 参数 pTData 生成的加速数据
  * 返回值:数组的长度
  * 其它说明: 
  * 
****************************************************************************************************************/
short GetTData(unsigned short* pTData,short SpeedMin,short SpeedMax,short nAccTime)
{
	short TabLen= 0;	
	double tSum=0;
	short RealSpeed=SpeedMin;//实时速度初始值
	unsigned int nAccTimer = nAccTime*1000*12;	//加速时间对应的定时器的数值:1S定时器数值变化12M次,那么1ms就变化12000次 
	short deltaSpeed = (SpeedMax-SpeedMin); 	//为了加快计算速度,所以预先计算斜率数值的一部分
	
	while(RealSpeed<SpeedMax)
	{
		RealSpeed = deltaSpeed*tSum/nAccTimer+SpeedMin;//deltaSpeed/nAccTimer是斜率a,SpeedMin是b
		pTData[Len] = 12000000/2*RealSpeed;//由于发一个高电平然后一个低电平电机才走一步,所以单个电平的速度需要乘2
		tSum  += 2*pTData[Len];		//走一步需要一个高电平和低电平所以*2 
		TabLen++;
	}

	return TabLen;
}

定时器设置

/***************************************************************************************************************
  * 函数名称:  定时器初始化
  * 函数描述: 
  * 其它说明: 
  * 
****************************************************************************************************************/
void MX_TIM_Init(TIM_TypeDef* TIMX,TIM_HandleTypeDef* htim,uint32_t nPresc)
{

  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim->Instance = TIMX;
  htim->Init.Prescaler = nPresc-1;						
  htim->Init.CounterMode = TIM_COUNTERMODE_UP;	//向上计数模式
  htim->Init.Period = 0;
  htim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
  htim->Init.RepetitionCounter = 0;
  if(HAL_TIM_Base_Init(htim) != HAL_OK)
  {
    Error_Handler();
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;	//内部时钟
  if (HAL_TIM_ConfigClockSource(htim, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(htim, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

void InitTimer()
{
    SystemClock_Config();
    MX_TIM_Init(TIM1,&htim1,14);	//时钟频率为168/14=12Mhz
	MX_TIM_Init(TIM2,&htim2,7);
	MX_TIM_Init(TIM3,&htim3,7);
	MX_TIM_Init(TIM4,&htim4,7);
	MX_TIM_Init(TIM5,&htim5,7);
	MX_TIM_Init(TIM8,&htim8,14);
	MX_TIM_Init(TIM9,&htim9,14);
	MX_TIM_Init(TIM10,&htim10,14);
	MX_TIM_Init(TIM11,&htim11,14);
	MX_TIM_Init(TIM12,&htim12,7);
	MX_TIM_Init(TIM13,&htim13,7);
	MX_TIM_Init(TIM14,&htim14,7);
}
	
	

路径规划

在电机运动前需要先计算好加速的步数,匀速的步数,减速的步数.

/***************************************************************************************************************
  * 函数名称:  路径规划
  * 函数描述: speed-运行速度,step-需要走的步数
  * 其它说明: 
  * 
****************************************************************************************************************/
void PlanMovePath(unsigned short speed,unsigned int step)
{
	unsigned short nTimerSpeed = 12000000/2*speed;	//speed 1S脉冲个数 12M
	for(int i=0;i<TabLen;i++)
	{
		if(pTData[i]<=nTimerSpeed)
		{
			TabIndex = i;
			break;
		}
	}

	if(speed>SpeedMax)
	{
		TabIndex = TabLen;
	}

	if((TabIndex) <= (step>>1))	//梯形走法
	{
		AccStep = TabIndex;
		ConstStep = step - (TabIndex)*2;
		DecStep = AccStep;
	}
	else//三角形
	{
		pSmCtrl->AccStep = (step>>1);
		pSmCtrl->ConstStep = 0;
		pSmCtrl->DecStep = step-AccStep;
	}
	
	if(step==1)
	{
		AccStep = 1;
		ConstStep = 0;
		DecStep = 0;
	}
}

中断响应

void StepMotorTimerISR()
{
	if (CurrentPulseLevel==HIGH_LEVEL)
	{
		CurrentPulseLevel = LOW_LEVEL;
		ResetPin(Pulse);
		return ;
	}

	if (AccStep!=0)		//加速阶段
	{
		AccStep--;
		ReloadTimer(pTimer,pTData[CurrentSpeed]);
		CurrentPulseLevel = HIGH_LEVEL;		
		SetPin(Pulse);
	}
	else if (ConstStep!=0)//匀速阶段
	{
	  ConstStep--;
	  CurrentPulseLevel = HIGH_LEVEL;
	  SetPin(Pulse);
	}
	else if (DecStep!=0) //减速阶段
	{
		DecStep--;
		if (CurrentSpeed>0)
		{
			pCurrentMotor->CurrentSpeed--;
		}
		
		ReloadTimer(pTimer,pTData[CurrentSpeed]);
		CurrentPulseLevel = HIGH_LEVEL;
		SetPin(Pulse);
	}
	else
	{
		StopTimer(pTimer);
		SetPin(Enable);
		ResetPin(Pulse);
	}
}
  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于STM32F103的S加速步进电机驱动代码示例: ```c #include "stm32f10x.h" #define STEPPER_PIN1 GPIO_Pin_0 #define STEPPER_PIN2 GPIO_Pin_1 #define STEPPER_PIN3 GPIO_Pin_2 #define STEPPER_PIN4 GPIO_Pin_3 #define STEPPER_PORT GPIOA #define S_STEP 1000 #define S_FREQ 5000 volatile uint16_t delay_count = 0; volatile uint16_t step_count = 0; void SysTick_Handler(void) { if (delay_count > 0) delay_count--; } void delay_ms(uint16_t ms) { delay_count = ms; while (delay_count) ; } void stepper_step(uint8_t step) { switch (step) { case 0: GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN2 | STEPPER_PIN3 | STEPPER_PIN4); break; case 1: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN1); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN2 | STEPPER_PIN3 | STEPPER_PIN4); break; case 2: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN2); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN3 | STEPPER_PIN4); break; case 3: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN2); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN3 | STEPPER_PIN4); break; case 4: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN3 | STEPPER_PIN2); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN4); break; case 5: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN3); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN2 | STEPPER_PIN4); break; case 6: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN4 | STEPPER_PIN3); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN2); break; case 7: GPIO_SetBits(STEPPER_PORT, STEPPER_PIN4); GPIO_ResetBits(STEPPER_PORT, STEPPER_PIN1 | STEPPER_PIN2 | STEPPER_PIN3); break; } } void stepper_rotate(uint16_t steps, uint16_t freq) { uint16_t delay_ms = 1000 / freq; uint16_t step_delay = S_STEP; for (uint16_t i = 0; i < steps; i++) { stepper_step(i % 8); delay_count = step_delay; while (delay_count) ; step_delay -= (step_delay * 2) / (4 * steps - 1); if (step_delay < S_STEP / 4) step_delay = S_STEP / 4; } } int main(void) { SysTick_Config(SystemCoreClock / 1000); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef gpio_init; gpio_init.GPIO_Pin = STEPPER_PIN1 | STEPPER_PIN2 | STEPPER_PIN3 | STEPPER_PIN4; gpio_init.GPIO_Mode = GPIO_Mode_Out_PP; gpio_init.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(STEPPER_PORT, &gpio_init); while (1) { stepper_rotate(200, 200); delay_ms(2000); stepper_rotate(400, 400); delay_ms(2000); } } ``` 该代码使用SysTick定时器进行延时,并使用S加速算法进行步进电机控制。您需要根据实际情况调整步进电机的频率和步数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值