步进电机是将电脉冲信号转变为角位移或线位移,通过控制施加在电机线圈上的电脉冲顺序、频率和数量,可以控制步进电机的转向、速度和旋转角度。
配合以直线运动执行机构(螺纹丝杆)或齿轮箱装置,更可以实现更加复杂、精密的线性运动控制要求。
在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响。
当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”。
它的旋转是以固定的角度一步一步运行的,可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的。同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
步进电机28BYJ-48名称含义:
28:表示步进电机的有效最大外径为28毫米
B:表示步进电机“步”字汉语拼音首字母
Y:表示永磁式“永”字汉语拼音首字母,永磁式表示转子为永磁体
J:表示减速型“减”字汉语拼音首字母
BYJ:组合即为永磁式减速步进电机
48:表示四相八拍,后续介绍
5V:表示额定电压为5V,且为直流电压
此步进电机有五根线(12345),5为公共端,假设5接VCC,1-4接GND。那么1-5、2-5、3-5、4-5为四条通路,称为五线四相。
如果1-5导通,然后1-5断开的同时2-5导通,接着2-5断开,3-5导通,之后3-5断开,4-5导通,之后4-5断开,1-5导通。如此循环下去,称之为四拍。
因为四拍的步距角过大,所以可以选择在两路交接的时候,让两路都导通一段时间,可以减少步距角。如下表八拍的表示方法:
若假设正转的分配顺序是1-8,则反转的分配顺序就是8-1。
查阅28BYJ-48的手册,其步距角是5.625/64度,减速比是1/64。
控制步进电机,说白了就是控制GPIO的高低电平。
此步进电机需要驱动板驱动,使用ULN2003,实物如下图所示。
当IN输入为0时,控制引脚不工作;当IN输入为1时,控制引脚输出为1。
只需要对IN1-4分别设置不同的电平,便可实现电机的运转和方向控制。
通过cubeMX设置外部时钟还有GPIO输出,使用STM32F407ZGT6。
设置时钟树
生成代码。
最终代码:
//为了编程方便,首先宏定义一些代码
#define MOTOR_A_H HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET);
#define MOTOR_A_L HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET);
#define MOTOR_B_H HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_SET);
#define MOTOR_B_L HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET);
#define MOTOR_C_H HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_SET);
#define MOTOR_C_L HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET);
#define MOTOR_D_H HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);
#define MOTOR_D_L HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
void MOTOR_CONTROL(uint16_t direction)//对电机进行控制,使用八拍
{
static uint8_t step=0;
if(1== direction)//控制电机方向
{
if(0==step)
{
step=8;
}
step--;
}
else if(0== direction)
{
step++;
if(8==step)
{
step=0;
}
}
if(0==step)
{
MOTOR_A_H;
MOTOR_B_L;
MOTOR_C_L;
MOTOR_D_L;
}
else if(1==step)
{
MOTOR_A_H;
MOTOR_B_H;
MOTOR_C_L;
MOTOR_D_L;
}
else if(2==step)
{
MOTOR_A_L;
MOTOR_B_H;
MOTOR_C_L;
MOTOR_D_L;
}
else if(3==step)
{
MOTOR_A_L;
MOTOR_B_H;
MOTOR_C_H;
MOTOR_D_L;
}
else if(4==step)
{
MOTOR_A_L;
MOTOR_B_L;
MOTOR_C_H;
MOTOR_D_L;
}
else if(5==step)
{
MOTOR_A_L;
MOTOR_B_L;
MOTOR_C_H;
MOTOR_D_H;
}
else if(6==step)
{
MOTOR_A_L;
MOTOR_B_L;
MOTOR_C_L;
MOTOR_D_H;
}
else if(7==step)
{
MOTOR_A_H;
MOTOR_B_L;
MOTOR_C_L;
MOTOR_D_H;
}
}
void Step_MOTOR_Start(uint16_t angle,uint8_t direction)//电机启动
{
int i=0;
int pulse =(int)((float)(angle*64/5.625));//脉冲与步距角的关系
for(i=0;i