继上一篇介绍如何使用VOFA+之后,本文介绍使用VOFA+工具用于调试PID算法(重点是实现使用此工具用于调试,而非介绍算法,我也不确定以下算法的正确性,大家参考即可)。
一、首先验证发的数据正确性。
当我配置发送“0”和“0”数据时,上位机收到数据如图。00 00 80 7F为帧尾。
当我配置发送“1”和“2”数据时,上位机收到数据如图。00 00 80 7F为帧尾。
如果收到数据不是以上情况,则说明串口发送数据的格式不正确。
定时器中断中调用,控制算法和发送函数均在一个函数中实现。
//定时器中,1Ms调用一次,固定时间调用
void AppAlgDeal(void)
{
static int32_t TimeCnt;
static float tempFloat[2];
static uint8_t tempData[12] = {0,0,0,0,0,0,0,0,0,0,0x80,0x7F};
int32_t speed;
TimeCnt++;
if(TimeCnt >= 10)
{
TimeCnt = 0;
//1. 速度计算(固定时间中,所走的路程,这里简化计算,按照固定实际所走的脉冲)
speed = SpeedCalc.CntCurt - SpeedCalc.CntRecd;
SpeedCalc.CntRecd = SpeedCalc.CntCurt;
//计算速度平均值(因速度计算波动大,所以采用求和进行滤波,但这样带来的结果是响应变慢)
SpeedCalc.SpeedSum = SpeedCalc.SpeedSum + speed - SpeedCalc.CntRecord[SpeedCalc.Cnt];
SpeedCalc.CntRecord[SpeedCalc.Cnt] = speed;
SpeedCalc.Cnt++;
SpeedCalc.Cnt&=3;
//2. PID算法(位置式PID)
pwmVal += PID_Contrl(&PID_Para, SpeedCalc.SpeedSum);
//3. PWM限幅,最大为500,最小为0
if(pwmVal > 500)
pwmVal = 500;
else if(pwmVal < 0)
pwmVal = 0;
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, pwmVal); //送出到PWM输出
//4. 串口发送
tempFloat[0] = PID_Para.TitelVal;
tempFloat[1] = (float)SpeedCalc.SpeedSum;
memcpy(tempData, (uint8_t *)&tempFloat, sizeof(tempFloat));
HAL_UART_Transmit_IT(&huart6, (uint8_t *)tempData, 12);
}
}
二、PID介绍。PID在离散领域实现时分为位置式和增量式。
以下介绍中使用位置式。(不过我也不确定我使用的对不对)
位置式PID算法。
/*************************************************
*函数名称:float PID_Contrl(sPID_Reg* sPt,float RealVal)
*功 能:PID控制
*参 数:sPt PID参数,RealVal 当前实际值
*返 回 值:void
*************************************************/
float PID_Contrl(sPID_Reg* sPt,float RealVal)
{
float error,add;
error = sPt->TitelVal - RealVal; //当前误差 设定的目标值和实际值的偏差
add = sPt->Kp * error //增量计算
- sPt->Ki * sPt->LastError
+ sPt->Kd * sPt->PrevError;
/*存储误差 用于下次计算*/
sPt->PrevError = sPt->LastError;
sPt->LastError = error;
return add; //返回增量值
}
参数初始化
typedef struct{
float TitelVal; //目标值
float SumError; //累计误差
float Kp; //比例项
float Ki; //积分项
float Kd; //微分项
float LastError; //上次偏差
float PrevError; //上上次偏差值
}sPID_Reg;
sPID_Reg PID_Para; //定义PID参数
void PID_Arg_Init(sPID_Reg* sPt)
{
memset(sPt, 0, sizeof(sPID_Reg));
sPt->Kp = 0.5;
sPt->Ki = 0.1;
sPt->Kd = 0.01;
sPt->TitelVal = 100;
}
三、配置发送2个数据。分别为目标速度和实际速度。
以下图片中,红色为目标速度,绿色为实际速度。右边框中分别为Kp,Ki,Kd数据。
Kp,Ki,Kd分别为1.5,0,0。
Kp,Ki,Kd分别为1,0,0。
Kp,Ki,Kd 分别为0.5,0,0。
Kp,Ki,Kd 分别为1,0.2,0。
Kp,Ki,Kd 分别为1,0.4,0。
Kp,Ki,Kd 分别为0.5,0.1,0.01。
以上工程我放在此链接下,供下载参考。(Stm32CubeMx工程也在附件中)
https://download.csdn.net/download/weixin_42316458/79692273
我使用的是STM32F401RCT6芯片。
以上完结。
本人新建了个QQ群,如想进一步沟通可添加:947187213。
版权声明:本文为CSDN博主「一个做底层的码农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42316458/article/details/121502912
暂无评论