使用 ULN2003 驱动 28BYJ-48 步进电机

简介: 使用 ULN2003 驱动 28BYJ-48 步进电机

使用 ULN2003 驱动 28BYJ-48 步进电机。

要用一个步进电机测试东西,不过需求来的比较突然手边也没有像是A4988或TMC2209这种硬件驱动,于是就用别人的ULN2003驱动和28BYJ-48步进电机来做了,正好给学弟大概说下如何驱动步进电机。

基本概念

  • 步进电机:将输入的脉冲信号转变成角位移,即给一个脉冲信号,步进电机就转动一个角度。

    可以通过控制脉冲频率,来控制电机转动的速度和加速度。

  • 从这个电机的名字入手28BYJ-48: 28表示电机直径28mm,B代表步进电机,Y代表永磁式步进电机PM,J代表减速型电机带减速箱,48表示四相八拍。

P1

  • 转子:最中间标注为0~5的六个齿。顾名思义,它是要转动的。转子的每个齿上都带有永久的磁性,是一块永磁体,这就是永磁式。
  • 定子:外圈的8个齿。它是保持不动的,跟电机的外壳固定在一起。每个齿上都缠上了一个线圈绕组,正对着的2个齿上的绕组又是串联在一起的,也就是说正对着的2个绕组总是会同时导通或关断的,如此就形成了4相,即图中标注的ABCD,相对的2个齿是1相。四项五线多吃来那条线是电源线。
  • 拍数:完成一个磁场周期性变化所需脉冲数。一拍就是一个脉冲信号。

    以四相电机为例,四相四拍为 AB-BC-CD-DA(-AB...), 四相八拍为 A-AB-B-BC-C-CD-D-DA(-A...)

  • 步距角(步进角):每接收到一个脉冲信号步进电机转动的角度。

    步距角 = 360° / (定子齿数 * 运行拍数)

​ 以八拍运行为例,电机主轴的步距角度为: 360/(8*8)=5.625。再除以减速比64,得到输出轴的步距角5.625/64=0.087890625。八拍运行俗称半步,对应四拍运行则为整步。

​ 查到步距角参数,也可以反推需要360/5.625=64个脉冲信号转子才会转动1圈,(因为带减速箱结构所以需要再乘上减速比)64*64=4096个脉冲信号电机主轴才会转1圈。

  • 齿轮减速比:这款为1:64。即内部转子转动64圈,外部输出主轴才转动1圈。于是就是需要64×64=4096个拍数才会让输出轴转过1圈。
  • 空载启动频率:这款步进电机是550P.P.S。即每秒最多给出550个步进脉冲数才可以正常启动,需要单个节拍持续时间(或节拍的刷新时间)至少为1/550=1.8ms

    当脉冲频率高于启动频率,电机不能正常启动,可能发生丢步或堵转。在有负载的情况下,启动频率应更低。

  • 如果要使电机达到高速转动,脉冲频率应该有加速过程,即启动频率较低,然后按一定加速度升到所希望的高频(电机转速从低速升到高速)
  • 保持转矩:步进电机通电但没有转动时,定子锁住转子的力矩。通常步进电机在低速时的力矩接近保持转矩。
  • 细分(角度细分):一般由硬件驱动器完成。如果主轴转1圈需要200个脉冲,那么2细分就是转1圈需要400个脉冲。细分是通过影响电机的步距角来影响转角和转速。

了解完了基本信息和原理之后

  • 可以得出转动一个角度的公式

​ 转动角度所需输出步数 = (角度 * 减速比) * (定子齿数 * 运行拍数) / 360°

  • 转速的公式

    转速(转/秒) = 脉冲频率(HZ) / (360 / 步距角 * 细分倍数)

    例如设置PWM波的频率为1kHz(1秒1000个脉冲),42步进电机的步距角是1.8°,在没有细分的情况下,转速为1000/(360/1.8*1)=5rad/s,即5*60=300rpm

  • 八拍模式是这类4相步进电机的最佳工作模式。八拍相较于四拍除了能使转动精度增加一倍,也能增加电机的整体扭力输出。

    除了单四拍和八拍的工作模式外,还有双四拍(双绕组通电四节拍)。双四拍步进角度同单四拍是一样的,但由于它是两个绕组同时导通,所以扭矩会比单四拍模式大。

28BYJ-48的减速比精度问题

然而实际数一下每个齿轮的齿数,然后将各级减速比相乘,算出的真实的减速比应该为 (32/9)(22/11)(26/9)(31/10)≈63.683950617 并非1:64整。

按真实减速比计算,需要64x63.68...≈4075.7拍主轴才会完整转过一圈。要是按1:64错误地计算那么每转过100.5圈就会使主轴差出来半圈。

后来查了下在实际应用中, 28BYJ-48最初的设计目的是用来控制空调的扇叶的,转动的角度也小于180度,也就不需要很高的精度。

代码

/********************************** DEFINE **********************************/
#define MOTOR_PORT    GPIOA
#define MOTOR_IN1    GPIO_PIN_4
#define MOTOR_IN2    GPIO_PIN_5
#define MOTOR_IN3    GPIO_PIN_6
#define MOTOR_IN4    GPIO_PIN_7

#define IN1_HIGH    HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN1, GPIO_PIN_SET);
#define IN1_LOW        HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN1, GPIO_PIN_RESET);
#define IN2_HIGH    HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN2, GPIO_PIN_SET);
#define IN2_LOW        HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN2, GPIO_PIN_RESET);
#define IN3_HIGH    HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN3, GPIO_PIN_SET);
#define IN3_LOW        HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN3, GPIO_PIN_RESET);
#define IN4_HIGH    HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN4, GPIO_PIN_SET);
#define IN4_LOW        HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_IN4, GPIO_PIN_RESET);

/******************************** FUNCTION ********************************/
/*
 * @function:   八拍驱动
 * @notion:     28BYJ-48步进电机delay最小为2ms
 */
static void Phase8_Single(uint8_t step, uint8_t delay)
{
    switch (step) {
        case 0:    IN1_LOW;IN2_HIGH; IN3_HIGH; IN4_HIGH;    break;
        case 1:    IN1_LOW; IN2_LOW; IN3_HIGH; IN4_HIGH;    break;
        case 2:    IN1_HIGH; IN2_LOW; IN3_HIGH; IN4_HIGH;    break;
        case 3:    IN1_HIGH; IN2_LOW; IN3_LOW; IN4_HIGH;    break;
        case 4:    IN1_HIGH; IN2_HIGH; IN3_LOW; IN4_HIGH;    break;
        case 5:    IN1_HIGH; IN2_HIGH; IN3_LOW; IN4_LOW;    break;
        case 6:    IN1_HIGH; IN2_HIGH; IN3_HIGH; IN4_LOW;    break;
        case 7:    IN1_LOW; IN2_HIGH; IN3_HIGH; IN4_LOW;    break;
        default :    break;
    }
    HAL_Delay(delay);
}

/*
 * @function:   转动指定角度
 * @param:        dir: 0为正转 1为反转
 * @notion:     28BYJ-48步进电机delay最小为2ms
 */
void SteppingMotor_TurnAngle(float angle, uint8_t delay)
{
    // 转动角度所需输出步数 = (角度 * 减速比) * (定子齿数 * 运行拍数) / 360°
//    float tmp = angle * 4096.0f / 360.0f;                            // 减速比1:64
    float tmp = fabsf(angle) * 283712.0f / 4455.0f * 8.0f / 45.0f;    // 减速比1:63.684
    uint16_t steps = (uint16_t)tmp;
    
    if (angle > 0) {
        for (uint16_t i = steps; i > 0; i -- ) {
            Phase8_Single(i % 8, delay);
        }
    } else {
        for (uint16_t i = steps; i > 0; i -- ) {
            Phase8_Single(abs(i % 8 - 7), delay);
        }
    }
}

_Single(i % 8, delay);

    }
} else {
    for (uint16_t i = steps; i > 0; i -- ) {
        Phase8_Single(abs(i % 8 - 7), delay);
    }
}

}

目录
相关文章
|
传感器 监控 API
基于STM32的智能灌溉系统设计与实现
基于STM32的智能灌溉系统设计与实现
1545 1
|
Linux
Linux下安装curl
Linux下安装curl
2992 0
micropython esp8266+ssd1306(OLED) 显示中文(示例)
1.Adafruit_SSD1306 OLED显示库使用Adafruit_SSD1306:https://github.com/adafruit/Adafruit_SSD1306 连接示例: 库使用示例: >>> from ...
8079 0
|
8月前
|
消息中间件 人工智能 Cloud Native
【云故事探索】NO.20:古茗奶茶背后的云原生力量
古茗依托阿里云云原生架构,以微服务+DevOps实现敏捷迭代,通过RocketMQ Serverless应对“周三会员日”十万级TPS洪峰,弹性降本超40%;结合全链路可观测体系保障稳定,并迈向AI原生演进,让技术真正赋能业务创新。
412 7
|
机器学习/深度学习 算法 数据安全/隐私保护
基于FPGA的SNN脉冲神经网络之LIF神经元verilog实现,包含testbench
本项目展示了 LIF(Leaky Integrate-and-Fire)神经元算法的实现与应用,含无水印运行效果预览。基于 Vivado2019.2 开发,完整代码配有中文注释及操作视频。LIF 模型模拟生物神经元特性,通过积分输入信号并判断膜电位是否达阈值产生脉冲,相较于 Hodgkin-Huxley 模型更简化,适合大规模神经网络模拟。核心程序片段示例,助您快速上手。
|
10月前
|
弹性计算 人工智能 应用服务中间件
阿里云服务器最新优惠价格表及选购指南(新版)
随着云计算技术的不断发展,阿里云再次推出了服务器优惠价格表,为用户提供更加灵活、经济的上云方案。本次优惠涵盖了轻量应用服务器、ECS云服务器以及GPU服务器等多种类型,满足不同用户的需求。以下是详细的价格表及选购指南。
|
机器学习/深度学习 资源调度 计算机视觉
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
589 2
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
|
NoSQL Java Redis
redisson分布式锁
Redisson 分布式锁提供了一种简单高效的方式来实现分布式系统中的锁机制。通过本文介绍的基本用法和高级用法,开发者可以根据具体的业务需求选择合适的锁类型来确保系统的稳定性和高并发性。希望本文能帮助读者更好地理解和使用 Redisson 分布式锁,提高系统的并发处理能力和可靠性。
861 10
|
存储 JavaScript 前端开发
vue前端自适应布局,一步到位所有自适应
【8月更文挑战第9天】在Vue前端实现全面自适应布局颇具挑战,但可通过多种方法达成接近目标的效果。首先,结合BootstrapVue或Element UI等响应式框架简化布局实现过程;其次,利用Sass或Less等预处理器增强CSS编写灵活性;再者,发挥Vue的响应式特性,动态调整组件尺寸与位置;同时采用Flexbox及媒体查询技术确保不同屏幕尺寸下的一致体验;针对移动设备,采取移动优先策略并使用专门框架优化表现;最后,多平台测试与细致调优保证布局效果。综合运用上述策略,可在复杂多变的设备环境中打造近乎完美的自适应布局。
1439 1
|
存储 关系型数据库 MySQL
【赵渝强老师】解决MySQL丢失root用户密码
本文介绍了MySQL数据库中用户密码存储的变化,以及如何通过特殊方法重置root用户的密码。从MySQL 5.7版本开始,密码字段由“password”改为“authentication_string”。文章详细列出了重置密码的步骤,并提供了相关代码示例和视频教程。
717 0