物联网开发笔记(34)- 使用Micropython开发ESP32开发板之控制步进电机(28BYJ-48)

一、目的

        这一节我们学习如何使用我们的ESP32开发板来控制步进电机。

二、环境

        ESP32 + 步进电机 + Thonny IDE + 几根杜邦线 + DC直流电源(可选)  

        步进电机型号:28BYJ-48(某宝上可以买到),其对应的驱动板芯片型号是:ULN2003

接线示意图:

注意1:步进电机停止后需要使四个相位引脚都为高电平,否则步进电机会发热。因为不进电机公共端为高电平,所有引脚都为高电平就不会产生电流,就不会发热。

注意2:建议采用外接直流电源 DC5-12V,直接接在驱动板上即可。避免直接从开发板5V角取电,以免烧坏开发板。

此此电机64步旋转一周,步距角是5.625度。以4拍或者8拍运行。

        

三、步进电机原理

        关于五步四相步进电机,网上有很多介绍,我这里简单介绍下,更多知识请大家自行搜索学习,有好的资源,请评论区留言分享,谢谢!

        看下图:开始时,开关SB接通电源,SA、SC、SD断开,B相磁极和转子0、3号齿对齐,同时,转子的1、4号齿就和C、D相绕组磁极产生错齿,2、5号齿就和D、A相绕组磁极产生错齿。

  当开关SC接通电源,SB、SA、SD断开时,由于C相绕组的磁力线和1、4号齿之间磁力线的作用,使转子转动,1、4号齿和C相绕组的磁极对齐。而0、3号齿和A、B相绕组产生错齿,2、5号齿就和A、D相绕组磁极产生错齿。依次类推,A、B、C、D四相绕组轮流供电,则转子会沿着A、B、C、D方向转动。

 步进电机型号:24BYJ-48,直流5-12V供电

        步进电机是将电脉冲信号转变为角位移或线位移的开环控制元步进电机件,通过控制施加在电机线圈上的电脉冲顺序、频率和数量,可以实现对步进电机的转向、速度和旋转角度的控制。

配合以直线运动执行机构(螺纹丝杆)或齿轮箱装置,更可以实现更加复杂、精密的线性运动控制要求。

在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响。

当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”。

它的旋转是以固定的角度一步一步运行的,可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的。同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

步进电机运行的速度越快,所能输出的转矩越小,容易造成失步(内部齿轮打滑)。步进电机运行的速度越快慢,转矩就越大越稳。

步进电机矩频特性:

        步进电机的磁极数量规格和接线规格很多,为简化问题,我们这里就先只以四相步进电机为例进行讨论。

所谓四相,就是说电机内部有4对磁极,此外还有一个公共端(COM)接电源,另外的A、B、C、D是四相的接头。而四相电机的可以向外引出六条接线(两条COM共同接入Vcc),也可以引出五条线,如下图所示,所以我们在购买时会看到有六线四相制和五线四相制的步进电机。

其中A、B、C、D四相接头是需要连接到单片机IO端,通过一定方式改变四相接口的通电状态来控制电机正反转动(下面有介绍)

四、步进电机参数
 

在以上众多参数中,单片机软件开发时,最需要了解的参数即为 步距角

如上图所示,步距角=5.625°/64,其意思就是每64个脉冲步进电机就会转5.625度。

因此可以很容易的得出旋转角度与脉冲之间的计算公式:pulse=(angle/5.625) * 65(划重点)

例如让电机转一圈有360°,那么转一圈的脉冲数为 (360 / 5.625) * 64 = 4096 个脉冲。

五、步进电机驱动方式

    驱动分三种模式,下表黄色区域中的1表示单片机对应管脚输出高电平、0表示输出低电平。步进电机四相对应的单片机管脚按照下表中的步序和频率依次输出电平即可驱动电机。

1.单四拍

这是最简单的步进电机驱动方式。这种方式,电机在每个瞬间只有一个线圈导通,消耗电力小。但在切换瞬间时没有任何的电磁作用在转子上,容易造成振动,也容易因为惯性而失步。


                                                                      单四拍步序

 2.双四拍

这种方式输出的转矩较大且振动较少,切换过程中至少有一个线圈通电作用于转子,使得输出的转矩较大,振动较小,也比单四拍平稳,不易失步。


                                                                       双四拍步序

3.八拍

综合上述两种驱动信号,使用单四拍和双四拍交替进行的方式,每传送一个励磁信号,步进电机前进半个步距角。其特点是分辨率高,运转更加平滑,也是最常用的一种方式。


                                                                         八拍步序

 下面是这三种驱动方式的时序波形图


                                                                       时序图

 六、驱动问题

        因为数字I/O口电流较小。因此,我们想到了使用晶体管进行放大。使用诸如ULN2003和ULN2803这样的激励器,它实际是内部集成好了放大功能的集成电路芯片,此外也无需额外添加二极管,因为它已经内置了。

        我们以ULN2003为例,现有的驱动板可以用来驱动步进电机,我们只需要选择单片机的四个输出端口用杜邦线分别连接驱动板的IN1、IN2、IN3、IN4,再用外置电源连接驱动板的5-12V+接口,并把电源和单片机的地(GND)与驱动板的(–)共线即可。

ULN2003采用的是达林顿管(Darlington transistor)方式来增强对大电流负载(如步进电机)的驱动,所谓达林顿管其实就是二级放大的三极管而已(如右图所示),经过恰当的三极管型号选择匹配后,两次放大的三极管驱动能力比一个三极管更强。详情请参考ULN2003的DataSheet。但无论哪种方式,记住,使用额外的外接电源来驱动晶体管和集成芯片,它才是电机的真正的能量提供者。

七、步进电机的主要特性

步进电机的主要特性:
1、 步进电机必须加驱动才可以运转, 驱动信号必须为脉冲信号,没有脉冲的时候,步进电机静止, 如果加入适当的脉冲信号, 就会以一定的角度(称为步角)转动。转动的速度和脉冲的频率成正比。
2、 黑金刚配套的是 28BYJ48 5V 驱动的 4 相 5 线的步进电机,而且是减速步进电机,减速比为 1:64,步进角为 5.625/64 度。如果需要转动 1 圈,那么需要360/5.625*64=4096 个脉冲信号。
3、 步进电机具有瞬间启动和急速停止的优越特性。
4、 改变脉冲的顺序, 可以方便的改变转动的方向。


步进电机公共端为高电平,各个相位给低电平则有电流通过产生磁场驱动电机转动。
注意: 使用ULN2003作为驱动时,其具有电平反向功能

 八、代码

from machine import Pin
import time


a = Pin(13, Pin.OUT)
b = Pin(12, Pin.OUT)
c = Pin(14, Pin.OUT)
d = Pin(27, Pin.OUT)

# 步进电机公共端为高电平,所有引脚都为高电平就不会产生电流,就不会发热
a.value(0)
b.value(0)
c.value(0)
d.value(0)

delay_time_ms = 5 # 这个时间不能设置太小,否则电机来不及响应

# 四拍模式
print("单四拍模式")
for i in range (0, 256):  # 顺时针转动180度
    a.value(1)
    b.value(0)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(1)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(0)
    c.value(1)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(0)
    c.value(0)
    d.value(1)
    time.sleep_ms(delay_time_ms)

# 改变脉冲的顺序, 可以方便的改变转动的方向
for i in range (0, 256):  # 逆时针转动转动180度
    a.value(0)
    b.value(0)
    c.value(0)
    d.value(1)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(0)
    c.value(1)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(1)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(1)
    b.value(0)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
# 双四拍模式
print("双四拍模式")
for i in range (0, 256):  # 顺时针转动180度
    a.value(1)
    b.value(1)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(1)
    c.value(1)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(0)
    c.value(1)
    d.value(1)
    time.sleep_ms(delay_time_ms)
    
    a.value(1)
    b.value(0)
    c.value(0)
    d.value(1)
    time.sleep_ms(delay_time_ms)

# 改变脉冲的顺序, 可以方便的改变转动的方向
for i in range (0, 256):  # 逆时针转动转动180度
    a.value(1)
    b.value(0)
    c.value(0)
    d.value(1)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(0)
    c.value(1)
    d.value(1)
    time.sleep_ms(delay_time_ms)
    
    a.value(0)
    b.value(1)
    c.value(1)
    d.value(0)
    time.sleep_ms(delay_time_ms)
    
    a.value(1)
    b.value(1)
    c.value(0)
    d.value(0)
    time.sleep_ms(delay_time_ms)


# 步进电机停止后需要使四个相位引脚都为高电平,否则步进电机会发热
a.value(0)
b.value(0)
c.value(0)
d.value(0)

九、演示效果

        运行上述代码,效果如下

 

十、八拍步进

        顺时针转90度,逆时针转90度。怎么计算的呢?其实上面已经讲到。

步距角=5.625°/64,其意思就是每64个脉冲步进电机就会转5.625度。

因此可以很容易的得出旋转角度与脉冲之间的计算公式:pulse=(angle/5.625) * 65(划重点)

例如让电机转一圈有360°,那么转一圈的脉冲数为 (360 / 5.625) * 64 = 4096 个脉冲。那么90度就是4096/4=1024个脉冲。

from machine import Pin
import time

STEP_MOTOR_A_PIN = Pin(13, Pin.OUT)  # 橙色
STEP_MOTOR_B_PIN = Pin(12, Pin.OUT)  # 黄色
STEP_MOTOR_C_PIN = Pin(14, Pin.OUT)  # 绿色
STEP_MOTOR_D_PIN = Pin(27, Pin.OUT)  # 蓝色

# 设置步进电机公共端为高电平
STEP_MOTOR_A_PIN.value(0)
STEP_MOTOR_B_PIN.value(0)
STEP_MOTOR_C_PIN.value(0)
STEP_MOTOR_D_PIN.value(0)

STEP_MOTOR_DIRE_FOREWARD  = 1  # 步进电机正向转:顺时针
STEP_MOTOR_DIRE_ROLLBACK  = 2  # 步进电机正向转:逆时针

STEP_MOTOR_SPEED = 5  # 设置步进电机转动的速度。这个值不能设置太小,否则电机来不及响应

#========================================================================
# 简述: 步进电机驱动
# 参数: dire:步进电机方向   speed:步进电机转速
# 返回: 无
# 详述: 
#========================================================================
def step_motor_drive(dire, speed):
    if dire == 1:
        step_motor_foreward(speed)
    elif dire == 2:
        step_motor_rollback(speed)
    else:
        print("print input right value!")

#========================================================================
# 简述: 步进电机停止
# 参数: 无
# 返回: 无
# 详述: (ULN2003有反向功能)
#========================================================================
def step_motor_stop():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(0)    

#========================================================================
# 简述: 步进电机正转
# 参数: 无
# 返回: 无
# 详述: 顺时针转
#========================================================================
def step_motor_foreward(speed):
    MotorStepCount = 0
    for i in range(0, 1024):
        if MotorStepCount > 7:
            MotorStepCount = 0
        step_motor_foreward_output(MotorStepCount)
        time.sleep_ms(speed);
        MotorStepCount = MotorStepCount + 1

#========================================================================
# 简述: 步进电机反转
# 参数: 无
# 返回: 无
# 详述: 逆时针转
#========================================================================
def step_motor_rollback(speed):
    MotorStepCount = 0
    for i in range(0, 1024):
        if (MotorStepCount) > 7:
            MotorStepCount = 0
        step_motor_rollback_output(MotorStepCount)
        time.sleep_ms(speed);
        MotorStepCount = MotorStepCount + 1 

#========================================================================
# 简述: 步进电机正向输出
# 参数: 无
# 返回: 无
# 详述: 
#========================================================================
def step_motor_foreward_output(step):
    if step == 0:
        step_motor_a_output()
    elif step == 1:
        step_motor_ab_output()
    elif step == 2:
        step_motor_b_output()
    elif step == 3:
        step_motor_bc_output()
    elif step == 4:
        step_motor_c_output()
    elif(step == 5):
        step_motor_cd_output()
    elif step == 6:
        step_motor_d_output()
    elif step == 7:
        step_motor_da_output()
    else:
        print("Please input right value")
    
#========================================================================
# 简述: 步进电机反向输出
# 参数: 无
# 返回: 无
# 详述: 
#========================================================================
def step_motor_rollback_output(step):
    if step == 0:
        step_motor_a_output()
    elif step == 1:
        step_motor_da_output()
    elif step == 2:
        step_motor_d_output()
    elif step == 3:
        step_motor_cd_output()
    elif step == 4:
        step_motor_c_output()
    elif(step == 5):
        step_motor_bc_output()
    elif step == 6:
        step_motor_b_output()
    elif step == 7:
        step_motor_ab_output()
    else:
        print("Please input right value")

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机A相输出(ULN2003有反向功能)
#========================================================================
def step_motor_a_output():
    STEP_MOTOR_A_PIN.value(1)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(0)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机AB相输出(ULN2003有反向功能)
#========================================================================
def step_motor_ab_output():
    STEP_MOTOR_A_PIN.value(1)
    STEP_MOTOR_B_PIN.value(1)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(0)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机B相输出(ULN2003有反向功能)
#========================================================================
def step_motor_b_output():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(1)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(0)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机BC相输出(ULN2003有反向功能)
#========================================================================
def step_motor_bc_output():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(1)
    STEP_MOTOR_C_PIN.value(1)
    STEP_MOTOR_D_PIN.value(0)
    
#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机C相输出(ULN2003有反向功能)
#========================================================================
def step_motor_c_output():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(1)
    STEP_MOTOR_D_PIN.value(0)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机CD相输出(ULN2003有反向功能)
#========================================================================
def step_motor_cd_output():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(1)
    STEP_MOTOR_D_PIN.value(1)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机D相输出(ULN2003有反向功能)
#========================================================================
def step_motor_d_output():
    STEP_MOTOR_A_PIN.value(0)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(1)

#========================================================================
# 简述: 步进电机引脚控制
# 参数: 无
# 返回: 无
# 详述: 步进电机DA相输出(ULN2003有反向功能)
#========================================================================
def step_motor_da_output():
    STEP_MOTOR_A_PIN.value(1)
    STEP_MOTOR_B_PIN.value(0)
    STEP_MOTOR_C_PIN.value(0)
    STEP_MOTOR_D_PIN.value(1)
    
def main():
    step_motor_drive(1, 5)  # 正向(顺时针)转动,每个相位间隔时间5ms
    step_motor_drive(2, 5)  # 反向(逆时针)转动,每个相位间隔时间5ms
    step_motor_stop()
    
if __name__ == "__main__":
    main()


十一、演示效果

        

 

物联沃分享整理
物联沃-IOTWORD物联网 » 物联网开发笔记(34)- 使用Micropython开发ESP32开发板之控制步进电机(28BYJ-48)

发表评论