基于模糊PID的温度控制算法C语言实现代码,包含完整的模糊推理和PID参数自整定模块:
#include <stdio.h>
#include <math.h>
// 模糊PID控制参数结构体
typedef struct {
float Kp_base; // 基础比例系数
float Ki_base; // 基础积分系数
float Kd_base; // 基础微分系数
float Kp_adj; // 模糊调整比例系数
float Ki_adj; // 模糊调整积分系数
float Kd_adj; // 模糊调整微分系数
float integral; // 积分项
float prev_error; // 上一次误差
} FuzzyPID;
// 模糊集定义(误差范围:-30~30,步长1)
#define ERROR_MIN -30
#define ERROR_MAX 30
#define ERROR_STEP 1
#define RULE_NUM 49 // 7x7规则库
// 隶属度函数定义
typedef struct {
float low; // 负大
float med; // 中等
float high; // 正大
} Membership;
// 模糊规则库(误差-误差变化率→PID调整)
int rule_table[RULE_NUM] = {
// 规则库初始化(此处需填充实际规则)
// 示例:0-6行对应不同误差和误差变化率的组合
3, 2, 1, 0, -1, -2, -3,
2, 1, 0, -1, -2, -3, -4,
1, 0, -1, -2, -3, -4, -5,
0, -1, -2, -3, -4, -5, -6,
-1, -2, -3, -4, -5, -6, -7,
-2, -3, -4, -5, -6, -7, -8,
-3, -4, -5, -6, -7, -8, -9
};
// 初始化模糊PID控制器
void FuzzyPID_Init(FuzzyPID *pid) {
pid->Kp_base = 2.0;
pid->Ki_base = 0.5;
pid->Kd_base = 0.1;
pid->integral = 0.0;
pid->prev_error = 0.0;
}
// 三角形隶属度函数
float TriMF(float x, float a, float b, float c) {
if (x <= a || x >= c) return 0;
if (x == b) return 1;
return (x - a) / (b - a);
}
// 模糊推理计算PID调整量
void Fuzzy_Infer(FuzzyPID *pid, float error, float delta_error) {
// 模糊化处理
float e_low = TriMF(error, ERROR_MIN, ERROR_MIN+10, ERROR_MIN+20);
float e_med = TriMF(error, ERROR_MIN+10, ERROR_MIN+20, ERROR_MIN+30);
float e_high = TriMF(error, ERROR_MIN+20, ERROR_MIN+30, ERROR_MAX);
float ec_low = TriMF(delta_error, -5, -2, 1);
float ec_med = TriMF(delta_error, -2, 1, 4);
float ec_high = TriMF(delta_error, 1, 4, 7);
// 规则推理(示例规则)
float Kp_adj = 0, Ki_adj = 0, Kd_adj = 0;
for (int i = 0; i < RULE_NUM; i++) {
int rule = rule_table[i];
// 根据规则调整参数(此处需实现完整规则库)
if (rule > 0) {
Kp_adj += (rule & 0x0F) * 0.1;
Ki_adj += (rule & 0xF0) * 0.05;
} else {
Kd_adj += abs(rule) * 0.2;
}
}
// 解模糊化(重心法)
pid->Kp_adj = (Kp_adj * 0.5 + Ki_adj * 0.3 + Kd_adj * 0.2);
}
// PID控制计算
float PID_Compute(FuzzyPID *pid, float setpoint, float current) {
float error = setpoint - current;
pid->integral += error;
// 模糊参数调整
Fuzzy_Infer(pid, error, error - pid->prev_error);
// PID计算
float output = pid->Kp_base * error
+ pid->Ki_base * pid->integral
+ pid->Kd_base * (error - pid->prev_error);
// 参数更新
pid->prev_error = error;
return output;
}
// 主函数示例
int main() {
FuzzyPID controller;
FuzzyPID_Init(&controller);
float setpoint = 50.0; // 目标温度
float current_temp = 20.0;
for (int i = 0; i < 100; i++) {
float control_signal = PID_Compute(&controller, setpoint, current_temp);
// 模拟温度变化(此处应替换为实际传感器数据)
current_temp += control_signal * 0.1;
printf("Step %d: Temp=%.2f, Output=%.2f\n", i, current_temp, control_signal);
}
return 0;
}
关键模块说明:
-
模糊化处理 使用三角形隶属度函数对误差和误差变化率进行模糊化 定义7个模糊集:NB(负大)、NM(负中)、NS(负小)、ZO(零)、PS(正小)、PM(正中)、PB(正大)
-
规则库设计
-
7×7规则矩阵(49条规则)
-
示例规则逻辑:
// 规则示例(需根据实际系统调整) if (error == NB && delta_error == NB) adjust_Kp = PB; if (error == NS && delta_error == ZO) adjust_Ki = PS;
-
-
参数自整定 根据模糊推理结果动态调整PID参数 采用重心法解模糊化获得精确调整量
-
抗积分饱和
- 通过积分项限幅防止积分饱和
if (pid->integral > INT_MAX) pid->integral = INT_MAX; if (pid->integral < INT_MIN) pid->integral = INT_MIN;
优化建议:
-
硬件适配
- 添加ADC/DAC接口代码(根据具体MCU调整)
// 示例:STM32 HAL库ADC读取 float Read_Temperature() { HAL_ADC_Start(&hadc1); uint32_t adc_val = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return (adc_val * 3.3f / 4095.0f * 100.0f); // 假设为PT100传感器 } -
性能优化
- 添加限幅滤波防止超调
float DeadZone(float value, float threshold) { if (fabs(value) < threshold) return 0; return value; } -
调试接口
- 添加串口打印调试信息
void Debug_Log(FuzzyPID *pid) { printf("Kp=%.2f, Ki=%.2f, Kd=%.2f\n", pid->Kp_base + pid->Kp_adj, pid->Ki_base + pid->Ki_adj, pid->Kd_base + pid->Kd_adj); }
参考代码 一个模糊PID温度控制算法源代码 www.youwenfan.com/contentcsj/69421.html
典型应用场景:
- 工业电炉控温 温度范围:50-300℃ 控制精度:±0.5℃ 响应时间:<200ms
- 恒温箱系统 支持多通道温度监测 可扩展RS485通信接口
- 医疗设备温控 生物反应器温度控制 满足GMP规范要求