STM32控制ULN2003驱动步进电机28BYJ-48

步进电机

步进电动机又称脉冲电动机,是一种将电脉冲信号转换成相应角位移或线位移的电动机。每输入一个脉冲信号,转子就转动一个角度或前进一步,其输出的角位移或线位移与输入的脉冲数成正比,转速与脉冲频率成正比。
传送门:一文搞懂步进电机特性、原理及驱动器设计

28BYJ-48步进电机

在这里插入图片描述

28BYJ-48永磁式减速单极性步进电机

  • 28:步进电机的有效最大外径是28毫米
  • B:表示是步进电机
  • Y:表示是永磁式
  • J:表示是减速型(减速比1:64)
  • 48:表示四相八拍
    传送门:28BYJ-48单极性步进电机

28BYJ-48步进电机的励磁方式

在这里插入图片描述

  • 1相励磁

    励磁控制:一瞬间步进电机只有一个线圈导通,没送一个励磁信号,步
    进电机转动一个角度。
    特点:精确度好,消耗电力小,但输出转矩最小,振动较大。

  • 2相励磁

    励磁控制:一瞬间步进电机有两个线圈导通。
    特点:输出转矩最大,振动较小。

  • 1-2相励磁

    励磁控制:1相励磁和2相励磁交替导通。
    特点:分辨率高,运转平滑,应用广。

28BYJ-48采用以上方式都可行,相较1相励磁和2相励磁来说,1-2相励磁方式应用更广。1-2相励磁驱动28BYJ-48获得更小的步进角度,运转更平滑,但同时28BYJ-48的转矩会随着1-2相励磁交替改变。

ULN2003

在这里插入图片描述

ULN2003驱动板
ULN2003 是高压大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。

在这里插入图片描述

ULN2003驱动原理

在这里插入图片描述

ULN2003驱动28BYJ-48接线

在实际使用中,只需要使用单片机的IO接ULN2003驱动板的IN1-IN4即可,当然,单片机和模块需要共地。

代码实现

(使用STM32F103C8最小系统板)

  • 创建step_motor.c和step_motor.h文件,并在step_motor.h中进行宏定义4个IO口,如下:
/* 宏定义 ------------------------------------------ */
/* 步进电机1参数宏 */
#define LA PAout(1)     /* A相 */
#define LB PAout(2)     /* B相 */
#define LC PAout(3)     /* C相 */
#define LD PAout(4)     /* D相 */

/* A相 */
#define LA_GPIO_PORT    GPIOA
#define LA_GPIO_PIN     GPIO_Pin_1
#define LA_GPIO_CLK     RCC_APB2Periph_GPIOA
/* B相 */
#define LB_GPIO_PORT    GPIOA
#define LB_GPIO_PIN     GPIO_Pin_2
#define LB_GPIO_CLK     RCC_APB2Periph_GPIOA
/* C相 */
#define LC_GPIO_PORT    GPIOA
#define LC_GPIO_PIN     GPIO_Pin_3
#define LC_GPIO_CLK     RCC_APB2Periph_GPIOA
/* D相 */
#define LD_GPIO_PORT    GPIOA
#define LD_GPIO_PIN     GPIO_Pin_4
#define LD_GPIO_CLK     RCC_APB2Periph_GPIOA
  • 在step_motor.c中初始化端口,代码如下:
/**
 * @name: Step_Motor_Init
 * @description: 步进电机初始化端口
 * @param {*}
 * @return {*}
 */
void Step_Motor_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(LA_GPIO_CLK | LB_GPIO_CLK | LC_GPIO_CLK | LD_GPIO_CLK, ENABLE);

    /* A相端口初始化 */
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Pin = LA_GPIO_PIN;
    GPIO_Init(LA_GPIO_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = LB_GPIO_PIN;
    GPIO_Init(LB_GPIO_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = LC_GPIO_PIN;
    GPIO_Init(LC_GPIO_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = LD_GPIO_PIN;
    GPIO_Init(LD_GPIO_PORT, &GPIO_InitStruct);

    GPIO_ResetBits(LA_GPIO_PORT, LA_GPIO_PIN);
    GPIO_ResetBits(LB_GPIO_PORT, LB_GPIO_PIN);
    GPIO_ResetBits(LC_GPIO_PORT, LC_GPIO_PIN);
    GPIO_ResetBits(LD_GPIO_PORT, LD_GPIO_PIN);
}
  • 在step_motor.c中宏定义或者枚举类型定义每个IO口或者是电机各个相的软件接通位。

    比如:

    • A相位定义为bit0,当A相导通的时候状态对应0x01;
    • B相位定义为bit1,当B相导通时位0x02;以此类推定义C相和D相;
/* 私有类型定义------------------------------------------------- */
typedef enum _PIN_BIT
{
    PLA = 0x01,
    PLB = 0x02,
    PLC = 0x04,
    PLD = 0x08,
} Pin_Bit;
  • 根据以上定义,很容易算1-2相励磁的时候各个步骤中的每相的状态,将状态组织成为数据,方便后续进行遍历,如下:

只要在以上定义的数字之间,穿插加上一个数字,值为两边的数字求和;

/* 私有变量定义------------------------------------- */
static uint8_t steps[8] = {0x01, 0x03, 0x02, 0x6, 0x04, 0x0c, 0x08, 0x09};
  • 定义电机正转函数:
/**
 * @name: Step_Motor_CW
 * @description: 电机正转函数
 * @param {uint32_t} nms
 * @return {*}
 */
void Step_Motor_CW(uint32_t nus)
{
    volatile uint8_t i;
    uint8_t temp = 0;
    for(i = 0; i < 8; i++)
    {
        temp = steps[i];
        LA = (uint8_t)((temp&PLA) >> 0);
        LB = (uint8_t)((temp&PLB) >> 1);
        LC = (uint8_t)((temp&PLC) >> 2);
        LD = (uint8_t)((temp&PLD) >> 3);
        
        delay_us(nus);
    }
    Step_Motor_Stop();
}
  • 定义电机反转函数:
/**
 * @name: Step_Motor_CCW
 * @description: 电机反转函数
 * @param {uint32_t} nms
 * @return {*}
 */
void Step_Motor_CCW(uint32_t nus)
{
    int i;
    for(i = 8; i > 0; i--)
    {
        LA = (uint8_t)((steps[i-1]&PLA) >> 0);
        LB = (uint8_t)((steps[i-1]&PLB) >> 1);
        LC = (uint8_t)((steps[i-1]&PLC) >> 2);
        LD = (uint8_t)((steps[i-1]&PLD) >> 3);
        
        delay_us(nus);
    }
    Step_Motor_Stop();
}
  • 定义一个电机停转函数,为了让电机停止的时候每一相都断电,不然长期通电会使电机线圈发热严重:
/**
 * @name: Step_Motor_Stop
 * @description: 电机停止
 * @param {*}
 * @return {*}
 */
void Step_Motor_Stop(void)
{
    LA = 0;
    LB = 0;
    LC = 0;
    LD = 0;
}

最后,在main.c中进行测试:

int main(void)
{
	initSysTick();
	LED1_Init();
	Step_Motor_Init();

	for(;;)
	{
		Step_Motor_CW(1000);
	}
}

以上是STM32驱动ULN2003的简单过程,在使用此种方法的同时会带来严重问题:

  • 28BYJ-48非常慢,转动一圈需要4096步,如果每步之间需要1ms,一圈需要4.096s;
  • 在电机旋转函数中调用了delay_ms进行每步之间的保持时间,消耗cpu运行效率,阻塞其他任务执行;
  • 如果28BYJ-48转动10圈,那么相当于cpu在41s一直在执行电机相位切换和delay_ms函数,阻塞整个程序,不利于整个系统的稳定性;

所以,如果想要系统及时稳定的处理其他问题,以上这样驱动ULN2003是不可取的,怎样才能在不影响系统及时稳定的前提下,驱动ULN2003呢?
请看下节分析


以上传送门:完整工程的驱动传


喜欢请点个赞哦,欢迎大家指正,谢谢

步进电机28BYJ-48是一种4相5线式步进电机,可以使用ULN2003芯片来驱动ULN2003是一种集成了7个开关型晶体管的芯片,可以方便地控制步进电机,具有低功耗、高可靠性等优点。 以下是使用stm32f103c8t6控制步进电机ULN2003驱动步进电机28BYJ-48的步骤: 1. 确定步进电机28BYJ-48的相序和控制信号,根据相序表将ULN2003的输出端口与步进电机连接。 2. 在stm32f103c8t6的开发环境中编写C语言程序,使用GPIO控制ULN2003的输出端口,从而控制步进电机的运动。 3. 根据需要设置步进电机的转速、方向等参数,调整程序代码,实现步进电机的精准控制。 下面是一个简单的示例程序,用于控制步进电机28BYJ-48以顺时针方向旋转一个圈: ```c #include "stm32f10x.h" #define IN1 GPIO_Pin_0 #define IN2 GPIO_Pin_1 #define IN3 GPIO_Pin_2 #define IN4 GPIO_Pin_3 #define DELAY 5 void delay_ms(uint16_t ms) { while(ms--) { uint16_t i = 5000; while(i--); } } void step(uint8_t i) { switch(i) { case 0: GPIO_ResetBits(GPIOA, IN1); GPIO_ResetBits(GPIOA, IN2); GPIO_ResetBits(GPIOA, IN3); GPIO_SetBits(GPIOA, IN4); break; case 1: GPIO_ResetBits(GPIOA, IN1); GPIO_ResetBits(GPIOA, IN2); GPIO_SetBits(GPIOA, IN3); GPIO_ResetBits(GPIOA, IN4); break; case 2: GPIO_SetBits(GPIOA, IN1); GPIO_ResetBits(GPIOA, IN2); GPIO_ResetBits(GPIOA, IN3); GPIO_ResetBits(GPIOA, IN4); break; case 3: GPIO_ResetBits(GPIOA, IN1); GPIO_SetBits(GPIOA, IN2); GPIO_ResetBits(GPIOA, IN3); GPIO_ResetBits(GPIOA, IN4); break; } } int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = IN1 | IN2 | IN3 | IN4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); for(int i = 0; i < 512; i++) { step(i % 4); delay_ms(DELAY); } return 0; } ``` 在本程序中,首先定义了步进电机28BYJ-48的4个控制信号IN1、IN2、IN3、IN4,然后使用GPIO初始化这些端口。在主函数中,使用step函数循环控制步进电机旋转一个圈。 step函数根据相序表依次控制ULN2003的输出端口,从而实现步进电机的旋转。为了让步进电机旋转得更平稳,还加入了一个延时函数delay_ms,以等待一定时间后再进行下一步操作。最后,程序返回0,结束执行。 需要注意的是,在实际使用过程中,还需要根据具体的步进电机型号和应用场景进行优化和调整。例如,可以通过增加步进电机的电压和电流来提高转速和扭矩,或者使用更高级别的控制算法来实现更精准的控制
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值