diff --git a/InkJetPrinter.cpp b/InkJetPrinter.cpp index 5f918d2..f940598 100644 --- a/InkJetPrinter.cpp +++ b/InkJetPrinter.cpp @@ -745,6 +745,38 @@ float PID_realize(float speed, float act){ } #endif +float PID_realize2(float speed, float act){ + pid.Kp = 0.08f; + pid.Ki = 0.003f; // 0.015 * (100ms/500ms) = 0.003,防积分饱和 + pid.Kd = 0.0f; + pid.SetSpeed = speed; + pid.ActualSpeed = act; + pid.err = pid.SetSpeed - pid.ActualSpeed; + + // 增量式PID差分公式:Δu = Kp*(e[k]-e[k-1]) + Ki*e[k] + Kd*(e[k]-2*e[k-1]+e[k-2]) + // e[k-2] 用 voltage 字段暂存 + float delta_u = pid.Kp * (pid.err - pid.err_last) + + pid.Ki * pid.err + + pid.Kd * (pid.err - 2.0f * pid.err_last + pid.voltage); + + // 自适应步长:误差大时快速逼近,误差小时精细调节 + float absErr = (pid.err < 0) ? -pid.err : pid.err; + float maxStep, minStep; + if(absErr > 50.0f) { + maxStep = 6.0f; minStep = -10.0f; // 大误差:快速逼近 + } else if(absErr > 20.0f) { + maxStep = 3.0f; minStep = -5.0f; // 中误差:适中 + } else { + maxStep = 1.5f; minStep = -2.5f; // 小误差:精细调节 + } + if(delta_u > maxStep) delta_u = maxStep; + if(delta_u < minStep) delta_u = minStep; + + pid.voltage = pid.err_last; // 暂存 e[k-2] + pid.err_last = pid.err; + return delta_u; +} + #if 0 struct _pid{ float SetSpeed; //定义设定值 @@ -783,69 +815,186 @@ float PID_realize(float speed, float act){ void InkJetPrinter::pressureAdj(int type) { - //float u, actual; - signed short delta_u; - signed short old = (signed short)sysPara->para.gearPumpValue; - static unsigned int oldPressure = 0; - static qint32 printOut = 0; - if(printOut++%2 !=0) { + if(sysPara->status.gearPumpRunStopFlag || sysPara->status.flagOfSpeedAlarm) + { + sysPara->para.gearPumpValue = 0; + u = 0.0f; + m_rampDone = false; + m_adjSkip = 0; + m_lastAvgPressure = 0; + m_bufValidCount = 0; + for(int i = 0; i < 20; i++) m_pressureBuf[i] = 0; + m_bufIdx = 0; + sysPara->devOp->WriteMoterPump(); return; } - int oldTargetPresuure = sysPara->para.pressure; - if(type == 1){ - sysPara->para.pressure = sysPara->para.pressure*1.2; - } - if(!sysPara->status.gearPumpRunStopFlag) + if(!sysPara->para.gearPumpEnable) { - if(u > 0 || ((sysPara->para.pressure - sysPara->status.PRESSURE) > 0) ) + // 非齿轮泵模式:沿用原有位置式PID + if(u > 0 || ((sysPara->para.pressure - sysPara->status.PRESSURE) > 0)) + u = PID_realize((float)sysPara->para.pressure, (float)sysPara->status.PRESSURE); + sysPara->para.gearPumpValue = (u > 0) ? (unsigned short)u : 0; + if(sysPara->para.gearPumpValue > 800) + sysPara->para.gearPumpValue = 800; + sysPara->devOp->WriteMoterPump(); + return; + } + + //回收泵模式限速 + int maxValue = sysPara->para.flagOfReclaimPumEnable ? 420 : 800; + if(maxValue < 60) maxValue = 60; + + int maxSpeed = (int)sysPara->para.gearPumpSpeedAlarm; + + int actual = sysPara->status.PRESSURE; + int target = (int)sysPara->para.pressure; + int cur; + + //每次进入都更新滑动平均缓冲 + m_pressureBuf[m_bufIdx] = actual; + m_bufIdx = (m_bufIdx + 1) % 20; + if(m_bufValidCount < 20) m_bufValidCount++; // 累积有效点数 + + // 优化:缓冲区未满时只对有效数据求平均,避免0值拉低平均值 + int avgPressure = 0; + for(int i = 0; i < m_bufValidCount; i++) { + avgPressure += m_pressureBuf[i]; + } + avgPressure /= m_bufValidCount; + + //硬保护:压力超过目标+50,立即强制减速,优先级最高 + if(actual > target + 50) + { + float overErr = (float)(actual - (target + 50)); + float delta = -0.1f * overErr; + if(delta < -15.0f) delta = -15.0f; + u += delta; + if(u < 60.0f) u = 60.0f; + if(u > (float)maxValue) u = (float)maxValue; + m_lastAvgPressure = actual; + sysPara->para.gearPumpValue = (unsigned short)(int)u; + sysPara->devOp->WriteMoterPump(); + return; + } + + // 软启动:自适应步长,每 800ms 一次 + // 自检期间也走此逻辑,自检完成后重置重新收敛 + // 软启动阶段不做压力稳定检测,优先快速收敛 + if(!m_rampDone) + { + if(++m_adjSkip < 8) { - u=PID_realize((float)sysPara->para.pressure,(float)sysPara->status.PRESSURE); + sysPara->para.gearPumpValue = (unsigned short)(int)u; + sysPara->devOp->WriteMoterPump(); + return; } - } - //u=PID_realize(350.0,(float)sysPara->status.PRESSURE); - if(u > 0) - { - sysPara->para.gearPumpValue = (unsigned short)u; - } - else - { - sysPara->para.gearPumpValue = 0; + m_adjSkip = 0; + + int err = target - actual; + + if(err < 0) + { + // 超压:小步减速 + u -= 1.0f; + } + else + { + // 自适应步长:差得远步子大,差得近步子小 + float step; + if (err > 200) step = 5.0f; + else if(err > 100) step = 3.0f; + else if(err > 50) step = 2.0f; + else step = 1.0f; + u += step; + } + + if(u < 60.0f) u = 60.0f; + if(u > (float)maxValue) u = (float)maxValue; + + // 转速上限保护:VX4特有,防止回收泵模式下转速超标 + if(sysPara->para.flagOfReclaimPumEnable && + sysPara->status.gearPumpRunSpeed >= maxSpeed) + { + u -= 3.0f; + if(u < 60.0f) u = 60.0f; + if(u > (float)maxValue) u = (float)maxValue; + } + + cur = (int)u; + + // 进入闭环条件:压力已接近目标±30以内 + if(sysPara->status.selfCheckDone && err >= -30 && err <= 30) + { + m_rampDone = true; + m_adjSkip = 0; + } + + sysPara->para.gearPumpValue = (unsigned short)cur; + sysPara->devOp->WriteMoterPump(); + return; } - if(sysPara->para.gearPumpValue>800) { - sysPara->para.gearPumpValue = 800; - } - /*********************改回收泵后压力调整*********************************/ - if(sysPara->para.gearPumpValue && sysPara->para.flagOfReclaimPumEnable){ - sysPara->para.gearPumpValue = (sysPara->para.gearPumpValue + old)/2; - if(sysPara->status.selfCheckDone){ - float ratio; - float ratio_c; - ratio = (float)sysPara->status.PRESSURE/sysPara->para.pressure; - if(sysPara->status.PRESSURE < oldPressure){ - if((ratio > 1.02 && ratio < 1.8) || - (ratio > 0.2 && ratio < 0.98)){ - ratio_c = ratio*1.15; - sysPara->para.gearPumpValue = (int)(sysPara->para.gearPumpValue*ratio_c); - } - } - } - if(sysPara->para.gearPumpValue < 60){ - sysPara->para.gearPumpValue = 75; - } - } - /************************************************************/ - - if(sysPara->status.gearPumpRunStopFlag) + //闭环:使用实时压力做快速小步修正,每200ms调整一次 { - sysPara->para.gearPumpValue = 0; + m_adjSkip++; + if(m_adjSkip < 2) + { + sysPara->para.gearPumpValue = (unsigned short)(int)u; + sysPara->devOp->WriteMoterPump(); + return; + } + m_adjSkip = 0; + + float err = (float)(target - actual); + float absErr = err; + if(absErr < 0.0f) absErr = -absErr; + + if(absErr < 0.5f) + { + m_lastAvgPressure = actual; + sysPara->para.gearPumpValue = (unsigned short)(int)u; + sysPara->devOp->WriteMoterPump(); + return; + } + + int pressureChange = actual - m_lastAvgPressure; + m_lastAvgPressure = actual; + + float delta_u; + if(absErr <= 5.0f && + ((err > 0.0f && pressureChange > 0) || + (err < 0.0f && pressureChange < 0))) + { + delta_u = -0.20f * (float)pressureChange; + } + else + { + delta_u = 0.05f * err - 0.20f * (float)pressureChange; + } + + float maxDelta; + if(absErr > 30.0f) maxDelta = 1.0f; + else if(absErr > 10.0f) maxDelta = 0.6f; + else maxDelta = 0.3f; + + if(delta_u > maxDelta) delta_u = maxDelta; + if(delta_u < -maxDelta) delta_u = -maxDelta; + + if(sysPara->para.flagOfReclaimPumEnable && + sysPara->status.gearPumpRunSpeed >= maxSpeed) + { + if(delta_u > 0.0f) delta_u = 0.0f; + } + + u += delta_u; + if(u < 60.0f) u = 60.0f; + if(u > (float)maxValue) u = (float)maxValue; + cur = (int)u; + + sysPara->para.gearPumpValue = (unsigned short)cur; + sysPara->devOp->WriteMoterPump(); } - if(sysPara->status.flagOfSpeedAlarm) - sysPara->para.gearPumpValue = 0; - sysPara->devOp->WriteMoterPump(); - oldPressure = sysPara->status.PRESSURE; - sysPara->para.pressure = oldTargetPresuure; } void InkJetPrinter::DacAdjustStore() @@ -1163,6 +1312,20 @@ void InkJetPrinter::timerHandler(void){ ControledSwitchFlag = false; pulse_3s = 0; } + // 直接恢复压力控制,不走 gearPumpStartFlag 的 3s 等待 + // 平滑切换,避免手动操作后自动恢复时出现压力突变 + if(m_lastByHand && !sysPara->status.isPumpValveControledByHand) + { + ControledSwitchFlag = true; + u = (float)sysPara->para.gearPumpValue; // 同步当前转速,避免突变 + m_rampDone = false; // 重新软启动,适应切换后的压力状态 + m_adjSkip = 0; + m_lastAvgPressure = 0; + m_bufValidCount = 0; + for(int i = 0; i < 20; i++) m_pressureBuf[i] = 0; + m_bufIdx = 0; + } + m_lastByHand = sysPara->status.isPumpValveControledByHand; if(!(sysPara->status.statWarn & WARN_STATUS_INK_SWINT)){//墨线开关,压力抖动 InkSwintFlag = true; } @@ -1530,11 +1693,19 @@ void InkJetPrinter::timerHandler(void){ if(sysPara->status.selfCheckCnt >= MAX_SELF_CHECK_CNT) { sysPara->status.selfCheckDone = 1; + // 自检完成平滑进入闭环,不强制跳转造成扰动 + m_rampDone = true; + m_adjSkip = 0; + // 同步 gearPumpValue 与 u,防止两者不一致 + sysPara->para.gearPumpValue = (unsigned short)u; LogInfo::setRunStatusText(tr("自检完成!!!")); ui->tabMainWindow->setRunStatus(tr("自检完成!!!")); qDebug()<<"自检完成!!!"; ui->tabPrintSetting->PrintSettingLog(); ui->tabMainWindow->enableReclaimCtrlButton(true); + + // 先让软件更新泵/阀的期望状态 + autoControlValvePump(); sysPara->devOp->mainInkCtrl(); sysPara->status.canRunAirPushing = true; if(sysPara->para.Reciclar) @@ -1552,7 +1723,28 @@ void InkJetPrinter::timerHandler(void){ if (!sysPara->status.airPushing || ui->tabMainWindow->m_2sFlag) { autoControlValvePump(); } - if(sysPara->para.gearPumpEnable && !sysPara->status.isPumpValveControledByHand && ControledSwitchFlag) { + // 检测回收泵模式切换,切换时重置泄漏保护学习状态和软启动状态 + if(m_lastReclaimMode != sysPara->para.flagOfReclaimPumEnable) + { + m_lastReclaimMode = sysPara->para.flagOfReclaimPumEnable; + gearPumpRunNormalFlag = false; // 泄漏保护重新学习 + gearPumpRunNormalValue = 0.0f; + + // 仅在压力偏离目标较大时才重置软启动 + // 避免模式抖动导致反复重新爬坡 + int err = (int)sysPara->para.pressure - sysPara->status.PRESSURE; + if(err < -100 || err > 100) { + m_rampDone = false; // 误差大时重新软启动 + m_adjSkip = 0; + m_lastAvgPressure = 0; + m_bufValidCount = 0; + for(int i = 0; i < 20; i++) m_pressureBuf[i] = 0; + m_bufIdx = 0; + } + // 否则保持当前控制状态,只更新maxValue限制 + } + // 压力调节改为100ms调用一次 + if(pulse_100ms && sysPara->para.gearPumpEnable && !sysPara->status.isPumpValveControledByHand && ControledSwitchFlag) { pressureAdj(0); } } @@ -3249,4 +3441,4 @@ void InkJetPrinter::resetPressureCnt(){ void InkJetPrinter::pressureAdjustForsystemseeting(){ pressureAdj(1); -} +} \ No newline at end of file diff --git a/InkJetPrinter.h b/InkJetPrinter.h index b8d463e..f50bd61 100644 --- a/InkJetPrinter.h +++ b/InkJetPrinter.h @@ -132,6 +132,16 @@ private: bool pushButtonStartFlag; unsigned char rWarnViscoReady; + + //压力控制相关状态变量 + bool m_rampDone = false; // 软启动完成标志 + int m_adjSkip = 0; // 节拍计数(闭环500ms周期) + int m_lastAvgPressure = 0; // 上次平均压力(微分项用) + int m_pressureBuf[20] = {}; // 压力滑动平均缓冲(20点=2s) + int m_bufIdx = 0; // 滑动平均写入索引 + int m_bufValidCount = 0; // 缓冲区有效数据点数(0~20) + bool m_lastReclaimMode = false; // 上次 flagOfReclaimPumEnable 状态 + bool m_lastByHand = false; // 上次 isPumpValveControledByHand 状态 }; -#endif // INKJETPRINTER_H +#endif // INKJETPRINTER_H \ No newline at end of file