一、tmc2209芯片

        我是从优信电子购买的tmc2209芯片(红色排针),优信电子淘宝商店有不同的型号,引脚和人性能落有不同,但都大差不差,我这里主要介绍红色排针型号的。

1.tmc2209性能介绍

核心技术亮点

  • StealthChop2™ (静音技术):这是它最核心的卖点。通过一种精密的电压斩波算法,能几乎完全消除电机在低速运转时产生的可听噪音和振动。

  • SpreadCycle™ (高性能斩波):当电机需要高速运转时,可以切换到这种模式。它提供了极其精准的电流控制,保证电机在高动态运动下也能有出色的性能和稳定性。

  • StallGuard4™ (无传感器堵转检测):这是一个非常实用的功能。它可以根据电机内部的电磁场变化,在不依赖外部机械限位开关的情况下,精准检测到电机是否发生了堵转或负载过重。这常用于实现“无传感器归零”。

  • CoolStep™ (节能技术):它能根据电机的实际负载,自动、动态地调整驱动电流。在轻负载时自动降低电流,最高可节约75%的能量,并显著减少芯片发热。

  • MicroPlyer™ (微步插值):即使您的微控制器发送的是较低分辨率的脉冲(比如只支持1/16步),它也能内部自动将这些粗糙的步进“插值”平滑为1/256微步,从而获得更顺滑的运动效果。

两种工作模式

独立模式 (Standalone)(DIR/STEP控制

  • 配置方式:通过硬件引脚(MS1, MS2)设置细分,通过电位器(VREF)调节电流。

  • 优点:简单,无需编程,可以快速上手,直接替换A4988等传统驱动器。

  • 缺点:无法使用StallGuard4、CoolStep等高级功能,配置后无法动态更改。

UART模式 (Serial)

  • 配置方式:通过UART_TX/UART_RX引脚与主控通信,通过软件配置寄存器来设置所有参数。

  • 优点功能全开,可以动态调整电流、细分、工作模式,并能读取芯片状态(如堵转报警)。

  • 缺点:需要编写或移植通信代码,连接和配置稍复杂。

这里我们介绍的是独立工作模式。

2.引脚图

引脚简要介绍:

EN芯片使能引脚,接低电平时使能芯片
MS1/MS2控制电机细分,具体后面会说
USART用于usart模式
CLK时钟线,如果使用内部时钟需要接地
STEP给脉冲驱动电机
DIR控制电机正转和反转,
VM给电机的电压,5到24V都可以,但是电压低可能会丢步
M1B/M1A电机线圈绕组1,接A+/A-  或者 B+/B-
M2B/M2A电机线圈绕组2,接A+/A-  或者 B+/B-
VIO给tmc2209芯片的电压,一般给3.3V或5V即可

3.细分介绍

原本42步进电机一个完整脉冲电机转动1.8度。


8细分控制精度=1.8°/8=0.225°,电机转一周需要1600个脉冲。
16细分控制精度=1.8°/16=0.1125°,电机转一周需要3200个脉冲。
32细分控制精度=1.8°/32=0.05625°,电机转一周需要6400个脉冲。
64细分控制精度=1.8°/64=0.0140625°,电机转一周需要12800个脉冲。


细分越细,精度越高,但是可能力矩会不够,看需求使用

二、步进电机介绍

基本的步距角为1.8度。

一般红线和蓝线是A相,绿色和黑色是B相

三、驱动代码

#define GPIO_PIN_RESET 0
#define GPIO_PIN_SET   1
#define DIR_Pin GPIO_NUM_1
#define STEP_Pin GPIO_NUM_2
#define EN_Pin GPIO_NUM_40
#define MS1_Pin GPIO_NUM_0
#define MS2_Pin GPIO_NUM_0

选择细分模式

​
uint8_t tmc_set_subdivision(uint8_t i)
{
    uint8_t subdevision_value = i;
    //电机使能
    gpio_set_level(EN_Pin, GPIO_PIN_RESET);

    if(i==8)
    {
       gpio_set_level(MS2_Pin, GPIO_PIN_RESET);
        gpio_set_level(MS1_Pin, GPIO_PIN_RESET);
    }
    else 	if(i==32)
    {
        gpio_set_level(MS2_Pin, GPIO_PIN_RESET);
        gpio_set_level(MS1_Pin, GPIO_PIN_SET);
    }
    else 	if(i==64)
    {
        gpio_set_level(MS2_Pin, GPIO_PIN_SET);
        gpio_set_level(MS1_Pin, GPIO_PIN_RESET);
    }
    else  if ( i== 128)
    {
        gpio_set_level(MS2_Pin, GPIO_PIN_SET);
        gpio_set_level(MS1_Pin, GPIO_PIN_SET);
    }

    //电机非使能
    gpio_set_level(EN_Pin, GPIO_PIN_SET);

    return subdevision_value;
}

​

电机pwm初始化

void tmc_pwm_init() {

    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_LOW_SPEED_MODE,    //配置低速模式
        .duty_resolution = LEDC_TIMER_10_BIT, //选择10位分辨率,即切分为1024个切片
        .timer_num = LEDC_TIMER_1,                        //配置定时器
        .freq_hz = 100,                          //配置频率
        .clk_cfg = LEDC_AUTO_CLK,                          //配置时钟源
    };
    ledc_timer_config(&ledc_timer);
    ledc_channel_config_t ledc_channel = {
        .channel = LEDC_CHANNEL_1,     //设置pwm输出通道(就是从把个通道中选择一个)
        .duty = 0,        //设置高电平所占的切块数量(控制占空比)
        .flags.output_invert = 0,       //配置pwm脉冲的高低电平是否翻转,对应pwm生成器的选择器1,
        .gpio_num = STEP_Pin,    //选择输出的引脚
        .hpoint = 0,      //设置hpoint
        .intr_type = LEDC_INTR_DISABLE,   //是否设置中断
        .speed_mode = LEDC_LOW_SPEED_MODE,  //pwm的输出模式,和上一结构体一致
        .timer_sel = LEDC_TIMER_1,   //设置pwm生成器的定时器
    };
    ledc_channel_config(&ledc_channel);
}

其他引脚初始化

void tmc_gpio_init() {
    //配置DIR引脚和STEP引脚
    gpio_config_t gpio_Config_1 = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_OUTPUT,
        .pin_bit_mask = (1ull <<DIR_Pin)  | (1ull <<STEP_Pin ) ,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .pull_up_en = GPIO_PULLUP_DISABLE,
    };
    gpio_config(&gpio_Config_1);

    //配置EN引脚,先拉高,失能芯片
    gpio_config_t gpio_Config_2 = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_INPUT_OUTPUT,
        .pin_bit_mask =   1ull << EN_Pin,
        .pull_down_en = GPIO_PULLDOWN_ENABLE,
        .pull_up_en = GPIO_PULLUP_DISABLE,
    };
    gpio_config(&gpio_Config_2);
    gpio_set_level(EN_Pin, GPIO_PIN_SET);

    //配置MS1与MS2引脚,默认先八细分
    gpio_config_t gpio_Config_3 = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_INPUT_OUTPUT,
        .pin_bit_mask =   (1ull << MS1_Pin)|(1ull<MS2_Pin),
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .pull_up_en = GPIO_PULLUP_DISABLE,
    };
    gpio_config(&gpio_Config_3);

}

设置转动角度:

void tmc_set_angle(uint8_t DIR,uint8_t subdevision_value,float angle) {

    //电机使能
    gpio_set_level(EN_Pin, GPIO_PIN_RESET);

    //设置方向
    if(DIR){
        gpio_set_level(DIR_Pin, GPIO_PIN_SET);//正转
    }
    else{
        gpio_set_level(DIR_Pin, GPIO_PIN_RESET); //反转
    }

    float per_angle = 1.8 / subdevision_value;       //计算细分后没个脉冲所运动的角度
    uint64_t pluse_num = (uint64_t)  ( angle / per_angle );       //需要的脉冲数
    uint32_t speed_hz = ledc_get_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_1);
    uint64_t time = ( (float)pluse_num * 1000 ) /  speed_hz ;   //计算需要等待的时间

    //开始发送脉冲
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 1024/2);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1);

    //延时直达相应的脉冲发送完毕
    vTaskDelay(pdMS_TO_TICKS(time));

    //停止发送脉冲
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 0);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1);

    //电机非使能
    gpio_set_level(EN_Pin, GPIO_PIN_SET);
}

demo

void app_main(void) {
    tmc_init();
    while(1) {
        //MoveStep(1,12800*10);													//正转一圈
        uint8_t subdivision_value = tmc_set_subdivision(8);
        tmc_set_angle(1,subdivision_value ,180);
        vTaskDelay(50);														//延时2S
        //MoveStep(0,12800*10);													//反转一圈
        tmc_set_angle(0,subdivision_value ,180);
        vTaskDelay(50);														//延时2S
    }
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐