在TMC2209驱动电机这一篇帖子中,已经介绍了让步进电机简单的转动起来了,并且介绍了整步和微步这两个名字。
在这一个帖子中我将在上几篇的帖子上从零实现本次DIY活动的主题一:基础步进电机运动控制系统。内容如下:
使用MCU控制TMC2209 SilentStepStick 驱动步进电机,实现一个可控制转动方向和速度的基础运动控制系统。 主要帮助参与者掌握:
STEP/DIR控制原理
定时器脉冲生成
基础运动控制逻辑
活动任务:
基础任务(入门级),控制端:
生成STEP脉冲信号
DIR控制电机正反转
支持至少两种转速,例如快速、慢速
电机能够稳定运行
进阶任务,在基础任务上实现:
速度调节功能
加速/减速控制
按键或串口控制运动,例如:启动、停止、反转
自由发挥方向(不做强制要求):
梯形加减速控制
多种运动模式
定位控制(步数控制)
PWM方式生成STEP
回顾一下连接示意图,除了MS1、MS2、PDN/UART、SPREAD、INDEX、GIDA未连接外,其他的引脚都是用了


首先需要初始化相关控制引脚:DIR、EN、STEP
void GPIO_Init(void)
{
gpio_config_t gpio_conf = {0};
gpio_conf.pin_bit_mask = 1ull << USR_LED_IO;
gpio_conf.mode = GPIO_MODE_OUTPUT;
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_conf.intr_type = GPIO_INTR_DISABLE;
gpio_config(&gpio_conf);
gpio_conf.pin_bit_mask = 1ull << TMC_EN_IO;
gpio_config(&gpio_conf);
gpio_conf.pin_bit_mask = 1ull << TMC_DIR_IO;
gpio_config(&gpio_conf);
TMC_STEP_PWM_Init();
TMC_SET_EN(0);
TMC_SET_DIR(0);
}
还需要三个相对应的控制函数,分别是控制模块是否使能、电机转动的方向、电机STEP驱动PWM的周期
void TMC_SET_EN(uint8_t en)
{
gpio_set_level(TMC_EN_IO, !en);
}
void TMC_SET_DIR(uint8_t dir)
{
tmc_dir_level = dir ? 1 : 0;
gpio_set_level(TMC_DIR_IO, tmc_dir_level);
}
static esp_err_t TMC_STEP_PWM_Set_Period_US(uint32_t period_us)
{
uint32_t freq_hz;
esp_err_t ret;
if (period_us < TMC_STEP_PWM_MIN_PERIOD_US || period_us > TMC_STEP_PWM_MAX_PERIOD_US) {
return ESP_ERR_INVALID_ARG;
}
freq_hz = 1000000UL / period_us;
if (freq_hz == 0) {
return ESP_ERR_INVALID_ARG;
}
ret = ledc_set_freq(TMC_STEP_PWM_MODE, TMC_STEP_PWM_TIMER, freq_hz);
if (ret != ESP_OK) {
return ret;
}
tmc_step_pwm_period_us = period_us;
return ESP_OK;
}
这时候在main中就可以随心随遇的控制电子的启动、方向和速度了
void app_main(void)
{
GPIO_Init();
TMC_SET_EN(1); //TMC_SET_EN(0);
TMC_SET_DIR(1); //TMC_SET_DIR(0);
TMC_STEP_PWM_Set_Period_US(1000);
}
但是这样不够优雅,于是计算用串口上位机来控制电机的相关状态。
串口命令分别为:
Moter Start
Moter Stop
Moter Reversal
Moter Period XXX
static void Moter_Start(const char *args, char *response, size_t response_size)
{
(void)args;
TMC_SET_EN(1);
ESP_ERROR_CHECK(TMC_STEP_PWM_Start());
snprintf(response, response_size, "OK: Moter Start\r\n");
}
static void Moter_Stop(const char *args, char *response, size_t response_size)
{
(void)args;
ESP_ERROR_CHECK(TMC_STEP_PWM_Stop());
TMC_SET_EN(0);
snprintf(response, response_size, "OK: Moter Stop\r\n");
}
static void Moter_Reversal(const char *args, char *response, size_t response_size)
{
(void)args;
TMC_SET_DIR(!tmc_dir_level);
snprintf(response, response_size, "OK: Moter Reversal, %d\r\n", tmc_dir_level);
}
static void Moter_Period(const char *args, char *response, size_t response_size)
{
char *end_ptr = NULL;
const unsigned long period_us = strtoul(args, &end_ptr, 10);
if (args[0] == '\0' || end_ptr == args || *end_ptr != '\0' ||
period_us < TMC_STEP_PWM_MIN_PERIOD_US || period_us > TMC_STEP_PWM_MAX_PERIOD_US ||
TMC_STEP_PWM_Set_Period_US((uint32_t)period_us) != ESP_OK) {
snprintf(response, response_size,
"ERR: period range %u-%u us\r\n",
(unsigned int)TMC_STEP_PWM_MIN_PERIOD_US,
(unsigned int)TMC_STEP_PWM_MAX_PERIOD_US);
return;
}
snprintf(response, response_size,
"OK: STEP period %lu us\r\n",
(unsigned long)tmc_step_pwm_period_us);
}
static const uart_command_t uart_command_table[] = {
{"Moter Start", NULL, Moter_Start},
{"Moter Stop", NULL, Moter_Stop},
{"Moter Reversal", NULL, Moter_Reversal},
{"Moter Period", "<us>", Moter_Period},
};
还需要编写一个简单的上位机,大概样子长这样,估计有大佬一眼就能看出来是用python写的Tkinter界面


我要赚赏金
