基本原理
模糊规则表
代码实现
include
include
include
enum fuzztab { NB = 0, NM = 1, NS = 2, ZO = 3, PS = 4, PM = 5, PB = 6, };
struct _MATH_FUZZYPID { / Property / float Property_Kp; float Property_Ki; float Property_Kd;
float Property_dt;float Property_integralMax;float Property_AimMax;float Property_OutputMax;float Value_errRange[7];float Value_errDotRange[7];float Value_deltaKpRange[7];float Value_deltaKiRange[7];float Value_deltaKdRange[7];/* Value */float Value_Aim;float Value_Actual;float Value_err;float Value_errDot;float Value_err_last;float Value_integral;float Value_output;rt_uint8_t Value_errBelongStage[2];float Value_errBelongValue[2];rt_uint8_t Value_errDotBelongStage[2];float Value_errDotBelongValue[2];float Value_deltaKp;float Value_deltaKi;float Value_deltaKd;/* Method */void (*Method_Init)(struct _MATH_FUZZYPID *module);void (*Method_Update)(struct _MATH_FUZZYPID *module,float Aim, float Feedback);
}; typedef struct _MATH_FUZZYPID MATH_FUZZYPID;
rt_err_t Module_FuzzyPID_Config(MATH_FUZZYPID *module);
endif
<a name="H4nEk"></a>## Math_FuzzyPID.c```c/** Copyright (c) 2020 - ~, HIT_HERO Team** FUZZYPID MODULE SOUCE FILE* Used in RT-Thread Operate System** Change Logs:* Date Author Notes Mail* 2020-08-20 WangXi first version WangXi_chn@foxmail.com** Note:**/#include "Math_FuzzyPID.h"#include <math.h>#define FUZZYPIDenum fuzztab KPTAB[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};enum fuzztab KITAB[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};enum fuzztab KDTAB[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};static void Module_FuzzyPIDInit(MATH_FUZZYPID *module);static void Module_FuzzyPIDUpdate(MATH_FUZZYPID *module,float Aim, float Feedback);static void fuzziFication(MATH_FUZZYPID *module);static void defuzzify(MATH_FUZZYPID *module);rt_err_t Module_FuzzyPID_Config(MATH_FUZZYPID *module){if( module->Method_Init ==NULL &&module->Method_Update ==NULL){/* Link the Method */module->Method_Init = Module_FuzzyPIDInit;module->Method_Update = Module_FuzzyPIDUpdate;}else{rt_kprintf("Warning: Module Fuzzy PID is Configed twice\n");return RT_ERROR;}/* Device Init */module->Method_Init(module);return RT_EOK;}static void Module_FuzzyPIDInit(MATH_FUZZYPID *module){module->Value_Actual = 0;module->Value_Aim = 0;module->Value_err = 0;module->Value_err_last = 0;module->Value_integral = 0;module->Value_output = 0;}static void Module_FuzzyPIDUpdate(MATH_FUZZYPID *module,float Aim, float Feedback){float P,I,D;module->Value_Aim = Aim;module->Value_Actual = Feedback;/* Culculate P */if(module->Value_Aim > module->Property_AimMax)module->Value_Aim = module->Property_AimMax;else if(module->Value_Aim < -module->Property_AimMax)module->Value_Aim = -module->Property_AimMax;module->Value_err = module->Value_Aim - module->Value_Actual;module->Value_errDot = module->Value_err - module->Value_err_last;module->Value_err_last = module->Value_err;#ifdef FUZZYPID/* Fuzzy PID Used */fuzziFication(module);defuzzify(module);module->Property_Kp += module->Value_deltaKp;module->Property_Ki += module->Value_deltaKi;//module->Property_Kd += module->Value_deltaKd;#endifP = module->Value_err * module->Property_Kp;/* Culculate I */if(fabs(module->Value_err) < 500){module->Value_integral += module->Value_err * module->Property_Ki * module->Property_dt;if(module->Value_integral > module->Property_integralMax)module->Value_integral = module->Property_integralMax;else if(module->Value_integral < -module->Property_integralMax)module->Value_integral = -module->Property_integralMax;I = module->Value_integral;}/* Culculate D */D = module->Property_Kd * (module->Value_err - module->Value_err_last) / module->Property_dt;/* Culculate Output */module->Value_output = P + I + D;if(module->Value_output > module->Property_OutputMax)module->Value_output = module->Property_OutputMax;else if(module->Value_output < -module->Property_OutputMax)module->Value_output = -module->Property_OutputMax;}static void fuzziFication(MATH_FUZZYPID *module){/* get err fuzzy */if(module->Value_err > module->Value_errRange[6]){module->Value_errBelongStage[0] = PB;module->Value_errBelongStage[1] = PB;module->Value_errBelongValue[0] = 1;module->Value_errBelongValue[1] = 0;}else if(module->Value_err < module->Value_errRange[0]){module->Value_errBelongStage[1] = NB;module->Value_errBelongStage[0] = NB;module->Value_errBelongValue[0] = 0;module->Value_errBelongValue[1] = 1;}else{for(rt_uint8_t i = 0;i<5;i++){if(module->Value_err == module->Value_errRange[i]){module->Value_errBelongStage[1] = i;module->Value_errBelongStage[0] = i;module->Value_errBelongValue[0] = 0;module->Value_errBelongValue[1] = 1;}else if((module->Value_err>module->Value_errRange[i])&&(module->Value_err<module->Value_errRange[i+1])){float step = fabs(module->Value_errRange[1]-module->Value_errRange[0]);module->Value_errBelongStage[0] = i;module->Value_errBelongStage[1] = i+1;module->Value_errBelongValue[0] =fabs((module->Value_err-module->Value_errRange[i])/step);module->Value_errBelongValue[1] = 1-module->Value_errBelongValue[0];break;}}}/* get err last fuzzy */if(module->Value_errDot > module->Value_errDotRange[6]){module->Value_errDotBelongStage[0] = PB;module->Value_errDotBelongStage[1] = PB;module->Value_errDotBelongValue[0] = 1;module->Value_errDotBelongValue[1] = 0;}else if(module->Value_errDot < module->Value_errDotRange[0]){module->Value_errDotBelongStage[1] = NB;module->Value_errDotBelongStage[0] = NB;module->Value_errDotBelongValue[0] = 0;module->Value_errDotBelongValue[1] = 1;}else{for(rt_uint8_t i = 0;i<5;i++){if(module->Value_errDot == module->Value_errDotRange[i]){module->Value_errDotBelongStage[1] = i;module->Value_errDotBelongStage[0] = i;module->Value_errDotBelongValue[0] = 0;module->Value_errDotBelongValue[1] = 1;}else if((module->Value_errDot>module->Value_errDotRange[i])&&(module->Value_errDot<module->Value_errDotRange[i+1])){float step = fabs(module->Value_errDotRange[1]-module->Value_errDotRange[0]);module->Value_errDotBelongStage[0] = i;module->Value_errDotBelongStage[1] = i+1;module->Value_errDotBelongValue[0] =fabs((module->Value_err-module->Value_errRange[i])/step);module->Value_errDotBelongValue[1] = 1-module->Value_errDotBelongValue[0];break;}}}}static void defuzzify(MATH_FUZZYPID *module){module->Value_deltaKp =module->Value_deltaKpRange[KPTAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[0]+module->Value_deltaKpRange[KPTAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[1]+module->Value_deltaKpRange[KPTAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[0]+module->Value_deltaKpRange[KPTAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[1];module->Value_deltaKi =module->Value_deltaKiRange[KITAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[0]+module->Value_deltaKiRange[KITAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[1]+module->Value_deltaKiRange[KITAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[0]+module->Value_deltaKiRange[KITAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[1];module->Value_deltaKd =module->Value_deltaKdRange[KDTAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[0]+module->Value_deltaKdRange[KDTAB[module->Value_errBelongStage[0]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[0]*module->Value_errDotBelongValue[1]+module->Value_deltaKdRange[KDTAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[0]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[0]+module->Value_deltaKdRange[KDTAB[module->Value_errBelongStage[1]][module->Value_errDotBelongStage[1]]]*module->Value_errBelongValue[1]*module->Value_errDotBelongValue[1];}
Module_DjiC610C620Group.h
修改电机的PID成员为模糊PIDstruct _MODULE_DjiC610620{/* Property */rt_uint8_t Enable;rt_uint8_t Mode;MATH_FUZZYPID PID_Speed;MATH_FUZZYPID PID_Angle;
Module_DjiC610C620Group.c
在电机群的电机成员初始化时,把原来对普通PID的初始化修改为对模糊PID的初始化/* Module PID controler Init */if(Dev_DjiC610620->Mode == DjiC610620MODE_SPEED){Module_FuzzyPID_Config(&(Dev_DjiC610620->PID_Speed));}else if(Dev_DjiC610620->Mode == DjiC610620MODE_ANGLE){Module_FuzzyPID_Config(&(Dev_DjiC610620->PID_Speed));Module_FuzzyPID_Config(&(Dev_DjiC610620->PID_Angle));}
main.c
和原来相比在main中电机群模块的初始化多了对模糊PID参数的初始化,主要是模糊范围
MODULE_DjiC610620GROUP dev_DjiC610620group ={.Property_CanDevName = "can1",.Value_module_DjiC610620[DjiC610620ID_1] ={.Enable = 1,.Mode = DjiC610620MODE_SPEED,.PID_Speed ={.Property_Kp = 6, .Property_Ki = 2, .Property_Kd = 0,.Value_errRange = {-6750, -4500, -2250, 0, 2250, 4500, 6750},.Value_errDotRange = {-13500, -9000, -4500, 0, 4500, 9000, 13500},.Value_deltaKpRange = {-0.015, -0.01, -0.005, 0, 0.005, 0.01, 0.015},.Value_deltaKiRange = {-0.003, -0.002, -0.001, 0, 0.001, 0.002, 0.003},.Value_deltaKdRange = {-0.015, -0.01, -0.005, 0, 0.005, 0.01, 0.015},.Property_dt = 0.005,.Property_integralMax = 500, .Property_AimMax = 9000, .Property_OutputMax =16300}},};
实际效果
- 电机的PID控制器中Kp、Ki可以实现闭环调整,在速度环运行过程中自动寻找Kp、Ki的最佳值
- 表现形式是电机在加速过程中Kp逐渐上升,直至电机抖动,然后Kp自动回落,电机平稳,往复进行
- 据此猜测模糊PID的适用场合
- 模糊PID和传统PID的优点在于无需给定明确的参数值,只需给定一个增量的调整范围
- 可以实现参数的自适应,此时的PID更像是一个学习过程
- 因为是学习过程,因此存在学习时间,可能不适合应用在实时性要求严格的场合
- 可以用来寻找系统的最佳的参数,从而成为一个工具
