STM32CubeMX PID差速循迹小车

在之前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 

### STM32 HAL库实现红外循迹PID控制 在嵌入式开发领域,STM32控制器因其高性能和丰富的外设资源而被广泛应用于各种项目中。通过HAL库可以简化硬件抽象层的操作,从而更方便地实现复杂功能,例如基于红外传感器的循迹控制以及PID算法的应用。 #### PID控制简介 比例-积分-衍生(Proportional Integral Derivative, PID)是一种常见的闭环控制系统算法,用于调节系统的动态行为并减少误差[^1]。其核心思想是通过对输入信号的比例、积分和导数项加权求和来计算输出值,最终达到稳定目标的目的。 对于红外循迹应用来说,通常会利用多个红外反射传感器检测地面颜色变化情况作为反馈数据源;再经过处理后送入到PID模块当中去调整电机转速差值进而改变机器人行驶方向直至回到轨迹线上为止。 #### 使用STM32 HAL库编写红外循迹PID程序框架 以下是采用C语言编写的简单示例代码片段展示如何结合上述提到的技术要点完成整个流程: ```c #include "stm32f4xx_hal.h" // 定义全局变量 float kp = 0.8; // 比例系数 float ki = 0.05; // 积分系数 float kd = 0.2; // 微分系数 int error_prev = 0; int integral_sum = 0; void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1){ int sensor_value = ReadInfraredSensor(); // 获取当前红外传感器读数 int setpoint = 1024 / 2; // 设定理想位置(假设满量程为1024) int error = setpoint - sensor_value; // 计算偏差 integral_sum += error; // 累积误差 float derivative = error - error_prev; // 当前时刻与上一时刻误差之差即为微分校正部分 error_prev = error; // 更新上次误差记录以便下次循环使用 float output = kp * error + ki * integral_sum + kd * derivative; ControlMotor(output); // 将结果传递给驱动函数以影响左右轮速度差异度 } } /** * @brief Reads the value from infrared sensor. */ int ReadInfraredSensor(){ // 实现具体读取逻辑... return ADC_ReadChannel(INFRARED_SENSOR_CHANNEL); } /** * @brief Adjusts motor speed based on control signal. * @param[in] correction The calculated adjustment needed by PID controller. */ void ControlMotor(float correction){ if(correction > THRESHOLD){ // 如果超出阈值则加速一侧马达减速另一侧形成转向效果 SetLeftMotorSpeed(BASE_SPEED - abs((int)correction)); SetRightMotorSpeed(BASE_SPEED + abs((int)correction)); }else{ SetBothMotorsToBaseSpeed(); // 否则保持直线前进状态 } } ``` 以上仅为基本结构示意,在实际工程实践中还需要考虑更多细节比如限幅防饱和措施防止过度累积造成震荡现象等问题都需要妥善解决才能获得良好性能表现[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chem4111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值