尝试用42系步进电机做倒立摆,总结步进电机控制
高精度系列二相混合式步进电机多细分驱动器
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+:方向信号输入; (从正面看,拉高逆时针,拉低正时针)
1、外壳上标注参数直观清晰;
2、单/双脉冲输入兼容;
3、双极恒流斩波方式驱动、微步控制、电源损耗低效率高;;
4、直流宽电压范围供电,DC20~40V;
5、最大驱动电流3A/相;
6、高细分:最高可定制为256细分;
7、所有控制信号光电隔离;
8、输入脉冲频率最大400KHz;
9、驱动器外壳与地电绝缘。
10、静止时锁定电流可在0~100%范围内选择。
11、可通过调节改善电机振动。
12、输入信号TTL兼容,同时可接受差分信号输入;
13、20KHz斩波频率;
14、高可靠性:采用多层板和表面贴封,功率器件留有足够裕量;
步进电机通过发送脉冲信号控制,每收到一个脉冲就转一个步进角,因此,在细分数数一定的情况下
脉冲生成有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 (生成脉冲)
我们利用中断生成脉冲,思想如下:从第一次进中断开始计数,进指定次数为一个周期,前若干次输出高电平,其余输出低电平。控制中断次数判断即可控制周期(转速)和高电平持续时间。
程序截选如下
//全局变量-------------------------------------------------------------------
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 与转速成正比,适于控制
使用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); //Çå³ýÖжϱê־λ
}
经测试,上述代码可以很好地执行步进电机的 速度&加速度 控制任务