PID评价函数 C语言实现

PID评价系统 C语言实现


前言

自大一入学以来,做电控接触的最多的就是pid了,但目前我们判断一个pid的好坏,主要还是通过肉眼来看曲线并借助经验来判断PID调的好坏,本文通过C语言写了一个函数来测量超调率,pid测量值到达目标值90%的响应时间以及稳态误差,便于我们pid调试时能够更加精确的判断pid的好坏,而不仅仅通过曲线粗略的观察


一、超调率是什么?

下面用一张图来解释,假设初始值是0,目标值是100,横坐标为t(时间),纵坐标为测量值和目标值的基本单位,通过matlab仿真得到下图:在这里插入图片描述
超调率用公式表示如下:
在这里插入图片描述
用文字表示则是:
在这里插入图片描述

二、响应时间是什么?

仍然是那张图:

在这里插入图片描述
放大后可以更清楚的看到响应时间
在这里插入图片描述

三、稳态误差是什么?

我们将那张图放大,可以看到测量值无限接近与目标值,但并未完全达到目标值,且这个误差并不会随着时间的推移而消失,这就是我们所说的稳态误差。
在这里插入图片描述

四、如何通过代码来实现对这几个量的测量

首先是结构体的建立:

typedef struct pid_eva
{
	float set_core;
	float last_set;
	int t_xiang;
	float angle;
	float evaluate_time;
	int core;
	int core1;
	float max_chao;
	float fps;
	float fps_core;
	float max_set;
	float max_get;
	float steady_error;
	float steady_core;
	float get;
	float last_get;
	float set;
	float set_time;
	float set_get_d;
} pid_eva;

其次是代码编写部分:

void pid_evaluate(pid_eva*pid_eva,float angle,float set)//在.h文件中定义外部结构体后,输入angle为位置或速度,set为目标值即可使用
{
	pid_eva->get=angle;//赋值
	pid_eva->set=set;
	//响应速率计算单位ms
	if(pid_eva->last_set!=pid_eva->set&&pid_eva->core1==0)
	{
	pid_eva->core1=1;//检测到目标值变化,开始记录响应时间
	pid_eva->max_get=pid_eva->get;
	pid_eva->max_set=0;
	pid_eva->t_xiang=0;
		if(pid_eva->last_set<pid_eva->set)//分两种情况对超调率进行讨论计算
			pid_eva->core=1;
		if(pid_eva->last_set>pid_eva->set)
			pid_eva->core=0;
			pid_eva->set_get_d=fabs(pid_eva->set-pid_eva->last_set);
	}
	if(pid_eva->core1==1)
	{
			if(pid_eva->t_xiang<2000)//记录之后2s秒的数据
	{		
			if(pid_eva->core==1)
			{
				if(pid_eva->get>pid_eva->max_get)//求出最大获取量
					pid_eva->max_get=pid_eva->get;
			}
			if(pid_eva->core==0)
			{
			if(pid_eva->get<pid_eva->max_get)//求出最小获取量
					pid_eva->max_get=fabs(pid_eva->get);
			}
			if(fabs(pid_eva->set)>fabs(pid_eva->max_set))//求出最大目标量
					{
						pid_eva->max_set=fabs(pid_eva->set);	
						pid_eva->set_time=pid_eva->t_xiang;//目标值到达最大值时的调节时间
					}	
			if(fabs(pid_eva->get)>fabs(0.85*pid_eva->set)&&fabs(pid_eva->get)<fabs(0.9*pid_eva->set))//阶跃至90%的响应时间
					pid_eva->evaluate_time=pid_eva->t_xiang;//计算响应时间/单位ms	
			if(fabs(pid_eva->set-pid_eva->get)<100)//稳态误差计算设置
					pid_eva->steady_error=fabs(pid_eva->set-pid_eva->get);	//稳态误差
			else
					pid_eva->steady_error=65535;//未达到稳态误差条件,稳态误差无穷大
					pid_eva->t_xiang+=1;//响应时间为1ms 		
		}
		else
			{	
			if(pid_eva->max_set!=0)//计算超调率时排除0的情况
					pid_eva->max_chao=(fabs(pid_eva->max_get)-fabs(pid_eva->max_set))/fabs(pid_eva->max_set);//循环结束后计算最大超调率
			else
					pid_eva->max_chao=(fabs(pid_eva->max_get)-0)/pid_eva->set_get_d;	
			pid_eva->core1=0;
			pid_eva->last_set=pid_eva->set;
//			pid_eva->max_get=0;
//			pid_eva->max_set=0;
		}	
}
}

五、PID评价函数的使用方法

首先在外部定义一个结构体
像这样:

extern pid_eva pid_eva1;

其次是将这个函数放在单片机1ms循环一次的任务中,这里通过cubemx创建了一个freertos系统,直接放在任务中,osDelay(1)即可
像这样,其中第一个数据为结构体,第二个数据为我们读出的测量值,一般是位置或者速度,第三个数据是我们设置的目标值:

void eva(void const * argument)
{
  /* USER CODE BEGIN eva */
  /* Infinite loop */
  for(;;)
  {
		pid_evaluate(&pid_eva1,motor_left_position,g_nSpeedTarget);
    osDelay(1);
  }
  /* USER CODE END eva */
}

最后通过硬件仿真查看这几个变量的值即可:
其中超调率为:
在这里插入图片描述
响应时间(单位ms)为:
在这里插入图片描述
稳态误差为:
在这里插入图片描述

总结

提示:这里对文章进行总结:
个人还只是个萌新,对自控原理还不是非常了解,所以有错的话希望大家能够批评指出。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值