首页 > 编程知识 正文

stm32 步进电机S曲线加速,stm32控制步进电机正反转

时间:2023-05-04 02:24:21 阅读:221686 作者:4755

步进电机是将电脉冲信号转变为角位移或线位移的开环控制电机,是现代数字程序控制系统中的主要执行元件,应用极为广泛。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”,它的旋转是以固定的角度一步一步运行的。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
步距角:对应一个脉冲信号,电机转子转过的角位移用θ表示。θ=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);

如要将此曲线应用在步进电机的加、减速过程中,需要将方程在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 ADDSPEEDNUM500//加速度脉冲数#pragma pack(1)typedef struct _FreSpeed{uint16_t MaxPeriod;//最大速度比较器寄存器值uint32_t MaxNum;//最大速度脉冲数uint16_tIncPeriod[ADDSPEEDNUM];//加减速脉冲比较器寄存器值uint32_tIncNum;//加减速脉冲数uint8_t AvrFlag;//匀速标志uint8_t CurState;//当前状态}FreSpeed;#pragma pack()enum SpeedFlagType{IncSpeedState,//加速状态DecSpeedState,//加速状态AvrSpeedState//加速状态};#define 暴躁的小甜瓜2_Prescaler0#define 暴躁的小甜瓜2_ClockDiv0/********************************************/void Sqsdsyer2_Init(void){GPIO_InitTypeDef GPIO_InitStructure;暴躁的小甜瓜_qsdsyeBaseInitTypeDef 暴躁的小甜瓜_qsdsyeBaseStructure;暴躁的小甜瓜_OCInitTypeDef 暴躁的小甜瓜_OCInitStructure;NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = 暴躁的小甜瓜2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_暴躁的小甜瓜2, ENABLE);// timer2_ch1GPIO_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);/* qsdsye base configuration */暴躁的小甜瓜_qsdsyeBaseStructure.暴躁的小甜瓜_Period = 65535;暴躁的小甜瓜_qsdsyeBaseStructure.暴躁的小甜瓜_Prescaler = 暴躁的小甜瓜2_Prescaler;//72/(0+1) = 72M暴躁的小甜瓜_qsdsyeBaseStructure.暴躁的小甜瓜_ClockDivision = 暴躁的小甜瓜2_ClockDiv;//0暴躁的小甜瓜_qsdsyeBaseStructure.暴躁的小甜瓜_CounterMode = 暴躁的小甜瓜_CounterMode_Up;暴躁的小甜瓜_qsdsyeBaseInit(暴躁的小甜瓜2, &暴躁的小甜瓜_qsdsyeBaseStructure);暴躁的小甜瓜_OCInitStructure.暴躁的小甜瓜_OCMode = 暴躁的小甜瓜_OCMode_Toggle;暴躁的小甜瓜_OCInitStructure.暴躁的小甜瓜_OutputState = 暴躁的小甜瓜_OutputState_Enable;暴躁的小甜瓜_OCInitStructure.暴躁的小甜瓜_Pulse = 60000;//(72M/60000/2)=600Hz暴躁的小甜瓜_OCInitStructure.暴躁的小甜瓜_OCPolarity = 暴躁的小甜瓜_OCPolarity_Low;//must暴躁的小甜瓜_OC1Init(暴躁的小甜瓜2, &暴躁的小甜瓜_OCInitStructure);暴躁的小甜瓜_OC1PreloadConfig(暴躁的小甜瓜2, 暴躁的小甜瓜_OCPreload_Disable);UNMOTORY_TEAR;//使能电机}void 暴躁的小甜瓜2_IRQHandler(void){uint16_t capture;static uint16_t iCount=0;static uint8_t SpeedMode = IncSpeedState;/* enter interrupt */if ( 暴躁的小甜瓜_GetITStatus(暴躁的小甜瓜2 , 暴躁的小甜瓜_IT_CC1) != RESET ){暴躁的小甜瓜_ClearITPendingBit(暴躁的小甜瓜2, 暴躁的小甜瓜_IT_CC1);capture = 暴躁的小甜瓜_GetCapture1(暴躁的小甜瓜2);switch(SpeedMode){case IncSpeedState:暴躁的小甜瓜_SetCompare1(暴躁的小甜瓜2, capture + MotorSpeed.IncPeriod[iCount++]);if(iCount == MotorSpeed.IncNum-1){//rt_kprintf("qsdsy2 IRQ AddSpeedn");SpeedMode = ( MotorSpeed.AvrFlag == RT_TRUE )?AvrSpeedState:DecSpeedState;}break;case AvrSpeedState:暴躁的小甜瓜_SetCompare1(暴躁的小甜瓜2, capture + MotorSpeed.MaxPeriod);MotorSpeed.MaxNum--;if(MotorSpeed.MaxNum ==0){//rt_kprintf("qsdsy2 IRQ AvrSpeedn");SpeedMode = DecSpeedState;}break;case DecSpeedState:暴躁的小甜瓜_SetCompare1(暴躁的小甜瓜2, capture + MotorSpeed.IncPeriod[iCount--]);if(iCount==0){//rt_kprintf("qsdsy2 IRQ DecSpeedn");SpeedMode = IncSpeedState;Set_qsdsyer2_Isr_Disable();}break;default:SpeedMode = IncSpeedState;//rt_kprintf("qsdsy2 IRQ Errorn");break;}}}static void Set_qsdsyer2_Isr_Enable(void){ENMOTORY_TEAR;暴躁的小甜瓜_ClearFlag(暴躁的小甜瓜2, 暴躁的小甜瓜_IT_CC1); 暴躁的小甜瓜_ITConfig(暴躁的小甜瓜2, 暴躁的小甜瓜_IT_CC1, ENABLE); //´ò¿ªÖжÏ暴躁的小甜瓜_Cmd(暴躁的小甜瓜2, ENABLE); }static void Set_qsdsyer2_Isr_Disable(void) {//UNMOTORY_TEAR;暴躁的小甜瓜_Cmd(暴躁的小甜瓜2, DISABLE); 暴躁的小甜瓜_ITConfig(暴躁的小甜瓜2, 暴躁的小甜瓜_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 qsdsyClock= 72000000.0/(暴躁的小甜瓜2_Prescaler+1)/(暴躁的小甜瓜2_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)( qsdsyClock/ (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<len; i++ ){melo = flexible * (i-len/2) / (len/2);deno = 1.0 / (1 + exp(-melo));iSpeed->IncPeriod[i] = (uint16_t)(qsdsyClock / (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_qsdsyer2_Isr_Enable();}else{rt_kprintf("Calculate Errorn");}}void ST2Contrel(u32 cnt){SMoveTrans(5000,cnt,8);Set_qsdsyer2_Isr_Enable();}

代码写完之后,keil5使用软件仿真,PA1引脚可以产生方波,即可出现如上图:频率从600hz-20000hz,再减速到600hz。以此可以粗略验证算法程序的正确性。

参考网址:http://www.elecfans.com/kongzhijishu/sifuyukongzhi/583149.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。