ESP32-S3基于ESP-IDF 控制 42 步进电机(学习笔记)
·
一、硬件装备清单

二、核心参数说明
- 42 步进电机参数:
- 步距角:1.8°(整步模式下,200 步 = 360°)
- 额定电流:1.7A
- 线圈分组:红 - 蓝(A 组)、黑 - 绿(B 组)(根据万用表测量结果)
- 驱动器参数:
- 供电电压:24V(电机电源)
- 控制信号电压:3.3V(兼容 ESP32-S3 输出)
- 细分设置:默认整步(S1=ON, S2=ON, S3=OFF)(需与代码匹配)
- 电流设置:1.7A(根据拨码开关说明书设置,如 S4=ON, S5=ON, S6=OFF)
- ESP32-S3 引脚功能:
- GPIO14:脉冲信号(PUL+)
- GPIO15:方向信号(DIR+)
- GPIO16:使能信号(ENA+)
- GND:共地引脚
三、接线表格(关键连接关系)
一、电机线圈与驱动器连接表(你的实际分组)

二、ESP32-S3 与驱动器信号连接表

三、电源与共地连接表(核心共地回路)

四、接线正确性验证表(自查用)

五、代码解析
- 头文件与宏定义
#include <stdio.h> // 标准输入输出(用于打印调试信息)
#include <math.h> // 数学函数库(用于 fabs() 取绝对值)
#include "freertos/FreeRTOS.h" // FreeRTOS 实时操作系统接口(任务调度)
#include "freertos/task.h" // FreeRTOS 任务相关函数(如 vTaskDelay)
#include "driver/gpio.h" // ESP32 GPIO 驱动库(配置引脚输入输出)
#include "esp_err.h" // ESP32 错误处理库(返回错误码)
#include "esp_rom_sys.h" // ESP32 内置 ROM 函数(用于 esp_rom_delay_us 延时)
引脚定义(核心控制信号)
电机参数(整步模式下)
#define STEP_ANGLE 1.8f // 步距角(每步转动的角度,42 电机常见值)
#define FULL_STEPS 200 // 360° 所需步数(360 / 1.8 = 200 步)
#define MAX_SPEED 1000 // 最大速度(每秒最多走 1000 步)
#define MIN_DELAY_US 1000 // 最小脉冲间隔(避免速度过快导致电机堵转)
方向枚举(简化方向控制)
二、核心函数解析
1. 电机初始化函数 stepper_init()
esp_err_t stepper_init(void) {
// 配置 GPIO 引脚参数
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << PUL_PIN) | (1ULL << DIR_PIN) | (1ULL << ENA_PIN),
// 要配置的引脚:PUL、DIR、ENA
.mode = GPIO_MODE_OUTPUT, // 设为输出模式(发送控制信号)
.pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉电阻
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉电阻
.intr_type = GPIO_INTR_DISABLE // 禁用中断(无需触发中断)
};
// 应用配置,返回错误码(如配置失败)
esp_err_t ret = gpio_config(&io_conf);
if (ret != ESP_OK) {
return ret; // 配置失败,返回错误
}
// 使能电机(ENA 引脚高电平有效,低电平会锁定电机)
gpio_set_level(ENA_PIN, 1);
// 初始方向设为顺时针(DIR 引脚输出低电平)
gpio_set_level(DIR_PIN, STEPPER_DIR_CW);
return ESP_OK; // 初始化成功
}
作用:将控制引脚配置为输出模式,使能电机并设置初始方向,为后续控制做准备。
2. 方向设置函数 stepper_set_dir()
void stepper_set_dir(stepper_dir_t dir) {
gpio_set_level(DIR_PIN, dir); // 通过 DIR 引脚电平控制方向
}
作用:通过改变 DIR 引脚的高低电平,切换电机旋转方向(0 为顺时针,非 0 为逆时针)。
3. 单步驱动函数 stepper_step()
void stepper_step(uint32_t delay_us) {
gpio_set_level(PUL_PIN, 1); // 脉冲引脚输出高电平(开始一步)
esp_rom_delay_us(10); // 高电平持续 10us(满足驱动器最小脉冲宽度要求)
gpio_set_level(PUL_PIN, 0); // 脉冲引脚输出低电平(结束一步)
esp_rom_delay_us(delay_us); // 步间延迟(控制转速:延迟越短,速度越快)
}
作用:发送一个完整的脉冲信号(高电平 + 低电平),驱动电机转动一步(1.8°)。步间延迟 delay_us 决定了电机速度(延迟越小,每秒步数越多,速度越快)。
4. 角度旋转函数 stepper_rotate()
void stepper_rotate(float angle, uint32_t speed) {
// 限制速度不超过最大值(避免电机过载)
if (speed > MAX_SPEED) {
speed = MAX_SPEED;
}
// 计算步间延迟(微秒):1秒=1e6微秒,除以每秒步数得每步间隔
uint32_t delay_us = 1000000 / speed;
// 确保延迟不小于最小值(避免速度过快导致堵转)
if (delay_us < MIN_DELAY_US) {
delay_us = MIN_DELAY_US;
}
// 计算所需步数:角度 → 步数(四舍五入)
// 公式:步数 = 角度绝对值 × 总步数(200) / 360°
uint32_t steps_needed = (uint32_t)(fabs(angle) * FULL_STEPS / 360.0f + 0.5f);
if (steps_needed == 0) { // 角度为0时无需转动
return;
}
// 根据角度正负设置方向(负角度为逆时针)
if (angle < 0) {
stepper_set_dir(STEPPER_DIR_CCW);
} else {
stepper_set_dir(STEPPER_DIR_CW);
}
// 循环发送脉冲,完成指定步数(即指定角度)
for (uint32_t i = 0; i < steps_needed; i++) {
stepper_step(delay_us);
}
}
作用:根据目标角度和速度,自动计算所需步数和步间延迟,控制电机旋转到指定角度。
三、主函数 app_main()
void app_main(void) {
// 初始化步进电机,检查是否成功
esp_err_t ret = stepper_init();
if (ret != ESP_OK) {
printf("Stepper init failed: %s\n", esp_err_to_name(ret));
return; // 初始化失败则退出
}
printf("Stepper initialized\n"); // 初始化成功提示
// 循环执行旋转动作
while (1) {
// 顺时针旋转90度,速度500步/秒
printf("Rotate 90 degrees CW\n");
stepper_rotate(90.0f, 500);
vTaskDelay(pdMS_TO_TICKS(2000)); // 暂停2秒(等待旋转完成)
// 逆时针旋转180度,速度800步/秒
printf("Rotate 180 degrees CCW\n");
stepper_rotate(-180.0f, 800);
vTaskDelay(pdMS_TO_TICKS(2000)); // 暂停2秒
// 顺时针旋转360度,速度1000步/秒
printf("Rotate 360 degrees CW\n");
stepper_rotate(360.0f, 1000);
vTaskDelay(pdMS_TO_TICKS(2000)); // 暂停2秒
}
}
作用:程序入口,初始化电机后进入循环,演示不同角度和速度的旋转动作(顺时针 90°→逆时针 180°→顺时针 360°,循环往复)。
四、核心逻辑总结
- 控制原理:通过 PUL 引脚的脉冲数量控制旋转角度(1 脉冲 = 1 步 = 1.8°),通过 DIR 引脚电平控制方向,通过脉冲间隔控制速度。
- 参数匹配:代码中 FULL_STEPS(200 步)需与驱动器细分设置一致(整步模式),否则角度计算会偏差。
- 安全性:限制最大速度和最小延迟,避免电机因过载或频率不匹配导致 “堵转”(只响不转)。
通过修改 stepper_rotate() 的参数(角度和速度),可实现任意角度的精准旋转,适用于需要精确定位的场景(如机械臂、精密平台等)。
更多推荐



所有评论(0)