|
c
/*
* 开源模糊控制算法
* 适用场景:温度控制、湿度调节、非线性系统控制等
* 核心逻辑:输入(偏差、偏差变化率)→ 模糊化 → 模糊推理 → 解模糊 → 输出
*/
#include "fuzzy_control.h"
// 模糊集合定义(以温度控制为例,输入:偏差e、偏差变化率ec;输出:控制量u)
// 模糊语言变量:负大(NB)、负中(NM)、负小(NS)、零(ZR)、正小(PS)、正中(PM)、正大(PB)
typedef enum {
NB = 0, NM, NS, ZR, PS, PM, PB
} Fuzzy_LinguisticVar;
// 模糊控制参数结构体
typedef struct {
float e_min; // 偏差e的最小值
float e_max; // 偏差e的最大值
float ec_min; // 偏差变化率ec的最小值
float ec_max; // 偏差变化率ec的最大值
float u_min; // 控制量u的最小值
float u_max; // 控制量u的最大值
// 模糊规则表(7×7,行:e的模糊集合,列:ec的模糊集合,值:u的模糊集合)
Fuzzy_LinguisticVar rule_table[7][7];
} Fuzzy_HandleTypeDef;
// 隶属度函数:三角形隶属度(最常用,计算简洁)
// x:输入值,a:左顶点,b:顶点,c:右顶点
float Triangle_Membership(float x, float a, float b, float c) {
if (x <= a || x >= c) {
return 0.0f;
} else if (x == b) {
return 1.0f;
} else if (x > a && x < b) {
return (x - a) / (b - a);
} else { // x > b && x < c
return (c - x) / (c - b);
}
}
// 模糊化:将精确输入e、ec转换为各模糊集合的隶属度
void Fuzzy_Fuzzification(Fuzzy_HandleTypeDef *fuzzy, float e, float ec,
float *e_membership, float *ec_membership) {
// 偏差e的模糊化(7个模糊集合,均匀划分输入范围)
float e_range = fuzzy->e_max - fuzzy->e_min;
float e_step = e_range / 6; // 7个集合,6个间隔
e_membership[NB] = Triangle_Membership(e, fuzzy->e_min, fuzzy->e_min, fuzzy->e_min + e_step);
e_membership[NM] = Triangle_Membership(e, fuzzy->e_min, fuzzy->e_min + e_step, fuzzy->e_min + 2*e_step);
e_membership[NS] = Triangle_Membership(e, fuzzy->e_min + e_step, fuzzy->e_min + 2*e_step, fuzzy->e_min + 3*e_step);
e_membership[ZR] = Triangle_Membership(e, fuzzy->e_min + 2*e_step, fuzzy->e_min + 3*e_step, fuzzy->e_min + 4*e_step);
e_membership[PS] = Triangle_Membership(e, fuzzy->e_min + 3*e_step, fuzzy->e_min + 4*e_step, fuzzy->e_min + 5*e_step);
e_membership[PM] = Triangle_Membership(e, fuzzy->e_min + 4*e_step, fuzzy->e_min + 5*e_step, fuzzy->e_max);
e_membership[PB] = Triangle_Membership(e, fuzzy->e_min + 5*e_step, fuzzy->e_max, fuzzy->e_max);
// 偏差变化率ec的模糊化(与e同理)
float ec_range = fuzzy->ec_max - fuzzy->ec_min;
float ec_step = ec_range / 6;
ec_membership[NB] = Triangle_Membership(ec, fuzzy->ec_min, fuzzy->ec_min, fuzzy->ec_min + ec_step);
ec_membership[NM] = Triangle_Membership(ec, fuzzy->ec_min, fuzzy->ec_min + ec_step, fuzzy->ec_min + 2*ec_step);
ec_membership[NS] = Triangle_Membership(ec, fuzzy->ec_min + ec_step, fuzzy->ec_min + 2*ec_step, fuzzy->ec_min + 3*ec_step);
ec_membership[ZR] = Triangle_Membership(ec, fuzzy->ec_min + 2*ec_step, fuzzy->ec_min + 3*ec_step, fuzzy->ec_min + 4*ec_step);
ec_membership[PS] = Triangle_Membership(ec, fuzzy->ec_min + 3*ec_step, fuzzy->ec_min + 4*ec_step, fuzzy->ec_min + 5*ec_step);
ec_membership[PM] = Triangle_Membership(ec, fuzzy->ec_min + 4*ec_step, fuzzy->ec_min + 5*ec_step, fuzzy->ec_max);
ec_membership[PB] = Triangle_Membership(ec, fuzzy->ec_min + 5*ec_step, fuzzy->ec_max, fuzzy->ec_max);
}
// 解模糊:重心法(精度高、计算简洁,最常用)
float Fuzzy_Defuzzification(Fuzzy_HandleTypeDef *fuzzy, float *u_membership) {
float u_range = fuzzy->u_max - fuzzy->u_min;
float u_step = u_range / 6;
// 各模糊集合的重心(中点)
float u_centroid[7] = {
fuzzy->u_min, // NB重心
fuzzy->u_min + e_step, // NM重心
fuzzy->u_min + 2*e_step, // NS重心
fuzzy->u_min + 3*e_step, // ZR重心
fuzzy->u_min + 4*e_step, // PS重心
fuzzy->u_min + 5*e_step, // PM重心
fuzzy->u_max // PB重心
};
// 重心法计算精确输出
float numerator = 0.0f; // 分子:隶属度×重心之和
float denominator = 0.0f; // 分母:隶属度之和
for (int i = 0; i < 7; i++) {
numerator += u_membership[i] * u_centroid[i];
denominator += u_membership[i];
}
// 避免分母为0(无模糊规则匹配时,输出默认值)
return denominator == 0.0f ? (fuzzy->u_min + fuzzy->u_max) / 2 : numerator / denominator;
}
// 模糊控制计算(循环调用,输入偏差e、偏差变化率ec,输出控制量u)
float Fuzzy_Calculate(Fuzzy_HandleTypeDef *fuzzy, float e, float ec) {
float e_membership[7] = {0}; // e的各模糊集合隶属度
float ec_membership[7] = {0}; // ec的各模糊集合隶属度
float u_membership[7] = {0}; // u的各模糊集合隶属度
// 1. 模糊化
Fuzzy_Fuzzification(fuzzy, e, ec, e_membership, ec_membership);
// 2. 模糊推理(最大最小推理法)
for (int i = 0; i < 7; i++) { // 遍历e的所有模糊集合
for (int j = 0; j < 7; j++) { // 遍历ec的所有模糊集合
// 取e和ec隶属度的最小值,作为当前规则的触发强度
float trigger_strength = e_membership[i] < ec_membership[j] ? e_membership[i] : ec_membership[j];
// 确定当前规则输出的模糊集合
Fuzzy_LinguisticVar u_var = fuzzy->rule_table[i][j];
// 更新输出模糊集合的隶属度(取最大值)
if (trigger_strength > u_membership[u_var]) {
u_membership[u_var] = trigger_strength;
}
}
}
// 3. 解模糊,得到精确控制量
return Fuzzy_Defuzzification(fuzzy, u_membership);
}
// 示例:初始化模糊控制参数(温度控制,目标温度25℃)
void Fuzzy_Init(Fuzzy_HandleTypeDef *fuzzy) {
// 初始化输入输出范围(根据实际场景调整)
fuzzy->e_min = -10.0f; // 温度偏差范围:-10℃ ~ +10℃
fuzzy->e_max = 10.0f;
fuzzy->ec_min = -5.0f; // 温度偏差变化率范围:-5℃/s ~ +5℃/s
fuzzy->ec_max = 5.0f;
fuzzy->u_min = 0.0f; // 控制量(加热功率)范围:0% ~ 100%
fuzzy->u_max = 100.0f;
// 初始化模糊规则表(核心,根据实际控制经验调整)
Fuzzy_LinguisticVar rule_table[7][7] = {
{PB, PB, PM, PM, PS, ZR, ZR},
{PB, PB, PM, PS, PS, ZR, NS},
{PM, PM, PM, PS, ZR, NS, NS},
{PM, PM, PS, ZR, NS, NM, NM},
{PS, PS, ZR, NS, NS, NM, NM},
{PS, ZR, NS, NM, NM, NM, NB},
{ZR, ZR, NM, NM, NM, NB, NB}
};
memcpy(fuzzy->rule_table, rule_table, sizeof(rule_table));
} |
所有评论(0)