0


自适应模糊PID(位置式)C语言实现

一、自适应模糊PID原理

自适应模糊PID 控制系统结构如图所示。控制系统以偏差e和偏差变化率ec作为输入量,利用模糊规则进行模糊推理,输出Δkp,Δki,Δkd。对PID三个参数进行在线分析与调整,而自适应模糊PID 控制器输出u( t) 作用Mosfet开关管上,从而使sepic的输出电压达到要求的实时稳定性。
在这里插入图片描述
图 4.2.1 模糊PID结构图
系统采用两输入一输出的模糊控制器的形式,以密度偏差e 和偏差变化率ec 作为模糊控制器的输入量,以PID 参数的修正量Δkp,Δki,Δkd分别为模糊控制器的输出量。其变量、基本论域、模糊子集、模糊论域、量化因子、比例因子如表所示。考虑到论域覆盖范围和灵敏度,并且为了F28027计算简便,各模糊子集采用三角形隶属函数。

表 4.2.1 ΔKp模糊规则表
在这里插入图片描述

表4.2.2ΔKi模糊规则表
在这里插入图片描述

表4.2.3ΔKd模糊规则表
在这里插入图片描述
在这里插入图片描述
图4.2.2 隶属度函数
根据已经确立的模糊控制规则和隶属度函数,采用Mamdani推理方法,面积重心法非模糊化。
在这里插入图片描述
总结一下,整个模糊自适应PID的运算工程如下所示:

在这里插入图片描述

二、代码实现

该工程来自https://github.com/FlameAlpha/fuzzy-pid
某位国内大佬编写,顶礼膜拜。

fuzzy_pid.h

#ifndef_FUZZY_PID_H_#define_FUZZY_PID_H_#ifdef__cplusplusextern"C"{#endif#include"math.h"#include"stdlib.h"#include"User_Component/mySci/printf.h"#ifndefbool#defineboolchar#endif#ifndeffalse#definefalse(char)0#endif#ifndeftrue#definetrue(char)1#endif// Fuzzy quantity fieldsenumquantity_fields{
    qf_small =5,
    qf_middle =7,
    qf_large =8};#defineqf_defaultqf_middlestructfuzzy{unsignedint input_num;unsignedint output_num;unsignedint fo_type;unsignedint*mf_type;int*mf_params;unsignedint df_type;int*rule_base;float*output;};structPID{float kp;float ki;float kd;float delta_kp_max;float delta_ki_max;float delta_kd_max;float delta_kp;float delta_ki;float delta_kd;float error_max;float delta_error_max;float last_error;float current_error;float intergral;float intergral_limit;float dead_zone;float feed_forward;float output;int output_min_value;int output_middle_value;int output_max_value;float linear_adaptive_kp;structfuzzy*fuzzy_struct;};#defineNB-3#defineNM-2#defineNS-1#defineZO0#definePS1#definePM2#definePB3//#define fuzzy_pid_debug_print//#define fuzzy_pid_dead_zone//#define fuzzy_pid_integral_limit//#define fuzzy_pid_rule_base_deep_copy#definepid_params_count7#definetorque_mode1#defineposition_mode2#definecontrol_modeposition_mode#ifcontrol_mode == position_mode#definemax_error5.0f#definemax_delta_error5.0f#else#definemax_error12.0f#definemax_delta_error12.0f#endif#definemin_pwm_output250#definemiddle_pwm_output1500#definemax_pwm_output2900structfuzzy*fuzzy_init(unsignedint input_num,unsignedint output_num);voidfuzzy_params_init(structfuzzy*fuzzy_struct,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int mf_params[],int rule_base[][qf_default]);voidfuzzy_control(float e,float de,structfuzzy*fuzzy_struct);structPID*raw_fuzzy_pid_init(float kp,float ki,float kd,float integral_limit,float dead_zone,float feed_forward,float error_max,float delta_error_max,float delta_kp_max,float delta_ki_max,float delta_kd_max,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int*mf_params,int rule_base[][qf_default],int output_min_value,int output_middle_value,int output_max_value);//float params[pid_params_count] = {kp, ki, kd, integral_limit, dead_zonefeed_forward, linear_adaptive_kp};structPID*fuzzy_pid_init(float*params,float delta_k,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int mf_params[],int rule_base[][qf_default]);structPID**fuzzy_pid_vector_init(float params[][pid_params_count],float delta_k,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int*mf_params,int rule_base[][qf_default],unsignedint count);floatfuzzy_pid_control(float real,float idea,structPID*pid);intdirect_control(int zero_value,int offset_value, bool direct);intfuzzy_pid_motor_pwd_output(float real,float idea, bool direct,structPID*pid);voiddelete_pid(structPID*pid);voiddelete_pid_vector(structPID**pid_vector,unsignedint count);#ifdef__cplusplus}#endif#endif//_FUZZY_PID_H_

fuzzy_pid.c

#include"User_Component/myPID/fuzzy_pid.h"structfuzzy*fuzzy_init(unsignedint input_num,unsignedint output_num){structfuzzy*fuzzy_struct =(structfuzzy*)malloc(sizeof(structfuzzy));
    fuzzy_struct->input_num = input_num;
    fuzzy_struct->output_num = output_num;
    fuzzy_struct->mf_type =(unsignedint*)malloc((input_num + output_num)*sizeof(unsignedint));#ifdeffuzzy_pid_rule_base_deep_copy
    fuzzy_struct->mf_params =(int*)malloc(4* qf_default *sizeof(int));
    fuzzy_struct->rule_base =(int*)malloc(output_num * qf_default * qf_default *sizeof(int));#endif
    fuzzy_struct->output =(float*)malloc(output_num *sizeof(float));return fuzzy_struct;}voiddelete_fuzzy(structfuzzy*fuzzy_struct){free(fuzzy_struct->mf_type);free(fuzzy_struct->output);free(fuzzy_struct);}voidfuzzy_params_init(structfuzzy*fuzzy_struct,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int mf_params[],int rule_base[][qf_default]){for(unsignedint i =0; i < fuzzy_struct->input_num + fuzzy_struct->output_num;++i){
        fuzzy_struct->mf_type[i]= mf_type;}for(unsignedint i =0; i < fuzzy_struct->output_num;++i){
        fuzzy_struct->output[i]=0;}#ifdeffuzzy_pid_rule_base_deep_copyfor(unsignedint j =0; j <4* qf_default;++j){
        fuzzy_struct->mf_params[j]= mf_params[j];}for(unsignedint k =0; k < fuzzy_struct->output_num * qf_default;++k){for(unsignedint i =0; i < qf_default;++i){
            fuzzy_struct->rule_base[k *7+ i]= rule_base[k][i];}}#else
    fuzzy_struct->mf_params = mf_params;
    fuzzy_struct->rule_base =(int*) rule_base;#endif

    fuzzy_struct->fo_type = fo_type;
    fuzzy_struct->df_type = df_type;}#defineinverse(parameter)1.0f/(float)parameter// Gaussian membership functionfloatgaussmf(float x,float sigma,float c){returnexpf(-powf(((x - c)/ sigma),2.0f));}// Generalized bell-shaped membership functionfloatgbellmf(float x,float a,float b,float c){returninverse(1.0f+powf(fabsf((x - c)/ a),2.0f* b));}// Sigmoidal membership functionfloatsigmf(float x,float a,float c){returninverse(1.0f+expf(a *(c - x)));}// Trapezoidal membership functionfloattrapmf(float x,float a,float b,float c,float d){if(x >= a && x < b)return(x - a)/(b - a);elseif(x >= b && x < c)return1.0f;elseif(x >= c && x <= d)return(d - x)/(d - c);elsereturn0.0f;}// Triangular membership functionfloattrimf(float x,float a,float b,float c){returntrapmf(x, a, b, b, c);}// Z-shaped membership functionfloatzmf(float x,float a,float b){if(x <= a)return1.0f;elseif(x >= a && x <=(a + b)/2.0f)return1.0f-2.0f*powf((x - a)/(b - a),2.0f);elseif(x >=(a + b)/2.0f&& x < b)return2.0f*powf((x - b)/(b - a),2.0f);elsereturn0;}// Membership functionfloatmf(float x,unsignedint mf_type,int*params){switch(mf_type){case0:returngaussmf(x, params[0], params[1]);case1:returngbellmf(x, params[0], params[1], params[2]);case2:returnsigmf(x, params[0], params[2]);case3:returntrapmf(x, params[0], params[1], params[2], params[3]);case5:returnzmf(x, params[0], params[1]);default:// set triangular as default membership functionreturntrimf(x, params[0], params[1], params[2]);}}// Union operatorfloator(float a,float b,unsignedint type){if(type ==1)// algebraic sum{return a + b - a * b;}elseif(type ==2)// bounded sum{returnfminf(1, a + b);}else// fuzzy union{returnfmaxf(a, b);}}// Intersection operatorfloatand(float a,float b,unsignedint type){if(type ==1)// algebraic product{return a * b;}elseif(type ==2)// bounded product{returnfmaxf(0, a + b -1);}else// fuzzy intersection{returnfminf(a, b);}}// Equilibrium operatorfloatequilibrium(float a,float b,float params){returnpowf(a * b,1- params)*powf(1-(1- a)*(1- b), params);}// Fuzzy operatorfloatfo(float a,float b,unsignedint type){if(type <3){returnand(a, b, type);}elseif(type <6){returnor(a, b, type -3);}else{returnequilibrium(a, b,0.5f);}}// Mean of centers defuzzifier, only for two input multiple indexvoidmoc(constfloat*joint_membership,constunsignedint*index,constunsignedint*count,structfuzzy*fuzzy_struct){float denominator_count =0;//    float numerator_count[fuzzy_struct->output_num];//注意 TI的C99编译器并不是完全支持动态数组的特性,所以这里改变了一下(c89写法)float*numerator_count=(float*)malloc(fuzzy_struct->output_num*sizeof(float));for(unsignedint l =0; l < fuzzy_struct->output_num;++l){
        numerator_count[l]=0;}for(int i =0; i < count[0];++i){for(int j =0; j < count[1];++j){
            denominator_count += joint_membership[i * count[1]+ j];}}for(unsignedint k =0; k < fuzzy_struct->output_num;++k){for(unsignedint i =0; i < count[0];++i){for(unsignedint j =0; j < count[1];++j){
                numerator_count[k]+= joint_membership[i * count[1]+ j]*
                                      fuzzy_struct->rule_base[k * qf_default * qf_default + index[i]* qf_default +
                                                index[count[0]+ j]];}}}#ifdeffuzzy_pid_debug_printprintf("output:\n");#endiffor(unsignedint l =0; l < fuzzy_struct->output_num;++l){
        fuzzy_struct->output[l]= numerator_count[l]/ denominator_count;#ifdeffuzzy_pid_debug_printprintf("%f,%f,%f\n", numerator_count[l], denominator_count, fuzzy_struct->index[l]);#endif}free(numerator_count);//有借有还再借不难}// Defuzzifiervoiddf(constfloat*joint_membership,constunsignedint*output,constunsignedint*count,structfuzzy*fuzzy_struct,int df_type){if(df_type ==0)moc(joint_membership, output, count, fuzzy_struct);else{printf("Waring: No such of defuzzifier!\n");moc(joint_membership, output, count, fuzzy_struct);}}voidfuzzy_control(float e,float de,structfuzzy*fuzzy_struct){float membership[qf_default *2];// Store membershipunsignedint index[qf_default *2];// Store the index of each membershipunsignedint count[2]={0,0};{int j =0;for(int i =0; i < qf_default;++i){float temp =mf(e, fuzzy_struct->mf_type[0], fuzzy_struct->mf_params +4* i);//            if (temp > 1e-4)//            {
                membership[j]= temp;
                index[j++]= i;//            }}

        count[0]= j;for(int i =0; i < qf_default;++i){float temp =mf(de, fuzzy_struct->mf_type[1], fuzzy_struct->mf_params +4* i);//            if (temp > 1e-4)//            {
                membership[j]= temp;
                index[j++]= i;//            }}

        count[1]= j - count[0];}#ifdeffuzzy_pid_debug_printprintf("membership:\n");for(unsignedint k =0; k < j;++k){printf("%f\n", membership[k]);}printf("index:\n");for(unsignedint k =0; k < j;++k){printf("%d\n", index[k]);}printf("count:\n");for(unsignedint k =0; k <2;++k){printf("%d\n", count[k]);}#endifif(count[0]==0|| count[1]==0){for(unsignedint l =0; l < fuzzy_struct->output_num;++l){
            fuzzy_struct->output[l]=0;}return;}// Joint membership//注意 TI的C99编译器并不是完全支持动态数组的特性,所以这里改变了一下(c89写法)//    float joint_membership[count[0] * count[1]];float*joint_membership=(float*)malloc(count[0]* count[1]*sizeof(float));for(int i =0; i < count[0];++i){for(int j =0; j < count[1];++j){
            joint_membership[i * count[1]+ j]=fo(membership[i], membership[count[0]+ j], fuzzy_struct->fo_type);}}df(joint_membership, index, count, fuzzy_struct,0);free(joint_membership);}structPID*raw_fuzzy_pid_init(float kp,float ki,float kd,float integral_limit,float dead_zone,float feed_forward,float error_max,float delta_error_max,float delta_kp_max,float delta_ki_max,float delta_kd_max,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int mf_params[],int rule_base[][qf_default],int output_min_value,int output_middle_value,int output_max_value){structPID*pid =(structPID*)malloc(sizeof(structPID));
    pid->kp = kp;
    pid->ki = ki;
    pid->kd = kd;

    pid->delta_kp_max = delta_kp_max;
    pid->delta_ki_max = delta_ki_max;
    pid->delta_kd_max = delta_kd_max;

    pid->delta_kp =0;
    pid->delta_ki =0;
    pid->delta_kd =0;

    pid->error_max = error_max;
    pid->delta_error_max = delta_error_max;int output_count =1;if(ki >1e-4){
        output_count +=1;if(kd >1e-4)
            output_count +=1;}

    pid->fuzzy_struct =fuzzy_init(2, output_count);fuzzy_params_init(pid->fuzzy_struct, mf_type, fo_type, df_type, mf_params, rule_base);

    pid->last_error =0;
    pid->current_error =0;

    pid->intergral =0;
    pid->intergral_limit = integral_limit;

    pid->dead_zone = dead_zone;
    pid->feed_forward = feed_forward;

    pid->output_max_value = output_max_value;
    pid->output_middle_value = output_middle_value;
    pid->output_min_value = output_min_value;return pid;}structPID*fuzzy_pid_init(float*params,float delta_k,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int mf_params[],int rule_base[][qf_default]){returnraw_fuzzy_pid_init(params[0], params[1], params[2], params[3], params[4], params[5], max_error,
                              max_delta_error, params[0]/ delta_k, params[1]/ delta_k, params[2]/ delta_k, mf_type,
                              fo_type, df_type, mf_params,
                              rule_base, min_pwm_output, middle_pwm_output, max_pwm_output);}intround_user(float parameter){if((int)(parameter *10.0)%10>=5)return parameter +1;elsereturn parameter;}intlimit(int value,int max_limit,int min_limit){if(value > max_limit)return max_limit;if(value < min_limit)return min_limit;return value;}floatlimits(float value,float max_limit,float min_limit){if(value > max_limit)return max_limit;if(value < min_limit)return min_limit;return value;}floatfuzzy_pid_control(float real,float idea,structPID*pid){
    pid->last_error = pid->current_error;
    pid->current_error = idea - real;float delta_error = pid->current_error - pid->last_error;float uk;#ifdeffuzzy_pid_dead_zoneif(pid->current_error < pid->dead_zone && pid->current_error >-pid->dead_zone){
        pid->current_error =0;}else{if(pid->current_error > pid->dead_zone)
            pid->current_error = pid->current_error - pid->dead_zone;else{if(pid->current_error <-pid->dead_zone)
                pid->current_error = pid->current_error + pid->dead_zone;}}#endif//关键代码fuzzy_control(pid->current_error / pid->error_max *3.0f, delta_error / pid->delta_error_max *3.0f,
                  pid->fuzzy_struct);//    pid->delta_kp = limits(pid->fuzzy_struct->output[0]/3.0f * pid->delta_kp_max, pid->delta_kp_max ,-pid->delta_kp_max);
    pid->delta_kp =limits(pid->fuzzy_struct->output[0], pid->delta_kp_max ,-pid->delta_kp_max);if(pid->fuzzy_struct->output_num >=2)//        pid->delta_ki = limits(pid->fuzzy_struct->output[1]/3.0f * pid->delta_ki_max, pid->delta_ki_max ,-pid->delta_ki_max);
        pid->delta_ki =limits(pid->fuzzy_struct->output[1], pid->delta_ki_max ,-pid->delta_ki_max);else pid->delta_ki =0;if(pid->fuzzy_struct->output_num >=3)//        pid->delta_kd =limits(pid->fuzzy_struct->output[2]/3.0f * pid->delta_kd_max, pid->delta_kd_max ,-pid->delta_kd_max);
        pid->delta_kd =limits(pid->fuzzy_struct->output[2], pid->delta_kd_max ,-pid->delta_kd_max);else pid->delta_kd =0;#ifdeffuzzy_pid_debug_printprintf("kp : %f, ki : %f, kd : %f\n", pid->kp + pid->delta_kp, pid->ki + pid->delta_ki, pid->kd + pid->delta_kd);#endif//    printf("kpkikd:%f,%f,%f,%f\n", pid->kp + pid->delta_kp, pid->ki + pid->delta_ki, pid->kd + pid->delta_kd,0.0);

    pid->intergral +=(pid->ki + pid->delta_ki)* pid->current_error;#ifdeffuzzy_pid_integral_limitif(pid->intergral > pid->intergral_limit)
        pid->intergral = pid->intergral_limit;else{if(pid->intergral <-pid->intergral_limit)
            pid->intergral =-pid->intergral_limit;}#endif// //这里位置式PID算法//    pid->output = (pid->kp + pid->delta_kp) * pid->current_error + pid->intergral +//                  (pid->kd + pid->delta_kd) * (pid->current_error - pid->last_error);

    uk =(pid->kp + pid->delta_kp)* pid->current_error + pid->intergral +(pid->kd + pid->delta_kd)*(pid->current_error - pid->last_error);//    pid->output += pid->feed_forward * (float) idea;

    uk +=pid->feed_forward *(float) idea;//前馈环节

    pid->output = uk;//限幅if(pid->output<pid ->output_min_value)
        pid->output=pid ->output_min_value;elseif(pid->output>pid ->output_max_value)
        pid->output=pid ->output_max_value;return pid->output;}voiddelete_pid(structPID*pid){if(pid->fuzzy_struct !=NULL){delete_fuzzy(pid->fuzzy_struct);}free(pid);}voiddelete_pid_vector(structPID**pid_vector,unsignedint count){for(unsignedint i =0; i < count;++i){delete_pid(pid_vector[i]);}free(pid_vector);}structPID**fuzzy_pid_vector_init(float params[][pid_params_count],float delta_k,unsignedint mf_type,unsignedint fo_type,unsignedint df_type,int*mf_params,int rule_base[][qf_default],unsignedint count){structPID**pid =(structPID**)malloc(sizeof(structPID*)* count);for(unsignedint i =0; i < count;++i){
        pid[i]=fuzzy_pid_init(params[i], delta_k, mf_type, fo_type, df_type, mf_params, rule_base);}return pid;}intdirect_control(int zero_value,int offset_value, bool direct){if(direct == true){return zero_value + offset_value;}else{return zero_value - offset_value;}}intfuzzy_pid_motor_pwd_output(float real,float idea, bool direct,structPID*pid){returnlimit(direct_control(pid->output_middle_value,fuzzy_pid_control(real, idea, pid), direct),
                 pid->output_max_value, pid->output_min_value);}

调用方法

//全局变量定义方式structPID**pid_vector;//main函数中初始化int rule_base[][qf_default]={//delta kp rule base{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},//delta ki rule base{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},//delta kd rule base{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, PS, PS, PS, PS, PS, PB},{PB, PM, PM, PM, PS, PS, PB}};// Default parameters of membership functionint mf_params[4* qf_default]={-3,-3,-2,0,-3,-2,-1,0,-2,-1,0,0,-1,0,1,0,0,1,2,0,1,2,3,0,2,3,3,0};float fuzzy_pid_params[1][pid_params_count]={{25.4597502f,10.0053997f,15.59500027f,1800,0,0,1}};structPID**subpid_vector =fuzzy_pid_vector_init(fuzzy_pid_params,4.0f,4,1,0, mf_params, rule_base,1);

     pid_vector=subpid_vector;//中断中调用
        control_uk =fuzzy_pid_control(Voltage_Real, pid.Ref, pid_vector[0]);if(control_uk<150)
            control_uk=150;elseif(control_uk>2800)
            control_uk=2800;

本文转载自: https://blog.csdn.net/qq_30759585/article/details/122382396
版权归原作者 龙晨天 所有, 如有侵权,请联系我们删除。

“自适应模糊PID(位置式)C语言实现”的评论:

还没有评论