模糊控制PID详解

前言

关于模糊PID网上及相关文献介绍掉了很多,但是我一直存在一个疑问,也是很多博客和文献中没有提到的一个细节,就是如何根据error与Δerror的隶属度求得kp、ki、kd的总隶属度。
这里我将整体描述以下一种模糊PID的算法与伪代码以及如何根据error与Δerror的隶属度求得kp、ki、kd的总隶属度。
采用重心法求总隶属度。

模糊控制框图

在这里插入图片描述
模糊控制算法环节处于整个控制器的核心地位,其在对PI参数进行修正的过程中起到承上启下的作用,模糊控制算法的设计过程主要可分为规则库建立和隶属函数选取两部分。

模糊控制器设计步骤

个模糊控制器的完整设计过程主要可分为输入模糊化、确定隶属函数、建立模糊控制规则与解模糊化输出四个步骤,下面分别对每个步骤进行介绍与分析。

一、输入模糊化

由于模糊控制器是根据语言变量来工作的,而一般系统中的误差量均为精确量,因此在这些误差信号进入模糊控制器之前需要进行模糊化处理。系统中误差和误差变化率的实际范围称为基本沦域,属于连续域,通过模糊化处理可将精确量从其基本论域映射到离散的模糊论域。
设误差E的基本论域为(-XE,XE)(XE>0),模糊化后可得其离散模糊论域为{-n,-n+l,…,0…,n-1,n},量化因子kq可由下式确定。在完成输入模糊化环节后,接下来需要将离散论域归类于相对应的模糊子集。
kq= n/XE;

量化函数:

float Quantization(float maximum,float minimum,float x)
{
	float qvalues= 6.0 *(x-minimum)/(maximum - minimum)-3;
	return qvalues;
}
将误差 error 和Δerror映射到论域中

下面展示一些 内联代码片

//输入e与de/dt隶属度计算函数
void Get_grad_membership(float error,float error_c)   
{
	if (error > e_membership_values[0] && error < e_membership_values[6])
	{
		for (int i = 0; i < num_area - 2; i++)
		{
			if (error >= e_membership_values[i] && error <= e_membership_values[i + 1])
			{
				e_gradmembership[0] = -(error - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
				e_gradmembership[1] = 1+(error - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
				e_grad_index[0] = i;
				e_grad_index[1] = i + 1;
				break;
			}
		}
	}
	else
	{
		if (error <= e_membership_values[0])
		{
			e_gradmembership[0] = 1;
			e_gradmembership[1] = 0;
			e_grad_index[0] = 0;
			e_grad_index[1] = -1;
		}
		else if (error >= e_membership_values[6])
		{
			e_gradmembership[0] = 1;
			e_gradmembership[1] = 0;
			e_grad_index[0] = 6;
			e_grad_index[1] = -1;
		}
	}
 
	if (error_c > ec_membership_values[0] && error_c < ec_membership_values[6])
	{
		for (int i = 0; i < num_area - 2; i++)
		{
			if (error_c >= ec_membership_values[i] && error_c <= ec_membership_values[i + 1])
			{
				ec_gradmembership[0] = -(error_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
				ec_gradmembership[1] = 1 + (error_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
				ec_grad_index[0] = i;
				ec_grad_index[1] = i + 1;
				break;
			}
		}
	}
	else
	{
		if (error_c <= ec_membership_values[0])
		{
			ec_gradmembership[0] = 1;
			ec_gradmembership[1] = 0;
			ec_grad_index[0] = 0;
			ec_grad_index[1] = -1;
		}
		else if (error_c >= ec_membership_values[6])
		{
			ec_gradmembership[0] = 1;
			ec_gradmembership[1] = 0;
			ec_grad_index[0] = 6;
			ec_grad_index[1] = -1;
		}
	}
 
}
二、确定隶属函数

隶属函数按分辨率可划分为宽型隶属函数和窄型隶属函数,宽型隶属函数分辨率较低,控制性能较缓和;窄型隶属函数分辨率较高,控制灵敏度也相应较高。在选取隶属函数时,需要从灵敏度、鲁棒性、运算能力以及指标需求等多方面进行综合考量;这里选取的隶属函数为三角形隶属函数。
在这里插入图片描述

三、建立模糊控制规则

在这里插入图片描述
在这里插入图片描述

四、解模糊化输出

解模糊化也称为反模糊化,经过模糊控制规则推理后的输出值是一个模糊值,但作用于被控对象上的控制量需要是一个精确值,解模糊化过程就是将模糊推理的结果转换成为精确值的过程,该精确值不仅需要能最大程度上地代表转换前的模糊值,而且需要有较好的连续性,这样才可以在整个论域范围内都保持较高的分辨率。这里采用重心法解模糊度输出。
如下图所示:
在这里插入图片描述
下面展示一些 内联代码片

void GetSumGrad()
{
	int  Kp_rule_list[7][7] = { {PB,PB,PM,PM,PS,ZO,ZO},        //kp规则表
			       {PB,PB,PM,PS,PS,ZO,NS},
			       {PM,PM,PM,PS,ZO,NS,NS},
			       {PM,PM,PS,ZO,NS,NM,NM},
			       {PS,PS,ZO,NS,NS,NM,NM},
			       {PS,ZO,NS,NM,NM,NM,NB},
			       {ZO,ZO,NM,NM,NM,NB,NB} };

	int  Ki_rule_list[7][7] = { {NB,NB,NM,NM,NS,ZO,ZO},     //ki规则表
			      {NB,NB,NM,NS,NS,ZO,ZO},
			      {NB,NM,NS,NS,ZO,PS,PS},
			      {NM,NM,NS,ZO,PS,PM,PM},
			      {NM,NS,ZO,PS,PS,PM,PB},
			      {ZO,ZO,PS,PS,PM,PB,PB},
			      {ZO,ZO,PS,PM,PM,PB,PB} };

    // 初始化 Kp、Ki、Kd 总的隶属度值为 0
	for (int i = 0; i <= num_area - 1; i++)
	{
		KpgradSums[i] = 0;
		KigradSums[i] = 0;
        		KdgradSums[i] = 0;
	}

    	for (int i = 0; i < 2; i++)
   	 {
        		if (e_grad_index[i] == -1)
        		{
            			continue;
       		}
        		for (int j = 0; j < 2; j++)
       		{
            			if (ec_grad_index[j] != -1)
            			{
                			int indexKp = Kp_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
               				int indexKi = Ki_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;

                			KpgradSums[indexKp]= KpgradSums[indexKp] + (e_gradmembership[i] * ec_gradmembership[j]);
               				KigradSums[indexKi] = KigradSums[indexKi] + (e_gradmembership[i] * ec_gradmembership[j]);
 
            			}
            			else
            			{
                			continue;
            			}
        		}
 	 }
}

// 计算输出增量kp,kd,ki对应论域值
void GetOUT()
{
	for (int i = 0; i < num_area - 1; i++)
	{
		qdetail_kp += kp_menbership_values[i] * KpgradSums[i];
		qdetail_ki += ki_menbership_values[i] * KigradSums[i];
	}
}
 
//反区间映射函数
float Inverse_quantization(float maximum, float minimum, float qvalues)
{
	float x = (maximum - minimum) *(qvalues + 3)/6 + minimum;
	return x;
}
五、模糊PID控制实现函数

下面展示一些 内联代码片

//模糊PID控制实现函数
float FuzzyPIDcontroller(float e_max, float e_min, float ec_max, float ec_min, float kp_max, float kp_min, float error, float error_c,float ki_max,float ki_min,float kd_max,float kd_min,float error_pre,float error_ppre)
{
	qerror = Quantization(e_max, e_min, error);	   //将 误差 error 映射到论域中
	qerror_c = Quantization(ec_max, ec_min, error_c);	  //将误差变化 error_c 映射到论域中
	Get_grad_membership(qerror, qerror_c);	//计算误差 error 和误差变化 error_c 的隶属度
	GetSumGrad();	//计算输出增量 △kp、△ki、△kd 的总隶属度
	GetOUT();		// 计算输出增量 △kp、△ki、△kd 对应论域值
	detail_kp = Inverse_quantization(kp_max, kp_min, qdetail_kp);    //去模糊化得到增量 △kp
	detail_ki = Inverse_quantization(ki_max, ki_min, qdetail_ki);    //去模糊化得到增量 △ki
	detail_kd = Inverse_quantization(kd_max, kd_min, qdetail_kd);    //去模糊化得到增量 △kd
	qdetail_kd = 0;
	qdetail_ki = 0;
	qdetail_kp = 0;

	kp = kp + detail_kp;    //得到最终的 kp 值
	ki = ki + detail_ki;    //得到最终的 ki 值
	kd = kd + detail_kd;    //得到最终的 kd 值
	if (kp < 0)
		kp = 0;
	if (ki < 0)
		ki = 0;
	if (kd < 0)
		kd = 0;
	detail_kp = 0;
   	detail_ki = 0;
    	detail_kd = 0;
    	float output = kp*(error - error_pre) + ki * error + kd * (error - 2 * error_pre + error_ppre);    //计算最终的输出
	return output;
}
  • 20
    点赞
  • 170
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Not Dr.Wang422

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

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

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

打赏作者

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

抵扣说明:

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

余额充值