Browse Source

PID调节风柜系统

dev_mz
v-lijf43 1 week ago
parent
commit
b22ba182dc
  1. 11
      mh-quartz/src/main/java/com/mh/quartz/domain/FuzzyLevel.java
  2. 16
      mh-quartz/src/main/java/com/mh/quartz/task/AHUTask.java
  3. 89
      mh-quartz/src/main/java/com/mh/quartz/util/AHUPIDControlUtil.java
  4. 29
      mh-quartz/src/main/java/com/mh/quartz/util/FuzzyRuleBase.java

11
mh-quartz/src/main/java/com/mh/quartz/domain/FuzzyLevel.java

@ -0,0 +1,11 @@
package com.mh.quartz.domain;
/**
* @Classname FuzzyLevel
* Todo:
* @Date 2025-05-31 14:19
* @Created by LJF
*/
public enum FuzzyLevel {
NB, NM, NS, ZO, PS, PM, PB; // 极小,较小,小,零,稍大,较大,极大
}

16
mh-quartz/src/main/java/com/mh/quartz/task/AHUTask.java

@ -93,10 +93,6 @@ public class AHUTask {
continue;
}
// 初始化PID参数(可动态调整)
// PIDParams params = new PIDParams(2.5, 0.1, 0.5);
PIDParams params = new PIDParams(new BigDecimal(kp).doubleValue(), new BigDecimal(ki).doubleValue(), new BigDecimal(kd).doubleValue()); // Kp, Ki, Kd
// 过滤获取回风温度设置值
Optional<CollectionParamsManage> second = collectionParamsManages
.stream()
@ -106,10 +102,12 @@ public class AHUTask {
continue;
}
// 得出回风温度设置值
double backTemp = second.get().getCurValue().doubleValue();
double backTempSet = second.get().getCurValue().doubleValue();
// 设定目标温度(夏季制冷24℃)
AHUPIDControlUtil pid = new AHUPIDControlUtil(params, backTemp);
AHUPIDControlUtil controller = new AHUPIDControlUtil();
System.out.println("开始模糊PID控制循环:");
// 过滤获取当前回风温度
Optional<CollectionParamsManage> third = collectionParamsManages
@ -123,7 +121,7 @@ public class AHUTask {
double temp = third.get().getCurValue().doubleValue();
// 2. 计算水阀开度(时间间隔1秒)
double valveOpening1 = pid.calculate(temp, 1.0);
double valveOpening1 = controller.compute(backTempSet, temp, 60.0);
int valveOpening = new BigDecimal(valveOpening1).intValue();
// 过滤获取水阀调节参数
@ -143,8 +141,8 @@ public class AHUTask {
changeValues.add(new OrderEntity(collectionParamsManage.getId(), String.valueOf(valveOpening), Integer.parseInt(collectionParamsManage.getParamType()), collectionParamsManage.getOtherName()));
sendOrderToMqtt(changeValues);
// 3. 应用水阀开度(实际应用发送给执行机构)
log.info("回风温度: {} ℃ | 水阀开度: {} % | P:{}, I:{} D:{} ",
temp, valveOpening, params.getKp(), params.getKi(), params.getKd());
log.info("回风温度: {} ℃ | 水阀开度: {} % ",
temp, valveOpening);
}
}

89
mh-quartz/src/main/java/com/mh/quartz/util/AHUPIDControlUtil.java

@ -1,5 +1,6 @@
package com.mh.quartz.util;
import com.mh.quartz.domain.FuzzyLevel;
import com.mh.quartz.domain.PIDParams;
/**
@ -11,46 +12,70 @@ import com.mh.quartz.domain.PIDParams;
*/
public class AHUPIDControlUtil {
// PID控制器核心实现
private PIDParams params;
private double setPoint; // 目标温度
private double prevError; // 上次误差
private double integral; // 积分累积值
private double minOutput = 0; // 输出下限(0%)
private double maxOutput = 100; // 输出上限(100%)
public AHUPIDControlUtil(PIDParams params, double setPoint) {
this.params = params;
this.setPoint = setPoint;
}
private double kp = 2.0, ki = 0.1, kd = 0.0;
private double integral = 0;
private double previousError = 0;
// 模糊增益修正比例
private double deltaKpScale = 0.5;
private double deltaKiScale = 0.01;
private double deltaKdScale = 0.01;
public double compute(double setTemp, double currentTemp, double deltaTime) {
double error = setTemp - currentTemp;
double dError = (error - previousError) / deltaTime;
// 计算水阀开度百分比 (0-100%)
public double calculate(double currentTemp, double deltaTime) {
// 1. 计算当前误差
double error = setPoint - currentTemp;
// 模糊映射
FuzzyLevel eLevel = toFuzzyLevel(error);
FuzzyLevel ecLevel = toFuzzyLevel(dError);
// 2. 比例项计算
double proportional = params.getKp() * error;
// 获取PID参数调整
FuzzyLevel kpAdjust = FuzzyRuleBase.getKpAdjust(eLevel, ecLevel);
FuzzyLevel kiAdjust = kpAdjust; // 简化处理
FuzzyLevel kdAdjust = kpAdjust;
// 3. 积分项计算(带抗饱和)
integral += params.getKi() * error * deltaTime;
// 积分限幅防止超调
integral = Math.max(minOutput, Math.min(maxOutput, integral));
kp += fuzzyDeltaToValue(kpAdjust, deltaKpScale);
ki += fuzzyDeltaToValue(kiAdjust, deltaKiScale);
kd += fuzzyDeltaToValue(kdAdjust, deltaKdScale);
// 4. 微分项计算(带低通滤波)
double derivative = params.getKd() * (error - prevError) / deltaTime;
prevError = error; // 更新误差记录
// 限幅
kp = Math.max(0, Math.min(kp, 10));
ki = Math.max(0, Math.min(ki, 1));
kd = Math.max(0, Math.min(kd, 1));
// 5. 综合输出(0-100%)
double output = proportional + integral + derivative;
// PID 计算
integral += error * deltaTime;
double output = kp * error + ki * integral + kd * dError;
// System.out.println("计算输出值:" + output + ",误差:" + error + ",误差变化:" + dError);
previousError = error;
// 输出冷冻水阀开度,限制在0~100%
return Math.max(0, Math.min(100, Math.abs(output)));
}
// 6. 输出限幅
return Math.max(minOutput, Math.min(maxOutput, output));
// 将数值误差映射为模糊等级
public static FuzzyLevel toFuzzyLevel(double value) {
if (value <= -3) return FuzzyLevel.NB;
else if (value <= -2) return FuzzyLevel.NM;
else if (value <= -1) return FuzzyLevel.NS;
else if (value <= 1) return FuzzyLevel.ZO;
else if (value <= 2) return FuzzyLevel.PS;
else if (value <= 3) return FuzzyLevel.PM;
else return FuzzyLevel.PB;
}
// 更新设定温度
public void setSetPoint(double setPoint) {
this.setPoint = setPoint;
// 将模糊等级转为实际数值调整量
public static double fuzzyDeltaToValue(FuzzyLevel level, double scale) {
switch (level) {
case NB: return -3 * scale;
case NM: return -2 * scale;
case NS: return -1 * scale;
case ZO: return 0;
case PS: return 1 * scale;
case PM: return 2 * scale;
case PB: return 3 * scale;
default: return 0;
}
}
}

29
mh-quartz/src/main/java/com/mh/quartz/util/FuzzyRuleBase.java

@ -0,0 +1,29 @@
package com.mh.quartz.util;
import com.mh.quartz.domain.FuzzyLevel;
/**
* @Classname FuzzyRuleBase
* Todo:
* @Date 2025-05-31 14:20
* @Created by LJF
*/
public class FuzzyRuleBase {
// ΔKp 规则:根据误差 e 与误差变化 ec 得到修正量
private static final FuzzyLevel[][] kpRuleTable = {
{FuzzyLevel.PB, FuzzyLevel.PM, FuzzyLevel.PS, FuzzyLevel.ZO, FuzzyLevel.NS, FuzzyLevel.NM, FuzzyLevel.NB},
{FuzzyLevel.PM, FuzzyLevel.PS, FuzzyLevel.ZO, FuzzyLevel.NS, FuzzyLevel.NM, FuzzyLevel.NB, FuzzyLevel.NB},
{FuzzyLevel.PS, FuzzyLevel.ZO, FuzzyLevel.NS, FuzzyLevel.NM, FuzzyLevel.NB, FuzzyLevel.NB, FuzzyLevel.NB},
{FuzzyLevel.ZO, FuzzyLevel.ZO, FuzzyLevel.ZO, FuzzyLevel.ZO, FuzzyLevel.ZO, FuzzyLevel.ZO, FuzzyLevel.ZO},
{FuzzyLevel.NS, FuzzyLevel.ZO, FuzzyLevel.PS, FuzzyLevel.PM, FuzzyLevel.PB, FuzzyLevel.PB, FuzzyLevel.PB},
{FuzzyLevel.NM, FuzzyLevel.NS, FuzzyLevel.ZO, FuzzyLevel.PS, FuzzyLevel.PM, FuzzyLevel.PB, FuzzyLevel.PB},
{FuzzyLevel.NB, FuzzyLevel.NB, FuzzyLevel.NS, FuzzyLevel.ZO, FuzzyLevel.PS, FuzzyLevel.PM, FuzzyLevel.PB}
};
public static FuzzyLevel getKpAdjust(FuzzyLevel e, FuzzyLevel ec) {
return kpRuleTable[e.ordinal()][ec.ordinal()];
}
// 可扩展为不同规则表:getKiAdjust(), getKdAdjust()
}
Loading…
Cancel
Save