嵌入式浅谈之“梯形”加减速MCU算法实现

书接上回,上章我们讲到原理,本章我们来聊聊实现。

在笔者的实际项目经历中,梯形加减速运用的比较广泛,主要以其优秀的加减速能力、对算法实现资源的需求较小、实现难度适中而被广泛应用。下面就简单介绍一下基于MCU的算法实现过程,以STM32为例。

采用“梯形”加减速算法,在运动过程中分成以下四个状态:空闲状态,加速状态,匀速状态与减速状态。

脉冲产生单元:用来产生指定频率的脉冲信号。

脉冲计数单元:用来记录各个运动状态下输出的脉冲个数。

脉宽计算单元:根据总的脉冲个数及记录的各个运动状态下的脉冲输出个数,进行状态跳转及速度计算。

脉冲产生单元

初始化STM32定时器,在定时器中断里面,翻转IO口,输出脉冲信号。

//初始化定时器功能,用来翻转IO信号,产生脉冲输出信号

//初始化定时器功能,用来翻转IO信号,产生脉冲输出信号
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
 
	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级1级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
 
	TIM_Cmd(TIM3, DISABLE);  //不使能TIMx					 
}
//设置定时器值,用来产生指定频率的脉冲信号
void Motor0TimeSet(unsigned int ARR,bool TimeEnable)
{	
	TIM3->ARR = (uint16_t)ARR;   
	if(TimeEnable) TIM_Cmd(TIM3, ENABLE);
	else TIM_Cmd(TIM3, DISABLE);
}
//翻转IO
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
		MotorPulsePinOut(&MotorControl[0]);
	}
}

脉冲计数单元

用来记录各个阶段输出的脉冲信号;根据设置的值和输出脉冲进行加减速状态切换

                                          

void MotorRunState(MOTOR_CTRL *Motor)
{
    switch(Motor->NowState.RunState)
    {
		case MIDLE://开始
			Motor->NowState.AllowMaxAddStep = Motor->SetData.RunStep/2;
			Motor->NowState.RunState = MACC;
		break;
		case MACC://加速状态
			Motor->NowState.AddStep ++;
			Motor->NowState.RunStep ++;
			if(Motor->NowState.AddStep >= Motor->NowState.AllowMaxAddStep)//三角形加速
				Motor->NowState.RunState = MDEC;
			else if(Motor->NowState.Speed >= Motor->SetData.SpeedMax)
				Motor->NowState.RunState = MKEEP;
		break;
		case MKEEP://最大速度阶段
			Motor->NowState.RunStep ++;
			if(Motor->NowState.AddStep >= Motor->SetData.RunStep - Motor->NowState.RunStep)
				Motor->NowState.RunState = MDEC;
		break;
		case MDEC://减速阶段
			Motor->NowState.RunStep ++;
			if(Motor->NowState.RunStep >= Motor->SetData.RunStep)//脉冲输出完成
			{
                Motor->TimeSet_Call_Back(Motor->NowState.TimeCountNum,false);//关闭定时器,停止脉冲信号输出
				Motor->NowState.SysState = MOV_IDLE;
				Motor->NowState.Consequence = 0; //执行结果
			}
		}
		if(Motor->NowState.SysState)Motor->TimeSet_Call_Back(Motor->NowState.TimeCountNum,true);//设置下一次脉冲输出频率
  }

速度计算单元

 根据当前处于电机加减速的那个状态,进行速度计算。采用定时1MS计算一次速度的方式。

void MotorCalculateSpeed(MOTOR_CTRL *Motor)
{
	switch(Motor->NowState.RunState)
	{
		case MIDLE:
			Motor->NowState.Speed = Motor->SetData.Speed0;
		break;
		case MACC:
			Motor->NowState.Speed += Motor->SetData.SpeedAdd;
			if(Motor->NowState.Speed > Motor->SetData.SpeedMax)
				Motor->NowState.Speed = Motor->SetData.SpeedMax;
		break;
		case MKEEP:
			Motor->NowState.Speed = Motor->SetData.SpeedMax;
		break;
		case MDEC:
			Motor->NowState.Speed -= Motor->SetData.SpeedAdd;
			if(Motor->NowState.Speed < Motor->SetData.Speed0)
				Motor->NowState.Speed = Motor->SetData.Speed0;
		break;
	}
	
	if(Motor->NowState.Busy)
	{		
		Motor->NowState.TimeCountNum = 1000*1000/Motor->NowState.Speed;//计算定时器应该重装的值
		Motor->NowState.MotorRunTime++;//统计电机运行时间
	}
}

以上是设计的核心思想和算法,旨在抛砖引玉,各位看官有更好的算法实现请在评论区留言,多多交流。若各位看官需要完整工程代码,请关注公众号或评论区私信留言。

好了,今天的分享就到这里。

各位看官,我们下期再见。

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: keil步进电机梯形减速算法代码是控制步进电机进行速和减速运动的一种算法实现算法的代码如下: 1. 定义必要的变量,包括步进电机的速度、速度和减速度。 2. 初始化步进电机速度为初始速度,速度为初始速度,减速度为初始减速度。 3. 进入循环,进行控制步进电机的运动。 4. 判断是否已达到目标速度,如果已达到则保持该速度不变,否则进行速运动。 5. 判断是否需要开始减速运动,如果需要则进入减速运动。 6. 当步进电机运动到目标位置时,停止运动。 7. 结束循环,完成步进电机的梯形减速运动。 该代码可以用于控制步进电机在系统中进行精准定位和控制运动速度,使得步进电机运动更平稳和稳定。通过调整初始速度、速度和减速度等参数,可以实现不同的运动需求。 ### 回答2: Keil 是一款嵌入开发工具,用于编写和调试嵌入系统的代码。步进电机梯形减速算法可以使步进电机在启动、速、匀速、减速和停止等阶段运行平稳,避免产生震动或其他不稳定现象。 以下是一个示例的 Keil 步进电机梯形减速算法代码: ``` #include <reg52.h> sbit coil_A1=P2^0; // 步进电机相位1 sbit coil_A2=P2^1; // 步进电机相位2 sbit coil_B1=P2^2; // 步进电机相位3 sbit coil_B2=P2^3; // 步进电机相位4 void Delay(unsigned int i) //延时函数 { while(i--); } void main() { unsigned char i, j; unsigned char speed = 10; // 设置步进电机速度,值越小速度越快 unsigned char step[8] = {0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09}; // 步进电机顺时针转动步进序列 while(1) { for(i=0; i<8; i++) { for(j=0; j<speed; j++) { coil_A1 = step[i] & 0x01; coil_A2 = (step[i]>>1) & 0x01; coil_B1 = (step[i]>>2) & 0x01; coil_B2 = (step[i]>>3) & 0x01; Delay(500); } } } } ``` 以上代码使用 P2 口控制步进电机的相位,通过循环遍历步进序列来实现电机转动。speed 变量用于控制电机速度,具体数值可以根据实际情况进行调整。 在循环中,代码会通过设置相位的值来控制电机的转动,通过适当的延时时间来控制电机的速度。这样,步进电机就能按照梯形减速算法运行,实现平稳的转动。 ### 回答3: 以下是一个示例的Keil步进电机梯形减速算法代码: ```c #include <reg51.h> #define M1 P2.0 #define M2 P2.1 #define M3 P2.2 #define M4 P2.3 void delay(unsigned int count) { unsigned int i, j; for(i = 0; i < count; i++) { for(j = 0; j < 1275; j++); } } void main() { unsigned char step = 0; unsigned int delay_cnt = 1000; // 初始延时计数器 unsigned char full_step[4] = {0x09, 0x03, 0x06, 0x0C}; // 步进电机全步相序 while(1) { // 设置步进电机相序 M1 = (full_step[step] & 0x01) >> 0; M2 = (full_step[step] & 0x02) >> 1; M3 = (full_step[step] & 0x04) >> 2; M4 = (full_step[step] & 0x08) >> 3; // 延时 delay(delay_cnt); // 更新步进电机相序 step++; step %= 4; // 延时计数器减速 if(delay_cnt > 200) delay_cnt -= 10; else if(delay_cnt > 100) delay_cnt -= 5; else if(delay_cnt > 50) delay_cnt -= 2; else delay_cnt = 50; // 最快速度限制 } } ``` 以上代码使用Keil开发环境,基于8051单片机,控制了一个4相2线的步进电机。代码中使用了一个步进电机的全步相序数组,通过循环依次设置电机四个控制引脚,来控制电机的转向。在每个相序设置后,都有一个延时函数来控制转速。延时函数的延时时间在每次循环中递减,实现梯形减速的效果。当延时计数器小于一定值时,延时时间不再减少,从而实现了最快速度的限制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值