Funpack4-3 MicroPython玩转步进电机控制:基于TMC4361A+TMC2160方案
该项目使用了Teensy4.1+TMC4361A+TMC2160,实现了步进电机控制的设计,它的主要功能为:实现电机定速旋转、指定角度旋转、指定圈数旋转、正反转切换功能。
标签
Funpack活动
开发板
步进电机
teensy4.1
TMC2160
Funpack4-3
TMC4361A
枫雪天
更新2026-02-10
11

任务介绍

本项目实现了Funpack第4-3期活动板卡二的任务一,基于MicroPython控制Teensy 4.1开发板实现了对TMC4361A+TMC2160步进电机控制,并在此软硬件基础上控制42步进电机,实现了一个精密运动控制系统,支持通过串口命令进行速度、位置控制,同时实时反馈电机运行状态信息。

硬件平台

本次使用Teensy 4.1开发板,是一款面向嵌入式开发的高性能评估平台。该开发板搭载了基于ARM Cortex-M7内核的IMXRT1062 MCU,具备丰富的外设资源,包括多个SPI接口、UART接口、I2C接口等,非常适合用于实时步进电机控制系统的开发。开发板集成了调试器接口、USB接口、用户可编程LED与GPIO,便于快速搭建电机控制原型系统。

在软件方面,本项目采用MicroPython实时编程环境作为底层运行环境。MicroPython以其轻量级、高可扩展性和良好的硬件抽象层支持而著称,适用于资源受限的嵌入式设备。通过将TMC4361驱动程序移植至Teensy平台,实现了精确的位置控制、速度调节以及实时状态监控等功能。

核心部件:TMC4361A-BOB & TMC2160-BOB步进电机控制评估套件

TMC4361A运动控制器

TMC4361A是ADI公司的一款高性能步进电机驱动芯片,支持SPI和Step/Dir接口,还具备编码器接口,能实现闭环控制。它集成了ChopSync和dcStep技术,支持S形或六点式斜坡发生器,可实时调整速度曲线。但它只是控制器,无法直接控制步进电机,我们还需要一个驱动器。

TMC4361A 板卡图.png

TMC2160栅极驱动器

TMC2160是ADI推出的一款高性能两相步进电机驱动芯片,专为高动态、高扭矩应用设计,支持外部MOSFET,具备静音、高效和紧凑等优势。它有以下几个关键特性:

  • 工作电压‌:8V 至 60V(支持外部N沟道MOSFET)
  • 电流能力‌:高达4.6A RMS(6.5A峰值)
  • 接口‌:SPI + Step/Direction,支持高达256微步细分
  • 优势功能‌:
    • StealthChop‌:实现超静音运行
    • SpreadCycle‌:智能混合衰减模式,优化能效和扭矩
    • CoolStep:动态电流调节,节能高效
    • StallGuard2‌:负载检测,无需传感器

主控设备:TEENSY 4.1开发板

  • 搭载IMXRT1062 MCU(ARM Cortex-M7内核)
  • 集成USB接口与调试器
  • 板载用户可编程LED指示灯
  • 支持MicroPython实时编程环境

被控对象:42步进电机

任务分析与实现

本系统实现了基于MicroPython的TMC4361A+TMC2160步进电机控制平台,主要功能包括:

三通道数据交互:

  • 电机控制指令
    • 串口命令解析频率:20Hz
    • 支持RPM转速、角度、圈数控制
  • SPI通信控制
    • 通信波特率:4MHz
    • 高可靠性数据传输
  • MicroPython任务调度
    • 实时反馈电机状态
    • 精确位置与速度控制


方案框图:

驱动编写

本项目基于 TEENSY 4.1 开发板完成了 TMC4361A+TMC2160 电机控制系统的成功移植,并在此基础上实现了对42步进电机的精密控制与运动监测功能。以下详细描述了MicroPython移植的关键流程和核心要点。

一、驱动编写前的准备

1. 硬件环境

  • 主控芯片:NXP IMXRT1062(ARM Cortex-M7 内核)
  • 开发板:TEENSY 4.1
  • 外设资源
    • SPI 接口用于驱动 TMC4361A 运动控制器
    • PWM 输出提供系统时钟信号
    • UART 串口用于命令控制与状态反馈

2. 软件环境

  • IDE:Thonny
  • MicroPython 版本:MicroPython 最新版
  • 构建工具:mpy-cross 编译器


二、驱动模块编写的核心步骤

1. 驱动模块创建 (tmc4361.py)

驱动模块是MicroPython针对TMC4361A运动控制器的支持包,主要包括寄存器定义、通信协议、控制接口以及运动参数配置。

a. 寄存器地址定义

  • 定义TMC4361A全部寄存器地址映射
  • 包含运动控制、速度设定、加速度配置等功能寄存器
  • 提供事件检测和状态反馈寄存器
# TMC4361 register addresses
TMC4361_GENERAL_CONFIG_REGISTER = 0x0
TMC4361_REFERENCE_CONFIG_REGISTER = 0x01
TMC4361_START_CONFIG_REGISTER = 0x2
TMC4361_INPUT_FILTER_REGISTER = 0x3

b. 功能枚举定义

  • 定义运动模式(速度模式、定位模式)
  • 定义斜坡类型(矩形、梯形、S型斜坡)
  • 定义事件类型和标志位
class RampMode:
VELOCITY_MODE = 0x00
POSITIONING_MODE = (0x01 << 2)

class RampType:
HOLD_RAMP = 0x00 # Follow max speed (rectangle shape)
TRAPEZOIDAL_RAMP = 0x01
S_SHAPED_RAMP = 0x02

2. SPI通信实现 (_spi_transfer函数)

完成SPI协议的底层实现:

def _spi_transfer(self, address, data):
"""Perform SPI transfer"""
return_buffer = 0

self._cs.value(0)
time.sleep_us(10)

if (address & 0x80) != 0: # Write operation
# For write operations, send the address + data (5 bytes)
data_bytes = struct.pack('>BI', address, data)
self._spi.write(data_bytes)
else: # Read operation
# Send address as one byte sequence for read
address_byte = struct.pack('>B', address)
self._spi.write(address_byte)

# Read response - first byte is dummy, next 4 bytes contain the actual data
response = self._spi.read(4)
# Unpack the 4 bytes of actual data (ignore first dummy byte)
return_buffer = struct.unpack('>I', response)[0]

self._cs.value(1)
time.sleep_ms(10)

return return_buffer

3. 运动控制接口实现

a. 位置与速度控制接口 (set_target_position, set_max_speed)

  • 实现目标位置设定功能
  • 提供最大速度限制控制
  • 支持当前实际位置查询
def set_target_position(self, position):
"""Set the target position
/!\ Set all other motion profile parameters before
"""
self.write_register(TMC4361_X_TARGET_REGISTER, position)

def set_max_speed(self, speed):
"""Set the max speed VMAX (steps/second)
/!\ Don't exceed clockFreq / 2 in velocity mode and clockFreq / 4 in positioning mode
"""
self.write_register(TMC4361_V_MAX_REGISTER, self._float_to_fixed_point(speed, 8))

b. 加速度控制接口 (set_accelerations)

  • 封装加速度、减速度参数设置
  • 实现起始加速度和最终减速度控制
  • 支持S型斜坡控制参数设定
def set_accelerations(self, max_accel, max_decel, start_accel, final_decel):
"""Set the ramp accelerations (in steps / second^2). See datasheet §6.3.6"""
self.write_register(TMC4361_A_MAX_REGISTER, self._float_to_fixed_point(abs(max_accel), 2) & 0xFFFFFFFF)
self.write_register(TMC4361_D_MAX_REGISTER, self._float_to_fixed_point(abs(max_decel), 2) & 0xFFFFFFFF)
self.write_register(TMC4361_A_START_REGISTER, self._float_to_fixed_point(abs(start_accel), 2) & 0xFFFFFFFF)
self.write_register(TMC4361_D_FINAL_REGISTER, self._float_to_fixed_point(abs(final_decel), 2) & 0xFFFFFFFF)

4. 应用层控制实现

使用MicroPython提供的高级接口,实现便捷的控制功能:

def set_speed_in_rpm(rpm):
"""Set motor speed in RPM"""
# Convert RPM to steps per second
# 1 RPM = 1 revolution per minute = STEPS_PER_REVOLUTION steps per minute
# So RPM * STEPS_PER_REVOLUTION / 60 = steps per second
steps_per_second = rpm * STEPS_PER_REVOLUTION // 60

tmc.set_ramp_mode(tmc4361.TMC4361.RampMode.VELOCITY_MODE, tmc4361.TMC4361.RampType.HOLD_RAMP)
tmc.set_max_speed(steps_per_second)

代码详解

整体软件流程图:


一、硬件初始化与电机配置

系统启动后首先完成TMC4361A控制器初始化序列,关键流程如下:

  • 配置SPI接口为模式1(CPOL=1, CPHA=1),设置通信波特率为4MHz
  • 初始化PWM输出提供TMC4361A系统时钟(16MHz)
  • 启动TMC4361A并配置基本运动参数
def setup():
print("Starting TMC4361 controller test...")

# Init TMC4361 clock using PWM
clk_pin = Pin(TMC4361_CLK_PIN, Pin.OUT)
clk_pwm = PWM(clk_pin)
clk_pwm.freq(TMC4361_CLK_FREQ)
clk_pwm.duty_u16(65535//2) # 50% duty cycle (65535 is max for default resolution)

# Initialize TMC4361
tmc.begin()

# Configuration sequence from original Arduino code

# SPI_OUT_CONF
tmc.write_register(tmc4361.TMC4361_SPIOUT_CONF_REGISTER, 0x4440128D)
time.sleep_ms(5)

在PWM代码编写完后,可以接示波器测量一下,是否有实际波形输出。如图:


二、串口命令解析与执行

def handle_serial_command(cmd):
"""Process a serial command"""
# Handle S command for setting speed in RPM
if len(cmd) >= 2 and cmd[0] == 'S':
try:
rpm_str = cmd[1:]
rpm = int(rpm_str)

print(f"Setting speed to {rpm} RPM")
set_speed_in_rpm(rpm)
except ValueError:
print("Error: Invalid RPM value.")

# Handle A command for rotation by degrees
elif len(cmd) >= 2 and cmd[0] == 'A':
try:
angle_str = cmd[1:]
angle = int(angle_str)

print(f"Rotating by {angle} degrees")
rotate_by_degrees(angle)
except ValueError:
print("Error: Invalid angle value.")

# Handle C command for rotation by number of turns
elif len(cmd) >= 2 and cmd[0] == 'C':
try:
turns_str = cmd[1:]
turns = int(turns_str)

print(f"Rotating by {turns} turns")
rotate_by_turns(turns)
except ValueError:
print("Error: Invalid turns value.")

elif len(cmd) > 0:
print("Invalid command. Use format: Sxxx (RPM), Axxx (degrees), Cxxx (turns)")

效果展示

遇到的难题与解决办法

问题:MicroPython驱动编写过程中遇到SPI通信没效果的问题

解法

整个移植过程中,有几个要注意的地方:

  • SPI通信时序与TMC4361A时序要求的精确匹配
  • 固定点数值转换算法的准确性,确保速度和位置控制精度
  • 连接逻辑分析仪,即时抓取波形观察是否符合预期

活动感想

通过本项目实践,我深入掌握了基于TMC4361A+TMC2160的步进电机控制方法。这个过程中TEENSY 4.1开发板良好的硬件兼容性与MicroPython强大的实时编程能力极大提升了开发效率,相比于C编程体验要更丝滑。果然还得是那句话:人生苦短,我用Python!

感谢硬禾学堂和得捷电子联合举办的Funpack活动,祝硬禾的活动越办越好!

附件下载
micropython_tmc4361.zip
项目源代码
团队介绍
个人
团队成员
枫雪天
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号