利用stm32控制步进电机 速度&&加速度控制

利用stm32控制步进电机

尝试用42系步进电机做倒立摆,总结步进电机控制

  • stm32f407控制
  • Microstep Driver驱动器

一、Miocrostep Driver驱动

高精度系列二相混合式步进电机多细分驱动器

1、使用说明:

1、VCC&GND:20~40V DC;
2、A+A- B+B-:接二相混合式步进电机的2相;
3、工作额定电流:3A;
4、拨码开关SW1~SW8:下拨代表ON(驱动器上有文字指示),上拨代表OFF;
5、拨码开关SW4~SW6:选择下拨(ON)或(OFF)时,M403列对应电流值;
6、拨码开关SW1~SW3:ON和OFF选择对应细分数;
7、Ena- Ena+:使能信号输入;(拉低使能
8、Pul- Pul+:脉冲信号输入;
9、Dir- Dir+:方向信号输入; (从正面看,拉高逆时针,拉低正时针

2、特性:

1、外壳上标注参数直观清晰;
2、单/双脉冲输入兼容;
3、双极恒流斩波方式驱动、微步控制、电源损耗低效率高;;
4、直流宽电压范围供电,DC20~40V;
5、最大驱动电流3A/相;
6、高细分:最高可定制为256细分;
7、所有控制信号光电隔离;
8、输入脉冲频率最大400KHz;
9、驱动器外壳与地电绝缘。
10、静止时锁定电流可在0~100%范围内选择。
11、可通过调节改善电机振动。
12、输入信号TTL兼容,同时可接受差分信号输入;
13、20KHz斩波频率;
14、高可靠性:采用多层板和表面贴封,功率器件留有足够裕量;

二、控制

步进电机通过发送脉冲信号控制,每收到一个脉冲就转一个步进角,因此,在细分数数一定的情况下

  • 加大(减小)脉冲频率,可以加(减)转速
  • 加大(减小)改变脉冲频率的速率,可以加(减)加速度

1、初始化设置

脉冲生成有3种方法:延时PWM中断,后两种可靠性较高,这里采用定时器中断生成脉冲

1、使能i/o

void DJ_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6; //DRIVER_DIR/DRIVER_OE
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    //--------------------------------------------------------------    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //STEP_PULSE
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //---------------------------------------------------------------
    GPIO_SetBits(GPIOE,GPIO_Pin_5);//拉高,正转
    GPIO_ResetBits(GPIOE,GPIO_Pin_6);//拉低,使能
}

2、定时器配置

void TIM4_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); 

    TIM_TimeBaseInitStructure.TIM_Period = arr; 
    TIM_TimeBaseInitStructure.TIM_Prescaler=psc; 
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;

    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); 

    NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM4,ENABLE); 
}

配置中断周期为10us

TIM4_Int_Init(10-1,84-1);   //84M/84=1Mhz(10^6)计数频率,计数10次为10us  (生成脉冲)

2、控制转速

我们利用中断生成脉冲,思想如下:从第一次进中断开始计数,进指定次数为一个周期,前若干次输出高电平,其余输出低电平。控制中断次数判断即可控制周期(转速)和高电平持续时间。

程序截选如下

//全局变量-------------------------------------------------------------------
u8 Start_Flag=0; //电机启动/锁定标志
u16 Pluse_High=10; //脉冲高电平中断次数      1->10us
u16 Pluse_Period=100;//脉冲周期中断次数 (转速)

//脉冲中断服务函数------------------------------------------------------------
u32 TimeCount=0;//进中断计数
void TIM4_IRQHandler(void)//10us
{
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)//溢出中断
    {       
        if(Start_Flag==0)
            GPIO_SetBits(GPIOE,GPIO_Pin_6);//motor_disable;
        else if(Start_Flag==1)
        {
            GPIO_ResetBits(GPIOE,GPIO_Pin_6);//motor_enable;
            TimeCount++;

            if(TimeCount//脉冲高电平
                GPIO_SetBits(GPIOB,GPIO_Pin_8);
            else if(TimeCount>Pluse_High)
                GPIO_ResetBits(GPIOB,GPIO_Pin_8);

            if(TimeCount>Pluse_Period)//周期控制(转速控制)
                TimeCount=0
        }
    }
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //Çå³ýÖжϱê־λ
}

注意到中断周期为:T=Pluse_Period * t
则脉冲频率为:f=1/T=1/(Pluse_Period * t), 注意此值与速度成正比
因此,虽然可以简单地通过控制全局变量Pluse_Period控制转速,但是此值与转速成反比例关系,不适合控制;

较好的方法是,设全局变量temp_x ,使Pluse_Period=1000/temp_x (1000可以为任意常数)
则脉冲频率为:f=1/T=1/(Pluse_Period * t)=temp_x/(1000*t)
此时全局变量temp_x 与转速成正比,适于控制

3、加速度控制

使用temp_x修改速度控制后,可以方便地进行加速度控制,按一定中断次数均匀地使temp_x递增(减)即可
程序修改如下:

#define MaxSpeed 20
//全局变量-------------------------------------------------------------------
float temp_x=1;
float Acc=1.5;//加速度
u32 TimeCount=0;
u32 AccCount=0;
//加速度控制函数--------------------------------------------------------------
void acc(float a)
{
    temp_x+=a;
    if(temp_x>0)//temp_x==0时发生换向
    {
        GPIO_ResetBits(GPIOE,GPIO_Pin_5);
        Pluse_Period=1000/temp_x;
    }
    else
    {
        GPIO_SetBits(GPIOE,GPIO_Pin_5);
        Pluse_Period=-1000/temp_x;
    }

    if(Pluse_Period//控制速度上限,防止电机抱死
        Pluse_Period=MaxSpeed ;
}

//修改后的脉冲中断服务函数------------------------------------------------------------
u32 TimeCount=0;//进中断计数
void TIM4_IRQHandler(void)//10us
{
    if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)//溢出中断
    {       
        if(Start_Flag==0)
            GPIO_SetBits(GPIOE,GPIO_Pin_6);//motor_disable;
        else if(Start_Flag==1)
        {
            GPIO_ResetBits(GPIOE,GPIO_Pin_6);//motor_enable;
            TimeCount++;
            AccCount++;

            if(TimeCount//脉冲高电平
                GPIO_SetBits(GPIOB,GPIO_Pin_8);
            else if(TimeCount>Pluse_High)
                GPIO_ResetBits(GPIOB,GPIO_Pin_8);

            if(TimeCount>Pluse_Period)//周期控制(转速控制)
                TimeCount=0
        }

        if(AccCount>1000)
            AccCount=0,acc(ACC);
    }
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //Çå³ýÖжϱê־λ
}

经测试,上述代码可以很好地执行步进电机的 速度&加速度 控制任务

你可能感兴趣的:(嵌入式)