// #include // // #include "freertos/FreeRTOS.h" // // #include "freertos/task.h" // static const char *TAG_MOTOR = "MotorControl"; // /** 置位后 motor_run_for_ms 与哨兵停 2 秒会提前退出,用于随时停止哨兵并回正 */ // static volatile bool motor_stop_request = false; // static bool flag = true; // void angle_control_task(void *pvParameter); // float current_angle = 0; // float target_angle = 0; // float motor_speed = 90; // uint32_t motor_rpm = 10; // uint32_t motor_pwm = 0; // uint32_t PWM_QUEUE[2] = {MOTOR_60_PWM, MOTOR_90_PWM}; // uint32_t SPEED_QUEUE[2] = {MOTOR_60_SPEED, MOTOR_90_SPEED}; // TaskHandle_t angle_control_handle = NULL; // // 电机控制结构体 // typedef struct // { // gpio_num_t ain1_pin; // gpio_num_t ain2_pin; // ledc_channel_t ain1_channel; // ledc_channel_t ain2_channel; // } motor_config_t; // static motor_config_t motor = { // .ain1_pin = MOTOR_AIN1_GPIO, // .ain2_pin = MOTOR_AIN2_GPIO, // .ain1_channel = LEDC_CHANNEL_AIN1, // .ain2_channel = LEDC_CHANNEL_AIN2}; // // 初始化PWM // void pwm_init(void) // { // // 配置PWM定时器 // ledc_timer_config_t ledc_timer = { // .speed_mode = LEDC_MODE, // .duty_resolution = LEDC_DUTY_RES, // .timer_num = LEDC_TIMER, // .freq_hz = LEDC_FREQ, // .clk_cfg = LEDC_AUTO_CLK}; // ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); // // 配置PWM通道 // ledc_channel_config_t ledc_channel_ain1 = { // .speed_mode = LEDC_MODE, // .channel = motor.ain1_channel, // .timer_sel = LEDC_TIMER, // .intr_type = LEDC_INTR_DISABLE, // .gpio_num = motor.ain1_pin, // .duty = 0, // .hpoint = 0}; // ledc_channel_config_t ledc_channel_ain2 = { // .speed_mode = LEDC_MODE, // .channel = motor.ain2_channel, // .timer_sel = LEDC_TIMER, // .intr_type = LEDC_INTR_DISABLE, // .gpio_num = motor.ain2_pin, // .duty = 0, // .hpoint = 0}; // ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_ain1)); // ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_ain2)); // } // void gpio_init(void) // { // // 配置GPIO为输出模式[2](@ref) // gpio_config_t io_conf = { // .pin_bit_mask = (1ULL << motor.ain1_pin | motor.ain2_pin), // .mode = GPIO_MODE_OUTPUT, // .pull_up_en = GPIO_PULLUP_DISABLE, // .pull_down_en = GPIO_PULLDOWN_ENABLE, // .intr_type = GPIO_INTR_DISABLE}; // gpio_config(&io_conf); // } // /** // * 按固定时长运行电机(可被 motor_stop_request 中断,收到停止时立即停) // * @param pwm 电机 PWM,正负表示方向 // * @param duration_ms 运行时长(毫秒) // * @return 实际运行的毫秒数(若被中断则小于 duration_ms,用于按比例回正) // */ // static uint32_t motor_run_for_ms(int32_t pwm, uint32_t duration_ms) // { // if (duration_ms == 0) // return 0; // TickType_t xWake = xTaskGetTickCount(); // TickType_t xStart = xWake; // const TickType_t xPeriod = pdMS_TO_TICKS(1); // TickType_t xEnd = xWake + pdMS_TO_TICKS(duration_ms); // while (xTaskGetTickCount() < xEnd) // { // if (motor_stop_request) // { // motor_set_speed(0); // return (uint32_t)pdTICKS_TO_MS(xTaskGetTickCount() - xStart); // } // motor_set_speed(pwm); // vTaskDelayUntil(&xWake, xPeriod); // } // return duration_ms; // } // /** 可被 motor_stop_request 中断的延时(毫秒),用于哨兵停 2 秒等 */ // static void delay_ms_check_stop(uint32_t duration_ms) // { // TickType_t xWake = xTaskGetTickCount(); // TickType_t xEnd = xWake + pdMS_TO_TICKS(duration_ms); // while (xTaskGetTickCount() < xEnd) // { // if (motor_stop_request) // return; // vTaskDelay(pdMS_TO_TICKS(1)); // } // } // void motor_request_stop(void) // { // motor_stop_request = true; // } // static void motor_clear_stop_request(void) // { // motor_stop_request = false; // } // // 设置电机速度和方向 // void motor_set_speed(int32_t speed) // { // speed = -speed; // if (speed == 0) // { // // 停止电机 // ledc_set_duty(LEDC_MODE, motor.ain1_channel, 0); // ledc_set_duty(LEDC_MODE, motor.ain2_channel, 0); // ledc_update_duty(LEDC_MODE, motor.ain1_channel); // ledc_update_duty(LEDC_MODE, motor.ain2_channel); // } // else if (speed > 0) // { // // 正转 // ledc_set_duty(LEDC_MODE, motor.ain1_channel, speed * 1023 / MOTOR_MAX_PWM); // ledc_set_duty(LEDC_MODE, motor.ain2_channel, 0); // ledc_update_duty(LEDC_MODE, motor.ain1_channel); // ledc_update_duty(LEDC_MODE, motor.ain2_channel); // } // else // { // // 反转 // speed = -speed; // ledc_set_duty(LEDC_MODE, motor.ain1_channel, 0); // ledc_set_duty(LEDC_MODE, motor.ain2_channel, speed * 1023 / MOTOR_MAX_PWM); // ledc_update_duty(LEDC_MODE, motor.ain1_channel); // ledc_update_duty(LEDC_MODE, motor.ain2_channel); // } // /* motor_speed = (speed < 0) ? -speed : speed; */ // // ESP_LOGI(TAG_MOTOR, "Motor speed set to: %ld", speed); // } // // 设置目标角度 // void motor_set_angle(float angle) // { // set_flag(false); // target_angle = angle; // int angle_milli = (int)(target_angle * 1000.0f); // ESP_LOGI(TAG_MOTOR, "Target angle set to: %d.%03d degrees", angle_milli / 1000, abs(angle_milli % 1000)); // } // // 转速控制函数,单位为度每秒 // void motor_set_motor_speed(uint32_t speed) // { // motor_speed = speed; // ESP_LOGI(TAG_MOTOR, "Motor_speed set to: %lu", speed); // } // // 电机初始化 // void motor_init(void) // { // gpio_init(); // pwm_init(); // target_angle = 0; // current_angle = 0; // motor_set_motor_speed(MOTOR_90_SPEED); // /* motor_set_speed(MOTOR_30_PWM); // vTaskDelay(pdMS_TO_TICKS(12000)); // motor_set_speed(0); */ // xTaskCreate(angle_control_task, "angle_control", 4096, NULL, 5, &angle_control_handle); // } // // 角度控制任务(需要编码器反馈,这里是开环控制示例) // void angle_control_task(void *pvParameter) // { // TickType_t xLastWakeTime = xTaskGetTickCount(); // const TickType_t xControlPeriod = pdMS_TO_TICKS(1); // pdMS_TO_TICKS(20) // ESP_LOGI(TAG_MOTOR, "Starting angle control task"); // uint32_t frist_back_time = 450; // uint32_t pwm_value = 42;//53 // uint32_t back_time_period = 2000;//ms -- 5800 // for (size_t i = 0; i < 1; i++) // // while(1) // { // motor_set_speed(pwm_value ); // vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(800)); // motor_set_speed(0); // vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1000)); // motor_set_speed(-pwm_value ); // vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(frist_back_time)); // 150 // ESP_LOGE("angle_task","back_time :%lu",frist_back_time); // motor_set_speed(0); // } // uint32_t bits = 0; // // int target_position = 0; // bool motor_run_flag = false; // MOTOR_STATE motor_state; // while (1) // { // // 必须是有效的任务句柄 // BaseType_t notify_ret = xTaskNotifyWait(0x00000000, ULONG_MAX, &bits, 0); // pdMS_TO_TICKS(100) // if (notify_ret == pdPASS) // { // motor_run_flag = true; // if (bits == 0x00) // { // motor_clear_stop_request(); // motor_set_speed(0); // } // else if (bits == 0x01) // { // motor_run_for_ms(-pwm_value , 600);//200 // motor_set_speed(0); // vTaskDelay(pdMS_TO_TICKS(back_time_period)); // motor_run_for_ms(pwm_value , 450); // motor_set_speed(0); // } // else if (bits == 0x02) // { // motor_run_for_ms(pwm_value , 600);//110 // motor_set_speed(0); // vTaskDelay(pdMS_TO_TICKS(back_time_period)); // motor_run_for_ms(-pwm_value,450);//310 // motor_set_speed(0); // } // else if (bits == 0x05) // { // motor_run_for_ms(-pwm_value, 150); // motor_set_speed(0); // vTaskDelay(pdMS_TO_TICKS(2000)); // motor_run_for_ms(pwm_value, 150); // motor_set_speed(0); // } // else if (bits == 0x06) // { // motor_run_for_ms(pwm_value , 150); // motor_set_speed(0); // vTaskDelay(pdMS_TO_TICKS(2000)); // motor_run_for_ms(-pwm_value , 115); // motor_set_speed(0); // } // else if (bits == 0x07) // { // motor_run_for_ms(-pwm_value , 1000); // motor_set_speed(0); // vTaskDelay(pdMS_TO_TICKS(2000)); // motor_run_for_ms(pwm_value , 900); // motor_set_speed(0); // } // else if (bits == 0x11) // { // motor_run_for_ms(-pwm_value , 10); // motor_set_speed(0); // } // else if (bits == 0x12) // { // motor_run_for_ms(pwm_value , 10); // motor_set_speed(0); // } // else // { // frist_back_time = bits; // // ESP_LOGE("angle_task","back_time :%lu",back_time); // } // } // } // } // static void set_flag(bool state) // { // flag = state; // } // bool get_flag(void) // { // return flag; // }