本文采用了28BYJ48步进电机,其中末尾的48表示4相8拍的驱动方式。
ULN2003驱动模块接受来自控制器的脉冲信号,并将其转换为步进电机的相位信号,从而驱动电机按预定的步进角度转动,由于本文采用四相八拍的步进电机,四相表示电机的绕组组数为四组。拍则表示通电状态的改变次数,因此可得在四相八拍工作模式下驱动器各引脚通电状态如下表:
表1 四相八拍引脚电平状态变化表
引脚 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
IN1 | 0 | 0 | 0 | |||||
IN2 | 0 | 0 | 0 | |||||
IN3 | 0 | 0 | 0 | |||||
IN4 | 0 | 0 | 0 |
由上表可得每一次改变通电状态即为一拍,每一拍步进角度为电机参数5.625*1/64,减速比为1/64,有如下公式:
旋转一周所需拍数 = 360/步进角度
计算可得本文选取的步进电机转一周需要的拍数N为4096,即电平发生4096次变化。由于各个引脚之间的电平变化八拍为一个周期,因此在软件程序中驱动电机旋转的函数本文使用一个周期为一个基础步,一个基础步的函数如下:
void Stepper_RotateByStep(bool direction,uint16_t step,uint16_t Delay_Time){
uint16_t STEP = 0;
for(uint32_t i=0;i<step;i++){
if(direction){
STEP++;
if(STEP > 7){
STEP=0;
}
}else{
if(STEP < 1){
STEP=8;
}
STEP--;
}
switch(STEP)
{
case 0: // 第一个节拍
GPIO_WriteBit(GPIOA, IN1, Bit_SET);
GPIO_WriteBit(GPIOA, IN2 | IN3 | IN4, Bit_RESET);
break;
case 1: // 第二个节拍
GPIO_WriteBit(GPIOA, IN1 | IN2, Bit_SET);
GPIO_WriteBit(GPIOA, IN3 | IN4, Bit_RESET);
break;
case 2: // 3
GPIO_WriteBit(GPIOA, IN2, Bit_SET);
GPIO_WriteBit(GPIOA, IN1 | IN3 | IN4, Bit_RESET);
break;
case 3: // 4
GPIO_WriteBit(GPIOA, IN2 | IN3, Bit_SET);
GPIO_WriteBit(GPIOA, IN1 | IN4, Bit_RESET);
break;
case 4: // 5
GPIO_WriteBit(GPIOA, IN3, Bit_SET);
GPIO_WriteBit(GPIOA, IN1 | IN2 | IN4, Bit_RESET);
break;
case 5: // 6
GPIO_WriteBit(GPIOA, IN3 | IN4, Bit_SET);
GPIO_WriteBit(GPIOA, IN1 | IN2, Bit_RESET);
break;
case 6: // 7
GPIO_WriteBit(GPIOA, IN4, Bit_SET);
GPIO_WriteBit(GPIOA, IN1 | IN2 | IN3, Bit_RESET);
break;
case 7: // 8
GPIO_WriteBit(GPIOA, IN1 | IN4, Bit_SET);
GPIO_WriteBit(GPIOA, IN2 | IN3, Bit_RESET);
break;
default: break;
}
Delay_ms(2);
Delay_ms(Delay_Time);
Stepper_Stop();
}
}
此外还有步进电机的初始化函数和停止函数
void Setpper_GPIOInit(void){
config(GPIOA,IN1,RCC_APB2Periph_GPIOA,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
config(GPIOA,IN2,RCC_APB2Periph_GPIOA,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
config(GPIOA,IN3,RCC_APB2Periph_GPIOA,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
config(GPIOA,IN4,RCC_APB2Periph_GPIOA,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
GPIO_ResetBits(GPIOA,IN1|IN2|IN3|IN4);
}
void Stepper_Stop(void)
{
GPIO_ResetBits(GPIOA,IN1|IN2|IN3|IN4);
}
通过统计调用Stepper_RotateByStep()次数即可计算当前旋转角度,通过保存当前旋转角度即可实现保存当前所在位置。