这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 静音步进电机控制实践-成果帖-使用串口控制步进电机运行

共1条 1/1 1 跳转至

静音步进电机控制实践-成果帖-使用串口控制步进电机运行

菜鸟
2026-06-21 19:30:37     打赏

一、项目概述

1.1 项目背景

步进电机因其开环控制精度高、定位准确、成本适中等特点,广泛应用于3D打印机、数控机床、机器人关节、自动化设备等领域。本项目基于ST公司NUCLEO-U575ZI-Q开发板和TMC2209步进电机驱动器,设计并实现了一套完整的步进电机控制系统,支持启动/停止、方向切换、平滑加减速、串口远程控制等功能

1.2 任务介绍

主题一:基础步进电机运动控制系统

使用MCU控制TMC2209驱动步进电机,实现一个可控制转动方向和速度的基础运动控制系统

1.     使用PWM方式生成STEP脉冲步进

2.     使用DIR控制电机正反转

3.     支持电机多种转速,可设(100Hz-20000Hz)

4.     支持串口发送命令调节电机工作(启动、停止、反转、调速、数据查看)

5.     支持梯形加减速控制

6.     支持反转保护(速度降为0后再反转)

1.3 系统框图

image.png

1.4 硬件接线图

TMC2209引脚功能连接Nucleo引脚STM32引脚连接器位置






STEP步进脉冲输入D10PD14 (TIM4_CH3)CN7 Pin16
DIR方向控制D11PA7CN7 Pin14
EN使能控制(低有效)D9PD15CN7 Pin18
VDD_IO逻辑电源3V3CN8 Pin7
GND逻辑地GNDCN8 Pin11/13
VM电机电源(4.75-28V)外部电源直接连接
M1A、1B、2A、2B电机线圈连接
步进电机引脚

注意:TMC2209的VM引脚需要外接7-24V电源供电,不能使用Nucleo板的5V供电;细分引脚使用默认即可。

二、硬件介绍

2.1 主控器:NUCLEO-U575ZI-Q开发板

NUCLEO-U575ZI-Q是基于STM32U575ZIT6Q芯片的Nucleo-144开发板,采用LQFP144封装,具备以下关键特性

特性说明



内核ARM Cortex-M33 with TrustZone
存储2MB Flash + 768KB RAM
调试接口板载STLINK-V3E调试器/编程器
扩展接口ARDUINO® Uno V3兼容的Zio连接器(CN7-CN10)
用户IO3个用户LED(LD1绿/LD2蓝/LD3红)、1个用户按钮(B1)、1个复位按钮(B2)
时钟32.768kHz晶振(LSE),内部HSI可作为主时钟

本项目的控制信号(STEP/DIR/EN)均通过ARDUINO®兼容的Zio连接器(CN7)引出,便于连接标准扩展模块

2.2 执行器:TMC2209步进电机驱动器

TMC2209是一款超静音两相步进电机驱动芯片,具备以下特点

参数规格


驱动电流2A RMS / 2.8A 峰值
电压范围4.75V - 28V
控制方式STEP/DIR 或 UART
细分模式1 ~ 1/256微步
静音技术StealthChop2

本项目采用最基础的STEP/DIR控制方式,仅需连接STEP、DIR、EN三个信号引脚即可实现完整控制

2.3 应用方向及应用场景

本系统可广泛应用于以下场景:

  • 3D打印机:精确控制挤出机和平台的步进运动

  • 数控机床:实现X/Y/Z轴的精准定位

  • 机器人关节:驱动机械臂的旋转关节

  • 自动化设备:传送带、旋转台、分拣机构等

三、设计思路

3.1 功能模块划分

板载模块实现功能



TIM4_CH3 (PD14)PWM输出,产生步进脉冲信号(STEP),频率决定电机转速
GPIO (PA7)方向控制(DIR),高电平正转/低电平反转
GPIO (PD15)使能控制(EN),低电平使能/高电平失能
USART1 (PA9/PA10)串口通信,接收上位机命令并回显状态
内部HSI时钟无需外部晶振即可提供稳定的系统时钟

3.2 核心控制逻辑

  1. PWM频率调速:通过修改定时器TIM4的自动重装载值(ARR)改变PWM频率,频率越高电机转速越快

  2. 平滑加减速:采用10ms定时斜坡策略,每10ms将当前速度向目标速度调整一个固定步长(10Hz),实现无冲击的速度过渡

  3. 反转保护:运行时收到反转命令,先减速至0,再切换DIR方向,最后从最低速重新加速,避免电机和驱动器受损。

  4. 状态机管理:通过 STATE_IDLESTATE_RUNNINGSTATE_DECEL_REVERSESTATE_REVERSE_RECOVER 四个状态管理电机行为,逻辑清晰可靠。

  5. 速度恢复stop 命令保存当前速度,start 命令恢复该速度,避免每次启动都从默认速度开始。

  6. 速度到达反馈:当实际速度达到目标速度时,串口自动输出“速度已到达目标 X Hz”提示。

四、如何开启运行

4.1 硬件连接

  1. 按硬件接线图连接NUCLEO-U575ZI-Q与TMC2209模块

  2. TMC2209的VM引脚接入7-24V外部电源

  3. 将Nucleo板通过USB线连接电脑

4.2 软件准备

  1. 使用STM32CubeIDE打开工程

  2. 编译并烧录程序

  3. 打开串口终端(波特率115200, 8N1)

4.3 基本操作流程

image.png

4.4 命令列表

image.png

五、主要参数情况

参数名称数值说明




系统时钟80 MHz使用内部HSI,无需外部晶振
定时器计数时钟100 kHzTIM4预分频后(160M/1600)
速度范围100 ~ 20000 Hz对应步进脉冲频率
默认速度1000 Hz上电初始速度
加减速步长10 Hz / 10ms即1000 Hz/s的加速度
串口波特率1152008N1格式

六、实现步骤

6.1 CubeMX配置

  1. 时钟配置:HSE禁用,使用HSI作为PLL时钟源,配置PLL使SYSCLK=80MHz

  2. GPIO配置

    • PD14 → TIM4_CH3 (PWM输出)

    • PA7 → GPIO_Output (DIR)

    • PD15 → GPIO_Output (EN)

  3. TIM4配置:Channel3 PWM模式,Prescaler=1599(计数时钟100kHz),自动重装载预装载使能

  4. USART1配置:异步模式,波特率115200,开启接收中断

  5. ICACHE:使能指令缓存提升性能

  6. PWR:启用SMPS降低功耗

6.2 代码实现

代码采用模块化设计,核心函数包括:

  • set_target_speed():设置目标速度

  • apply_speed():立即应用速度到定时器

  • speed_ramp_handler():10ms周期斜坡处理(加减速+换向+停止检测)

  • handle_command():串口命令解析执行

6.3 调试与验证

  1. 烧录程序后通过串口发送各命令验证功能

  2. 使用 status 命令实时监控速度变化

  3. 观察速度到达反馈确认加减速完成

七、代码展示

7.1 关键宏定义调试与验证

#define SPEED_DEFAULT   1000   // 默认速度 (Hz)
#define SPEED_MIN     100    // 最低速度限制
#define SPEED_MAX     20000   // 最高速度限制
#define TIM_CLK      100000  // 定时器计数时钟 (Hz) = 160M / 1600
#define ACCEL_STEP     10    // 每10ms调整的频率步长 (Hz)

说明:这些宏定义了电机运行的基本参数,速度范围100-20000Hz,加减速步长10Hz/10ms。

7.2 速度控制核心函数

/**
 * @brief 立即将频率写入定时器(强制输出)
 */
 static void apply_speed(uint32_t freq) {
    current_speed = freq;
    if (freq == 0) {
        __HAL_TIM_SET_AUTORELOAD(&htim4, 0);
        __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
        return;
    }
    // 计算ARR = 计数时钟 / 频率 - 1
    uint32_t arr = (TIM_CLK / freq) - 1;
    if (arr > 0xFFFF) arr = 0xFFFF;   // TIM4为16位
    __HAL_TIM_SET_AUTORELOAD(&htim4, arr);
    __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, arr / 2);
    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
}

说明:通过修改定时器自动重装载值(ARR)改变PWM频率,同时保持50%占空比。

7.3 速度斜坡处理(核心)

void speed_ramp_handler(void) {
    static uint32_t last_tick = 0;
    uint32_t now = HAL_GetTick();
    if ((now - last_tick) < 10) return;  // 10ms周期
    last_tick = now;

    if (!motor_enabled) {
        // 清空辅助状态
        if (pending_reverse) {
            pending_reverse = 0;
            saved_target_speed = 0;
        }
        speed_reached_flag = 0;
        return;
    }

    // 第一步:速度斜坡(加减速)
    if (current_speed < target_speed) {
        uint32_t step = ACCEL_STEP;
        if (target_speed - current_speed < step) 
            step = target_speed - current_speed;
        apply_speed(current_speed + step);
        speed_reached_flag = 0;
    } else if (current_speed > target_speed) {
        uint32_t step = ACCEL_STEP;
        if (current_speed - target_speed < step) 
            step = current_speed - target_speed;
        apply_speed(current_speed - step);
        speed_reached_flag = 0;
    } else {
        // 速度到达,输出反馈(仅一次)
        if (current_speed != 0 && target_speed != 0 && !speed_reached_flag) {
            printf("速度已到达目标 %lu Hz\r\n", current_speed);
            speed_reached_flag = 1;
        }
    }

    // 第二步:换向保护(速度=0时换向)
    if (current_speed == 0 && pending_reverse) {
        motor_direction = !motor_direction;
        HAL_GPIO_WritePin(DIR_GPIO_Port, DIR_Pin, 
                          motor_direction ? GPIO_PIN_SET : GPIO_PIN_RESET);
        printf("方向已切换为 %s\r\n", motor_direction ? "正转" : "反转");
        pending_reverse = 0;
        if (saved_target_speed > 0) {
            target_speed = saved_target_speed;
            saved_target_speed = 0;
            if (current_speed == 0) {
                apply_speed(SPEED_MIN);  // 从最低速重新起步
            }
            printf("恢复目标速度 %lu Hz,开始加速\r\n", target_speed);
            speed_reached_flag = 0;
        }
    }

    // 第三步:自动停止检测
    if (current_speed == 0 && target_speed == 0 && motor_enabled == 1) {
        motor_enabled = 0;
        HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET);
        HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3);
        printf("电机已停止\r\n");
        speed_reached_flag = 0;
    }
}

说明:这是整个程序最核心的函数,每10ms执行一次,完成三项关键任务:

  1. 平滑加减速:逐步逼近目标速度,避免突变

  2. 换向保护:速度降到0后才切换方向,防止冲击

  3. 自动停止:速度降至0且目标为0时自动失能

7.4 反转命令处理

else if (strcmp(cmd, "reverse") == 0) {
    if (!motor_enabled || current_speed == 0) {
        // 停止时直接换向
        motor_direction = !motor_direction;
        HAL_GPIO_WritePin(DIR_GPIO_Port, DIR_Pin, 
                          motor_direction ? GPIO_PIN_SET : GPIO_PIN_RESET);
        printf("方向已切换为 %s(电机停止)\r\n", 
               motor_direction ? "正转" : "反转");
    } else {
        // 运行时换向:先减速到0,再换向,再加速
        if (pending_reverse) {
            printf("正在换向中,请等待完成\r\n");
            return;
        }
        saved_target_speed = target_speed;
        if (saved_target_speed == 0) saved_target_speed = SPEED_MIN;
        set_target_speed(0);      // 触发减速
        pending_reverse = 1;      // 标记等待换向
        printf("正在减速至零以换向...\r\n");
    }
}

说明:区分两种场景——停止时直接换向(安全),运行时先减速再换向(保护电机和驱动器)。

7.5 主循环

while (1)
{
    if (cmd_ready) {
        handle_command();       // 解析串口命令
    }
    speed_ramp_handler();       // 速度斜坡(每10ms有效)
    HAL_Delay(1);              // 1ms延时,释放CPU
}

说明:主循环结构简洁,每秒执行约1000次,其中速度斜坡每10ms(10次循环)调整一次。

7.6 串口接收中断

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        if (rx_char == '\r' || rx_char == '\n') {
            cmd_ready = 1;      // 完整命令接收完成
        } else if (cmd_index < sizeof(cmd_buffer) - 1) {
            cmd_buffer[cmd_index++] = rx_char;  // 存入缓冲区
        }
        HAL_UART_Receive_IT(&huart1, (uint8_t*)&rx_char, 1);
    }
}

说明:中断方式接收串口数据,收到回车/换行时标记命令就绪,不阻塞主循环。

八、必完成任务的功能演示

任务名称演示方法预期结果




电机启动串口发送 start电机从最低速(100Hz)平滑加速到目标速度,到达后输出反馈
速度调节串口发送 speed 2000电机从当前速度平滑加减速到2000Hz,到达后输出反馈
速度微调串口发送 speed+ / speed-目标速度±100Hz,平滑变化
方向切换串口发送 reverse运行时先减速至0→换向→重新加速;停止时立即换向
停止控制串口发送 stop电机减速至0,自动失能,串口输出“电机已停止”
速度恢复stop 后发送 start恢复上一次运行速度,无需重新设置
状态查询串口发送 status显示运行状态、当前速度、目标速度、方向等信息

8.1 STM32初上电,串口打印消息,默认电机上电停机

image.png

8.2 串口发送help命令,打印可用命令

image.png

8.3 串口发送start命令,电机以1000Hz初始速度启动

image.png

6月21日 (1).gif

8.4 串口发送speed 5000命令,电机以5000Hz速度为目标缓慢加速

image.png

6月21日 (1)(1).gif

8.4 串口发送status命令,串口打印当前电机状态

image.png

8.5 串口发送reverse命令,电机开始减速、停止、反转、加速、直到达到之前目标速度

image.png

6月21日 (1)(5).gif

8.6 串口发送stop命令,电机开始减速、停止、失能。

image.png

6月21日 (1)(3).gif

资料分享:静音步进电机控制实践-stepping motor




关键词: 电机     静音     串口     STM32     TMC2209    

共1条 1/1 1 跳转至

回复

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