步进电机相关知识 以及 TMC2660 步进电机驱动芯片驱动步进电机

前言

这是前段时间项目中使用到的电机驱动芯片,拥有标准SPI和STEP/DIR两种接口模式,很好用,具备内部细分,很好用的一款步进电机驱动芯片。

这也是一款典型的SPI接口的步进电机驱动芯片,时序简单。

本文主要是针对 步进电机的相关理论知识和TMC2660 驱动芯片做一个总结。


一、步进电机基础知识

步进电机是一种将电脉冲信号转变为角位移或线位移的开环控制电机,是现代数字程序控制系统中的主要执行元件,应用极为广泛。
在非超载的情况下,步进电机的转速、停止的位置只取决于脉冲信号的频率和脉冲个数不受负载变化的影响。

步进电机,结构简单,驱动方便,没有累积误差,但是可能因为存在丢步的现象,常用于对精度要求不高的场合

1、电机常用概念

① 转速:电机输出轴的速度,一般单位是 r/min(转每分钟),也常用 RPM 表示。② 输出扭矩:表示了电机输出轴可以输出力的大小,单位一般为 N· m 或者 kg· cm。③ 工作电压:电机正常工作的电压。④ 额定电流:电机正常工作时的电流。⑤ 堵转电流:电机负载过大,驱动力不足,发生堵转时的电流。

2、步进电机小知识


每输入一个脉冲信号,转子就转动一个角度或者前进一步
输出的角位移或线位移 与 输入的脉冲数成正比
转速和脉冲频率成正比
在非超载且不超频的情况下,电机旋转位置只取决于脉冲个数,转速只取决于脉冲信号频率
步进电机调速

  • 控制电机的脉冲频率,来控制电机的转速或者加速度

驱动控制

  • 基础的旋转或者换向控制
3、步进电机分类
  1. 按磁激励划分
  • 永磁式
  • 反应式(磁阻式)
  • 混合式步进电机

  1. 以极性划分
  • 单极性步进电机
  • 双极性步进电机

4、步进电机工作原理

步进电机核心部件

  • 定子
  • 转子
  • 定子上的绕组

步进电机的工作原理

控制定子绕组周期性、交替得电,使定子产生磁场,进而控制步进电机转子一步一步的运动起来
分类可以分为单极性和双极性的步进电机

而我使用的步进电机一般是双极性步进电机,这个步进电机有四根线,双极性步进电机通过改变电流方向来改变每磁场的方向

  • A+
  • A-
  • B+
  • B-

单向极性步进电机,这个不同的是多了一根公共端

  • AB相,四相
  • 公共端一直通电
  • ABCD相交替得电

双极性的双向激励驱动步进电机,整步驱动
分为单向激励和双向激励
双向激励通电顺序

  • AB、A+,B+接正
  • AB、 A-,B+接正
  • AB、A-,B-接正
  • AB、A+,B+接正
细分驱动步进电机

通过改变定子的电流比例,就可以控制转子在一个整步中的不同位置,即可以将一个整步分为多个小步来运行
如果驱动器的细分能力很强,可以将其细分成32细分,64细分
这样就提高了步进电机旋转的流畅度并且提高了每步的精度

5、使用的步进电机型号以及相关参数

下方是我使用的步进电机的型号以及相关参数。
http://www.szrongmai.com/products_detail/productId=124.html

  • 型号:SST43D1125
  • 步距角:1.8 一般一个完整的脉冲可以驱使步进电机旋转一步,如果不使用细分的话,对于步距角为1.8°步距角的步进电机,一次脉冲即可旋转1.8°
  • 额定电流:1.7
  • 电阻:1.35
  • 电感:2.3
  • 保持转矩 260

二、步进电机驱动芯片 TMC2660 和MCU端

步进电机驱动芯片TMC2660

步进电机电机驱动芯片TMC2660,下面是电机驱动芯片资料
TMC2660C-PA 电机驱动器及控制器 Trinamic 封装LQFP44 (10x10) 批次21+ (baidu.com)
参考
基于TMC2660驱动芯片的步进电机驱动设计-电子发烧友网 (elecfans.com)
这里的TMC2660芯片,TMC2660芯片
TMC2660驱动器提供了业界领先的功能集,包括高分辨率微步、无传感器机械负载测量、负载自适应功率优化和低共振斩波操作。

  1. 拥有标准SPISTEP/DIR两种接口模式。
  2. 集成功率MOSFET处理电机电流高达2.2A。
  3. 集成的保护和诊断功能支持稳健和可靠的运行。

TMC2660参数配置通过SPI接口实现,TMC2660具有5个配置和控制寄存器,通过SPI接口来访问这些寄存器

所有的寄存器都是20位,在最高的2位或者3位表示的是寄存器地址也称之为操作码
**根据具体的寄存器选择不同的操作码实现对寄存器的写操作,而每一个写操作都会有一个20位的数据返回。**返回数据的内容可以通过修改配置寄存器来设置,具体格式如下

TMC2660允许通过SPI接口完全控制所有配置参数和模式位。在电机运行之前需要进行初始化。SPI接口也允许回读状态值和位
SPI接口访问方式

从机通过芯片上的低电平选择输入CSN来启用SPI事务。比特传输与总线时钟SCK是同步的,从机在SCK的上升沿上锁存来自SDI的数据,并沿着下降沿将数据驱动到SDO。首先发送最高有效位。与TMC2660的总线事务至少需要20个SCK时钟周期。
如果驱动的时钟超过20个,那么移到SDI的额外位在a之后在SDO上移出,通过内部移位寄存器的20时钟延迟。这可以用于菊花链多个芯片。
在整个总线事务期间,CSN必须是低的。当CSN变高时,内部移位寄存器的内容被锁存到内部控制寄存器中,并被识别为从主设备到从设备的命令。如果发送超过20位,则只将CSN上升沿之前接收到的最后20位识别为命令。
时序图
image.png

1、TMC2660端

芯片上的SPI接口----配置电机参数

  • SCK SPI时钟线
  • SDI SPI主机输出,从机输入
  • SDO SPI主机输入,从机输出
  • CSN CS,SPI片选,从机选择

起始条件

  • CS从高电平切换到低电平

终止条件

  • CS从低电平切换到高电平

在从机的整个选择过程中,CS始终都是低电平
下降沿是通信的开始,上升沿是通信的结束
芯片的输出接口----控制电机

输入
  • STEP
  • DIR
  • ENN
  • CS
  • SCK
  • SDI
  • SDO
  • CS
输出
  • VCC
  • GND
  • OA1 ------>A+
  • OA2 ------>A-
  • OB1 ------>B+
  • OB2 ------>B-
2、MCU端
SPI接口

使用SPI3资源,使用SPI3对TMC2660端寄存器发送数据,控制电机参数

  • SCK ------> SPI_CLK
  • SDI ------> SPI_MOSI
  • SDO ------> SPI_MISO
  • CS ------> SPI_CS
电机控制接口

这里以单个步进电机为例,MCU IO引脚

  • STEP ------> PE5 TIM9_CH1
  • DIR ------> PA8
  • ENN ------> PC9
  • CS ------> PD0

三、步进电机速度控制

有两种模式,学习中使用到的有两种模式

  • PWM模式
  • 输出比较翻转模式
1、PWM模式

image.png

2、输出比较模式

image.png

需要对步进电机的脉冲进行调节,不能太快,太快可能会出现丢步或者堵转的现象

1、初始化定时器
设置ARR、PSC,计数方式以及脉冲输出模式,使能定时器以及中断,设置优先级分组等
2、初始化IO
初始化定时器通道IO、方向引脚、脱机使能引脚
3、逻辑实现
改变转速:修改比较值的大小,改变方向:修改方向引脚高低电平
改变脉冲的频率
4、编写中断服务函数
设置比较值,控制运行的速度

3、翻转模式下如何修改频率

比较值的增量大小

假设定时器,设置的ARR值是1000

那么计数到1000后,又重新开始计数

假如设置CCRX每250次翻转一次,那么此时的增量值就是250
250、500、750、1000时翻转
250时,从高电平变成低电平,

设置CCRX每500翻转一次
500、1000时翻转

周期更长,频率就更低

只需要修改增量值的大小,增量值越小,代表频率越快,速度就越快
增量值越大,频率就越小,速度就越慢


四、步进电机定位控制

其中TMC2660驱动芯片,X,Y轴的电机设置的是16细分
image.png
这个步进电机步距角为1.8°,不细分的情况下,旋转一圈360°需要200个脉冲。为了让旋转更加流畅,使用16细分,实际的输出的步距角就是1.8/16 = 0.1125
所以旋转360°需要3200个脉冲数

可以将角度转换成脉冲数,然后通过控制脉冲个数,驱动步进电机旋转到指定位置停止

实现脉冲计数,当达到指定的脉冲数后就关闭PWM输出或脉冲输出(输出比较模式)

PWM模式,进入一次更新中断,输出一个脉冲,发生一个中断对应一个完整脉冲
输出比较模式需要进入两次输出中断才为一个完整的脉冲

1、PWM模式驱动

image.png

2、输出比较翻转模式

image.png


五、部分demo

下面展示输出比较模式的部分demo

#include "bsp_tim.h"
#include "bsp_uart.h"
#include <stdio.h>
#include <string.h>

STEPPER_MOTOR g_stepper = {
   0};

// 开启
void bsp_tim_init(void)
{
   
	// 置低电平
	// ENN  PC9
	// DIR  PA8

	MOTOR1_EN(EN_OFF); // 初始时刻电机EN脚失能

	LL_TIM_CC_EnableChannel(TIM9, LL_TIM_CHANNEL_CH1); /*TIM9 CCR1 通道使能*/
	LL_TIM_EnableAllOutputs(TIM9);					   /*全输出使能*/
	LL_TIM_DisableCounter(TIM9);					   // 计数使能
}

// 开启pwm输出  电机启动
void stepper_star(uint8_t dir)
{
   
	MOTOR1_EN(EN_ON);			// 使能EN
	MOTOR1_DIR(dir);			// DIR引脚
	LL_TIM_EnableCounter(TIM9); // CNT计数使能

	LL_TIM_EnableIT_UPDATE(TIM9); // 使能更新中断
}

// 失能PWM输出   电机失能
void stepper_stop(void)
{
   
	MOTOR1_EN(EN_OFF); // 失能EN
	LL_TIM_DisableIT_UPDATE(TIM9);
	LL_TIM_DisableCounter(TIM9); // CNT计数失能
}

void stepper_set_angle(uint16_t angle, uint8_t dir)
{
   
	g_stepper.pulse_count = angle / MAX_STEP_ANGLE;
	if (g_stepper.pulse_count == 0)
	{
   
		stepper_stop();
	}
	else
		stepper_star(dir);
}

// 定时器9中断回调函数
uint16_t g_run_flag = 0;
void bsp_tim9_callback(void)
{
   
	g_run_flag = 1;
	g_stepper.pulse_count--; // 每一个完整的脉冲就--
	printf("%d\r\n", g_stepper.pulse_count);
	if (g_stepper.dir == CW)
	{
   
		g_stepper.add_pulse_count++; /*顺时针 绝对位置++*/
		printf("++ %d \r\n", g_stepper.add_pulse_count);
	}
	else
	{
   
		g_stepper.add_pulse_count--; /*绝对位置--*/
		printf("-- %d \r\n", g_stepper.add_pulse_count);
	}
	/*当脉冲数等于0时,代表要发送的脉冲个数已经完成 停止定时器输出*/
	if (g_stepper.pulse_count <= 0)
	{
   
		stepper_stop();
		g_run_flag = 0;
	}
}

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
   
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM9_Init();
  MX_SPI3_Init();
  /* USER CODE BEGIN 2 */
  bsp_spi3_init();
  bsp_tim_init();                        // 定时器输出以及step、dir位初始化
  motor_driver_xy_init(STEPPER_MOTOR_1); // 电机驱动初始�???

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  // stepper_star(CW);
  g_stepper.dir = CW;
  stepper_set_angle(165, g_stepper.dir); // 145
  while (1)
  {
   
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

    // stepper_stop();
    // printf(" hello world!\r\n");
  }
  /* USER CODE END 3 */
}

六、源代码

由于涉及项目代码,后续将会把TMC2660 驱动步进电机的两种方式 开源至我的gitee上

包括

  • 步进电机基础驱动
    • PWM模式驱动
    • 输出比较模式驱动
  • 步进电机定位控制
    • PWM 模式驱动
    • 输出比较模式驱动
  • 步进电机梯形加减速

七、参考

大家可以参考 正点原子 电机驱动教程,里面讲的非常清楚,可以自己亲身实践一下,遇到困难解决困难

也可以在评论区里留言,大家一起解决

多看几次就明白了。

相关推荐

  1. 电机调速原理

    2024-01-14 00:38:05       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-14 00:38:05       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-14 00:38:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-14 00:38:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-14 00:38:05       20 阅读

热门阅读

  1. JDK介绍

    JDK介绍

    2024-01-14 00:38:05      36 阅读
  2. 管理者与员工如何进行高效的一对一面谈?

    2024-01-14 00:38:05       48 阅读
  3. 程序员必备的面试技巧

    2024-01-14 00:38:05       45 阅读