Funpack4-3 基于TMC4361A+TMC2160实现的步进电机控制系统
该项目使用了TMC4361A+TMC2160,实现了步进电机控制系统的设计,它的主要功能为:实现了高精度、高性能的步进电机控制系统,该系统能够实现精确的位置控制、速度控制和加速度控制。
标签
Funpack活动
步进电机
ESP32S3
tmc
xwb
更新2026-02-25
3

基于TMC4361A+TMC2160实现的步进电机控制系统

一、项目描述

1.1 项目介绍

本项目基于ESP32-S3微控制器,搭配Trinamic公司的TMC4361A运动控制器和TMC2160步进电机驱动芯片,实现了高精度、高性能的步进电机控制系统。该系统能够实现精确的位置控制、速度控制和加速度控制,适用于3D打印机、数控机床、自动化设备等需要精密运动控制的应用场景。

1.2 设计思路

运动控制策略

  1. 时钟系统:使用ESP32-S3的LEDC外设生成8MHz时钟信号供TMC4361A使用
  2. SPI总线隔离:TMC4361A使用SPI2_HOST,TMC2160使用SPI3_HOST,避免总线冲突
  3. 梯形速度曲线:采用梯形加减速曲线,确保运动平滑无失步
  4. 细分技术:256微步细分配置,200步/圈的电机达到51200步/圈精度

控制参数设计

  • 速度参数:VMAX=51200 (1圈/秒),VSTART=1,VSTOP=10
  • 加速度参数:AMAX=100000,DMAX=100000,ASTART=100,DSTOP=10
  • 电流设置:运行电流15/32,保持电流8/32,平衡扭矩与发热




二、硬件介绍

2.1 核心硬件组成

硬件模块

型号

主要功能

关键参数

主控芯片

ESP32-S3

系统控制、SPI主机

240MHz双核、2个独立SPI

运动控制器

TMC4361A

运动规划、斜坡生成

32位位置计数器、梯形/S曲线

电机驱动

TMC2160

电流驱动、细分控制

256微步、StealthChop2

步进电机

200步/圈

执行机构

1.8°步距角

2.2 硬件连接

TMC4361A连接 (运动控制器)

ESP32-S3          TMC4361A
GPIO11 (MOSI) --> SPI_SDI
GPIO13 (MISO) <-- SPI_SDO
GPIO12 (SCK) --> SPI_SCK
GPIO10 (CS)   --> SPI_CSN
GPIO9 (CLK) --> CLK_EXT (8MHz时钟输入)
GPIO6 (RST) --> NRST (复位)
  • SPI总线:SPI2_HOST,4MHz时钟,Mode 3 (CPOL=1, CPHA=1)
  • 外部时钟:ESP32 LEDC生成8MHz方波

TMC2160连接 (电机驱动器)

ESP32-S3          TMC2160
GPIO17 (MOSI) --> SDI
GPIO18 (MISO) <-- SDO
GPIO16 (SCK) --> SCK
GPIO15 (CS)   --> CSN
  • SPI总线:SPI3_HOST (独立总线),4MHz时钟,Mode 3
  • 电机接口:通过步进脉冲输入(来自TMC4361A的STEP/DIR信号)

三、软件代码说明

关键功能代码说明

功能1:TMC4361A初始化与时钟配置

// 1. 生成8MHz外部时钟
static void clk_ext_init(void)
{
   // 使用LEDC产生8MHz时钟信号
   ledc_timer_config_t ledc_timer = {
      .speed_mode       = LEDC_LOW_SPEED_MODE,
      .timer_num        = LEDC_TIMER_0,
      .duty_resolution  = LEDC_TIMER_1_BIT,  // 1位分辨率,50%占空比
      .freq_hz          = TMC4361A_CLK_FREQ, // 8 MHz
      .clk_cfg          = LEDC_USE_APB_CLK   // 使用APB时钟 (80MHz)
  };
   ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
   
   ledc_channel_config_t ledc_channel = {
      .speed_mode     = LEDC_LOW_SPEED_MODE,
      .channel        = LEDC_CHANNEL_0,
      .timer_sel      = LEDC_TIMER_0,
      .intr_type      = LEDC_INTR_DISABLE,
      .gpio_num       = TMC4361A_PIN_CLK_EXT,
      .duty           = 1,  // 50%占空比
      .hpoint         = 0
  };
   ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

功能说明

  • TMC4361A需要外部时钟才能工作
  • 使用ESP32的LEDC(LED PWM控制器)生成精确的8MHz方波
  • 1位分辨率确保50%占空比(duty=1时为50%)
  • 时钟必须在芯片复位前启动

功能2:SPI通信实现

// 全双工SPI读写,软件控制CS
static void spi_read_write(uint8_t *data, size_t length)
{
   spi_transaction_t t;
   uint8_t rx_data[8] = {0};
   
   memset(&t, 0, sizeof(t));
   t.length = length * 8;
   t.tx_buffer = data;
   t.rxlength = length * 8;
   t.rx_buffer = rx_data;
   
   // 软件控制CS - 拉低
   gpio_set_level(TMC4361A_PIN_CS, 0);
   
   ret = spi_device_polling_transmit(spi_handle, &t);
   
   // 软件控制CS - 拉高
   gpio_set_level(TMC4361A_PIN_CS, 1);
   
   // 将接收的数据复制回data数组
   memcpy(data, rx_data, length);
}

功能说明

  • TMC4361A使用SPI Mode 3 (CPOL=1, CPHA=1)
  • 全双工通信:发送的同时接收数据
  • 软件控制CS信号,确保时序精确
  • 读寄存器需要两次传输:第一次发请求,第二次读数据

功能3:运动控制 - 位置模式

void tmc4361a_move_to(int32_t position)
{
   ESP_LOGI(TAG, "移动到位置: %ld", (long)position);
   
   // 设置位置模式 + 梯形斜坡
   tmc4361a_write_register(TMC4361A_RAMPMODE,
                          TMC4361A_RAMP_POSITION | TMC4361A_RAMP_TRAPEZ);
   
   // 设置目标位置
   tmc4361a_write_register(TMC4361A_XTARGET, position);
}

功能说明

  • 位置模式适用于点对点运动
  • RAMPMODE设置为位置模式+梯形曲线
  • 写入XTARGET后自动生成加减速曲线
  • 系统自动使用VMAX、AMAX、DMAX参数

功能4:运动控制 - 速度模式

void tmc4361a_rotate(int32_t velocity)
{
   ESP_LOGI(TAG, "设置旋转速度: %ld", (long)velocity);
   
   // 设置速度模式 + 梯形斜坡
   tmc4361a_write_register(TMC4361A_RAMPMODE, TMC4361A_RAMP_TRAPEZ);
   
   // 设置目标速度(需要左移8位)
   tmc4361a_write_register(TMC4361A_VMAX, abs(velocity) << 8);
   
   // 设置方向和启动
   if (velocity >= 0) {
       tmc4361a_write_register(TMC4361A_XTARGET, 0x7FFFFFFF);  // 正向
  } else {
       tmc4361a_write_register(TMC4361A_XTARGET, 0x80000000);  // 反向
  }
}

功能说明

  • 速度模式适用于连续旋转
  • 速度值需要左移8位(TMC4361A内部格式)
  • 通过设置XTARGET为极值确保持续运动
  • 自动按AMAX参数加速到目标速度

功能5:平滑停止

代码位置tmc4361a.c

void tmc4361a_smooth_stop(void)
{
   ESP_LOGI(TAG, "平滑停止 (速度模式)");
   
   // 保持速度模式 + 梯形斜坡
   tmc4361a_write_register(TMC4361A_RAMPMODE, TMC4361A_RAMP_TRAPEZ);
   
   // 将目标速度设置为0,使电机平滑减速停止
   tmc4361a_write_register(TMC4361A_VMAX, 0);
}

功能说明

  • 不使用急停,而是平滑减速
  • 在速度模式下将VMAX设为0
  • 系统按DMAX参数自动减速
  • 避免失步和机械冲击

功能6:TMC2160驱动配置

代码位置tmc2160.c (大致位置)

esp_err_t tmc2160_init(void)
{
   // 1. 配置CHOPCONF - 斩波器配置
   int32_t chopconf = 0x00010185;  // StealthChop模式
   tmc2160_write_register(TMC2160_CHOPCONF, chopconf);
   
   // 2. 配置IHOLD_IRUN - 电流设置
   int32_t ihold_irun = (8 << 0) |   // IHOLD=8 (保持电流)
                        (15 << 8) |   // IRUN=15 (运行电流)
                        (5 << 16);    // IHOLDDELAY=5
   tmc2160_write_register(TMC2160_IHOLD_IRUN, ihold_irun);
   
   // 3. 配置PWMCONF - StealthChop PWM配置
   int32_t pwmconf = 0xC40C001E;  // 启用StealthChop
   tmc2160_write_register(TMC2160_PWMCONF, pwmconf);
   
   // 4. 配置GCONF - 全局配置
   int32_t gconf = TMC2160_GCONF_EN_PWM_MODE;  // 启用PWM模式
   tmc2160_write_register(TMC2160_GCONF, gconf);
}

功能说明

  • CHOPCONF配置斩波器参数和微步细分
  • IHOLD_IRUN设置运行和保持电流
  • PWMCONF启用StealthChop静音技术
  • GCONF全局使能PWM模式

功能7:应用层测试程序

代码位置hello_world_main.c

// 测试1:定速旋转
case 0:
   ESP_LOGI(TAG, "测试1: 电机定速旋转 (1秒一圈)");
   
   float seconds_per_rev = 1.0;
   int32_t rotation_speed = (int32_t)(STEPS_PER_REV / seconds_per_rev);
   
   tmc4361a_set_velocity_params(STEPS_PER_REV, 1, 10);
   tmc4361a_rotate(rotation_speed);
   
   // 运行10秒观察
   for (int i = 0; i < 10; i++) {
       vTaskDelay(pdMS_TO_TICKS(1000));
       int32_t pos = tmc4361a_get_position();
       int32_t vel = tmc4361a_get_velocity();
       ESP_LOGI(TAG, "位置: %ld, 速度: %ld Hz",
                (long)pos, (long)(vel >> 8));
  }
   
   tmc4361a_smooth_stop();
   break;

// 测试2:指定角度旋转
case 1:
   ESP_LOGI(TAG, "测试2: 指定角度旋转 (90度)");
   int32_t angle_90 = STEPS_PER_REV / 4;  // 90度
   int32_t start_pos = tmc4361a_get_position();
   int32_t target_pos = start_pos + angle_90;
   
   tmc4361a_move_to(target_pos);
   
   // 等待到达
   while (!tmc4361a_is_target_reached()) {
       vTaskDelay(pdMS_TO_TICKS(100));
  }
   break;

功能说明

  • 4个测试用例展示不同控制模式
  • 测试1:速度模式,观察匀速旋转
  • 测试2:位置模式,精确角度控制
  • 测试3/4:多圈旋转和反转
  • 实时监控位置和速度

3.3 数据流图

用户程序
  │
  ├─> tmc4361a_rotate(51200)       [设置速度]
  │     │
  │     └─> RAMPMODE = 速度模式
  │     └─> VMAX = 51200 << 8     [速度值左移8]
  │     └─> XTARGET = 0x7FFFFFFF   [正向最大值]
  │
  ├─> tmc4361a_move_to(12800)       [移动到位置]
  │     │
  │     └─> RAMPMODE = 位置模式 | 梯形
  │     └─> XTARGET = 12800       [目标位置]
  │
  └─> tmc4361a_get_position()       [读取位置]
        │
        └─>XACTUAL寄存器
        └─> 返回32位位置值




四、功能展示及说明

4.1 系统初始化输出

====================================
ESP32-S3 TMC4361A + TMC2160 步进电机控制测试
====================================

--- 初始化TMC4361A运动控制器 ---
[TMC4361A] 初始化CLK_EXT (8MHz)...
[TMC4361A] CLK_EXT初始化完成, GPIO9输出8MHz时钟
[TMC4361A] 执行TMC4361A硬件复位...
[TMC4361A] SPI总线初始化成功
[TMC4361A] SPI设备添加成功
[TMC4361A] TMC4361A状态: 0x00000001
[TMC4361A] 配置CLK_FREQ = 8000000 Hz
[TMC4361A] 配置STEP_CONF: FS_PER_REV=200, MSTEP_PER_FS=0 (256细分)
[TMC4361A] TMC4361A初始化完成

--- 初始化TMC2160步进驱动器 ---
[TMC2160] SPI总线初始化成功
[TMC2160] SPI设备添加成功
[TMC2160] 读取版本: 0x21
[TMC2160] TMC2160初始化完成


4.2 测试1 - 定速旋转演示

--- 测试1: 电机定速旋转 (1秒一圈) ---
[MAIN] 电机参数: 51200/
[MAIN] 目标速度: 1.0/= 51200 Hz (60.00 RPM)
[TMC4361A] 设置旋转速度: 51200

[MAIN] 位置: 52134, 速度: 51200 Hz     <- 1秒后
[MAIN] 位置: 103268, 速度: 51200 Hz     <- 2秒后
[MAIN] 位置: 154402, 速度: 51200 Hz     <- 3秒后
[MAIN] 位置: 205536, 速度: 51200 Hz     <- 4秒后
[MAIN] 位置: 256670, 速度: 51200 Hz     <- 5秒后
[MAIN] 位置: 307804, 速度: 51200 Hz     <- 6秒后
[MAIN] 位置: 358938, 速度: 51200 Hz     <- 7秒后
[MAIN] 位置: 410072, 速度: 51200 Hz     <- 8秒后
[MAIN] 位置: 461206, 速度: 51200 Hz     <- 9秒后
[MAIN] 位置: 512340, 速度: 51200 Hz     <- 10秒后

[TMC4361A] 平滑停止 (速度模式)


4.3 测试2 - 精确角度控制

--- 测试2: 指定角度旋转 (90) ---
[MAIN] 起始位置: 512340
[MAIN] 目标角度: 90= 12800
[MAIN] 目标位置: 525140
[TMC4361A] 移动到位置: 525140

[MAIN] ✓ 到达位置: 525140 (误差: 0)


4.4 测试3 - 多圈旋转监控

--- 测试3: 指定圈数旋转 (2) ---
[MAIN] 起始位置: 525140
[MAIN] 目标圈数: 2= 102400
[MAIN] 目标位置: 627540

[MAIN] 进度: 0.52 (位置: 551940)     <- 运动中
[MAIN] 进度: 1.02 (位置: 577340)
[MAIN] 进度: 1.52 (位置: 602740)
[MAIN] 进度: 2.00 (位置: 627540)     <- 到达

[MAIN] ✓ 完成 2 圈旋转
[MAIN]   最终位置: 627540 (误差: 0)


4.5 测试4 - 反转控制

--- 测试4: 反转两圈 ---
[MAIN] 起始位置: 627540
[MAIN] 目标: 反转 2= -102400
[MAIN] 目标位置: 525140

[MAIN] 进度: -0.50 (位置: 601940)   <- 反向运动
[MAIN] 进度: -1.00 (位置: 576340)
[MAIN] 进度: -1.50 (位置: 550740)
[MAIN] 进度: -2.00 (位置: 525140)   <- 回到起点

[MAIN] ✓ 完成反转 2
[MAIN]   最终位置: 525140 (误差: 0)


4.6 性能指标总结

性能指标

数值

说明

位置精度

0步误差

测试中所有位置到达误差为0

细分精度

256微步

0.00703°/步 (1.8°/256)

最高速度

60 RPM

实测稳定运行,可更高

加速度

100000 steps/s²

快速启停

噪音水平

极低

StealthChop静音技术

SPI通信速度

4 MHz

稳定可靠




五、项目中遇到的难题和解决方法

问题1:TMC4361A初始化失败,SPI读取全0xFF

问题描述
项目初期,初始化TMC4361A后读取寄存器全是0xFFFFFFFF,SPI通信无响应。

原因分析

  1. TMC4361A需要外部时钟才能工作
  2. 初始化顺序错误:先初始化SPI后才启动时钟
  3. 复位时序不正确

解决方法

// 修改后的初始化顺序
static void gpio_init(void)
{
   gpio_config(&io_conf);
   gpio_set_level(TMC4361A_PIN_CS, 1);
   
   // ✅ 关键:先初始化CLK_EXT
   clk_ext_init();
   vTaskDelay(pdMS_TO_TICKS(10));  // 等待时钟稳定
   
   // ✅ 然后执行复位
   gpio_set_level(TMC4361A_PIN_NRST, 1);
   vTaskDelay(pdMS_TO_TICKS(10));
   gpio_set_level(TMC4361A_PIN_NRST, 0);
   vTaskDelay(pdMS_TO_TICKS(10));
   gpio_set_level(TMC4361A_PIN_NRST, 1);
   vTaskDelay(pdMS_TO_TICKS(100)); // 充分的启动时间
}

问题2:tmc4361a_smooth_stop()无法停止电机

问题描述
调用tmc4361a_smooth_stop()后,电机继续旋转,不减速停止。

原因分析
初版代码尝试切换到位置模式并设置当前位置为目标:

// ❌ 错误版本
void tmc4361a_smooth_stop(void)
{
   int32_t current_pos = tmc4361a_get_position();
   tmc4361a_write_register(TMC4361A_RAMPMODE,
                          TMC4361A_RAMP_POSITION | TMC4361A_RAMP_TRAPEZ);
   tmc4361a_write_register(TMC4361A_XTARGET, current_pos);
}

问题:从速度模式切换到位置模式时,电机正在高速旋转,切换瞬间位置已经变化,导致XTARGET总是滞后于XACTUAL。

解决方法
改用速度模式停止,将目标速度设为0:

// ✅ 正确版本
void tmc4361a_smooth_stop(void)
{
   // 保持速度模式
   tmc4361a_write_register(TMC4361A_RAMPMODE, TMC4361A_RAMP_TRAPEZ);
   
   // 目标速度设为0
   tmc4361a_write_register(TMC4361A_VMAX, 0);
}

工作原理:

  • 在速度模式下,芯片会自动按DMAX参数减速
  • VMAX=0表示目标速度为0
  • 系统自动生成减速曲线直到停止
  • 避免了模式切换时的位置跟踪问题


六、对本活动的心得体会

从理论到实践,理解了梯形/S型加减速曲线的重要性,掌握了位置模式、速度模式、扭矩模式的应用场景,学会了如何配置细分、电流、加速度等核心参数。

遇到的挑战

TMC4361A的时钟配置问题

起初没有理解TMC4361A必须有外部时钟才能工作,导致SPI通信完全失败。通过阅读数据手册的时序图,学习LEDC外设的使用,最终解决了这个关键问题。这个经验让我深刻体会到:

  • RTFM (Read The F**king Manual):数据手册是最权威的参考
  • 逐步验证:先验证时钟输出,再验证SPI通信,最后验证功能


对TMC芯片的体会

  • Trinamic的芯片功能强大,但学习曲线陡峭
  • 数据手册内容详尽但较长(TMC4361A手册200+页)
  • 建议厂商提供更多应用笔记和快速入门指南
附件下载
code.zip
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号