这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【let'sdo|2026年第1期】静音步进电机控制实践2过程帖(测试元件及环境

共1条 1/1 1 跳转至

【let'sdo|2026年第1期】静音步进电机控制实践2过程帖(测试元件及环境)

助工
2026-06-04 17:17:06     打赏


【let's do|2026年第1期】  静音步进电机控制实践


2 过程帖  (测试元件及环境)

 image.png

  

  一 硬件环境:

  1.主控板

image.png

  2.步进驱动扩展版

image.png


  3.转接板

image.png


  4.42步进电机

image.png


  5.电池

  image.png

  

  二 导线连接

  1 硬件连接描述

步骤1:ESP32 → 扩展板

STEP → GPIO 21

DIR → GPIO 15

EN → GPIO 25

VIO → 3.3V

GND → 信号地


步骤2:扩展板 → 转接板

要注意2209驱动板的引脚与4988的不同,需转接板桥接一下,安装时需注意,可以根据VMOT引脚位置来定


步骤3:电池 → 扩展板

电池正极(+) → 扩展板 VMOT

电池负极(-) → 扩展板 GND


步骤4:步进电机 → 扩展板

步进电机 A1 → 扩展板 A1

步进电机 B1 → 扩展板 B1

步进电机 A2 → 扩展板 A2

步进电机 B2 → 扩展板 B2


步骤5:转接板 → TMC2209

TMC2209驱动模块直接插在转接板上。


  2 实物连接

  以下是实物连接图

image.png

  二 软件环境:

  1.thonny

   https://thonny.org/


  2.esp32固件

   https://micropython.org/download/ESP32_GENERIC/


  三 测试程序:

  1.运行测试

from machine import Pin
import utime

step = Pin(21, Pin.OUT)
dir_pin = Pin(15, Pin.OUT)
en = Pin(25, Pin.OUT)

en.value(0)   # 启用电机
dir_pin.value(0)  # 设置顺时针

# 顺时针转 10000 步
for _ in range(10000):
    step.value(1)
    utime.sleep_us(1000)
    step.value(0)
    utime.sleep_us(1000)

en.value(1)   # 禁用电机


  2.角度测试

import machine
import utime

# ==================== 引脚定义 ====================
motor_dir = machine.Pin(15, machine.Pin.OUT)
motor_step = machine.Pin(21, machine.Pin.OUT)
motor_en = machine.Pin(25, machine.Pin.OUT)

# ==================== 参数设置 ====================
MICRO_STEP_MODE = "1/8"      # 细分:1/8, 1/16, 1/32, 1/64
STEP_ANGLE = 1.8
FULL_STEP_PULSES = int(360 / STEP_ANGLE)  # = 200

MICRO_STEP_MAP = {"1/8":8, "1/16":16, "1/32":32, "1/64":64}
multiplier = MICRO_STEP_MAP[MICRO_STEP_MODE]
PULSES_PER_REV = FULL_STEP_PULSES * multiplier

def rotate(angle, rpm=30, direction="CW"):
    """
    旋转指定角度
    angle: 角度(0-360,支持小数)
    rpm: 转速(转/分钟)
    direction: 方向 "CW"(顺时针) 或 "CCW"(逆时针)
    """
    # 计算需要的脉冲数
    pulses_needed = int((angle / 360) * PULSES_PER_REV)
    
    if pulses_needed == 0:
        print("角度太小,无需转动")
        return
    
    # 计算脉冲延时
    pulse_delay_us = int(30_000_000 / (rpm * PULSES_PER_REV))
    
    # 设置方向
    dir_value = 0 if direction == "CW" else 1
    motor_dir.value(dir_value)
    
    # 使能电机
    motor_en.value(0)
    
    # 发送脉冲
    for i in range(pulses_needed):
        motor_step.value(1)
        utime.sleep_us(pulse_delay_us)
        motor_step.value(0)
        utime.sleep_us(pulse_delay_us)
    
    # 关闭电机
    motor_en.value(1)
    
    print(f"旋转 {angle}° 完成 (脉冲数: {pulses_needed})")

# ==================== 使用示例 ====================
# 旋转90度
rotate(90, rpm=30, direction="CW")

utime.sleep(1)

# 旋转180度,逆时针,转速20rpm
rotate(180, rpm=20, direction="CCW")

utime.sleep(1)

# 旋转45度
rotate(45)


  3.速度测试

import machine
import utime

# ==================== 引脚定义 ====================
motor_dir = machine.Pin(15, machine.Pin.OUT)
motor_step = machine.Pin(21, machine.Pin.OUT)
motor_en = machine.Pin(25, machine.Pin.OUT)

# ==================== 用户设置 ====================
MICRO_STEP_MODE = "1/8"      # 细分:1/8, 1/16, 1/32, 1/64
CURRENT_DIRECTION = "CW"     # 方向:CW(顺时针), CCW(逆时针)
TARGET_RPM = 30              # 转速:30转/分钟

# ==================== 转速范围参考 ====================
"""
【推荐转速范围】
  低速精密定位: 5-30 RPM    ← 力矩大,不失步
  中速运行:    30-120 RPM   ← 常用范围
  高速运行:    120-300 RPM  ← 需加减速,力矩下降
  极限转速:    300-600 RPM  ← 力矩很小,容易失步
"""

# ==================== PULSES_PER_REV 计算 ====================
"""
【一圈需要多少个脉冲?】

  第1步:电机步距角 = 1.8°
        意思是:驱动器每收到1个脉冲,电机转1.8°
  
  第2步:整步一圈需要多少脉冲?
        360° ÷ 1.8° = 200 个脉冲
  
  第3步:设置细分倍数
        1/8细分 = 把1个整步分成8个微步
        所以脉冲数变成原来的8倍
  
  第4步:一圈脉冲数 = 200 × 细分倍数
        举例:200 × 8 = 1600 个脉冲/圈
"""
STEP_ANGLE = 1.8
FULL_STEP_PULSES = int(360 / STEP_ANGLE)  # = 200

MICRO_STEP_MAP = {"1/8":8, "1/16":16, "1/32":32, "1/64":64}
multiplier = MICRO_STEP_MAP[MICRO_STEP_MODE]

PULSES_PER_REV = FULL_STEP_PULSES * multiplier

# ==================== pulse_delay_us 计算 ====================
"""
【脉冲延时需要多少微秒?】

  已知:
    转速 = 30 转/分钟
    一圈脉冲 = 1600 脉冲
  
  第1步:转速换算成 转/秒
    30 转/分钟 ÷ 60 = 0.5 转/秒
  
  第2步:每秒需要多少个脉冲?
    0.5 转/秒 × 1600 脉冲/圈 = 800 脉冲/秒 (即 800 Hz)
  
  第3步:每个脉冲的周期是多少?
    周期 = 1 ÷ 频率 = 1 ÷ 800 = 0.00125 秒 = 1250 微秒
  
  第4步:每个脉冲需要高电平和低电平,各占一半时间
    脉冲延时 = 周期 ÷ 2 = 1250 ÷ 2 = 625 微秒
  
  【合并成一条公式】
    脉冲延时(us) = 30,000,000 ÷ (转速 × 一圈脉冲数)
    
    30,000,000 怎么来的?
      60(分钟→秒) × 1,000,000(秒→微秒) ÷ 2(高低电平各一半)
      = 60 × 1,000,000 ÷ 2 = 30,000,000
    
    代入验证:30,000,000 ÷ (30 × 1600) = 30,000,000 ÷ 48,000 = 625 ✅
"""
pulse_delay_us = int(30_000_000 / (TARGET_RPM * PULSES_PER_REV))

# ==================== 方向设置 ====================
dir_value = 0 if CURRENT_DIRECTION == "CW" else 1

# ==================== 执行旋转 ====================
motor_en.value(0)
motor_dir.value(dir_value)

for i in range(PULSES_PER_REV):
    motor_step.value(1)
    utime.sleep_us(pulse_delay_us)
    motor_step.value(0)
    utime.sleep_us(pulse_delay_us)

motor_en.value(1)
print("转动一圈完成")


  4.距离测试

import machine
import utime

# ==================== 引脚定义 ====================
motor_dir = machine.Pin(15, machine.Pin.OUT)
motor_step = machine.Pin(21, machine.Pin.OUT)
motor_en = machine.Pin(25, machine.Pin.OUT)

# ==================== 固定参数 ====================
STEP_ANGLE = 1.8                    # 步距角:电机每收到1个脉冲转动的角度
LEAD = 2                            # 导程:丝杆转一圈,滑台移动的距离(mm)
MICRO_STEP = 8                      # 细分:1/8细分

# ==================== 计算公式 ====================
"""
【导程与距离的计算公式】

1. 一圈脉冲数 = (360° ÷ 步距角) × 细分倍数
   示例:360 ÷ 1.8 = 200个整步,200 × 8细分 = 1600脉冲/圈

2. 每毫米脉冲数 = 一圈脉冲数 ÷ 导程
   示例:1600脉冲 ÷ 2mm = 800脉冲/mm

3. 目标距离脉冲数 = 距离(mm) × 每毫米脉冲数
   示例:20mm × 800 = 16000脉冲

4. 脉冲延时(us) = 1,000,000 ÷ (速度 × 每毫米脉冲数 × 2)
   示例:20mm/s → 1,000,000 ÷ (20 × 800 × 2) = 31us
"""
PULSES_PER_REV = int(360 / STEP_ANGLE) * MICRO_STEP       # 一圈脉冲数 = 1600
PULSES_PER_MM = PULSES_PER_REV / LEAD                     # 每毫米脉冲数 = 800

# ==================== 方向映射 ====================
DIR = {"UP": 0, "DOWN": 1}          # 方向:UP上升,DOWN下降(反了交换0和1)

# ==================== 移动函数 ====================
def move(direction, distance, speed):
    """
    移动函数
    参数:
        direction: 方向 ("UP" 或 "DOWN")
        distance:  距离 (mm)
        speed:     速度 (mm/s)
    
    计算过程:
        脉冲数 = 距离 × 每毫米脉冲数
        延时(us) = 1,000,000 ÷ (速度 × 每毫米脉冲数 × 2)
    """
    if distance == 0:
        return
    
    # 根据速度和距离计算脉冲参数
    delay_us = int(1_000_000 / (speed * PULSES_PER_MM * 2))  # 脉冲延时
    pulses = int(distance * PULSES_PER_MM)                   # 所需脉冲数
    
    # 设置方向
    motor_dir.value(DIR[direction])
    
    # 打印计算过程
    print(f"\n【{direction}移动计算】")
    print(f"  目标: {direction} {distance}mm, 速度{speed}mm/s")
    print(f"  计算: {distance}mm × {PULSES_PER_MM:.0f}脉冲/mm = {pulses}脉冲")
    print(f"  计算: 1,000,000 ÷ ({speed} × {PULSES_PER_MM:.0f} × 2) = {delay_us}us")
    print(f"  结果: 延时{delay_us}us, 脉冲{pulses}")
    
    # 发送脉冲
    for _ in range(pulses):
        motor_step.value(1)
        utime.sleep_us(delay_us)
        motor_step.value(0)
        utime.sleep_us(delay_us)
    
    utime.sleep(0.5)  # 移动完成后停顿0.5秒

# ==================== 执行移动 ====================
motor_en.value(0)                    # 使能电机(0=使能,1=释放)

# 高速上升20mm,低速下降20mm
move("UP", 20, 10)                   # 上升20mm,速度20mm/s(高速)
move("DOWN", 20, 5)                  # 下降20mm,速度5mm/s(低速)

motor_en.value(1)                    # 释放电机
print("\n完成!")


四 演示视频:




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]