add:drv8825案例

This commit is contained in:
duruofu
2025-08-26 10:44:15 +08:00
parent ef991fe9f1
commit e9b1c29663
4 changed files with 291 additions and 51 deletions

View File

@@ -9,9 +9,9 @@
#define PIN3 GPIO_NUM_18
#define PIN4 GPIO_NUM_19
// 电机步数和旋转延迟(越小越快)
// // 电机步数和旋转延迟(越小越快)
#define STEPS_PER_REVOLUTION 4096
int rotation_speed_ms = 10; // 全局速度变量单位ms
int rotation_speed_ms = 0.1; // 全局速度变量单位ms
// 初始化 GPIO
void stepper_gpio_init(void) {
@@ -26,78 +26,143 @@ void stepper_gpio_init(void) {
printf("步进电机 GPIO 初始化完成\n");
}
// 八步半步激励序列半步驱动共8步
// 顺序依次是单相激励与双相激励交替,提升平滑度
const int step_sequence[8][4] = {
{1, 0, 0, 0}, // 1
{1, 1, 0, 0}, // 1+2
{0, 1, 0, 0}, // 2
{0, 1, 1, 0}, // 2+3
{0, 0, 1, 0}, // 3
{0, 0, 1, 1}, // 3+4
{0, 0, 0, 1}, // 4
{1, 0, 0, 1} // 4+1
// // 八步半步激励序列半步驱动共8步
// // 顺序依次是单相激励与双相激励交替,提升平滑度
// const int step_sequence[8][4] = {
// {1, 0, 0, 0}, // 1
// {1, 1, 0, 0}, // 1+2
// {0, 1, 0, 0}, // 2
// {0, 1, 1, 0}, // 2+3
// {0, 0, 1, 0}, // 3
// {0, 0, 1, 1}, // 3+4
// {0, 0, 0, 1}, // 4
// {1, 0, 0, 1} // 4+1
// };
const uint8_t step_sequence[4][4] = {
{1, 0, 0, 0}, // A
{0, 1, 0, 0}, // B
{0, 0, 1, 0}, // C
{0, 0, 0, 1}, // D
};
int current_step_index = 0; // 全局步进索引
// 输出对应步进序列的电平
void step_motor(int step) {
int idx = step % 8;
int idx = step % 4;
gpio_set_level(PIN1, step_sequence[idx][0]);
gpio_set_level(PIN2, step_sequence[idx][1]);
gpio_set_level(PIN3, step_sequence[idx][2]);
gpio_set_level(PIN4, step_sequence[idx][3]);
}
// 顺时针旋转指定步数
void rotate_clockwise(int steps) {
for (int i = 0; i < steps; i++) {
current_step_index = (current_step_index + 1) % 8;
step_motor(current_step_index);
vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
}
}
// // 顺时针旋转指定步数
// void rotate_clockwise(int steps) {
// for (int i = 0; i < steps; i++) {
// current_step_index = (current_step_index + 1) % 4;
// step_motor(current_step_index);
// vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
// }
// }
// 逆时针旋转指定步数
void rotate_counterclockwise(int steps) {
for (int i = 0; i < steps; i++) {
current_step_index = (current_step_index - 1 + 8) % 8;
step_motor(current_step_index);
vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
}
}
// // 逆时针旋转指定步数
// void rotate_counterclockwise(int steps) {
// for (int i = 0; i < steps; i++) {
// current_step_index = (current_step_index - 1 + 4) % 4;
// step_motor(current_step_index);
// vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
// }
// }
// 旋转指定角度(正数顺时针,负数逆时针)
void rotate_angle(float degrees) {
// 细分了步数要乘以8/4=2倍
int steps = (int)(STEPS_PER_REVOLUTION * 2 * degrees / 360.0f);
if (steps > 0) {
rotate_clockwise(steps);
} else if (steps < 0) {
rotate_counterclockwise(-steps);
}
}
// // 旋转指定角度(正数顺时针,负数逆时针)
// void rotate_angle(float degrees) {
// // 细分了步数要乘以8/4=2倍
// int steps = (int)(STEPS_PER_REVOLUTION * 2 * degrees / 360.0f);
// if (steps > 0) {
// rotate_clockwise(steps);
// } else if (steps < 0) {
// rotate_counterclockwise(-steps);
// }
// }
// // 主任务
// // void stepper_task(void *arg) {
// // while (1) {
// // // rotate_counterclockwise(STEPS_PER_REVOLUTION / 4); // 逆时针旋转90度
// // // // printf("顺时针旋转一整圈...\n");
// // // // rotate_clockwise(STEPS_PER_REVOLUTION * 2); // 注意步数乘2
// // // // vTaskDelay(pdMS_TO_TICKS(1000));
// // // // printf("逆时针旋转一整圈...\n");
// // // // rotate_counterclockwise(STEPS_PER_REVOLUTION * 2);
// // // // vTaskDelay(pdMS_TO_TICKS(1000));
// // // // printf("顺时针旋转25度...\n");
// // // // rotate_angle(25);
// // // vTaskDelay(pdMS_TO_TICKS(1000));
// // // for (int i = 0; i < steps; i++) {
// // // current_step_index = (current_step_index +1) % 4;
// // // step_motor(current_step_index);
// // // vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
// // }pdMS_TO_TICKS(rotation_speed_ms)
// // }
// 主任务
void stepper_task(void *arg) {
const TickType_t interval = pdMS_TO_TICKS(rotation_speed_ms); // 每步时间间隔
TickType_t last_wake_time = xTaskGetTickCount();
while (1) {
printf("顺时针旋转一整圈...\n");
rotate_clockwise(STEPS_PER_REVOLUTION * 2); // 注意步数乘2
vTaskDelay(pdMS_TO_TICKS(1000));
TickType_t now = xTaskGetTickCount();
if (now - last_wake_time >= interval) {
last_wake_time = now;
current_step_index = (current_step_index + 1);
step_motor(current_step_index);
}
printf("逆时针旋转一整圈...\n");
rotate_counterclockwise(STEPS_PER_REVOLUTION * 2);
vTaskDelay(pdMS_TO_TICKS(1000));
printf("顺时针旋转25度...\n");
rotate_angle(25);
vTaskDelay(pdMS_TO_TICKS(1000));
// 主动让出 CPU一点点时间防止 Watchdog 触发
taskYIELD(); // 立即让出 CPU或使用更保险的
vTaskDelay(1);
}
}
// app_main 入口
void app_main(void) {
stepper_gpio_init();
xTaskCreate(stepper_task, "stepper_task", 2048, NULL, 5, NULL);
// while(1)
// {
// current_step_index = (current_step_index +1) % 4;
// step_motor(current_step_index);
// vTaskDelay(pdMS_TO_TICKS(rotation_speed_ms));
// }
}
// #include "esp_timer.h"
// #define STEP_INTERVAL_US 3000 // 每步间隔时间单位微秒例如1000us = 1ms
// volatile int current_step_index = 0;
// // 步进电机定时器回调函数(中断上下文,不能用 printf
// void stepper_timer_callback(void* arg) {
// current_step_index = (current_step_index + 1) % 4;
// step_motor(current_step_index); // 注意:此函数必须足够快、不能阻塞
// }
// void app_main(void) {
// // 创建定时器
// stepper_gpio_init();
// const esp_timer_create_args_t stepper_timer_args = {
// .callback = &stepper_timer_callback,
// .name = "stepper_timer"
// };
// esp_timer_handle_t stepper_timer;
// ESP_ERROR_CHECK(esp_timer_create(&stepper_timer_args, &stepper_timer));
// // 启动周期性定时器
// ESP_ERROR_CHECK(esp_timer_start_periodic(stepper_timer, STEP_INTERVAL_US)); // 每 STEP_INTERVAL_US 微秒触发一次
// }

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "")

View File

@@ -0,0 +1,167 @@
#include <stdio.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_rom_sys.h"
// 定义 DRV8825 控制引脚
#define DIR_PIN GPIO_NUM_16 // 方向控制引脚
#define EN_PIN GPIO_NUM_17 // 使能控制引脚(低电平使能)
#define STEP_PIN GPIO_NUM_18 // 步进脉冲引脚
// 电机步数和旋转延迟(越小越快)
// DRV8825默认为全步模式200步/圈1.8度/步)
// 细分由外部硬件设置MS1、MS2、MS3引脚
#define STEPS_PER_REVOLUTION 200
int step_delay_us = 10000; // 步进脉冲延迟,单位微秒
/**
* @brief 初始化DRV8825控制引脚
* 配置DIR、EN、STEP三个GPIO引脚为输出模式
*/
void drv8825_gpio_init(void) {
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << DIR_PIN) | (1ULL << EN_PIN) | (1ULL << STEP_PIN),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = 0,
.pull_down_en = 0,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
// 初始化引脚状态
gpio_set_level(DIR_PIN, 0); // 默认方向
gpio_set_level(EN_PIN, 0); // 使能电机(低电平使能)
gpio_set_level(STEP_PIN, 0); // 步进引脚初始为低电平
printf("DRV8825 GPIO 初始化完成\n");
}
/**
* @brief 使能或禁用DRV8825电机驱动
* @param enable true为使能false为禁用
*/
void drv8825_enable(bool enable) {
gpio_set_level(EN_PIN, enable ? 0 : 1); // 低电平使能,高电平禁用
}
/**
* @brief 设置电机旋转方向
* @param clockwise true为顺时针false为逆时针
*/
void drv8825_set_direction(bool clockwise) {
gpio_set_level(DIR_PIN, clockwise ? 1 : 0);
}
/**
* @brief 发送一个步进脉冲
* 产生一个高-低电平脉冲来驱动电机前进一步
*/
void drv8825_step_once(void) {
gpio_set_level(STEP_PIN, 1); // 拉高
esp_rom_delay_us(10); // 保持高电平10微秒确保脉冲稳定
gpio_set_level(STEP_PIN, 0); // 拉低
esp_rom_delay_us(step_delay_us); // 步进间隔延迟
}
/**
* @brief 顺时针旋转指定步数
* @param steps 要旋转的步数
*/
void rotate_clockwise(int steps) {
drv8825_set_direction(true); // 设置顺时针方向
drv8825_enable(true); // 使能电机
for (int i = 0; i < steps; i++) {
drv8825_step_once();
}
}
/**
* @brief 逆时针旋转指定步数
* @param steps 要旋转的步数
*/
void rotate_counterclockwise(int steps) {
drv8825_set_direction(false); // 设置逆时针方向
drv8825_enable(true); // 使能电机
for (int i = 0; i < steps; i++) {
drv8825_step_once();
}
}
/**
* @brief 旋转指定角度
* @param degrees 旋转角度(正数顺时针,负数逆时针)
*/
void rotate_angle(float degrees) {
// 根据细分设置计算实际步数
// 全步模式200步/圈,如果使用细分需要相应调整
int steps = (int)(STEPS_PER_REVOLUTION * degrees / 360.0f);
if (steps > 0) {
rotate_clockwise(steps);
} else if (steps < 0) {
rotate_counterclockwise(-steps);
}
}
/**
* @brief 设置步进速度
* @param delay_us 步进间隔延迟(微秒),值越小速度越快
*/
void drv8825_set_speed(int delay_us) {
step_delay_us = delay_us;
}
/**
* @brief DRV8825步进电机控制演示
* 演示各种旋转控制功能
*/
void drv8825_demo(void) {
printf("DRV8825 - 顺时针旋转一整圈...\n");
rotate_clockwise(STEPS_PER_REVOLUTION);
drv8825_enable(false); // 旋转完成后禁用电机以节省功耗
vTaskDelay(pdMS_TO_TICKS(2000));
printf("DRV8825 - 逆时针旋转一整圈...\n");
rotate_counterclockwise(STEPS_PER_REVOLUTION);
drv8825_enable(false);
vTaskDelay(pdMS_TO_TICKS(2000));
printf("DRV8825 - 顺时针旋转90度...\n");
rotate_angle(90);
drv8825_enable(false);
vTaskDelay(pdMS_TO_TICKS(2000));
printf("DRV8825 - 逆时针旋转90度...\n");
rotate_angle(-90);
drv8825_enable(false);
vTaskDelay(pdMS_TO_TICKS(2000));
// 演示速度控制
printf("DRV8825 - 高速旋转180度...\n");
drv8825_set_speed(600); // 设置高速
rotate_angle(180);
drv8825_enable(false);
drv8825_set_speed(1000); // 恢复默认速度
vTaskDelay(pdMS_TO_TICKS(2000));
}
/**
* @brief 应用程序入口
* 初始化DRV8825并执行控制演示
*/
void app_main(void) {
printf("DRV8825步进电机驱动器示例程序启动\n");
printf("引脚配置: DIR=%d, EN=%d, STEP=%d\n", DIR_PIN, EN_PIN, STEP_PIN);
printf("细分设置由外部硬件控制(MS1, MS2, MS3引脚)\n");
drv8825_gpio_init();
// 循环执行演示
while (1) {
drv8825_demo();
}
}