mirror of
https://github.com/DuRuofu/ESP32-Guide.git
synced 2026-02-05 22:52:22 +08:00
add:drv8825案例
This commit is contained in:
@@ -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 微秒触发一次
|
||||
// }
|
||||
|
||||
6
code/10.practice/common_modules/drv8825/CMakeLists.txt
Normal file
6
code/10.practice/common_modules/drv8825/CMakeLists.txt
Normal 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)
|
||||
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "")
|
||||
167
code/10.practice/common_modules/drv8825/main/main.c
Normal file
167
code/10.practice/common_modules/drv8825/main/main.c
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user