基于TMC4361A与TMC2160的步进电机控制系统项目总结报告
一、项目描述
1.1 项目介绍
本项目旨在开发一个基于TMC4361A运动控制器和TMC2160步进电机驱动器的电机控制系统,通过MicroPython编程实现对步进电机的精确控制。系统实现了定速旋转、指定角度旋转、指定圈数旋转以及正反转切换等核心功能.
TMC4361A是一款高性能运动控制器,支持多种运动模式,包括速度模式和位置模式,能够实现精确的速度和位置控制。TMC2160则是功能强大的步进电机驱动芯片,具有StealthChop2静音技术和SpreadCycle技术,能够在不同工况下提供出色的电机性能。
本项目采用模块化设计思想,将硬件控制、运动逻辑和用户交互分离,通过面向对象的方式构建了完整的电机控制系统架构。系统支持实时速度调节和精确定位,具有良好的可扩展性和易用性。
1.2 设计思路
本项目的整体设计遵循"分层解耦、模块化实现"的原则,主要包含以下几个层次:
硬件抽象层:设计通用的SPI通信类,封装底层SPI通信协议,提供统一的寄存器读写接口。这一层屏蔽了具体的硬件通信细节,为上层提供标准化的数据传输服务。
驱动控制层:分别实现TMC2160驱动器和TMC4361A控制器的封装类。TMC2160类负责电机驱动器的初始化和配置,包括电流设置、微步控制等;TMC4361A类负责运动控制逻辑,包括速度模式、位置模式的切换和运动参数配置。
系统接口层:设计MotorSystem类作为系统的统一接口,整合驱动器和控制器的功能,提供简洁易用的API,如speed()、angle()、turn()等方法,隐藏底层实现细节。
用户交互层:通过命令行接口实现用户与系统的交互,支持简单的命令解析和参数处理,使用户能够方便地测试和控制电机运动。
二、硬件介绍
2.1 硬件平台
本系统采用以下硬件平台:
- 主控制器:RP2040
- 运动控制器:TMC4361A-BOB评估板
- 电机驱动器:TMC2160-BOB评估板
- 执行机构:步进电机(标准200步/圈,支持256微步)
2.2 TMC4361A运动控制器
TMC4361A是一款高度集成的运动控制器,具有以下特点:
- 支持多种运动模式:速度模式、位置模式、斜坡发生器模式
- 内置加速和减速斜坡发生器,可实现平滑的运动曲线
- 支持24位位置计数器和32位速度设定
- 通过SPI接口进行配置和控制
- 内置编码器接口(本项目中未使用)
TMC4361A的核心寄存器包括:
- 0x00(GLOBAL_CONFIG):全局配置寄存器
- 0x20(RAMP_MODE):运动模式选择(0x00=速度模式,0x04=位置模式)
- 0x21(X_ACTUAL):当前实际位置寄存器
- 0x24(V_MAX):最大速度寄存器
- 0x28(A_MAX):最大加速度寄存器
- 0x37(X_TARGET):目标位置寄存器
2.3 TMC2160电机驱动器
TMC2160是一款高性能步进电机驱动芯片,主要特性包括:
- 支持高达46V的电机电压和4.5A的相电流
- StealthChop2静音技术:在低速时实现几乎静音的电机运行
- SpreadCycle技术:在高速时提供高精度的电流控制
- 支持256微步分辨率
- StallGuard2无传感器堵转检测
- CoolStep动态电流调节,降低功耗
TMC2160的关键配置寄存器:
- 0x00(GCONF):全局配置寄存器
- 0x10(IHOLD_IRUN):电流控制寄存器(运行电流和保持电流)
- 0x6C(CHOPCONF):斩波配置寄存器
2.4 硬件连接
系统通过SPI总线连接各个模块:
- SPI时钟(SCK):连接到GPIO 18
- SPI主机输出从机输入(MOSI):连接到GPIO 19
- SPI主机输入从机输出(MISO):连接到GPIO 16
- TMC2160片选(CS_DRV):连接到GPIO 17
- TMC4361A片选(CS_CTRL):连接到GPIO 0
- 时钟输出(CLK):连接到GPIO 15,输出16MHz参考时钟
SPI通信参数:波特率1Mbps,极性=1,相位=1(CPOL=1,CPHA=1)
三、软件设计
3.1 系统架构
系统采用三层架构设计:
┌─────────────────────────────────────┐
│ 用户交互层 (Main Loop) │
│ 命令解析 -> 参数处理 -> 调用接口 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 系统接口层 (MotorSystem) │
│ speed(), angle(), turn() 统一接口 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 控制层 (TMC4361A) │ 驱动层 (TMC2160) │
│ 运动模式管理 │ 电机驱动配置 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 硬件抽象层 (TMC_SPI_Device) │
│ SPI通信、寄存器读写、数据转换 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 硬件层 │
│ TMC4361A, TMC2160, 步进电机 │
└─────────────────────────────────────┘
3.2 软件流程图
主程序流程图
开始
↓
初始化SPI和GPIO
↓
创建MotorSystem实例
↓
等待用户输入
↓
解析命令 (v/a/t/stop/exit)
↓
├─ v: 速度模式 → 设置VMAX
├─ a: 角度模式 → 计算目标位置
├─ t: 圈数模式 → 计算目标位置
├─ stop: 停止 → 设置VMAX=0
└─ exit: 退出 → 程序结束
↓
返回等待输入
速度模式控制流程
调用speed(rps)
↓
设置RAMP_MODE = 0x00 (速度模式)
↓
计算速度值: vel = rps × 51200 × 256
↓
处理负速度(使用补码表示)
↓
写入VMAX寄存器 (0x24)
↓
电机以指定速度持续旋转
位置模式控制流程
调用move_relative(delta_steps)
↓
设置VMAX = 0 (安全停止)
↓
设置RAMP_MODE = 0x04 (位置模式)
↓
读取当前实际位置X_ACTUAL (0x21)
↓
计算目标位置: target = current + delta
↓
写入X_TARGET寄存器 (0x37)
↓
恢复VMAX = 51200 << 8 (设定运行速度)
↓
电机运动到目标位置后自动停止
3.3 核心代码实现及说明
3.3.1 SPI通信基础类
class TMC_SPI_Device:
def __init__(self, spi, cs_pin):
self.spi = spi
self.cs = machine.Pin(cs_pin, machine.Pin.OUT, value=1)
self.buf = bytearray(5)
def _transfer(self, address, value=0, write=False):
addr_byte = (address & 0x7F) | (0x80 if write else 0x00)
self.buf[0] = addr_byte
self.buf[1] = (value >> 24) & 0xFF
self.buf[2] = (value >> 16) & 0xFF
self.buf[3] = (value >> 8) & 0xFF
self.buf[4] = value & 0xFF
self.cs.low()
receive_buf = bytearray(5)
self.spi.write_readinto(self.buf, receive_buf)
self.cs.high()
return (receive_buf[1] << 24) | (receive_buf[2] << 16) |
(receive_buf[3] << 8) | receive_buf[4]
代码说明:
- 这是基础的SPI通信类,封装了与TMC芯片的通信协议
_transfer方法实现了完整的5字节SPI传输协议- 第一个字节为地址字节,bit7表示读/写操作(1=写,0=读)
- 后续4字节为32位数据(大端格式)
- 使用
write_readinto同时发送数据和接收响应
3.3.2 TMC2160驱动器初始化
class TMC2160(TMC_SPI_Device):
def __init__(self, spi, cs_pin):
super().__init__(spi, cs_pin)
self.init_driver()
def init_driver(self):
self.write_reg(0x00, 0x00000008)
self.write_reg(0x10, 0x000A0506)
self.write_reg(0x6C, 0x000100C3)
代码说明:
0x00(GCONF = 0x00000008):使能位置使能(shaft)位,允许电机转动0x10(IHOLD_IRUN = 0x000A0506):- IHOLD(保持电流)= 6,节省能耗
- IRUN(运行电流)= 10(约31%最大电流),提供足够扭矩
- IHOLDDELAY(保持电流延迟)= 5,电机停止后逐步降低电流
0x6C(CHOPCONF = 0x000100C3):- 使能StealthChop2静音模式
- 配置微步为256细分,提高分辨率
- 设置斩波参数,优化电机运行质量
3.3.3 TMC4361A速度控制实现
def rotate_constant(self, rps):
"""速度模式:rps为正负表示方向"""
# 设置为速度模式
self.write_reg(0x20, 0x00000000)
# 计算速度:每秒脉冲数 × 2^8
# 1 RPS = 51200 脉冲/秒
vel = int(rps * 51200 * 256)
# 处理负速度(使用补码表示)
if vel < 0:
vel = (0xFFFFFFFF + vel + 1) & 0xFFFFFFFF
self.write_reg(0x24, vel)
代码说明:
- 速度模式通过RAMP_MODE=0x00设置
- 速度计算公式:vel = rps × 51200 × 256
- 51200 = 200步/圈 × 256微步
- 256 = TMC4361A内部小数部分精度(24+8位格式)
- 负速度使用补码表示,这是标准的32位有符号数表示方法
- 写入VMAX寄存器后,电机将以指定速度持续旋转
3.3.4 TMC4361A位置控制实现
def move_relative(self, delta_steps):
"""位置模式:delta_steps为脉冲数"""
# 1. 停止当前运动(安全措施)
self.write_reg(0x24, 0)
# 2. 切换到位置模式
self.write_reg(0x20, 0x00000004)
# 3. 读取当前位置
current_pos = self.read_reg(0x21)
if current_pos & 0x80000000:
current_pos -= 0x100000000
# 4. 设置目标位置
target = current_pos + int(delta_steps)
self.write_reg(0x37, target)
# 5. 恢复速度(允许运动)
self.write_reg(0x24, 51200 << 8)
代码说明:
- 步骤1:先将VMAX设为0,确保电机停止,避免模式切换时的冲击
- 步骤2:设置RAMP_MODE=0x04,进入位置模式
- 步骤3:读取X_ACTUAL寄存器获取当前位置
- 处理有符号32位数的转换(最高位为1表示负数)
- 步骤4:计算并写入X_TARGET寄存器,设定目标位置
- 相对运动:目标 = 当前 + 增量
- 步骤5:恢复VMAX值,触发电机运动
- 默认速度约为1 RPS(51200 << 8)
- 电机将按照配置的加速度曲线运动到目标位置
3.3.5 MotorSystem系统接口
class MotorSystem:
def __init__(self, clk_pin=15, sck=18, mosi=19, miso=16,
cs_drv=17, cs_ctrl=0):
self.clk = machine.PWM(machine.Pin(clk_pin))
self.clk.freq(16000000)
self.clk.duty_u16(32768) # 50%占空比
self.spi = machine.SPI(0, baudrate=1000000, polarity=1,
phase=1, sck=machine.Pin(sck),
mosi=machine.Pin(mosi), miso=machine.Pin(miso))
self.driver = TMC2160(self.spi, cs_pin=cs_drv)
self.controller = TMC4361A(self.spi, cs_pin=cs_ctrl)
self.steps_per_rev = 51200 # 200 × 256
def speed(self, val):
"""速度模式:val为RPS"""
self.controller.rotate_constant(val)
def angle(self, val):
"""角度模式:val为度数"""
self.controller.move_relative((val/360)*self.steps_per_rev)
def turn(self, val):
"""圈数模式:val为圈数"""
self.controller.move_relative(val*self.steps_per_rev)
代码说明:
- 初始化:
- 配置16MHz时钟输出,为TMC芯片提供参考时钟
- 配置SPI接口,CPOL=1,CPHA=1(SPI模式3)
- 初始化TMC2160驱动器和TMC4361A控制器
- 定义每圈步数为51200(200步×256微步)
- speed(val):
- 输入参数单位:RPS(每秒转数)
- 正值表示顺时针旋转,负值表示逆时针旋转
- 直接调用控制器的速度模式方法
- angle(val):
- 输入参数单位:度数
- 自动将角度转换为脉冲数:脉冲 = (角度/360) × 每圈步数
- 支持正负角度(正角度顺时针,负角度逆时针)
- turn(val):
- 输入参数单位:圈数
- 自动将圈数转换为脉冲数:脉冲 = 圈数 × 每圈步数
- 支持正负圈数(正数顺时针,负数逆时针)
3.3.6 用户交互主程序
try:
motor = MotorSystem()
print("System Online. Format: <v/a/t> <value>")
while True:
raw = input(">> ").strip().lower().split()
if not raw: continue
cmd, val = raw[0], float(raw[1]) if len(raw)>1 else 0
if cmd == 'v':
motor.speed(val)
print(f"V-Mode: {val} RPS")
elif cmd == 'a':
motor.angle(val)
print(f"P-Mode: {val} deg")
elif cmd == 't':
motor.turn(val)
print(f"P-Mode: {val} turns")
elif cmd == 'stop':
motor.controller.stop()
print("Stopped.")
elif cmd == 'exit':
break
except Exception as e:
print(f"Error: {e}")
代码说明:
- 命令格式:
<命令> <数值> - 支持的命令:
v <RPS>:速度模式,电机以指定RPS持续旋转a <度数>:角度模式,电机旋转指定角度后停止t <圈数>:圈数模式,电机旋转指定圈数后停止stop:立即停止电机运动exit:退出程序
具体效果展示参考b站视频