From 7edc34dd4ddbf47c7caed6df44743e3d76ece76a Mon Sep 17 00:00:00 2001 From: Byons Date: Thu, 30 Jul 2026 15:13:04 +0800 Subject: [PATCH] =?UTF-8?q?2026-07-30=E9=99=86=E5=B7=A5=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9A=84=E5=8E=8B=E5=8A=9B=E7=AE=97=E6=B3=95=E7=AC=AC=E5=9B=9B?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- InkJetPrinter.cpp | 74 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/InkJetPrinter.cpp b/InkJetPrinter.cpp index e92ed93..f2967b7 100644 --- a/InkJetPrinter.cpp +++ b/InkJetPrinter.cpp @@ -372,7 +372,7 @@ struct DualModePIDParams { float deadzone; // 死区:误差小于此值时不调整 }; -// 无分流管设备参数(第二次调整:更保守的参数,优先稳定性) +// 无分流管设备参数 static DualModePIDParams params_no_reclaim = { // 快速模式:保持不变 0.06f, // fast_Kp @@ -381,22 +381,22 @@ static DualModePIDParams params_no_reclaim = { 8.0f, // fast_maxDelta 10, // fast_cycle (1000ms) - // 精准模式:大幅降低所有参数,优先稳定 - 0.010f, // precision_Kp (从0.018降到0.010,降低45%) - 0.002f, // precision_Ki (从0.005降到0.002,降低60%) - 0.005f, // precision_Kd (从0.015降到0.005,降低67%) - 1.5f, // precision_maxDelta (从2.5降到1.5) - 15, // precision_cycle (从12增加到15,即1500ms) - 100.0f, // integral_limit (从150降到100) - 8, // stable_threshold (从10降到8,更严格) - 15, // stable_count_req (从10增加到15,等待更久) + // 精准模式:降低Kp,大幅增加Kd抑制振荡 + 0.004f, // precision_Kp (从0.010降到0.004,降低60%,减少过调) + 0.0015f, // precision_Ki (从0.002降到0.0015,降低25%,减缓积分) + 0.025f, // precision_Kd (从0.005增加到0.025,提高5倍,抑制振荡) + 1.0f, // precision_maxDelta (从1.5降到1.0,更平滑) + 15, // precision_cycle (1500ms) + 80.0f, // integral_limit (从100降到80,防止积分饱和) + 8, // stable_threshold (保持8) + 8, // stable_count_req (从15降到8,更快响应) 80.0f, // switch_threshold 15.0f, // switch_hysteresis - 15.0f // deadzone (从8增加到15,更大的不动区) + 5.0f // deadzone (从15降到5,缩小不动区,减少振荡幅度) }; -// 有分流管设备参数(第二次调整) +// 有分流管设备参数 static DualModePIDParams params_with_reclaim = { // 快速模式 0.08f, // fast_Kp @@ -405,25 +405,26 @@ static DualModePIDParams params_with_reclaim = { 10.0f, // fast_maxDelta 10, // fast_cycle (1000ms) - // 精准模式:大幅降低 - 0.015f, // precision_Kp (从0.025降到0.015) - 0.003f, // precision_Ki (从0.008降到0.003) - 0.008f, // precision_Kd (从0.020降到0.008) - 2.0f, // precision_maxDelta (从3.0降到2.0) + // 精准模式:降低Kp,大幅增加Kd抑制振荡 + 0.006f, // precision_Kp (从0.015降到0.006,降低60%,减少过调) + 0.002f, // precision_Ki (从0.003降到0.002,降低33%,减缓积分) + 0.035f, // precision_Kd (从0.008增加到0.035,提高4倍,抑制振荡) + 1.2f, // precision_maxDelta (从2.0降到1.2,更平滑) 15, // precision_cycle (1500ms) - 120.0f, // integral_limit (从180降到120) - 12, // stable_threshold (从15降到12) - 12, // stable_count_req (从8增加到12) + 100.0f, // integral_limit (从120降到100,防止积分饱和) + 12, // stable_threshold (保持12) + 8, // stable_count_req (从12降到8,更快响应) 80.0f, // switch_threshold 15.0f, // switch_hysteresis - 18.0f // deadzone (从10增加到18) + 8.0f // deadzone (从18降到8,缩小不动区,减少振荡幅度) }; // PID控制器状态 struct PIDController { float integral; // 积分累积 float last_actual; // 上次实际值(用于微分先行) + float last_output; // 上次输出值(用于变化率限制) int adjust_skip; // 周期计数器 int stable_count; // 稳定计数器 bool in_precision_mode; // 当前是否在精准模式 @@ -431,6 +432,7 @@ struct PIDController { void reset() { integral = 0.0f; last_actual = 0.0f; + last_output = 0.0f; adjust_skip = 0; stable_count = 0; in_precision_mode = false; @@ -489,7 +491,7 @@ float DualModePID_Calculate(float setpoint, float actual, const DualModePIDParam // 比例项 float p_term = Kp * error; - // 积分项(带抗饱和) + // 积分项(带抗饱和和变速积分) float i_term = 0.0f; if (use_precision && Ki > 0.0f) { // 积分分离:只在精准模式下累积 @@ -498,7 +500,15 @@ float DualModePID_Calculate(float setpoint, float actual, const DualModePIDParam bool at_lower_limit = (u_current <= u_min + 1.0f) && (error < 0); if (!at_upper_limit && !at_lower_limit) { - ctrl.integral += error; + // 变速积分:误差越大,积分增益越小,防止积分饱和 + float ki_adjust = 1.0f; + if (abs_error > 30.0f) { + ki_adjust = 0.3f; // 大误差时降低积分作用 + } else if (abs_error > 15.0f) { + ki_adjust = 0.6f; // 中等误差时适度降低 + } + + ctrl.integral += error * ki_adjust; // 积分限幅 if (ctrl.integral > params.integral_limit) { @@ -531,6 +541,19 @@ float DualModePID_Calculate(float setpoint, float actual, const DualModePIDParam delta_u = -max_delta; } + // 输出变化率限制(精准模式下更平滑) + if (use_precision && ctrl.last_output != 0.0f) { + float max_rate = max_delta * 0.5f; // 最大变化率为max_delta的50% + float output_change = delta_u - ctrl.last_output; + if (output_change > max_rate) { + delta_u = ctrl.last_output + max_rate; + } else if (output_change < -max_rate) { + delta_u = ctrl.last_output - max_rate; + } + } + + ctrl.last_output = delta_u; + return delta_u; } @@ -668,10 +691,11 @@ void InkJetPrinter::pressureAdj() // 死区控制:误差很小时不调整,避免频繁微调 // 使用平均压力判断,与后续调整逻辑一致 + // 优化:在死区内不清零积分,保持积分补偿效果 if(abs_error_avg < params.deadzone) { - // 在死区内:清零积分,避免积分累积 - pid_ctrl.integral = 0.0f; + // 在死区内:保持积分不变,不再清零 + // 只有误差超过死区时才会重新累积或调整积分 pid_ctrl.adjust_skip = 0; pid_ctrl.stable_count = 0;