树莓派RP2350实现步进电机精确控制

2025-05-03 16:03:37
标签: diy 树莓派 python 步进电机

树莓派RP2350 - 步进电机驱动

本文介绍了树莓派 RP2350 开发板实现步进电机驱动的项目设计,主要包括旋转角度的精确控制、串口发送实现自定义角度旋转、OLED 显示旋转状态三部分。

扩展板PCB工程详见:RP2350扩展板 - 立创开源硬件平台

.

项目介绍

包括步进电机原理、该项目使用的 28BYJ-48 步进电机,及其驱动器——ULN2003 驱动模块介绍。

步进电机原理

步进电机(Stepper Motor)是一种将电脉冲信号转换为精确角度位移的执行器件,属于开环控制电机

 

核心特点:每接收一个脉冲,转子就转动一个固定的角度(称为“步距角”),无需反馈传感器即可实现位置控制。

  1. 结构组成

    • 定子

:绕有线圈的磁极,分为多相(常见2相、4相、5相)。

  • 转子

:永磁体(永磁式)或齿状铁芯(反应式/混合式)。

  • 定子绕组按特定顺序通电,产生旋转磁场,吸引转子逐步转动。

  • 工作过程

  • 通过控制器(如单片机)发送脉冲信号,驱动电路按顺序切换定子绕组的电流方向。

  • 每切换一次,转子转动一个步距角,连续脉冲使电机连续旋转。

28BYJ-48 步进电机

 

28BYJ-48 是一款常见的低成本、小扭矩 5 线单极步进电机,可使用 ULN2003 控制器和单片机实现旋转控制,广泛用于打印机、扫描仪、摄像机云台、空调、家电、玩具、消费电子等领域。

 

参数

 

28BYJ-48 是一款适应性强的 5V DC步进电机,设计紧凑,适用于各种应用。

它具有四个相位,速度变化比为1/64,步距角为5.625°/64步,允许精确控制。

电机在100Hz频率下工作,25°C 时的直流电阻为 50Ω ±7% .

它的空载牵引频率大于600Hz,空载脱离频率超过1000Hz,确保在不同场景下的可靠性。

28BYJ-48 在 120Hz 时的自定位转矩和牵引转矩均超过 34.3mN.m,提供强劲性能。

其摩擦转矩范围为600到1200 gf.cm,而拉入转矩为300 gf.cm。


实际输出轴步距角为 5.625°/64 ≈ 0.0879°,转一圈理论上需要 64×64=4096 步,实际可能存在误差。

详见:

28BYJ-48 数据手册

.

ULN2003 驱动器

 

ULN2003 是一款常用的达林顿晶体管阵列芯片,专为驱动高电流负载(如继电器、步进电机、LED阵列等)设计。其作用是将 MCU 输出的弱电流信号转换为大电流输出,是控制 28BYJ-48 步进电机的核心驱动芯片。

 

原理图


 

使用时需要将 28BYJ-48 步进电机的5线快接插头与 ULN2003 模块对应接口连接,并将模块的 4 个控制引脚(信号输入端,丝印 IN1、IN2、IN3、IN4)与单片机对应引脚相连,实现控制信号输入。

详见:

ULN2003A 数据手册 - Texas Instruments

.

项目方案

 

具体执行方案和工程测试流程如下

  1. 1.步进电机原理

  • 2.旋转角度的精确控制

  • 3.串口发送实现自定义角度旋转

  • 4. OLED 显示旋转状态

#1 旋转指定角度

本节介绍并实现了指定角度的步进电机旋转控制。

硬件连接

  • GP0 ---- IN1 (ULN2003)
  • GP1 ---- IN2 (ULN2003)
  • GP18 ---- IN3 (ULN2003)
  • GP19 ---- IN4 (ULN2003)


代码

'''

Name: Stepper Motor driven by ULN2003

Version: v1.0

Date: 2025.05

Author: ljl

Other: Rotate stepper motor (28byj-48) for custom angle.

Hardware connect:

0 ---- IN1 (ULN2003)

1 ---- IN2 (ULN2003)

18 ---- IN3 (ULN2003)

19 ---- IN4 (ULN2003)

Ref: https://pico.nxez.com/2023/11/24/how-to-use-the-stepper-motors-on-raspberry-pi-pico.html

'''

from

machine import Pin

import

utime

# 电机控制引脚

coils

= [

   Pin

(0, Pin.OUT),  # A相 (IN1)

   Pin

(1, Pin.OUT),  # B相 (IN2)

   Pin

(18, Pin.OUT),  # C相 (IN3)

   Pin

(19, Pin.OUT)   # D相 (IN4)

]

# 四相八拍步进电机的顺序值

STEP_SEQ

= [

  [1

, 0, 0, 1],  # AB'

  [1

, 0, 0, 0],  # A

  [1

, 1, 0, 0],  # AB

  [0

, 1, 0, 0],  # B

  [0

, 1, 1, 0],  # BC

  [0

, 0, 1, 0],  # C

  [0

, 0, 1, 1],  # CD

  [0

, 0, 0, 1]   # D

]

'''

驱动电机旋转指定步数

:param steps: 正数=顺时针,负数=逆时针

:param delay_ms: 步间延时(ms),控制转速

'''

def

step_motor(steps, delay_ms=1):

   direction

= 1 if steps >=0 else -1

   for

_ in range(abs(steps)):

       for

phase in range(8)[::direction]:  # 方向控制

           for

coil, state in zip(coils, STEP_SEQ[phase]):

               coil

.value(state)

           utime

.sleep_ms(delay_ms)

# 旋转角度控制

def

rotate_angle(angle):

   steps_per_rev

= 509

   steps

= int(angle * (steps_per_rev / 360))

   step_motor

(steps)

# 释放电机扭矩

def

release():

   for

coil in coils:

       coil

.value(0)

while

True:

   #rotate_angle(1) # 以单步方式持续转动

   rotate_angle

(180) # 逆时针

   release

()

   utime

.sleep_ms(2000)

   rotate_angle

(-90) # 顺时针

   release

()

   utime

.sleep_ms(2000)




由供电处的电压-电流计量工具可知,步进电机旋转工作时的功率约为 1W

#2 串口自定义角度

在实现步进电机旋转驱动的基础上,进一步实现串口发送自定义角度并旋转的功能设计方案。

硬件连接

  • GP0 ---- IN1 (ULN2003)
  • GP1 ---- IN2 (ULN2003)
  • GP4 ---- IN3 (ULN2003)
  • GP5 ---- IN4 (ULN2003)
  • GP8 ---- RXD (CH340)
  • GP9 ---- TXD (CH340)



代码

'''

Name: Stepper Motor rotate custom angle from serial

Version: v1.0

Date: 2025.05

Author: ljl

Other: Rotate stepper motor (28byj-48) for custom angle from UART.

Hardware connect:

0 ---- IN1 (ULN2003)

1 ---- IN2 (ULN2003)

4 ---- IN3 (ULN2003)

5 ---- IN4 (ULN2003)

8 ---- RXD (CH340)

9 ---- TXD (CH340)

'''

from

machine import Pin, UART

import

utime

import

ujson

# 电机控制引脚

coils

= [

   Pin

(0, Pin.OUT),  # A相 (IN1)

   Pin

(1, Pin.OUT),  # B相 (IN2)

   Pin

(4, Pin.OUT),  # C相 (IN3)

   Pin

(5, Pin.OUT)   # D相 (IN4)

]

# 四相八拍步进电机的相序

STEP_SEQ

= [

  [1

, 0, 0, 1],  # AB'

  [1

, 0, 0, 0],  # A

  [1

, 1, 0, 0],  # AB

  [0

, 1, 0, 0],  # B

  [0

, 1, 1, 0],  # BC

  [0

, 0, 1, 0],  # C

  [0

, 0, 1, 1],  # CD

  [0

, 0, 0, 1]   # D

]

# 驱动电机旋转指定步数;delay_ms 步间延时(ms),控制转速

def

step_motor(steps, delay_ms=1):

   direction

= 1 if steps >=0 else -1

   for

_ in range(abs(steps)):

       for

phase in range(8)[::direction]:  # 方向控制

           for

coil, state in zip(coils, STEP_SEQ[phase]):

               coil

.value(state)

           utime

.sleep_ms(delay_ms)

# 角度控制

def

rotate_angle(angle):

   steps_per_rev

= 509

   steps

= int(angle * (steps_per_rev / 360))

   step_motor

(steps)

# 释放电机扭矩

def

release():

   for

coil in coils:

       coil

.value(0)

# 串口控制旋转角度

def

uart_control():

   uart

= machine.UART(1, baudrate=9600, tx=Pin(8), rx=Pin(9))

   while

True:

       if

uart.any():

           cmd

= uart.read()

           try

:

               data

= ujson.loads(cmd)

               rotate_angle

(int(data['angle']))

               release

()

           except

:

               uart

.write('Invalid command\r\n')

               release

()

       else

:

           release

()

       utime

.sleep_ms(100)

# main loop

while

True:

   uart_control

()

这里为了节能并提高效率,仅在串口发送正确指令时旋转,其他情况均释放步进电机扭矩,此时电流约为 0 .

效果


 

由于调用了 ujson 库,因此串口发送指令需符合 json 格式,如

{"angle":40}

.

若串口发送 json 消息的格式错误,则反馈指令无效的提示。

#3 OLED 显示旋转状态

在前面实现步进电机旋转驱动、串口自定义角度控制的基础上,进一步实现串口发送角度、旋转、OLED 状态显示的功能设计方案。

硬件连接

  • GP0 ---- IN1 (ULN2003)
  • GP1 ---- IN2 (ULN2003)
  • GP18 ---- IN3 (ULN2003)
  • GP19 ---- IN4 (ULN2003)
  • GP8 ---- RXD (CH340)
  • GP9 ---- TXD (CH340)
  • GP4 ---- SDA (OLED_SSD1306)
  • GP5 ---- SCL (OLED_SSD1306)




流程图

 

代码

 

'''

Name: Stepper Motor rotate custom angle from serial and OLED display

Version: v1.0

Date: 2025.05

Author: ljl

Other: Rotate stepper motor (28byj-48) for custom angle from UART, and OLED display the motor state in moving or steady.

Hardware connect:

0 ---- IN1 (ULN2003)

1 ---- IN2 (ULN2003)

18 ---- IN3 (ULN2003)

19 ---- IN4 (ULN2003)

8 ---- RXD (CH340)

9 ---- TXD (CH340)

4 ---- SDA (OLED_SSD1306)

5 ---- SCL (OLED_SSD1306)

Serial send style: {"angle": 40}

'''

from

machine import Pin, UART, SoftI2C

import

ssd1306 # OLED

import

ujson # read uart string

import

utime

# ==== Initialized IIC OLED ====

i2c

= SoftI2C(scl=Pin(5), sda=Pin(4))

oled_width

= 128

oled_height

= 64

oled

= ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)

# display the motor state

def

display_motor(angle,state):

   oled

.fill(0)  # 清屏

   oled

.text("Rotate Angle: ", 0, 0)

   oled

.text("{:.1f} deg".format(angle), 20, 15)

   oled

.text("State: ", 0, 35)

   if

state == 1:

       oled

.text("Rotating ...", 20, 50)

   elif

state == 0:

       oled

.text("Reset", 20, 50)

   else

:

       oled

.text("Error", 20, 50)

   oled

.show()

# 电机控制引脚

coils

= [

   Pin

(0, Pin.OUT),  # A相 (IN1)

   Pin

(1, Pin.OUT),  # B相 (IN2)

   Pin

(18, Pin.OUT),  # C相 (IN3)

   Pin

(19, Pin.OUT)   # D相 (IN4)

]

# 四相八拍步进电机的相序

STEP_SEQ

= [

  [1

, 0, 0, 1],  # AB'

  [1

, 0, 0, 0],  # A

  [1

, 1, 0, 0],  # AB

  [0

, 1, 0, 0],  # B

  [0

, 1, 1, 0],  # BC

  [0

, 0, 1, 0],  # C

  [0

, 0, 1, 1],  # CD

  [0

, 0, 0, 1]   # D

]

# 驱动电机旋转指定步数;delay_ms 步间延时(ms),控制转速

def

step_motor(steps, delay_ms=1):

   direction

= 1 if steps >=0 else -1

   for

_ in range(abs(steps)):

       for

phase in range(8)[::direction]:  # 方向控制

           for

coil, state in zip(coils, STEP_SEQ[phase]):

               coil

.value(state)

           utime

.sleep_ms(delay_ms)

# 角度控制

def

rotate_angle(angle):

   steps_per_rev

= 509  # 64步/拍 × 8拍 × 8相位

   steps

= int(angle * (steps_per_rev / 360))

   step_motor

(steps)

# 释放电机扭矩

def

release():

   for

coil in coils:

       coil

.value(0)

# 串口控制旋转角度

def

uart_control():

   uart

= machine.UART(1, baudrate=9600, tx=Pin(8), rx=Pin(9))

   while

True:

       if

uart.any():

           cmd

= uart.read()

           try

:

               data

= ujson.loads(cmd)

               ra

= float(data['angle']) # rotate angle

               display_motor

(ra,1)

               rotate_angle

(ra)

               release

()

               display_motor

(ra,0)

           except

:

               uart

.write('Invalid command\r\n')

               release

()

       else

:

           release

()

           #display_motor(0,0)

       utime

.sleep_ms(100)

# main loop

display_motor

(0,0) # initialize OLED display

while

True:

   uart_control

()

效果

 


总结

本文介绍了 RP2350 开发板实现步进电机驱动的项目设计,包括旋转角度的精确控制、串口发送实现自定义角度旋转、OLED 显示旋转状态等,为 RP2350 的开发、设计和应用提供了参考。


阅读(0) 收藏(0) 转载(0) 举报/Report
相关阅读

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有