本文目录
- 一、知识点
- 1. 位置式pid
- (1)公式
- (2)代码
- 2. 串级PID
- 简易代码
一、知识点
1. 位置式pid
(1)公式
(2)代码
pid.c
typedef struct PID {float Kp; // Proportional Const P系数float Ki; // Integral Const I系数float Kd; // Derivative Const D系数float LastError; // Error[-1] float Error; // Error[0 ] float DError; //pid->Error - pid->LastError float SumError; // Sums of Errors float output;float Integralmax; //积分项的最大值float outputmax; //输出项的最大值
} PID;//为了防止积分项过度累积,引入积分项的限幅是一种常见的做法。
//限制积分项的幅值可以防止积分项过度增加,从而限制了系统的累积误差。这样可以避免系统过度响应或者不稳定。
float abs_limit(float value, float ABS_MAX) //积分限幅,设置最大值。
{if(value > ABS_MAX)value = ABS_MAX;if(value< -ABS_MAX)value = -ABS_MAX;return value;
}//函数里传入指针,修改时会修改指针里的值。
float PID_Position_Calc( PID *pid, float Target_val, float Actual_val) //位置式PID
{ pid->Error = Target_val - Actual_val; //与pid P系数相乘。比例误差值 当前差值=目标值-实际值pid->SumError += pid->Error; //与pid I系数相乘。稳态误差值 误差相加作为误差总和,给积分项pid->DError = pid->Error - pid->LastError; //与pid D系数相乘。 微分项-消除震荡pid->output = pid->Kp* pid->Error + \ //这里的\是续航符,表示和下面的内容是连着的。abs_limit( pid->Ki* pid->SumError, pid->Integralmax ) + \pid->Kd* pid->DError ; pid->LastError = pid->Error; //更新误差//限制输出最大值,防止出现突发意外。if(pid->output > pid->outputmax ) pid->output = pid->outputmax; if(pid->output < - pid->outputmax ) pid->output = -pid->outputmax;return pid->output ;
}//PID初始化
void PIDInit(PID *pid, float Kp , float Ki , float Kd , float Limit_value)
{ pid->Kp= Kp;pid->Ki= Ki;pid->Kd= Kd;pid->LastError = pid->Error =pid->SumError= pid->output = 0; pid->Integralmax = pp->outputmax = Limit_value;
}
2. 串级PID
利用位置式pid的方法将位置环和速度环组合在一起使用。
简易代码
将目标位置和实际位置传入PID中,计算出期望转速。
#include "stdio.h"PID postion_pid;
PID speed_pid;int main(void) {// 初始化系统时钟SystemClock_Config();// 初始化PID控制器PID_Init(&postion_pid, 1.0f, 0.1f, 0.01f); // PID参数根据实际情况调整PID_Init(&speed_pid, 1.0f, 0.1f, 0.01f); // PID参数根据实际情况调整// 设置目标位置float target_position = 100.0f; // 假设目标位置为100while (1) {float current_position = GetPosition(); // 获取当前位置float current_speed = GetSpeed (); // 获取当前转速// 更新PID控制器并计算控制量,这个输出值为当前位置向目标位置变换的一个速度或力。float control_output = PID_Position_Calc(&pid, target_position, current_position); //位置环float velocity_output = PID_Position_Calc(&speed_pid, control_output , current_speed ); //速度环Set_Pwm(velocity_output); //电机转动HAL_Delay(10); // 这里延时10毫秒,可根据实际情况调整}
}// 用于模拟读取位置的函数,这里假设返回的是传感器测量到的位置
float GetPosition() {// 在这里替换为获取位置的实际代码return 0.0f; // 这里暂时返回0,表示初始位置
}
// 用于模拟读取转速的函数。
float GetSpeed () {// 在这里替换为获取位置的实际代码return 0.0f; // 这里暂时返回0,表示初始位置
}
void Set_Pwm(int pwm) //设置速度
{TIM4->CCR1=1550-pwm; //速度环设置--
}