在之前TB6612驱动中,主要实现了固定速度下小车的循迹,在车身偏转使用默认的速度进行纠偏,使车身恢复正常状态。接线图和之前TB6612一样STM32Cubemx TB6612直流电机驱动-CSDN博客。
今天要做的是,两路循迹判断车身偏的情况下,使用PID进行差速调节最后将误差分别给到左右电机,实现自动调速。
实现两路循迹PID控制差速的关键在于根据循迹模块的读数来计算出控制差速的误差,然后再利用PID控制算法来调节左右两侧驱动轮的转速。
一、CubeMX配置
SYS
RCC 选则外部高速晶振
GPIO 配置
T6612PWM配置
时钟树配置
freertos配置
二、Keil代码配置
在freertos.c添加代码
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "tim.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ uint16_t base_speed=120; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define Kp 15 // 比例参数 #define Ki 0.1 // 积分参数 #define Kd 0.05 // 微分参数 /* USER CODE END PD */
/* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ void motorControlL(uint8_t direction, uint16_t speed) {//左电机驱动 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); /* 根据方向设置 IN1 和 IN2 引脚 */ HAL_GPIO_WritePin(GPIOA, BIN1_Pin, (direction & 0x01)); HAL_GPIO_WritePin(GPIOA, BIN2_Pin, ((direction & 0x01) ^ 0x01)); /* 设置 PWM 引脚以控制速度 */ __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, speed); } void motorControlR(uint8_t direction, uint16_t speed) {//右电机驱动 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); /* 根据方向设置 AIN1 和 IN2 引脚 */ HAL_GPIO_WritePin(GPIOA, AIN2_Pin, (direction & 0x01)); HAL_GPIO_WritePin(GPIOA, AIN1_Pin, ((direction & 0x01) ^ 0x01)); /* 设置 PWM 引脚以控制速度 */ __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, speed); } // 读取左右循迹传感器数据 int read_left_trace_sensor() { // 返回左侧循迹传感器的读数 uint16_t a=0; if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==1){a=10;} else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==0){a=6;} return a; } int read_right_trace_sensor() { // 返回右侧循迹传感器的读数 uint16_t a=0; if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)==1){a=10;} else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)==0){a=6;} return a; } // 设置左右电机转速 void set_motor_speed(float left_speed, float right_speed) { motorControlL(1, left_speed); //第一个参数 0反向转 1正向转 第二个参数控制小车速度 motorControlR(1, right_speed); // 控制左右电机的转速 } // PID控制差速 void pid_control_diff() { int left_sensor_reading = read_left_trace_sensor(); int right_sensor_reading = read_right_trace_sensor(); // 计算误差 float error = left_sensor_reading - right_sensor_reading; // 计算PID输出 float output = Kp * error; // 根据输出值调整左右电机的转速 float left_speed = base_speed + output; float right_speed = base_speed - output; // 将PID输出应用到电机控制 set_motor_speed(right_speed, left_speed); } void BEEP(){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET); osDelay(500); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET); osDelay(500); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET); osDelay(500); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET); } /* USER CODE END FunctionPrototypes */
默认任务
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ uint8_t start=0; for(;;) { HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); osDelay(300); } /* USER CODE END StartDefaultTask */ }
主任务
/* USER CODE END Header_MainTask */ void MainTask(void const * argument) { /* USER CODE BEGIN MainTask */ /* Infinite loop */ for(;;) { // 执行PID控制差速 pid_control_diff(); if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==1 && HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)==1){//stop motorControlL(0, 0); motorControlR(0, 0); BEEP(); } } /* USER CODE END MainTask */ }
链接: https://pan.baidu.com/s/1Pz_WwB-WyBlk_gm2Gab3xg?pwd=9yjh 提取码: 9yjh