刚开始在网上搜了下相关代码,发现全都是这个版本的(3条消息) c# 实现模糊PID控制算法_chinaherolts2008的博客-CSDN博客_c# pid算法

原作者简述中提到“这段算法在实际值低于目标值c#教程是工作正常,超过后会有问题,不知道如何调教”,我以为稳了,1天时间摸着鱼也就完成了,没想到远远没这么简单,以下是详情。


在熟悉代码的过程中发现了有下列3个问题:
1. 将“de = e - e_pre_1;”更正为“de = e - e_pre_1/Ke;   //此处的e为外部反馈的e,而e_pre_1为转化论域后的值”;
2. 在“e_pre_2 = e_pre_1;”前增加“u += delta_u;”,并提前声明全局变量u,此处应用的是增量式PID,详情可以百度搜索“离散化PID公式”或“位置式PID与增量式PID”;
3. e和de模糊化过程中,富余空间直接填0的代码不严谨,有u_e[0]!=0或u_de[0]!=0的情况存在,需要添加两个变量更改,但影响也不是特别大。

再运行时发现e为负数时还是震荡特别厉害,然后我怀疑了三个点:

1.模糊规则有问题;2.基本论域上限有问题;3.在realize方法中不该限定Ki、Kp、Kd的值为非负数。


对于1和2问题我开始去知网查论文,结果发现没有人讲过模糊规则和基本论域如何选择,他们好像都直接得到了,而且对比大家的模糊规则,基本都是吻合的;对于3,我尝试了放开限定或更改限定范围,好像都没有结果。

附上我当前的代码,再调不出来我就没时间了啊啊啊

算法类 .cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;namespace Test_FuzzPID
{internal class FuzzyPID{public const int N = 7;double target; //系统的控制目标double actual; //采样获得的实际值double e; //误差double e_pre_1; //上一次的误差double e_pre_2; //上上次的误差double de;      //误差的变化率double emax;    //误差基本论域上限double demax;   //误差变化率基本论域的上限double delta_Kp_max;   //delta_kp输出的上限double delta_Ki_max;   //delta_ki输出上限double delta_Kd_max;   //delta_kd输出上限double Ke;      //Ke=n/emax,   量化论域为[-3,-2,-1,0,1,2,3]double Kde;     //Kde=n/demax, 量化论域为[-3,-2,-1,0,1,2,3]double Ku_p;    //Ku_p=Kpmax/n,量化论域为[-3,-2,-1,0,1,2,3]double Ku_i;    //Ku_i=Kimax/n,量化论域为[-3,-2,-1,0,1,2,3]double Ku_d;    //Ku_d=Kdmax/n,量化论域为[-3,-2,-1,0,1,2,3]int[,] Kp_rule_matrix = new int[N, N];//Kp模糊规则矩阵int[,] Ki_rule_matrix = new int[N, N];//Ki模糊规则矩阵int[,] Kd_rule_matrix = new int[N, N];//Kd模糊规则矩阵string mf_t_e;       //e的隶属度函数类型string mf_t_de;      //de的隶属度函数类型string mf_t_Kp;      //kp的隶属度函数类型string mf_t_Ki;      //ki的隶属度函数类型string mf_t_Kd;      //kd的隶属度函数类型double[] e_mf_paras; //误差的隶属度函数的参数double[] de_mf_paras;//误差的偏差隶属度函数的参数double[] Kp_mf_paras; //kp的隶属度函数的参数double[] Ki_mf_paras; //ki的隶属度函数的参数double[] Kd_mf_paras; //kd的隶属度函数的参数double Kp;double Ki;double Kd;double A;double B;double C;double u = 0;public FuzzyPID(double e_max, double de_max, double kp_max, double ki_max, double kd_max, double Kp0, double Ki0, double Kd0){emax = e_max;demax = de_max;delta_Kp_max = kp_max;delta_Ki_max = ki_max;delta_Kd_max = kd_max;e = target - actual;de = e - e_pre_1;Ke = (N / 2) / emax;Kde = (N / 2) / demax;Ku_p = delta_Kp_max / (N / 2);Ku_i = delta_Ki_max / (N / 2);Ku_d = delta_Kd_max / (N / 2);Kp = Kp0;Ki = Ki0;Kd = Kd0;A = Kp + Ki + Kd;B = -2 * Kd - Kp;C = Kd;}//三角隶属度函数double trimf(double x, double a, double b, double c){double u;if (x >= a && x <= b)u = (x - a) / (b - a);else if (x > b && x <= c)u = (c - x) / (c - b);elseu = 0;return u;}//正态隶属度函数double gaussmf(double x, double ave, double sigma){double u;if (sigma < 0){throw new Exception("In gaussmf, sigma must larger than 0");}u = Math.Exp(-Math.Pow(((x - ave) / sigma), 2));return u;}//梯形隶属度函数double trapmf(double x, double a, double b, double c, double d){double u;if (x >= a && x < b)u = (x - a) / (b - a);else if (x >= b && x < c)u = 1;else if (x >= c && x <= d)u = (d - x) / (d - c);elseu = 0;return u;}//设置模糊规则Matrixpublic void setRuleMatrix(int[,] kp_m, int[,] ki_m, int[,] kd_m){for (int i = 0; i < N; i++)for (int j = 0; j < N; j++){Kp_rule_matrix[i, j] = kp_m[i, j];Ki_rule_matrix[i, j] = ki_m[i, j];Kd_rule_matrix[i, j] = kd_m[i, j];}}//设置模糊隶属度函数的子函数void setMf_sub(string type, double[] paras, int n){int N_mf_e = 0, N_mf_de = 0, N_mf_Kp = 0, N_mf_Ki = 0, N_mf_Kd = 0;switch (n){case 0:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_e = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_e == "trimf")N_mf_e = 3;else if (mf_t_e == "gaussmf")N_mf_e = 2;else if (mf_t_e == "trapmf")N_mf_e = 4;e_mf_paras = new double[N * N_mf_e];for (int i = 0; i < N * N_mf_e; i++)e_mf_paras[i] = paras[i];break;case 1:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_de = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_de == "trimf")N_mf_de = 3;else if (mf_t_de == "gaussmf")N_mf_de = 2;else if (mf_t_de == "trapmf")N_mf_de = 4;de_mf_paras = new double[N * N_mf_de];for (int i = 0; i < N * N_mf_de; i++)de_mf_paras[i] = paras[i];break;case 2:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Kp = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Kp == "trimf")N_mf_Kp = 3;else if (mf_t_Kp == "gaussmf")N_mf_Kp = 2;else if (mf_t_Kp == "trapmf")N_mf_Kp = 4;Kp_mf_paras = new double[N * N_mf_Kp];for (int i = 0; i < N * N_mf_Kp; i++)Kp_mf_paras[i] = paras[i];break;case 3:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Ki = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Ki == "trimf")N_mf_Ki = 3;else if (mf_t_Ki == "gaussmf")N_mf_Ki = 2;else if (mf_t_Ki == "trapmf")N_mf_Ki = 4;Ki_mf_paras = new double[N * N_mf_Ki];for (int i = 0; i < N * N_mf_Ki; i++)Ki_mf_paras[i] = paras[i];break;case 4:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Kd = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Kd == "trimf")N_mf_Kd = 3;else if (mf_t_Kd == "gaussmf")N_mf_Kd = 2;else if (mf_t_Kd == "trapmf")N_mf_Kd = 4;Kd_mf_paras = new double[N * N_mf_Kd];for (int i = 0; i < N * N_mf_Kd; i++)Kd_mf_paras[i] = paras[i];break;default: break;}}//设置模糊隶属度函数的类型和参数public void setMf(string mf_type_e, double[] e_mf, string mf_type_de, double[] de_mf, string mf_type_Kp, double[] Kp_mf, string mf_type_Ki, double[] Ki_mf, string mf_type_Kd, double[] Kd_mf){setMf_sub(mf_type_e, e_mf, 0);setMf_sub(mf_type_de, de_mf, 1);setMf_sub(mf_type_Kp, Kp_mf, 2);setMf_sub(mf_type_Ki, Ki_mf, 3);setMf_sub(mf_type_Kd, Kd_mf, 4);}//实现模糊控制public double realize(double t, double a){double[]u_e  = new double[N],u_de = new double[N],u_u  = new double[N];int[] u_e_index = new int[3], u_de_index = new int[3];//假设一个输入最多激活3个模糊子集double delta_Kp, delta_Ki, delta_Kd;double delta_u;target = t;actual = a;e = target - actual;de = e - e_pre_1/Ke;   //此处的e为外部反馈的e,而e_pre_1为转化论域后的值e = Ke * e;      //将e转化成论域内的量de = Kde * de;   //将de转化成论域内的量/* 将误差e模糊化*/int j = 0;for (int i = 0; i < N; i++) {if (mf_t_e == "trimf")u_e[i] = trimf(e, e_mf_paras[i * 3], e_mf_paras[i * 3 + 1], e_mf_paras[i * 3 + 2]);//e模糊化,计算它的隶属度else if (mf_t_e == "gaussmf")u_e[i] = gaussmf(e, e_mf_paras[i * 2], e_mf_paras[i * 2 + 1]);//e模糊化,计算它的隶属度else if (mf_t_e == "trapmf")u_e[i] = trapmf(e, e_mf_paras[i * 4], e_mf_paras[i * 4 + 1], e_mf_paras[i * 4 + 2], e_mf_paras[i * 4 + 3]);//e模糊化,计算它的隶属度if (u_e[i] != 0)u_e_index[j++] = i;                //存储被激活的模糊子集的索引,可以减小计算量}for (; j < 3; j++) u_e_index[j] = 0;             //富余的空间填0,当e在(-3,-2)范围内时,256行的i=0,故此处有问题///*将误差变化率de模糊化*/j = 0;for (int i = 0; i < N; i++){if (mf_t_de == "trimf")u_de[i] = trimf(de, de_mf_paras[i * 3], de_mf_paras[i * 3 + 1], de_mf_paras[i * 3 + 2]);//de模糊化,计算它的隶属度else if (mf_t_de == "gaussmf")u_de[i] = gaussmf(de, de_mf_paras[i * 2], de_mf_paras[i * 2 + 1]);//de模糊化,计算它的隶属度else if (mf_t_de == "trapmf")u_de[i] = trapmf(de, de_mf_paras[i * 4], de_mf_paras[i * 4 + 1], de_mf_paras[i * 4 + 2], de_mf_paras[i * 4 + 3]);//de模糊化,计算它的隶属度if (u_de[i] != 0)u_de_index[j++] = i;            //存储被激活的模糊子集的下标,可以减小以下三个PID参数的计算量}for (; j < 3; j++) u_de_index[j] = 0;          //富余的空间填0double den = 0, num = 0;/*计算delta_Kp和Kp*/for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Kp_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}if (den == 0) MessageBox.Show("误差过大超限","Warnning!");delta_Kp = num / den;delta_Kp = Ku_p * delta_Kp;if (delta_Kp >= delta_Kp_max) delta_Kp = delta_Kp_max;else if (delta_Kp <= -delta_Kp_max) delta_Kp = -delta_Kp_max;//if(itera>=2)Kp += delta_Kp;if (Kp < 0) Kp = 0;//if (Kp > 0) Kp = 0;Console.WriteLine("Kp="+Kp);/*计算delta_Ki和Ki*/den = 0; num = 0;for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Ki_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}delta_Ki = num / den;delta_Ki = Ku_i * delta_Ki;if (delta_Ki >= delta_Ki_max) delta_Ki = delta_Ki_max;else if (delta_Ki <= -delta_Ki_max) delta_Ki = -delta_Ki_max;//if (itera >= 2)Ki += delta_Ki;if (Ki < 0) Ki = 0;//if (Ki > 0) Ki = 0;Console.WriteLine("Ki=" + Ki);/*计算delta_Kd和Kd*/den = 0; num = 0;for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Kd_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}delta_Kd = num / den;delta_Kd = Ku_d * delta_Kd;if (delta_Kd >= delta_Kd_max) delta_Kd = delta_Kd_max;else if (delta_Kd <= -delta_Kd_max) delta_Kd = -delta_Kd_max;//if (itera >= 2)Kd += delta_Kd;if (Kd < 0) Kd = 0;//if (Kd > 0) Kd = 0;Console.WriteLine("Kd=" + Kd);//根据以上所得Kp,Ki,Kd计算纠偏值A = Kp + Ki + Kd;B = -2 * Kd - Kp;C = Kd;delta_u = A * e + B * e_pre_1 + C * e_pre_2;delta_u = delta_u / Ke;if (delta_u >= 0.95 * target) delta_u = 0.95 * target;else if (delta_u <= -0.95 * target) delta_u = -0.95 * target;Console.WriteLine("delta_u=" + delta_u);u += delta_u;e_pre_2 = e_pre_1;e_pre_1 = e;return u;}}
}

以及主函数

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;namespace Test_FuzzPID
{internal class FuzzyPID{public const int N = 7;double target; //系统的控制目标double actual; //采样获得的实际值double e; //误差double e_pre_1; //上一次的误差double e_pre_2; //上上次的误差double de;      //误差的变化率double emax;    //误差基本论域上限double demax;   //误差变化率基本论域的上限double delta_Kp_max;   //delta_kp输出的上限double delta_Ki_max;   //delta_ki输出上限double delta_Kd_max;   //delta_kd输出上限double Ke;      //Ke=n/emax,   量化论域为[-3,-2,-1,0,1,2,3]double Kde;     //Kde=n/demax, 量化论域为[-3,-2,-1,0,1,2,3]double Ku_p;    //Ku_p=Kpmax/n,量化论域为[-3,-2,-1,0,1,2,3]double Ku_i;    //Ku_i=Kimax/n,量化论域为[-3,-2,-1,0,1,2,3]double Ku_d;    //Ku_d=Kdmax/n,量化论域为[-3,-2,-1,0,1,2,3]int[,] Kp_rule_matrix = new int[N, N];//Kp模糊规则矩阵int[,] Ki_rule_matrix = new int[N, N];//Ki模糊规则矩阵int[,] Kd_rule_matrix = new int[N, N];//Kd模糊规则矩阵string mf_t_e;       //e的隶属度函数类型string mf_t_de;      //de的隶属度函数类型string mf_t_Kp;      //kp的隶属度函数类型string mf_t_Ki;      //ki的隶属度函数类型string mf_t_Kd;      //kd的隶属度函数类型double[] e_mf_paras; //误差的隶属度函数的参数double[] de_mf_paras;//误差的偏差隶属度函数的参数double[] Kp_mf_paras; //kp的隶属度函数的参数double[] Ki_mf_paras; //ki的隶属度函数的参数double[] Kd_mf_paras; //kd的隶属度函数的参数double Kp;double Ki;double Kd;double A;double B;double C;double u = 0;public FuzzyPID(double e_max, double de_max, double kp_max, double ki_max, double kd_max, double Kp0, double Ki0, double Kd0){emax = e_max;demax = de_max;delta_Kp_max = kp_max;delta_Ki_max = ki_max;delta_Kd_max = kd_max;e = target - actual;de = e - e_pre_1;Ke = (N / 2) / emax;Kde = (N / 2) / demax;Ku_p = delta_Kp_max / (N / 2);Ku_i = delta_Ki_max / (N / 2);Ku_d = delta_Kd_max / (N / 2);Kp = Kp0;Ki = Ki0;Kd = Kd0;A = Kp + Ki + Kd;B = -2 * Kd - Kp;C = Kd;}//三角隶属度函数double trimf(double x, double a, double b, double c){double u;if (x >= a && x <= b)u = (x - a) / (b - a);else if (x > b && x <= c)u = (c - x) / (c - b);elseu = 0;return u;}//正态隶属度函数double gaussmf(double x, double ave, double sigma){double u;if (sigma < 0){throw new Exception("In gaussmf, sigma must larger than 0");}u = Math.Exp(-Math.Pow(((x - ave) / sigma), 2));return u;}//梯形隶属度函数double trapmf(double x, double a, double b, double c, double d){double u;if (x >= a && x < b)u = (x - a) / (b - a);else if (x >= b && x < c)u = 1;else if (x >= c && x <= d)u = (d - x) / (d - c);elseu = 0;return u;}//设置模糊规则Matrixpublic void setRuleMatrix(int[,] kp_m, int[,] ki_m, int[,] kd_m){for (int i = 0; i < N; i++)for (int j = 0; j < N; j++){Kp_rule_matrix[i, j] = kp_m[i, j];Ki_rule_matrix[i, j] = ki_m[i, j];Kd_rule_matrix[i, j] = kd_m[i, j];}}//设置模糊隶属度函数的子函数void setMf_sub(string type, double[] paras, int n){int N_mf_e = 0, N_mf_de = 0, N_mf_Kp = 0, N_mf_Ki = 0, N_mf_Kd = 0;switch (n){case 0:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_e = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_e == "trimf")N_mf_e = 3;else if (mf_t_e == "gaussmf")N_mf_e = 2;else if (mf_t_e == "trapmf")N_mf_e = 4;e_mf_paras = new double[N * N_mf_e];for (int i = 0; i < N * N_mf_e; i++)e_mf_paras[i] = paras[i];break;case 1:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_de = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_de == "trimf")N_mf_de = 3;else if (mf_t_de == "gaussmf")N_mf_de = 2;else if (mf_t_de == "trapmf")N_mf_de = 4;de_mf_paras = new double[N * N_mf_de];for (int i = 0; i < N * N_mf_de; i++)de_mf_paras[i] = paras[i];break;case 2:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Kp = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Kp == "trimf")N_mf_Kp = 3;else if (mf_t_Kp == "gaussmf")N_mf_Kp = 2;else if (mf_t_Kp == "trapmf")N_mf_Kp = 4;Kp_mf_paras = new double[N * N_mf_Kp];for (int i = 0; i < N * N_mf_Kp; i++)Kp_mf_paras[i] = paras[i];break;case 3:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Ki = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Ki == "trimf")N_mf_Ki = 3;else if (mf_t_Ki == "gaussmf")N_mf_Ki = 2;else if (mf_t_Ki == "trapmf")N_mf_Ki = 4;Ki_mf_paras = new double[N * N_mf_Ki];for (int i = 0; i < N * N_mf_Ki; i++)Ki_mf_paras[i] = paras[i];break;case 4:if (type == "trimf" || type == "gaussmf" || type == "trapmf")mf_t_Kd = type;elsethrow new Exception("Type of membership function must be \"trimf\" or \"gaussmf\" or \"trapmf\"");if (mf_t_Kd == "trimf")N_mf_Kd = 3;else if (mf_t_Kd == "gaussmf")N_mf_Kd = 2;else if (mf_t_Kd == "trapmf")N_mf_Kd = 4;Kd_mf_paras = new double[N * N_mf_Kd];for (int i = 0; i < N * N_mf_Kd; i++)Kd_mf_paras[i] = paras[i];break;default: break;}}//设置模糊隶属度函数的类型和参数public void setMf(string mf_type_e, double[] e_mf, string mf_type_de, double[] de_mf, string mf_type_Kp, double[] Kp_mf, string mf_type_Ki, double[] Ki_mf, string mf_type_Kd, double[] Kd_mf){setMf_sub(mf_type_e, e_mf, 0);setMf_sub(mf_type_de, de_mf, 1);setMf_sub(mf_type_Kp, Kp_mf, 2);setMf_sub(mf_type_Ki, Ki_mf, 3);setMf_sub(mf_type_Kd, Kd_mf, 4);}//实现模糊控制public double realize(double t, double a){double[]u_e  = new double[N],u_de = new double[N],u_u  = new double[N];int[] u_e_index = new int[3], u_de_index = new int[3];//假设一个输入最多激活3个模糊子集double delta_Kp, delta_Ki, delta_Kd;double delta_u;target = t;actual = a;e = target - actual;de = e - e_pre_1/Ke;   //此处的e为外部反馈的e,而e_pre_1为转化论域后的值e = Ke * e;      //将e转化成论域内的量de = Kde * de;   //将de转化成论域内的量/* 将误差e模糊化*/int j = 0;for (int i = 0; i < N; i++) {if (mf_t_e == "trimf")u_e[i] = trimf(e, e_mf_paras[i * 3], e_mf_paras[i * 3 + 1], e_mf_paras[i * 3 + 2]);//e模糊化,计算它的隶属度else if (mf_t_e == "gaussmf")u_e[i] = gaussmf(e, e_mf_paras[i * 2], e_mf_paras[i * 2 + 1]);//e模糊化,计算它的隶属度else if (mf_t_e == "trapmf")u_e[i] = trapmf(e, e_mf_paras[i * 4], e_mf_paras[i * 4 + 1], e_mf_paras[i * 4 + 2], e_mf_paras[i * 4 + 3]);//e模糊化,计算它的隶属度if (u_e[i] != 0)u_e_index[j++] = i;                //存储被激活的模糊子集的索引,可以减小计算量}for (; j < 3; j++) u_e_index[j] = 0;             //富余的空间填0,当e在(-3,-2)范围内时,256行的i=0,故此处有问题///*将误差变化率de模糊化*/j = 0;for (int i = 0; i < N; i++){if (mf_t_de == "trimf")u_de[i] = trimf(de, de_mf_paras[i * 3], de_mf_paras[i * 3 + 1], de_mf_paras[i * 3 + 2]);//de模糊化,计算它的隶属度else if (mf_t_de == "gaussmf")u_de[i] = gaussmf(de, de_mf_paras[i * 2], de_mf_paras[i * 2 + 1]);//de模糊化,计算它的隶属度else if (mf_t_de == "trapmf")u_de[i] = trapmf(de, de_mf_paras[i * 4], de_mf_paras[i * 4 + 1], de_mf_paras[i * 4 + 2], de_mf_paras[i * 4 + 3]);//de模糊化,计算它的隶属度if (u_de[i] != 0)u_de_index[j++] = i;            //存储被激活的模糊子集的下标,可以减小以下三个PID参数的计算量}for (; j < 3; j++) u_de_index[j] = 0;          //富余的空间填0double den = 0, num = 0;/*计算delta_Kp和Kp*/for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Kp_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}if (den == 0) MessageBox.Show("误差过大超限","Warnning!");delta_Kp = num / den;delta_Kp = Ku_p * delta_Kp;if (delta_Kp >= delta_Kp_max) delta_Kp = delta_Kp_max;else if (delta_Kp <= -delta_Kp_max) delta_Kp = -delta_Kp_max;//if(itera>=2)Kp += delta_Kp;if (Kp < 0) Kp = 0;//if (Kp > 0) Kp = 0;Console.WriteLine("Kp="+Kp);/*计算delta_Ki和Ki*/den = 0; num = 0;for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Ki_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}delta_Ki = num / den;delta_Ki = Ku_i * delta_Ki;if (delta_Ki >= delta_Ki_max) delta_Ki = delta_Ki_max;else if (delta_Ki <= -delta_Ki_max) delta_Ki = -delta_Ki_max;//if (itera >= 2)Ki += delta_Ki;if (Ki < 0) Ki = 0;//if (Ki > 0) Ki = 0;Console.WriteLine("Ki=" + Ki);/*计算delta_Kd和Kd*/den = 0; num = 0;for (int m = 0; m < 3; m++)for (int n = 0; n < 3; n++){num += u_e[u_e_index[m]] * u_de[u_de_index[n]] * Kd_rule_matrix[u_e_index[m], u_de_index[n]];den += u_e[u_e_index[m]] * u_de[u_de_index[n]];}delta_Kd = num / den;delta_Kd = Ku_d * delta_Kd;if (delta_Kd >= delta_Kd_max) delta_Kd = delta_Kd_max;else if (delta_Kd <= -delta_Kd_max) delta_Kd = -delta_Kd_max;//if (itera >= 2)Kd += delta_Kd;if (Kd < 0) Kd = 0;//if (Kd > 0) Kd = 0;Console.WriteLine("Kd=" + Kd);//根据以上所得Kp,Ki,Kd计算纠偏值A = Kp + Ki + Kd;B = -2 * Kd - Kp;C = Kd;delta_u = A * e + B * e_pre_1 + C * e_pre_2;delta_u = delta_u / Ke;if (delta_u >= 0.95 * target) delta_u = 0.95 * target;else if (delta_u <= -0.95 * target) delta_u = -0.95 * target;Console.WriteLine("delta_u=" + delta_u);u += delta_u;e_pre_2 = e_pre_1;e_pre_1 = e;return u;}

C#实现模糊PID算法的代码相关推荐

  1. 模糊pid算法实现一般步骤

    模糊PID控制算法(Fuzzy PID Control Algorithm)是根据模糊控制理论和PID控制理论相结合的方法,可以解决传统PID控制在控制非线性.大惯性.复杂系统时效果不佳的问题. 模糊 ...

  2. 模糊PID算法及其MATLAB仿真(1)

    目录 1.PID控制基础 2.模糊控制 3.模糊PID简介 4.模糊自整定PID的理论内容(重点内容) 4.1 基本原理 4.2 模糊子集及其论域的确定 4.3 模糊规则的建立 4.4 模糊推理 4. ...

  3. 基于自适应算法和增量式PID算法的模拟直升飞机控制系统

    基于自适应算法和增量式PID算法的模拟直升飞机控制系统 文章目录 基于自适应算法和增量式PID算法的模拟直升飞机控制系统 控制系统硬件 单片机系统 传感器系统介绍 直升机模拟系统介绍 系统模块介绍 A ...

  4. 2021-03-31 Matlab simulink 模糊PID在无刷直流电机中的应用

    Matlab simulink 模糊PID在无刷直流电机中的应用 无刷直流电机的数学模型. 1.无刷直流电机数学模型 然后给出无刷直流电机的动态数学模型 看到上述这张图,不知聪明的你有没有发觉,图中采 ...

  5. 模糊pid控制的温度系统matlab源代码_模糊PID控制系统(二)对比分析

    0 参考资料 模糊PID是以误差e和误差的变化率ec作为输入,利用设定好的模糊规则表,找出PID三个参数与e和ec之间的模糊关系. 在运行中不断检测e和ec,根据模糊控制原理,来对3个参数进行在线修改 ...

  6. [控制原理基础]浅谈PID算法

    一.PID使用背景 当今的自动控制技术都是基于反馈的概念.即一个In Loop闭环的理论,反馈理论的要素包括三个部分:测量.比较和执行.测量关心的变量,与期望值相比较,用这个误差纠正调节控制系统的响应 ...

  7. 模糊PID基本原理及matlab仿真实现(新手!新手!新手!)

    有关模糊pid的相关知识就把自己从刚接触到仿真出结果看到的大部分资料总结一下,以及一些自己的ps 以下未说明的都为转载内容 1.转自  https://blog.csdn.net/weixin_363 ...

  8. 搭建机器人电控系统——PID算法——位置式、增量式、模糊式PID

    PID算法 PID算法介绍,不同系数仿真,优缺点 位置式.增量式.模糊式PID 大林算法.史密斯算法和PID算法的区别 文章目录 PID算法 位置式PID和增量式PID 位置式PID: 增量式PID: ...

  9. 总结PID算法,位置式增量式理解以及C代码实现

    前言 近日刚接触PID,于是查找了所有资料(PID是经典算法,有很多文章),理解一大堆资料后,整理总结才写下在这篇博客. 自己也用STM32F103写些代码实现验证,先是单纯比例控制,后来PI控制,到 ...

  10. c语言程序位置式pid算法,位置式PID算法的C语言代码

    描述 位置式PID的C语言写法详解 PID调节口诀: 参数整定找最佳,从小到大顺序查 先是比例后积分,最后再把微分加 曲线振荡很频繁,比例度盘要放大 曲线漂浮绕大湾,比例度盘往小扳 曲线偏离回复慢,积 ...

最新文章

  1. Xilinx Altera FPGA中的逻辑资源(Slices VS LE)比较
  2. 在vue中给列表中的奇数行添加class
  3. 数据结构实验之串一:KMP简单应用
  4. 输出倒逼输入 加速自己成长
  5. Effective Java(1)-创建和销毁对象
  6. python排序sorted_sorted排序的两个方法 - Python
  7. 超大超长图片居中显示且放大缩小无影响
  8. Anaconda-Navigator无法打开
  9. cgcs2000大地坐标系地图_wgs84和cgcs2000坐标系有什么区别
  10. serv-u 用户使用sftp登录 时间显示不对_宜家中国电商化之路步履蹒跚 或因忽视消费者的使用习惯...
  11. vue报错 | Duplicate keys detected: ‘0’. This may cause an update error.
  12. Thunderbolt3 方案介绍及应用案例介绍
  13. ubuntu16.04 护眼神器Redshift
  14. Java学习 --- 设计模式七大原则的依赖倒转原则
  15. 【HTML】之marquee标签的使用和说明
  16. 数据结构 day07 基础知识学习 (二叉树 的 前中后遍历 ,插入节点,删除叶子节点, 二叉树的节点个数 )
  17. As-Projective-As-Possible Image Stitching with Moving DLT阅读笔记
  18. 用Python试了试人脸识别
  19. 有了这款数据恢复软件再也不用害怕数据丢失了
  20. mysql-cluste多少钱_mysql-cluster集群(亲测)

热门文章

  1. 手撸一个基于Springboot+Vue的书籍论坛系统,可用于课程设计和毕业设计或者练手
  2. vue+elementui+quill富文本框+秀米编辑器和135编辑器
  3. BT中的磁力链接(转)
  4. config配置文件原理及使用
  5. android 100以内的随机数
  6. ff14个服务器位置,新人求推荐个服务器
  7. linux编写脚本的基本方法
  8. STM32MP157AAA3裸机点灯(汇编)
  9. vulkan sdk 下载地址
  10. 如何正确使用条码标签打印软件