From e9b1c296635a3ccae8a9dba44d8b89892b86e4e4 Mon Sep 17 00:00:00 2001 From: duruofu <2747211095@qq.com> Date: Tue, 26 Aug 2025 10:44:15 +0800 Subject: [PATCH] =?UTF-8?q?add:drv8825=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common_modules/28byj-48/main/main.c | 167 ++++++++++++------ .../common_modules/drv8825/CMakeLists.txt | 6 + .../drv8825/main/CMakeLists.txt | 2 + .../common_modules/drv8825/main/main.c | 167 ++++++++++++++++++ 4 files changed, 291 insertions(+), 51 deletions(-) create mode 100644 code/10.practice/common_modules/drv8825/CMakeLists.txt create mode 100644 code/10.practice/common_modules/drv8825/main/CMakeLists.txt create mode 100644 code/10.practice/common_modules/drv8825/main/main.c diff --git a/code/10.practice/common_modules/28byj-48/main/main.c b/code/10.practice/common_modules/28byj-48/main/main.c index 9d86abc..9da3f59 100644 --- a/code/10.practice/common_modules/28byj-48/main/main.c +++ b/code/10.practice/common_modules/28byj-48/main/main.c @@ -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 微秒触发一次 +// } diff --git a/code/10.practice/common_modules/drv8825/CMakeLists.txt b/code/10.practice/common_modules/drv8825/CMakeLists.txt new file mode 100644 index 0000000..0a454d0 --- /dev/null +++ b/code/10.practice/common_modules/drv8825/CMakeLists.txt @@ -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) diff --git a/code/10.practice/common_modules/drv8825/main/CMakeLists.txt b/code/10.practice/common_modules/drv8825/main/CMakeLists.txt new file mode 100644 index 0000000..8a3ab69 --- /dev/null +++ b/code/10.practice/common_modules/drv8825/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS "") diff --git a/code/10.practice/common_modules/drv8825/main/main.c b/code/10.practice/common_modules/drv8825/main/main.c new file mode 100644 index 0000000..3a4a3ac --- /dev/null +++ b/code/10.practice/common_modules/drv8825/main/main.c @@ -0,0 +1,167 @@ +#include +#include +#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(); + } +}