本文驱动的步进电机为较基础的28BYJ-48步进电机,属于入门级水平,比较好驱动,价格也是相对便宜的,因而步进电机驱动开篇就讲他了!
1、步进电机驱动原理
之前在网上看到一张动态图是很详细的描述了步进电机的驱动过程,没有了解专业知识的同学也可以看下,比较通俗易懂!
下面我们回到我们本文用到的步进电机,常见的电机还有驱动如下所示,当然ULN2003驱动模块也有贴片式的,不过都差不多,是没有很大区别的,可以自行选用!
步进电机的驱动方式可以描述为:
- 1、步进电机是一种将电脉冲转化为角位移的执行机构。
- 2、当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。
- 3、通过控制脉冲个来控制角位移量,从而达到准确定位的目的。
- 4、同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
具体到本文讲的电机,28BYJ48步进电机而言:
- 1、驱动电压为DC5V—DC12V。
- 2、每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。
- 3、当通电状态的改变完成一个循环时,转子转过一个齿距。
- 4、四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A)双(双相绕组通电)四拍(AB-BC-CD-DA-AB),八拍(A-AB-B-BC-C-CD-D-DA-A)。
2、步进电机驱动设计
上面讲的拍数对应的关系图如下所示:
这里我把他列成表格:
四项八拍
绕组 | 一 | 二 | 三 | 四 | 五 | 六 | 七 | 八 |
---|---|---|---|---|---|---|---|---|
A | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 |
B | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
C | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
D | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
对应示意图
四项单四拍
绕组 | 一 | 二 | 三 | 四 |
---|---|---|---|---|
A | 0 | 1 | 1 | 1 |
B | 1 | 0 | 1 | 1 |
C | 1 | 1 | 0 | 1 |
D | 1 | 1 | 1 | 0 |
对应示意图
四项双四拍
绕组 | 一 | 二 | 三 | 四 |
---|---|---|---|---|
A | 0 | 0 | 1 | 1 |
B | 1 | 0 | 0 | 0 |
C | 1 | 1 | 1 | 0 |
D | 0 | 1 | 1 | 0 |
关于转动角度的计算:
28BYJ-48步进电动机的步距角是5.625度,也就是说每个脉冲转5.625度而360/5.625=64,所以64个脉冲转一圈,但这是指电机的转子而转子到输出轴有齿轮减速器连接,减速比为64,那么转子转64圈,输出轴转一圈,所以结论是64*64=4096个脉冲才能使输出轴转一圈。
对应四拍和八拍的计算角度来看:
8拍计算公式 = 64角度/360/8,4拍计算公式 = 64角度/360/4。
3、步进电机驱动编写
首先我们在cubemx中初始化对应的引脚:
根据上面讲到的时序编写四项单四拍对应的程序
根据上面讲到的时序编写四项双四拍对应的程序
根据上面讲到的时序编写四项八拍对应的程序
注意上面四项四拍和八拍额区别就在于精度,其他其实没什么区别的,当然肯定是八拍的精度高于四拍的:
当然要想做的更好一点,我们还可以准备下方向速度函数,改变方向其实就是把前面说的四拍八拍这个顺序倒着来一下就行了,也是很方便的!
这里我还加入了角度函数,也是在上面讲到的角度计算方法里面讲的!
主函数中调用情况如下,这里我们让他正转180度,在反转180度
4、源码
uln2003.c
/*
* uln2003.c
*
* Created on: Feb 17, 2022
* Author: LX
*/
#include "uln2003.h"
void motor_stop()
{
MA_LOW;MB_LOW;MC_LOW;MD_LOW;
}
void motor_start_sig4(uint8_t motor,uint8_t speed) //四项单四拍
{
switch(motor)
{
// 0111 1011 1101 1110,这个过程逆向为反向
case 0:
MA_LOW;MB_HIGH;MC_HIGH;MD_HIGH;
break;
case 1:
MA_HIGH;MB_LOW;MC_HIGH;MD_HIGH;
break;
case 2:
MA_HIGH;MB_HIGH;MC_LOW;MD_HIGH;
break;
case 3:
MA_HIGH;MB_HIGH;MC_HIGH;MD_LOW;
break;
}
HAL_Delay(speed);
motor_stop();
}
void motor_start_dou4(uint8_t motor,uint8_t speed) //四项双四拍
{
switch(motor)
{
// 0110 0011 1011 1100,这个过程逆向为反向
case 0:
MA_LOW;MB_HIGH;MC_HIGH;MD_LOW;
break;
case 1:
MA_LOW;MB_LOW;MC_HIGH;MD_HIGH;
break;
case 2:
MA_HIGH;MB_LOW;MC_HIGH;MD_HIGH;
break;
case 3:
MA_HIGH;MB_HIGH;MC_LOW;MD_LOW;
break;
}
HAL_Delay(speed);
motor_stop();
}
void motor_start_eig(uint8_t motor,uint8_t speed) //四项八拍
{
switch(motor)
{
// 0111 0011 1011 1001 1101 1100 1110 0110,这个过程逆向为反向
case 0:
MA_LOW;MB_HIGH;MC_HIGH;MD_HIGH;
break;
case 1:
MA_LOW;MB_LOW;MC_HIGH;MD_HIGH;
break;
case 2:
MA_HIGH;MB_LOW;MC_HIGH;MD_HIGH;
break;
case 3:
MA_HIGH;MB_LOW;MC_HIGH;MD_LOW;
break;
case 4:
MA_HIGH;MB_HIGH;MC_LOW;MD_HIGH;
break;
case 5:
MA_HIGH;MB_HIGH;MC_LOW;MD_HIGH;
break;
case 6:
MA_HIGH;MB_HIGH;MC_HIGH;MD_LOW;
break;
case 7:
MA_LOW;MB_HIGH;MC_HIGH;MD_LOW;
break;
}
HAL_Delay(speed);
motor_stop();
}
uint8_t motor;
void motor_uln2003(uint8_t dir,uint8_t speed)
{
for(uint8_t i = 0;i<8;i++)
{
if(dir == 1)
{
motor++;
if(motor > 7)motor = 0;
}
else
{
if(motor == 0)motor = 8;
motor--;
}
motor_start_eig(motor,speed);
}
}
void motor_angle(uint8_t dir,uint16_t angle,uint8_t speed)
{
static uint8_t flag = 1;
if(flag == 1)
{
for(uint16_t num;num<64*angle/45;num++)
{
motor_uln2003(dir,speed);
flag = 0;
}
flag = 1;
}
}
uln2003.h
#ifndef ULN2003_H_
#define ULN2003_H_
#include "main.h"
#define MA_HIGH HAL_GPIO_WritePin(INTC_GPIO_Port, INTC_Pin, GPIO_PIN_SET)
#define MA_LOW HAL_GPIO_WritePin(INTC_GPIO_Port, INTC_Pin, GPIO_PIN_RESET)
#define MB_HIGH HAL_GPIO_WritePin(INTD_GPIO_Port, INTD_Pin, GPIO_PIN_SET)
#define MB_LOW HAL_GPIO_WritePin(INTD_GPIO_Port, INTD_Pin, GPIO_PIN_RESET)
#define MC_HIGH HAL_GPIO_WritePin(INTB_GPIO_Port, INTB_Pin, GPIO_PIN_SET)
#define MC_LOW HAL_GPIO_WritePin(INTB_GPIO_Port, INTB_Pin, GPIO_PIN_RESET)
#define MD_HIGH HAL_GPIO_WritePin(INTA_GPIO_Port, INTA_Pin, GPIO_PIN_SET)
#define MD_LOW HAL_GPIO_WritePin(INTA_GPIO_Port, INTA_Pin, GPIO_PIN_RESET)
void motor_stop();
void motor_start_sig4(uint8_t motor,uint8_t speed);
void motor_start_dou4(uint8_t motor,uint8_t speed);
void motor_start_eig(uint8_t motor,uint8_t speed);
void motor_uln2003(uint8_t dir,uint8_t speed);
void motor_angle(uint8_t dir,uint16_t angle,uint8_t speed);
#endif /* ULN2003_H_ */