完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
步进电机是将电脉冲信号转变为角位移或线位移的开环控制电机,是现代数字程序控制系统中的主要执行元件,应用极为广泛。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”,它的旋转是以固定的角度一步一步运行的。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
步距角:对应一个脉冲信号,电机转子转过的角位移用θ表示。θ=360度/(转子齿数运行拍数),以常规二、四相,转子齿为50齿电机为例。四拍运行时步距角为θ=360度/(504)=1.8度(俗称整步),八拍运行时步距角为θ=360度/(50*8)=0.9度(俗称半步)。 转速(Rotational Speed或Rev):是做圆周运动的物体单位时间内沿圆周绕圆心转过的圈数(与频率不同)。常见的转速有额定转速和最大转速等。 硬盘转速以每分钟多少转来表示,单位表示为RPM,RPM是Revolutions Per minute的缩写,是转/每分钟。RPM值越大,内部传输率就越快,访问时间就越短,硬盘的整体性能也就越好。 S型曲线的的方程: y=1/(1+exp(-x)); x在[-5,5]的图形如下图所示: 在Matlab软件中代码如下: x=-5:0.01:5; y=1./(1+exp(-x)); plot(x,y); 1 2 3 如要将此曲线应用在步进电机的加、减速过程中,需要将方程在XY坐标系进行平移,同时对曲线进行拉升变化: Y=A+B/(1+exp(-ax+b)); 其中的A分量在y方向进行平移,B分量在y方向进行拉伸,ax+b分量在x方向进行平移和拉伸。 其中的A分量在y方向进行平移,B分量在y方向进行拉伸,ax+b分量在x方向进行平移和拉伸。 项目中加速过程:从600Hz加速到20000Hz,采用4细分。输出比较模块所用的定时器驱动频率为10M,采用1000个点进行加速处理。最终根据项目的需要,在加速过程中采用的曲线方程为: Fcurrent = Fmin + (Fmax-Fmin)/(1+exp( -flexible(i - num )/num) );* 步进电机S型曲线加减速算法与实现。 其中的Fcurrent为length(1000)个点中的单个频率值。Fmin起始频率为600; Fmax为最大频率20000; -flexible*(i - num)/num是对S型曲线进行拉伸变化,其中flexible代表S曲线区间(越大代表压缩的最厉害,中间(x坐标0点周围)加速度越大;越小越接近匀加速。理想的S曲线的取值为4-6),i是在循环计算过程中的索引,从0开始,num为 length/2 大小(这样可以使得S曲线对称)。在项目中i的区间[0,1000), num=1000/2=500。这些参数均可以修改。 下面代码是基于STM32F103定期器2中断产生方波: /*********************这部分是MOTOR.H文件***********************/ #define ADDSPEEDNUM 500 //加速度脉冲数 #pragma pack(1) typedef struct _FreSpeed { uint16_t MaxPeriod; //最大速度比较器寄存器值 uint32_t MaxNum; //最大速度脉冲数 uint16_t IncPeriod[ADDSPEEDNUM]; //加减速脉冲比较器寄存器值 uint32_t IncNum; //加减速脉冲数 uint8_t AvrFlag; //匀速标志 uint8_t CurState; //当前状态 }FreSpeed; #pragma pack() enum SpeedFlagType { IncSpeedState, //加速状态 DecSpeedState, //加速状态 AvrSpeedState //加速状态 }; #define TIM2_Prescaler 0 #define TIM2_ClockDiv 0 /********************************************/ void STimer2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // timer2_ch1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;//PA0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = TIM2_Prescaler; //72/(0+1) = 72M TIM_TimeBaseStructure.TIM_ClockDivision = TIM2_ClockDiv;//0 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 60000; //(72M/60000/2)=600Hz TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//must TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable); UNMOTORY_TEAR;//使能电机 } void TIM2_IRQHandler(void) { uint16_t capture; static uint16_t iCount=0; static uint8_t SpeedMode = IncSpeedState; /* enter interrupt */ if ( TIM_GetITStatus(TIM2 , TIM_IT_CC1) != RESET ) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); capture = TIM_GetCapture1(TIM2); switch(SpeedMode) { case IncSpeedState: TIM_SetCompare1(TIM2, capture + MotorSpeed.IncPeriod[iCount++]); if(iCount == MotorSpeed.IncNum-1) { //rt_kprintf("Tim2 IRQ AddSpeedn"); SpeedMode = ( MotorSpeed.AvrFlag == RT_TRUE )?AvrSpeedState:DecSpeedState; } break; case AvrSpeedState: TIM_SetCompare1(TIM2, capture + MotorSpeed.MaxPeriod); MotorSpeed.MaxNum--; if(MotorSpeed.MaxNum ==0) { //rt_kprintf("Tim2 IRQ AvrSpeedn"); SpeedMode = DecSpeedState; } break; case DecSpeedState: TIM_SetCompare1(TIM2, capture + MotorSpeed.IncPeriod[iCount--]); if(iCount==0) { //rt_kprintf("Tim2 IRQ DecSpeedn"); SpeedMode = IncSpeedState; Set_Timer2_Isr_Disable(); } break; default: SpeedMode = IncSpeedState; //rt_kprintf("Tim2 IRQ Errorn"); break; } } } static void Set_Timer2_Isr_Enable(void) { ENMOTORY_TEAR; TIM_ClearFlag(TIM2, TIM_IT_CC1); TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE); //´ò¿ªÖÐ¶Ï TIM_Cmd(TIM2, ENABLE); } static void Set_Timer2_Isr_Disable(void) { //UNMOTORY_TEAR; TIM_Cmd(TIM2, DISABLE); TIM_ITConfig(TIM2, TIM_IT_CC1, DISABLE); } /************************************************************************ * ------------------------------------------------------------------------------------ * 2018/12/18 V1.0 CCPY 实现S型加减速算法 ************************************************************************/ uint8_t CalculateSModelLine(FreSpeed *iSpeed, float len,uint32_t PulseNum, float fre_min,float fre_max, float flexible) { int i; float TimClock= 72000000.0/(TIM2_Prescaler+1)/(TIM2_ClockDiv+1); float deno; float melo; float delt = fre_max-fre_min; if(delt<=0) { rt_kprintf("fre_max errorn"); return RT_FALSE; } if((PulseNum -2*len)>0) //存在匀速运动 { iSpeed->AvrFlag = RT_TRUE; iSpeed->MaxPeriod = (uint16_t)( TimClock/ (fre_max) / 2); iSpeed->MaxNum = PulseNum -2*len; iSpeed->IncNum = len; } else //不存在匀速运动 { len = PulseNum/2.0; iSpeed->AvrFlag = RT_FALSE; iSpeed->MaxPeriod = RT_FALSE; iSpeed->MaxNum = RT_FALSE; iSpeed->IncNum = len; } for(i=0; i melo = flexible * (i-len/2) / (len/2); deno = 1.0 / (1 + exp(-melo)); iSpeed->IncPeriod = (uint16_t)(TimClock / (delt * deno + fre_min) / 2); } return RT_TRUE; } static void SMoveTrans(float iMaxVel,int32_t PulseNum,float flexible) { float fre_min = 600; //最小速度600hz // float flexible = 8; float Addlen =ADDSPEEDNUM; if(CalculateSModelLine(&MotorSpeed,Addlen,PulseNum,fre_min,iMaxVel,flexible) ==RT_TRUE) { rt_kprintf("Calculate OKn"); Set_Timer2_Isr_Enable(); } else { rt_kprintf("Calculate Errorn"); } } void ST2Contrel(u32 cnt) { SMoveTrans(5000,cnt,8); Set_Timer2_Isr_Enable(); } 代码写完之后,keil5使用软件仿真,PA1引脚可以产生方波,即可出现如上图:频率从600hz-20000hz,再减速到600hz。以此可以粗略验证算法程序的正确性。 |
|
|
|
只有小组成员才能发言,加入小组>>
2444 浏览 0 评论
9148 浏览 4 评论
36829 浏览 19 评论
5036 浏览 0 评论
24813 浏览 34 评论
1549浏览 2评论
1774浏览 1评论
2220浏览 1评论
1575浏览 0评论
548浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 08:53 , Processed in 1.287371 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号