最近在做毕业设计,其中涉及到了步进电机,本来用驱动器驱动得很顺利的,但是因为便携的需求改用了小得多驱动模块,tb买了用2个L9110的驱动模块,如下图.
电路图如下:
首先,我根据最常见的三种励磁方式写了程序,实现的时序如下图所示,图从左到右分别是一相励磁,二相励磁,一-二相励磁(8拍).
四个通道从上到下分别是A+,B+,A-,B-.
但是将这三种励磁时序分别输出到驱动模块后,电机产生
比较大的震动和噪声(与驱动器相比),只转动了1秒左右就停下来,震动依然持续.
PWM程序代码如下:
#include "stm32f10x.h"
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIM_Configuration_8beat(void);
void TIM_Configuration_2beat(void);
void TIM_Configuration_4beat(void);
void NVIC_Configuration(void);
u16 LowBitVal;
u16 HighBitVal;
void Delay(u32 ms)
{
u16 count;
while(ms)
{
count = 1800;
while(count--);
ms--;
}
}
int main()
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
//选择励磁方式
//TIM_Configuration_8beat();
//TIM_Configuration_4beat();
//TIM_Configuration_2beat();
while(1);
}
void RCC_Configuration()
{
SystemInit();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
}
void GPIO_Configuration()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; //PA0: A+; PA1: B+; PA2: A-; PA3: B-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void NVIC_Configuration()
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//一-二相励磁(8拍)
void TIM_Configuration_8beat()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
LowBitVal = 37500; //高电平时的比较值,即其持续时间
HighBitVal = 22500; //低电平时的比较值,即其持续时间
TIM_TimeBaseStructure.TIM_Period = 65535-1;
TIM_TimeBaseStructure.TIM_Prescaler = 100-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, 4, TIM_PSCReloadMode_Immediate);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //使用比较输出翻转模式,计数到达比较值自动翻转,并触发中断
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 7500-1; //初始比较值设置,能够产生移相效果
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 22500-1;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 37500-1;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 52500-1;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
//禁止计数溢出事件
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
//一相励磁
void TIM_Configuration_2beat()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
LowBitVal = 45000;
HighBitVal = 15000;
TIM_TimeBaseStructure.TIM_Period = 65535-1;
TIM_TimeBaseStructure.TIM_Prescaler = 150-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, 4, TIM_PSCReloadMode_Immediate);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 15000-1;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 30000-1;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 45000-1;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 60000-1;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
//二相励磁
void TIM_Configuration_4beat()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
LowBitVal = 30000;
HighBitVal = 30000;
TIM_TimeBaseStructure.TIM_Period = 65535-1;
TIM_TimeBaseStructure.TIM_Prescaler = 100-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, 4, TIM_PSCReloadMode_Immediate);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 15000-1;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 30000-1;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 45000-1;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 60000-1;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
其中断程序如下:
void TIM2_IRQHandler(void)
{
u16 capture = 0;
extern u16 LowBitVal;
extern u16 HighBitVal;
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
capture = TIM_GetCapture1(TIM2);
//通过控制高低电平时的比较值,控制了高低电平的持续时间,即占空比
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
TIM_SetCompare1(TIM2, capture + HighBitVal-1);//自动翻转后电平为高电平时,比较值=原值+HighBitVal
else
TIM_SetCompare1(TIM2, capture + LowBitVal-1); //自动翻转后电平为低电平时,比较值=原值+LowBitVal
}
else if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM2);
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
TIM_SetCompare2(TIM2, capture + HighBitVal-1);
else
TIM_SetCompare2(TIM2, capture + LowBitVal-1);
}
else if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
capture = TIM_GetCapture3(TIM2);
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2))
TIM_SetCompare3(TIM2, capture + HighBitVal-1);
else
TIM_SetCompare3(TIM2, capture + LowBitVal-1);
}
else if(TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
capture = TIM_GetCapture4(TIM2);
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3))
TIM_SetCompare4(TIM2, capture + HighBitVal-1);
else
TIM_SetCompare4(TIM2, capture + LowBitVal-1);
}
}
PWM失败之后,我参考了论坛的STM32产生SPWM来驱动步进电机的教程,因为我不是相关专业的,不懂脉冲调制的原理,直接实现了SPWM时序如下图,直接用查表法,SPWM数据来自教程里的matlab程序.
同样,四个通道从上到下分别是A+,B+,A-,B-.可以看出A+和A-,B+和B-是互补的,而且A和B相差90度相位,符合教程的正弦波要求
但是输出到驱动模块后,依然无法成功驱动步进电机,现象是:
步进电机转动了一个小角度后自动回到原位置,然后不断重复.震动依然存在,但是比PWM的小.
程序代码如下:
- #include "stm32f10x.h"
- void RCC_Configuration(void);
- void GPIO_Configuration(void);
- void TIM_Configuration(void);
- void NVIC_Configuration(void);
- /*****************************************
- * 函数名 : main
- ******************************************/
- int main()
- {
- RCC_Configuration();
- GPIO_Configuration();
- NVIC_Configuration();
- TIM_Configuration();
- while(1);
- }
- /*****************************************
- * 函数名 : RCC_Configuration
- ******************************************/
- void RCC_Configuration()
- {
- SystemInit();
- //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_TIM1,ENABLE);
- }
- /*****************************************
- * 函数名 : GPIO_Configuration
- ******************************************/
- void GPIO_Configuration()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; //PA8: A+; PA9: B+; PA10: A-; PA11: B-
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
- /*****************************************
- * 函数名 : NVIC_Configuration
- ******************************************/
- void NVIC_Configuration()
- {
- NVIC_InitTypeDef NVIC_InitStructure;
- #ifdef VECT_TAB_RAM
- NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
- #else
- NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
- #endif
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
-
- //TIM1更新事件NVIC设置
- NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /*****************************************
- * 函数名 : TIM_Configuration
- ******************************************/
- void TIM_Configuration()
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- TIM_TimeBaseStructure.TIM_Period = 16050 - 1;
- TIM_TimeBaseStructure.TIM_Prescaler = 100 - 1;
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
- TIM_ARRPreloadConfig(TIM1, ENABLE);
- TIM_ClearFlag(TIM1, TIM_FLAG_Update);
-
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
- TIM_OCInitStructure.TIM_Pulse = 0;
- TIM_OC1Init(TIM1, &TIM_OCInitStructure);
- TIM_OC2Init(TIM1, &TIM_OCInitStructure);
- TIM_OC3Init(TIM1, &TIM_OCInitStructure);
- TIM_OC4Init(TIM1, &TIM_OCInitStructure);
-
- TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
- TIM_CtrlPWMOutputs(TIM1, ENABLE);
- TIM_Cmd(TIM1, ENABLE);
- }
其中断程序为:
void TIM1_UP_IRQHandler(void)
{
#define TIM1_CH1_Pulse TIM1->CCR1 //A+
#define TIM1_CH2_Pulse TIM1->CCR2 //B+
#define TIM1_CH3_Pulse TIM1->CCR3 //A-
#define TIM1_CH4_Pulse TIM1->CCR4 //B-
//半个周期的正弦表
static vu16 SinwaveTable[128] = {
0,392,785,1177,1568,1958,2347,2735,3121,3505,3887,4267,4644,5018,5390,5758,
6122,6483,6840,7193,7542,7886,8225,8559,8889,9212,9531,9843,10150,10450,10744,11032,
11313,11587,11855,12115,12368,12613,12851,13081,13303,13517,13723,13921,14110,14291,14463,14627,
14782,14927,15064,15192,15311,15420,15520,15611,15692,15764,15826,15879,15922,15956,15980,15995,
16000,15995,15980,15956,15922,15879,15826,15764,15692,15611,15520,15420,15311,15192,15064,14927,
14782,14627,14463,14291,14110,13921,13723,13517,13303,13081,12851,12613,12368,12115,11855,11587,
11313,11032,10744,10450,10150,9843,9531,9212,8889,8559,8225,7886,7542,7193,6840,6483,
6122,5758,5390,5018,4644,4267,3887,3505,3121,2735,2347,1958,1568,1177,785,392
};
static u8 stepcounter_A = 0;
static u8 stepcounter_B = 64; //控制相位
static u8 WhosTurnFlag_A = 1;
static u8 WhosTurnFlag_B = 1;
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
//A+和A-交替产生半个周期的SPWM,组成一个完整的正弦波
//A+
if (WhosTurnFlag_A)
{
if (stepcounter_A > 127)
{
stepcounter_A = 0;
WhosTurnFlag_A = 0;
}
TIM1_CH1_Pulse = SinwaveTable[stepcounter_A];
stepcounter_A++;
}
//A-
else
{
if (stepcounter_A > 127)
{
stepcounter_A = 0;
WhosTurnFlag_A = 1;
}
TIM1_CH3_Pulse = SinwaveTable[stepcounter_A];
stepcounter_A++;
}
//B+和B-交替产生半个周期的SPWM,组成一个完整的正弦波
//B+
if (WhosTurnFlag_B)
{
if (stepcounter_B > 127)
{
stepcounter_B = 0;
WhosTurnFlag_B = 0;
}
TIM1_CH2_Pulse = SinwaveTable[stepcounter_B];
stepcounter_B++;
}
//B-
else
{
if (stepcounter_B > 127)
{
stepcounter_B = 0;
WhosTurnFlag_B = 1;
}
TIM1_CH4_Pulse = SinwaveTable[stepcounter_B];
stepcounter_B++;
}
}
TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update);
}
对于一些基本问题的排除:1. 供电: 采用的是24V转5V降压模块,输出5V/3A,我用驱动器时使用0.3A即可驱动步进电机,所以供电应该没有问题;
2. 接线: 步进电机的接线方式与使用驱动器时的相同,由于驱动器能够顺利地驱动步进电机,所以接线应该没有问题;
3. 工作频率: 我需求的运转速度不高,不超过50Hz,而这种速度在驱动器上能够顺利运转,因此不是速度过高的问题.
希望论坛的各位大神能够帮我这个门外汉分析一下是哪里出了问题,事关毕业,感激不尽!
本帖最后由 lizoyu 于 2016-3-27 22:36 编辑