C#实现模糊PID算法的代码

刚开始在网上搜了下相关代码,发现全都是这个版本的(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);
            else
                u = 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);
            else
                u = 0;
            return u;
        }


        //设置模糊规则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];
                }

        }


        //设置模糊隶属度函数的子函数
        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 = 
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值