STM32之28BYJ-48步进电机驱动

发布于:2025-06-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、引言

二、28BYJ-48步进电机简介

2.1  基本特性

2.2  内部结构

2.3  工作模式

2.4  驱动原理

2.5  性能特点

2.6  驱动方案

2.7  使用注意事项

三、ULN2003驱动板简介

3.1  基本概述

3.2  电路结构

3.3  驱动原理

3.4  接口定义

3.5  使用注意事项

四、硬件准备

五、硬件连接

5.1 接线示意图

5.2  电源注意事项

六、软件设计

6.1 开发环境配置

6.2 关键代码实现

6.2.1 引脚定义与初始化

6.2.2 步进序列定义

6.2.3 定时器配置(TIM4)

6.2.4 运动控制核心逻辑

七、功能实现

7.1  基本运动控制

7.2  速度控制

7.3  加减速控制

八、应用示例

8.1 简单测试程序

8.2 带加减速的位置控制

九、常见问题解决

十、总结


一、引言

        28BYJ-48步进电机因其价格低廉、控制简单等特点,在各类小型自动化项目中广泛应用。本文将详细介绍如何使用STM32F103C8T6单片机通过ULN2003驱动芯片控制这种步进电机,实现正反转、调速和精确位置控制。

二、28BYJ-48步进电机简介

2.1  基本特性

电机类型:

  • 永磁式步进电机(Unipolar)
  • 内置1:64减速齿轮箱

电气参数:

  • 额定电压:5V DC

  • 相电流:约100-120mA/相

  • 线圈电阻:50Ω/相

  • 驱动方式:单极性驱动(ULN2003驱动板兼容)

机械参数:

  • 步距角:5.625°(原始步距)

  • 减速后步距角:5.625°/64 ≈ 0.0879°

  • 输出轴转速范围:0-15 RPM(建议工作范围)

电机图片:

2.2  内部结构

电磁部分:

  • 4相8极绕组结构

  • 每组线圈中心抽头接正极

齿轮箱结构:

  • 四级行星齿轮减速

  • 总减速比1:64

  • 输出轴扭矩:≥34.3mN·m(5V时)

2.3  工作模式

模式 步数/转 步距角 特点
全步(单相) 64步 5.625° 低分辨率,振动较大
全步(双相) 64步 5.625° 扭矩大,功耗高
半步 128步 2.8125° 分辨率提高,运行更平稳
8步微步 512步 0.703° 最高分辨率,需专用驱动

2.4  驱动原理

励磁顺序(以全步双相为例):

// 4相8拍驱动序列
const uint8_t seq[8] = {
    0b1000, // A
    0b1100, // A+B
    0b0100, // B
    0b0110, // B+C
    0b0010, // C
    0b0011, // C+D
    0b0001, // D
    0b1001  // D+A
};

转速计算: 

例:每秒683脉冲 → 10 RPM (转每分钟)

2.5  性能特点

优点

  • 价格低廉

  • 驱动电路简单(ULN2003即可)

  • 低速大扭矩输出

  • 保持转矩大(断电后能保持位置)

局限性

  • 最高转速较低(通常<15RPM)

  • 齿轮箱存在回程差(约3°)

  • 长时间工作可能发热

2.6  驱动方案

驱动方案对比:

驱动芯片 最大电流 特点
ULN2003 500mA 经济,适合低速应用
DRV8825 2.5A 支持微步,精度高
A4988 2A 带过热保护

2.7  使用注意事项

电气保护

  • 反接保护二极管必接

  • 避免长时间堵转(>2秒)

机械安装

  • 输出轴避免径向受力

  • 齿轮箱需定期润滑(硅脂)

        该电机特别适合学生项目和原型开发,其优异的性价比使其成为入门级运动控制的首选。实际使用时建议配合光电编码器实现闭环控制以提升精度。

三、ULN2003驱动板简介

3.1  基本概述

        ULN2003驱动板是专为28BYJ-48等小型步进电机设计的低成本驱动模块,核心采用ULN2003达林顿阵列芯片,具有以下特性:

关键参数

  • 工作电压:5-12V(与电机电压匹配)

  • 单路最大电流:500mA

  • 总功耗:1.5W(需配合散热片)

  • 输入兼容性:3.3V/5V逻辑电平

板载资源

  • 4路LED指示灯(显示相位状态)

  • 反接保护二极管

  • 电机接口防插反设计

  • 5.08mm间距接线端子

UNL2003驱动板示意图:

ULN2003原理图: 

3.2  电路结构

核心芯片

ULN2003包含7路达林顿管(实际使用4路)。

典型应用电路

3.3  驱动原理

相位控制真值表:

步序 IN1 IN2 IN3 IN4 励磁相
1 1 0 0 0 A
2 1 1 0 0 AB
3 0 1 0 0 B
... ... ... ... ... ...

电流路径(以A相为例):

5V -> 线圈A -> ULN2003_OUT1 -> 达林顿管 -> GND

3.4  接口定义

引脚标号 功能说明 连接目标
IN1-IN4 相位控制输入 MCU GPIO
VCC 逻辑电源(可选) MCU 5V
GND 公共地 电源地
A-D 电机相线输出 28BYJ-48对应相线

3.5  使用注意事项

电源配置

当电机电压>5V时,建议:

  •     逻辑电源(VCC)接MCU
  •     5V电机电源单独供电

保护措施

  • 电机断电时产生的反电动势可能达30V,必须保留板载续流二极管

  • 长时间工作需监测芯片温度(>70℃应停止使用)

典型问题处理

  • 电机抖动不转:检查相位顺序是否正确

  • 驱动芯片发烫:

        (1)降低PWM频率(建议<2kHz)

        (2)增加散热片

四、硬件准备

所需材料:

  • STM32F103C8T6最小系统板

  • 28BYJ-48步进电机(带ULN2003驱动板)

  • 杜邦线若干

  • USB转TTL模块(用于程序下载)

  • 电源(5V/2A)

五、硬件连接

5.1 接线示意图

STM32F103C8T6 ULN2003驱动板
PB6 IN1
PB7 IN2
PB8 IN3
PB9 IN4
GND GND
5V VCC 

5.2  电源注意事项

建议为电机驱动单独供电,避免单片机电源受干扰。

六、软件设计

6.1 开发环境配置

  1. 安装Keil MDK-ARM

  2. 安装STM32标准外设库

  3. 配置工程包含必要头文件

6.2 关键代码实现

6.2.1 引脚定义与初始化

// 引脚定义
#define IN1_PIN    GPIO_Pin_6
#define IN2_PIN    GPIO_Pin_7
#define IN3_PIN    GPIO_Pin_8
#define IN4_PIN    GPIO_Pin_9
#define MOTOR_PORT GPIOB

// GPIO初始化
void GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    GPIO_InitStruct.GPIO_Pin = IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(MOTOR_PORT, &GPIO_InitStruct);
}

6.2.2 步进序列定义

// 8步驱动序列(更高精度)
const uint8_t stepSequence[8] = {
    0b1000,  // A
    0b1100,  // AB
    0b0100,  // B
    0b0110,  // BC
    0b0010,  // C
    0b0011,  // CD
    0b0001,  // D
    0b1001   // DA
};

6.2.3 定时器配置(TIM4)

void TIM4_Init(void) {
    TIM_TimeBaseInitTypeDef TIM_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    
    // 1MHz计数频率(1μs分辨率)
    TIM_InitStruct.TIM_Period = 1000;  // 初始ARR值
    TIM_InitStruct.TIM_Prescaler = SystemCoreClock/1000000 - 1;
    TIM_InitStruct.TIM_ClockDivision = 0;
    TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM4, &TIM_InitStruct);
    
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
    
    NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    TIM_Cmd(TIM4, ENABLE);
}

6.2.4 运动控制核心逻辑

// 全局变量
volatile int32_t stepPosition = 0;
volatile int32_t targetSteps = 0;
volatile uint32_t stepDelay = 2000;  // 初始延迟2000μs
volatile int8_t direction = 1;

// 设置电机相位
void SetMotorPhase(uint8_t phase) {
    GPIO_WriteBit(MOTOR_PORT, IN1_PIN, (phase & 0x08) ? Bit_SET : Bit_RESET);
    GPIO_WriteBit(MOTOR_PORT, IN2_PIN, (phase & 0x04) ? Bit_SET : Bit_RESET);
    GPIO_WriteBit(MOTOR_PORT, IN3_PIN, (phase & 0x02) ? Bit_SET : Bit_RESET);
    GPIO_WriteBit(MOTOR_PORT, IN4_PIN, (phase & 0x01) ? Bit_SET : Bit_RESET);
}

// 定时器中断服务函数
void TIM4_IRQHandler(void) {
    static uint8_t currentPhase = 0;
    
    if (TIM_GetITStatus(TIM4, TIM_IT_Update)) {
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
        
        if ((direction > 0 && stepPosition < targetSteps) || 
            (direction < 0 && stepPosition > targetSteps)) {
            
            currentPhase = (currentPhase + direction + 8) % 8;
            SetMotorPhase(stepSequence[currentPhase]);
            stepPosition += direction;
            
            // 更新定时器
            TIM_SetAutoreload(TIM4, stepDelay);
            TIM_SetCounter(TIM4, 0);
        } else {
            SetMotorPhase(0x00);  // 停止电机
        }
    }
}

七、功能实现

7.1  基本运动控制

// 相对移动
void MoveSteps(int32_t steps) {
    targetSteps = stepPosition + steps;
    direction = (steps > 0) ? 1 : -1;
}

// 绝对移动
void MoveToPosition(int32_t position) {
    targetSteps = position;
    direction = (position > stepPosition) ? 1 : -1;
}

7.2  速度控制

// 设置转速(RPM)
void SetSpeed(float rpm) {
    // RPM转步进延迟(μs)
    uint32_t delay = (60 * 1000000) / (4096 * rpm);
    
    // 限制在合理范围
    if (delay < 800) delay = 800;    // 最大约15RPM
    if (delay > 10000) delay = 10000; // 最小约1.46RPM
    
    stepDelay = delay;
}

7.3  加减速控制

// 梯形加减速控制
void UpdateSpeed(void) {
    static uint32_t acceleration = 100; // 加速度步/秒²
    
    int32_t remainingSteps = abs(targetSteps - stepPosition);
    
    // 加速阶段(前1/3路程)
    if (remainingSteps > (2 * totalSteps / 3)) {
        if (stepDelay > minDelay + acceleration) {
            stepDelay -= acceleration;
        }
    } 
    // 减速阶段(后1/3路程)
    else if (remainingSteps < (totalSteps / 3)) {
        if (stepDelay < maxDelay - acceleration) {
            stepDelay += acceleration;
        }
    }
}

八、应用示例

8.1 简单测试程序

实现正转一圈然后反转一圈循环。

int main(void) {
    SystemInit();
    GPIO_Init();
    TIM4_Init();
    
    // 设置转速为10RPM
    SetSpeed(10.0);
    
    while(1) {
        // 正转1圈
        MoveSteps(4096);
        while(stepPosition < targetSteps);
        Delay_ms(1000);
        
        // 反转1圈
        MoveSteps(-4096);
        while(stepPosition > targetSteps);
        Delay_ms(1000);
    }
}

8.2 带加减速的位置控制

可设置目标位置以及速度。

void ControlledMove(int32_t target, float speed) {
    SetSpeed(speed);
    MoveToPosition(target);
    
    while(stepPosition != target) {
        UpdateSpeed();  // 实时更新速度
        Delay_ms(1);
    }
}

九、常见问题解决

电机抖动但不转动:

  1. 检查电源是否充足(≥5V/1A)
  2. 验证步进序列是否正确

  3. 确保接线牢固

转速达不到预期:

  1. 适当减小minDelay
  2. 检查ULN2003是否过热

  3. 确认电机负载是否过大

位置控制不准确:

  1. 增加减速阶段时间
  2. 考虑使用闭环控制(如加装编码器)

优化建议:

  1. 微步驱动:通过PWM实现更精细的256微步控制

  2. 闭环控制:增加编码器反馈实现真正的位置闭环

  3. 电流控制:动态调整相电流以降低发热

十、总结

        本文详细介绍了使用STM32F103C8T6控制28BYJ-48步进电机的完整方案,包括硬件连接、软件实现和运动控制算法。通过合理设置参数,可以实现精确的位置控制和速度调节,满足大多数小型自动化项目的需求。


网站公告

今日签到

点亮在社区的每一天
去签到