单极性步进电机
极性
单极性——电流只有一个方向——用ULN2003A驱动,比较简单
双极性——电流有两个方向——需要桥路驱动
典型的步进电机分类
两相式步进电机
- 低速下扭矩比较大
- 驱动方式多,控制比较简单
- 很多变种:四相五线、六线步进电机、八线步进电机
三相式步进电机
- 体积大
- 高速性能好
- 步距角比较小,控制精度更高,运行更稳定
- 驱动方式单一且复杂
- 本质(无刷直流电机)
步进电机工作原理
步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为"步距角",它的旋转是以固定的角度一步一步运行的。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
步进电机特征
- 步进电机要加驱动才可以运转,驱动信号,没有脉冲的时候,步进电机静止,加入适当的脉冲信号,就会以角度(称为步角)转动。转动的速度和脉冲的频率成正比。
- 步进电机具有瞬间启动和急速停止的特征。
- 改变脉冲的顺序,可以方便改变转动的方向。
步进电机驱动方法
步进电机不能直接接到工频交流或直流电源上工作,必须使用专用的步进电动机驱动器,它由脉冲发生控制单元,功率驱动单元,保护单元等组成。驱动单元与步进电动机直接耦合,也可以理解成步进电动机微机控制器的功率接口。
28BYJ-48步进电机名称解析
28:步进电机的有效最大外径是28毫米
B:表示是步进电机
Y:表示是永磁式
J:表示是减速型(减速比1:64)
48:表示四相八拍
换句话说,28BYJ-48的含义为外径28毫米四相八拍式永磁减速型步进电机。
28BYJ-48参数表
步距角和减速比是两个比较重要的参数
2、https://www.bilibili.com/read/cv11379422/
3、http://szdelco.com/m/jszx/jszx_209.html
从步进电机内部看,因为正对着的齿上的绕组是串联的,A、B、C、D四个绕组的一端都接到了5V,另一端通过按键接到GND,当某一个按键被按下了,如图中第二个按键被按下,则B和其对面的绕组都有电流流过,电生磁,所以中间转子的0和3端就被磁力吸住维持在一个平衡状态
参考链接的文章,我的理解是:
步距角
意思是:每64个脉冲(节拍)步进电机就会转5.625度。
驱动方式:单四拍
四个绕组按B、C、D、A这样的顺序节拍(也可按其他顺序,这个不一定),轮流通电一次,可以让中间的转子转过一个绕组的角度,比如转子的0端本来是对着正上方的,就转到了左上方,这样,再来一个四节拍,转子就将再转过一个齿的角度,到了左边,所以8个四节拍以后转子就转完了一圈,单节拍(这是指8 * 4个节拍)的步进角度(步进电机转动的角度)就可以算出来了:360度/(4*8)= 360/32 = 11.25度,所以每32个脉冲步进电机就会转11.25度
驱动方式:双四拍
顺序:AB-BC-CD-DA,A和B两个绕组同时通电,步距角与单四拍的一样,为11.25°/32
驱动方式:八拍
而八拍就类似这样的节拍:A-AB-B-BC-C-CD-D-DA,因为有两个绕组同时导电的情况,对转子的吸力一样,这样就又会产生一个新的转动角度,所以转子就会比原来4个节拍的多了4个转动的角度,这样再转一圈,就要(4+4)* 8 = 64个节拍了,所以360度/64 = 5.625度,这5.625度是步进电机转动的角度,也就是是下面讲到的输出轴的转动角度;
通俗理解:64个节拍,转子转动一周,步进电机转动5.625度,所以这种驱动方式下一个节拍步进电机转动的角度为:5.625/64 = 0.087890625度
这就是参数表步距角 5.625°/64的由来。
减速比
根据步进电机的内部拆解图,参考文章里介绍了中间的转子如果带动周边齿轮,最后带动输出轴转动,这部分不太好理解,我认为只需知道中间的齿轮是转子,也就是上面介绍步距角时的转子以及与最终的输出轴之间的关系就行了。
如果在八拍的转动方式下,64个节拍转子就转动一圈,根据减速比为1/64,意思就是说转子要转64圈,输出轴才转一圈,所以64*64 = 4096个节拍输出轴就转一圈,根据上面八拍的步距角可得,64个节拍已经让输出轴转了5.625度,所以5.625 * 64 = 360度
三种驱动方式的特点
单四拍:电流最小,扭矩最小
双四拍:电流最大,扭矩最大
八拍:电流居中,扭矩居中,常用
接线图
四相五线接法
公共线红5接5V电源,是所有线圈的供电端,通过红5线将线圈分成了四个,所以是四相
电流只能从红5引脚流入,从某一个相的引脚流出
蓝1,粉红2,黄3,橙4接到驱动IC的输出端,驱动IC的输入端接到单片机引脚
四相六线接法
驱动IC——ULN2003A
ULN2003是高耐压、大电流达林顿陈列,由七个NPN 达林顿管组成。所有单元共用发射极,每个单元采用开集电极输出。每一对达林顿都串联一个2.7K 的基极电阻,直接兼容TTL 和5V CMOS 电路,可以直接处理原先需要标准逻辑缓冲器来处理的数据。 ULN2003 工作电压高,工作电流大,灌电流可达500mA
应用:1、继电器驱动 2、直流照明驱动 3、步进电机驱动 4、电磁阀 5、直流无刷电机驱动
电路框图
左边为输入,右边为输出,中间是NPN达林顿管,当输入为1时,输出为0,输入为0时,输出为1
CubeMX配置
GPIO配置
32单片机引脚连接到ULN2003A驱动IC的输入引脚,IC再外接电机端子,所以PF1 ~ PF4要配置为推挽输出,默认输出低电平
TIM7配置
分频系数选择7199,然后重装载值设置为49,定时器溢出时间为5ms
程序
通过改变不同相通电的顺序,可以改变转动的方向
通过改变脉冲数量,可以控制转动的角度
通过改变脉冲的频率,可以改变转动的速度
手上的步进电机接线,红色(电源线5V)、橙色(A相)、黄色(B相)、粉红色(C相)、蓝色(D相)
Uniplar_Step_Motor.h
步进电机的结构体类型
//定义结构体类型
typedef struct
{
Status_t Status; //步进电机状态
Direction_t Direction; //步进电机方向
Speed_t Speed; //步进电机速度
uint8_t Circle; //步进电机转动圈数
Drive_Mode_t Drive_Mode; //步进电机驱动模式
uint16_t Pulse_Cnt; //步进电机脉冲计数(定时器计数)
uint16_t one_Circle_Pulse; //步进电机转动一圈的脉冲数
void (*Start_Or_Stop)(void);
void (*Direction_Adjust)(void);
void (*Speed_Adjust)(Speed_Change_t );
void (*Step_One_Puls)(void);
}Uniplar_Step_Motor_t;
Uniplar_Step_Motor.c
启动或停止步进电机
/*
* @name Start_Or_Stop
* @brief 启动或停止步进电机
* @param None
* @retval None
*/
static void Start_Or_Stop()
{
//如果本来是启动状态
if(Uniplar_Step_Motor.Status == Start_Status)
{
//改变步进电机状态
Uniplar_Step_Motor.Status = Stop_Status;
//关闭步进电机,单片机引脚输出低电平,经过ULN2003A反相器,输出高电平,线圈不导电
CLR_Motor_A;
CLR_Motor_B;
CLR_Motor_C;
CLR_Motor_D;
Uniplar_Step_Motor.Circle = 0; //圈数清零
}
else //本来是停止状态
{
//改变步进电机状态
Uniplar_Step_Motor.Status = Start_Status;
Uniplar_Step_Motor.Circle = Circle_Set_Value; //设置转动的圈数
Uniplar_Step_Motor.Pulse_Cnt = 0; //脉冲数清零
Display.Disp_Hex(Disp_NUM_6,Uniplar_Step_Motor.Circle,Disp_DP_OFF); //显示圈数
}
}
控制步进电机的正反转
/*
* @name Direction_Adjust
* @brief 控制步进电机正转或反转
* @param None
* @retval None
*/
static void Direction_Adjust()
{
if(Uniplar_Step_Motor.Status == Start_Status)
{
if(Uniplar_Step_Motor.Direction == Forward_Status)
{
Uniplar_Step_Motor.Direction = Reverse_Status; //反转
}
else
{
Uniplar_Step_Motor.Direction = Forward_Status; //正转
}
Uniplar_Step_Motor.Circle = Circle_Set_Value; //设置转动的圈数
Uniplar_Step_Motor.Pulse_Cnt = 0; //脉冲数清零
}
}
控制步进电机加减速
/*
* @name Speed_Adjust
* @brief 控制步进电机加减速
* @param Speed_Change:选择加速还是减速
* @retval None
*/
static void Speed_Adjust(Speed_Change_t Speed_Change)
{
uint8_t temp;
//判断电机是否在启动状态
if(Uniplar_Step_Motor.Status == Start_Status)
{
//加速
if(Speed_Change == Speed_up)
{
switch (Uniplar_Step_Motor.Speed)
{
case Speed_1: Uniplar_Step_Motor.Speed = Speed_2; temp = 2;break;
case Speed_2: Uniplar_Step_Motor.Speed = Speed_3; temp = 3;break;
case Speed_3: Uniplar_Step_Motor.Speed = Speed_4; temp = 4;break;
case Speed_4: Uniplar_Step_Motor.Speed = Speed_5; temp = 5;break;
case Speed_5: Uniplar_Step_Motor.Speed = Speed_6; temp = 6;break;
case Speed_6: Uniplar_Step_Motor.Speed = Speed_7; temp = 7;break;
case Speed_7: Uniplar_Step_Motor.Speed = Speed_8; temp = 8;break;
case Speed_8: Uniplar_Step_Motor.Speed = Speed_9; temp = 9;break;
case Speed_9: Uniplar_Step_Motor.Speed = Speed_9; temp = 9;break;
default: Uniplar_Step_Motor.Speed = Speed_6; temp = 6;break;
}
}
else
{
switch (Uniplar_Step_Motor.Speed)
{
case Speed_9: Uniplar_Step_Motor.Speed = Speed_8; temp = 8;break;
case Speed_8: Uniplar_Step_Motor.Speed = Speed_7; temp = 7;break;
case Speed_7: Uniplar_Step_Motor.Speed = Speed_6; temp = 6;break;
case Speed_6: Uniplar_Step_Motor.Speed = Speed_5; temp = 5;break;
case Speed_5: Uniplar_Step_Motor.Speed = Speed_4; temp = 4;break;
case Speed_4: Uniplar_Step_Motor.Speed = Speed_3; temp = 3;break;
case Speed_3: Uniplar_Step_Motor.Speed = Speed_2; temp = 2;break;
case Speed_2: Uniplar_Step_Motor.Speed = Speed_1; temp = 1;break;
case Speed_1: Uniplar_Step_Motor.Speed = Speed_1; temp = 1;break;
default: Uniplar_Step_Motor.Speed = Speed_6; temp = 6;break;
}
}
//更新定时器7ARR的值,改变脉冲频率
TIM7->ARR = Uniplar_Step_Motor.Speed;
//显示速度
Display.Disp_Hex(Disp_NUM_1,temp,Disp_DP_OFF);
}
}
根据驱动模式的不同,单片机输出一个节拍给到步进电机,控制转动,转动的方向根实际电机的接线,摆放有关系,应根据实物去调整
CallBack.c
通过4个按键控制步进电机,按键1控制电机启动和停止,按键2控制正反转,按键3控制加速,按键4控制减速
/*
* @name StaHAL_GPIO_EXTI_Callbackrt
* @brief 外部中断回调函数
* @param GPIO_Pin:触发外部中断的引脚
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//如果按键1被按下
if(GPIO_Pin == KEY1_Pin)
{
LED.LED_Fun(LED1,LED_Flip);
Uniplar_Step_Motor.Start_Or_Stop(); //控制步进电机启动或停止
}
//如果按键2被按下
if(GPIO_Pin == KEY2_Pin)
{
LED.LED_Fun(LED2,LED_Flip);
Uniplar_Step_Motor.Direction_Adjust(); //控制步进电机正反转
}
//如果按键3被按下
if(GPIO_Pin == KEY3_Pin)
{
LED.LED_Fun(LED3,LED_Flip);
Uniplar_Step_Motor.Speed_Adjust(Speed_up); //加速
}
//如果按键4被按下
if(GPIO_Pin == KEY4_Pin)
{
LED.LED_Fun(LED3,LED_Flip);
Uniplar_Step_Motor.Speed_Adjust(Speed_down); //减速
}
}
定时器每隔5ms中断一次,PSC:7199,ARR:49
/*
* @name HAL_TIM_PeriodElapsedCallback
* @brief 定时器中断回调函数
* @param htim:定时器指针变量
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//控制步进电机
if(htim->Instance == htim7.Instance)
{
//没转完指定圈数
if(Uniplar_Step_Motor.Circle > 0)
{
//电机转动一个脉冲
Uniplar_Step_Motor.Step_One_Puls();
//根据脉冲计数判断是否转了一圈
if(++Uniplar_Step_Motor.Pulse_Cnt == Uniplar_Step_Motor.one_Circle_Pulse)
{
Uniplar_Step_Motor.Pulse_Cnt = 0; //脉冲数清零,为下次准备
Uniplar_Step_Motor.Circle--; //已经转了1圈,圈数减1,启动时设置圈数为3
Display.Disp_Hex(Disp_NUM_6,Uniplar_Step_Motor.Circle,Disp_DP_OFF); //显示圈数
}
}
else //转完指定圈数
{
Uniplar_Step_Motor.Status = Stop_Status; //电机状态为停止
CLR_Motor_A;
CLR_Motor_B;
CLR_Motor_C;
CLR_Motor_D;
}
}
}
实验结果
1、在八拍的情况下,脉冲数为4096,则步进电机刚好转一圈
2、在单四拍的情况下,脉冲数为2048,则步进电机刚好转一圈,如果脉冲数为4096,则电机转两圈
3、在双四拍的情况下,脉冲数为2048,则步进电机刚好转一圈,如果脉冲数为4096,则电机转两圈
因为八拍让转子转一圈的脉冲数是64,单四拍或双四拍让转子转一圈的脉冲数都是32,是八拍的一半,在减速比都是64的情况下,让步进电机转一圈,则
八拍:64 * 64 = 4096
单四拍或双四拍:32 * 64 = 2048
所以当选择单四拍或双四拍的情况下,如果脉冲数仍然是4096,则步进电机就转两圈