The effect of running depends on the test method of each class, and call it yourself to test it.
The purpose is to see which algorithm is easy to use. When transplanting, it is simple and has not understood the algorithm. The code structure has not been changed. It is just ported to C# to view the code and test. It is also very convenient for everyone to copy it. Copy the entire class to the .cs file.
This algorithm works normally when the actual value is lower than the target value. There will be problems after it exceeds it. I don’t know how to train it.
using System; using ; using ; using ; using ; using ; namespace FuzzyPID { class FuzzyPID { public const int N = 7; double target; //The system's control target double actual; //The actual value obtained by sampling double e; //error double e_pre_1; //The last error double e_pre_2; //The last error double de; //The rate of change of error double emax; //The upper limit of error basic theory domain double demax; //The upper limit of the basic theory domain of error debate rate double delta_Kp_max; //Upper limit of delta_kp output double delta_Ki_max; //delta_ki output upper limit double delta_Kd_max; //delta_kd output upper limit double Ke; //Ke=n/emax, the quantization theory domain is [-3,-2,-1,0,1,2,3] double Kde; //Kde=n/demax, the quantization theory domain is [-3,-2,-1,0,1,2,3] double Ku_p; //Ku_p=Kpmax/n, the quantization theory domain is [-3,-2,-1,0,1,2,3] double Ku_i; //Ku_i=Kimax/n, the quantization theory domain is [-3,-2,-1,0,1,2,3] double Ku_d; //Ku_d=Kdmax/n, the quantization theory domain is [-3,-2,-1,0,1,2,3] int[,] Kp_rule_matrix = new int[N, N];//Kp fuzzy rule matrix int[,] Ki_rule_matrix = new int[N, N];//Ki fuzzy rule matrix int[,] Kd_rule_matrix = new int[N, N];//Kd fuzzy rule matrix string mf_t_e; //E membership function type string mf_t_de; //De membership function type string mf_t_Kp; //Kp membership function type string mf_t_Ki; //Ki membership function type string mf_t_Kd; //Kd membership function type double[] e_mf_paras; // Parameters of the membership function of error double[] de_mf_paras;// Parameters of the deviation membership function of error double[] Kp_mf_paras; //The parameters of the membership function of kp double[] Ki_mf_paras; //Arguments of ki membership function double[] Kd_mf_paras; //Arguments of the membership function of kd double Kp; double Ki; double Kd; double A; double B; double C; 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; } //Triangular membership function 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); else u = 0; return u; } //Normal membership function double gaussmf(double x, double ave, double sigma) { double u; if (sigma < 0) { throw new Exception("In gaussmf, sigma must larger than 0"); } u = (-(((x - ave) / sigma), 2)); return u; } //Trainform membership function 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); else u = 0; return u; } //Set fuzzy rules Matrix public 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]; } } //Set subfunctions of fuzzy membership function 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; else throw 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; else throw 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; else throw 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; else throw 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; else throw 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; } } //Set the types and parameters of the fuzzy membership function 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); } //Implement fuzzy control 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];//Suppose that one input activates up to 3 fuzzy subsets double delta_Kp, delta_Ki, delta_Kd; double delta_u; target = t; actual = a; e = target - actual; de = e - e_pre_1; e = Ke * e; de = Kde * de; /* Fuzzy the error 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]);//efuzzy, calculate its membership else if (mf_t_e == "gaussmf") u_e[i] = gaussmf(e, e_mf_paras[i * 2], e_mf_paras[i * 2 + 1]);//efuzzy, calculate its membership 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]);//efuzzy, calculate its membership if (u_e[i] != 0) u_e_index[j++] = i; //Storing the subscript of the activated fuzzy subset can reduce the amount of calculation } for (; j < 3; j++) u_e_index[j] = 0; //Fill in 0 with the excess space /*Fuse the error rate 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 fuzzy, calculate its membership else if (mf_t_de == "gaussmf") u_de[i] = gaussmf(de, de_mf_paras[i * 2], de_mf_paras[i * 2 + 1]);//de fuzzy, calculate its membership 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 fuzzy, calculate its membership if (u_de[i] != 0) u_de_index[j++] = i; //Storing the subscript of the activated fuzzy subset can reduce the amount of calculation } for (; j < 3; j++) u_de_index[j] = 0; //Fill in 0 with the excess space double den = 0, num = 0; /* Calculate delta_Kp and 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]]; } 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; Kp += delta_Kp; if (Kp < 0) Kp = 0; /* Calculate delta_Ki and 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; Ki += delta_Ki; if (Ki < 0) Ki = 0; /* Calculate delta_Kd and 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; Kd += delta_Kd; if (Kd < 0) Kd = 0; 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; e_pre_2 = e_pre_1; e_pre_1 = e; return delta_u; } void showMf(string type, double[] mf_paras) { int tab = 0; if (type == "trimf") tab = 2; else if (type == "gaussmf") tab = 1; else if (type == "trapmf") tab = 3; ($"Function Type:{mf_t_e}"); ("Function parameter list:"); double[] p = mf_paras; for (int i = 0; i < N * (tab + 1); i++) { (p[i] + " "); if (i % (tab + 1) == tab) ("\r\n"); } } public void showInfo() { ("Info of this fuzzy controller is as following:"); ($"Basic Domaine:[{-emax},{emax}]"); ($"Basic Domainde:[{-demax},{demax}]"); ($"Basic Domaindelta_Kp:[{-delta_Kp_max},{delta_Kp_max}]"); ($"Basic Domaindelta_Ki:[{-delta_Ki_max},{delta_Ki_max}]"); ($"Basic Domaindelta_Kd:[{-delta_Kd_max},{delta_Kd_max}]"); ("Fuzzy membership function parameters of error e:"); showMf(mf_t_e, e_mf_paras); ("Fuzzy membership function parameters of error rate de:"); showMf(mf_t_de, de_mf_paras); ("Fuzzy membership function parameters of delta_Kp:"); showMf(mf_t_Kp, Kp_mf_paras); ("Fuzzy membership function parameters of delta_Ki:"); showMf(mf_t_Ki, Ki_mf_paras); ("Fuzzy membership function parameters of delta_Kd:"); showMf(mf_t_Kd, Kd_mf_paras); ("Fuzzy Rules Table:"); ("Fuzzy rule matrix of delta_Kp"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { (Kp_rule_matrix[i, j]); } ("\r\n"); } ("The fuzzy rule matrix of delta_Ki"); ; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { (Ki_rule_matrix[i, j]); } WriteEnd(); } ("Fuzzy rule matrix of delta_Kd"); ; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { (Kd_rule_matrix[i, j]); } WriteEnd(); } ($"Quantitative scale factor of errorKe={Ke}"); ($"Quantitative proportional factor of error rate changeKde={Kde}"); ($"Quantitative scale factor of outputKu_p={Ku_p}"); ($"Quantitative scale factor of outputKu_i={Ku_i}"); ($"Quantitative scale factor of outputKu_d={Ku_d}"); ($"Set goalstarget={target}"); ($"errore={e}"); ($"Kp={Kp}"); ($"Ki={Ki}"); ($"Kd={Kd}"); WriteEnd(); } public void Write(object str) { (str); } public void WriteLine(object str) { (str); } public void WriteEnd() { ("\r\n"); } public static void test() { int NB = -3; int NM = -2; int NS = -1; int ZO = 0; int PS = 1; int PM = 2; int PB = 3; double target = 300; double actual = 400; double u = 0; int[,] deltaKpMatrix = new int[7, 7] {{PB,PB,PM,PM,PS,ZO,ZO }, {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[,] deltaKiMatrix = new int[7, 7]{{NB,NB,NM,NM,NS,ZO,ZO}, {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}}; int[,] deltaKdMatrix = new int[7, 7]{{PS,NS,NB,NB,NB,NM,PS}, {PS,NS,NB,NM,NM,NS,ZO}, {ZO,NS,NM,NM,NS,NS,ZO}, {ZO,NS,NS,NS,NS,NS,ZO}, {ZO,ZO,ZO,ZO,ZO,ZO,ZO}, {PB,NS,PS,PS,PS,PS,PB}, {PB,PM,PM,PM,PS,PS,PB}}; double[] e_mf_paras = { -3, -3, -2, -3, -2, -1, -2, -1, 0, -1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 3 }; double[] de_mf_paras = { -3, -3, -2, -3, -2, -1, -2, -1, 0, -1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 3 }; double[] Kp_mf_paras = { -3, -3, -2, -3, -2, -1, -2, -1, 0, -1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 3 }; double[] Ki_mf_paras = { -3, -3, -2, -3, -2, -1, -2, -1, 0, -1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 3 }; double[] Kd_mf_paras = { -3, -3, -2, -3, -2, -1, -2, -1, 0, -1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 3 }; var fuzzypid = new FuzzyPID(1500, 1000, 0.3, 0.9, 0.6, 0.01, 0.04, 0.01); ("trimf", e_mf_paras, "trimf", de_mf_paras, "trimf", Kp_mf_paras, "trimf", Ki_mf_paras, "trimf", Kd_mf_paras); (deltaKpMatrix, deltaKiMatrix, deltaKdMatrix); for (int i = 0; i < 50; i++) { u = (target, actual); actual += u; ($"{i} {target} {u} {actual}"); //if (i>19) //{ // target = 300; //} } //(); } } }
The above is the detailed content of c# implementing fuzzy PID control algorithm. For more information about c# fuzzy PID control algorithm, please pay attention to my other related articles!