# 开机 60 秒自检逻辑分析 ## 结论 这个项目的 **开机 60 秒自检**,确实和 **齿轮泵启动、压力建立、阀泵联动控制** 密切相关。 它不是单纯的软件倒计时,而是一个持续 **60 秒的供墨/压力建立过程**。在这段时间里,程序会: - 禁止打印; - 禁止部分回收控制; - 启动并调节齿轮泵; - 控制循环阀、主墨泵、压缩泵、泄压阀等; - 根据压力反馈不断调整齿轮泵输出; - 60 秒结束后才将自检标记为完成。 --- ## 1. 60 秒是怎么定义的 在 `SysPara.h` 中有定义: ```cpp #define MAX_SELF_CHECK_CNT 6000 // 60S, 以10ms为单位 ``` 也就是说: - 自检计数单位:`10ms` - 总计数:`6000` - 总时长:`6000 × 10ms = 60 秒` 因此,这个“60 秒自检”是代码里明确写死的固定时长。 --- ## 2. 自检主逻辑在哪里 核心逻辑在: - `InkJetPrinter::timerHandler()` - `InkJetPrinter::autoControlValvePump()` - `InkJetPrinter::pressureAdj()` - `DevOp::mainInkCtrl()` - `DevOp::WriteMoterPump()` 其中,`timerHandler()` 是整个开机阶段的主状态机。 在 `InkJetPrinter.cpp` 中,自检逻辑大致如下: ```cpp if(!sysPara->status.selfCheckDone) { /*开机自检*/ autoControlValvePump(); if(pulse_100ms){ pressureAdj(); } if(!sysPara->status.selfCheckCnt) { LogInfo::setRunStatusText(tr("开始自检,请等待60秒...............")); m_MainWidget->enableReclaimCtrlButton(false); m_MainWidget->enablePrintButton(false); sysPara->devOp->mainInkCtrl(); } if((++sysPara->status.selfCheckCnt % 100) == 0){ m_MainWidget->setRunStatus(tr("开始自检,请等待%1秒...") .arg((MAX_SELF_CHECK_CNT - sysPara->status.selfCheckCnt)/100)); } if(sysPara->status.selfCheckCnt >= MAX_SELF_CHECK_CNT) { sysPara->status.selfCheckDone = 1; LogInfo::setRunStatusText(tr("自检完成!!!")); m_MainWidget->enableReclaimCtrlButton(true); sysPara->devOp->mainInkCtrl(); } } ``` 这说明: ### 自检期间持续执行的动作 - 调用 `autoControlValvePump()`:控制阀和泵; - 每 `100ms` 调用一次 `pressureAdj()`:做压力闭环调节; - 禁止打印按钮; - 禁止回收控制按钮; - UI 持续显示倒计时; - 到 60 秒后,才置 `selfCheckDone = 1`。 --- ## 3. 这 60 秒内是不是和齿轮泵启动有关 **是,直接相关。** 在 `timerHandler()` 里,开机初期会先给齿轮泵一个启动值: ```cpp if(!(sysPara->status.statWarn & WARN_STATUS_INK_WARN) && !gearPumpRunFlag && !sysPara->status.isPumpValveControledByHand) { if(sysPara->para.gearPumpEnable) { sysPara->para.gearPumpValue = 150; if(tempFlag){ sysPara->devOp->WriteMoterPump(); tempFlag=0; } gearPumpStartFlag = true; } } ``` 这段逻辑的含义是: - 如果没有墨水报警; - 齿轮泵尚未进入稳定运行状态; - 当前不是手动控制; - 并且启用了齿轮泵; 那么就先给齿轮泵一个初始驱动值 `150`,用于 **开机启动齿轮泵**。 然后 3 秒后: ```cpp if(gearPumpStartFlag) { pulse_3s ++; if(pulse_3s == 3) { pulse_3s = 0; gearPumpRunFlag = true; ControledSwitchFlag = true; } } ``` 说明程序认为: - 前 3 秒主要是齿轮泵启动阶段; - 3 秒后进入可控运行阶段; - 后续允许更正式的压力闭环控制。 --- ## 4. 压力建立逻辑是什么 ### 4.1 压力调节函数:`pressureAdj()` `pressureAdj()` 是压力闭环调节核心。 它会读取: - 目标压力:`sysPara->para.pressure` - 当前压力:`sysPara->status.PRESSURE` 然后通过 PID 算法计算齿轮泵输出值: ```cpp if(!sysPara->status.gearPumpRunStopFlag) { if(sysPara->para.gearPumpEnable && sysPara->para.flagOfReclaimPumEnable) u=PID_realize2((float)sysPara->para.pressure,(float)sysPara->status.PRESSURE); else if(u > 0 || ((sysPara->para.pressure - sysPara->status.PRESSURE) > 0) ) { u=PID_realize((float)sysPara->para.pressure,(float)sysPara->status.PRESSURE); } } ``` 然后把计算结果写回齿轮泵控制值: ```cpp sysPara->para.gearPumpValue = (unsigned short)u; sysPara->devOp->WriteMoterPump(); ``` 也就是说: ### 压力建立过程的本质 1. 读取当前压力; 2. 与设定压力比较; 3. 用 PID 算法算出新的齿轮泵输出; 4. 将新的齿轮泵值下发给电机; 5. 周期性重复,直到压力逐渐建立并稳定。 因此,**60 秒自检的核心目标之一,就是把系统压力建立起来并趋于稳定。** --- ## 5. 自检期间阀泵还做了什么 `autoControlValvePump()` 负责阀和泵的联动。 从代码搜索结果可以看到,自检期间会执行: - 循环阀控制; - 主墨泵控制; - 泄压阀控制; - 压缩泵控制; - 自检特殊过程中的循环阀交替动作。 其中有一段很关键: ```cpp if(!sysPara->status.selfCheckDone || (sysPara->status.needPowerOffTimerout && sysPara->para.gearPumpEnable)){ cycleValveRunForSelfCheck(); } ``` 并且代码注释明确写了: ```cpp // 在开机自检过程中交替打开和关闭循环阀 void InkJetPrinter::cycleValveRunForSelfCheck() ``` 这说明: ### 自检不是只有齿轮泵在转 同时还包含: - 循环阀交替开关; - 供墨路径切换; - 主墨泵动作; - 压缩泵辅助建立压力; - 泄压阀根据压力状态切换。 也就是说,这 60 秒更像是一个 **整套流体系统的上电初始化过程**。 --- ## 6. 压力建立成功后,程序如何判断“运行正常” 在 `timerHandler()` 里有一段逻辑: ```cpp if(pushButtonStartFlag && sysPara->status.selfCheckDone) { if((sysPara->status.PRESSURE > (sysPara->para.pressure -10)) && (sysPara->status.PRESSURE < (sysPara->para.pressure +10))) { if(pulse_1s) { pulse_5s++; } if(pulse_5s == 5) { pulse_5s = 0; gearPumpRunNormalFlag = true; gearPumpRunNormalValue = u; } } } ``` 说明: - 当前压力进入目标压力 ±10 范围; - 并且持续 5 秒; - 才会认为齿轮泵运行正常,置 `gearPumpRunNormalFlag = true`。 这说明系统不仅要求“压力到达”,还要求“稳定一段时间”。 --- ## 7. 如果压力建立失败,会发生什么 代码中有一套异常判断: ```cpp if(gearPumpRunNormalFlag && !sysPara->status.isPumpValveControledByHand && sysPara->para.gearPumpEnable) { if(u > gearPumpRunNormalValue*1.5) { if(pulse_1s) { count_3s++; if(count_3s == 3) { sysPara->status.gearPumpRunStopFlag = true; gearPumpRunNormalFlag = false; } } } } ``` 含义是: - 如果原本已经进入正常运行; - 但后面为了维持压力,齿轮泵输出突然需要比正常值高很多(超过 1.5 倍); - 并持续 3 秒; 程序就会认为: - 可能有压力泄漏; - 或者压力传感器异常; - 然后置 `gearPumpRunStopFlag = true`,停泵保护。 所以从设计意图看,系统在持续监控: - 压力是否能建立; - 建立后是否能稳定; - 若不能稳定,是否可能存在泄漏或故障。 --- ## 8. `mainInkCtrl()` 里和自检有什么关系 在 `DevOp::mainInkCtrl()` 中: ```cpp dataOfmainInkCtrl[0] = (isReleaseValveOpen()?(1<<3):0) + (isMainInkPumpOpen()?(1<<2):0) + (sysPara->status.selfCheckDone?(1<<1):0) + (sysPara->status.isPumpValveControledByHand?1:0); ``` 这里把 `selfCheckDone` 编码到发送给底层控制板的数据位中。 说明: - 下位机/控制板也知道“自检是否完成”; - 自检完成前后,底层控制行为可能不同; - 这进一步证明自检不是单纯界面逻辑,而是参与底层泵阀控制状态机的。 --- ## 9. 最终结论 ### 这 60 秒内做了什么? 它主要在做: 1. **禁止打印与部分人工操作**; 2. **启动齿轮泵**,先给初始值; 3. **切换并控制循环阀、主墨泵、压缩泵、泄压阀**; 4. **每 100ms 根据压力反馈调节齿轮泵输出**; 5. **持续尝试建立并稳定系统压力**; 6. **监测压力异常、泄漏、转速异常等问题**; 7. **满 60 秒后置自检完成标志**。 ### 是否和齿轮泵启动、压力建立有关? **是,明确相关,而且这就是主线逻辑。** 可以理解为: > 开机 60 秒自检 = 齿轮泵启动 + 阀泵联动 + 压力建立 + 状态稳定确认 的初始化阶段。 --- ## 10. 一个更直观的时序理解 可以粗略理解为: ### 第 0~3 秒 - 给齿轮泵一个初始驱动值; - 启动供墨相关执行机构; - 为后续闭环控制做准备。 ### 第 3 秒以后到 60 秒内 - 进入正常自检控制阶段; - 循环阀交替动作; - 主墨泵/压缩泵/泄压阀按状态联动; - 每 100ms 调整齿轮泵输出; - 持续建立和稳定压力。 ### 到 60 秒 - 不管压力是否已经很早达标,代码仍会继续走完整个自检窗口; - 计时结束后才标记 `selfCheckDone = 1`; - 允许进入正常工作阶段。 所以它更像: > **固定时长的初始化窗口 + 期间持续进行压力闭环建立** 而不是: > **压力一达标就立刻结束自检** --- ## 11. 补充说明 从代码风格上看,这套逻辑明显是“设备控制型状态机”: - 上位机负责状态判断与策略; - `DevOp` 负责向底层板卡发送控制命令; - `selfCheckDone`、`gearPumpRunFlag`、`gearPumpRunNormalFlag`、`gearPumpRunStopFlag` 这些标志位共同构成了开机阶段的控制流程。 如果还要继续深挖,下一步最值得分析的是: 1. `autoControlValvePump()` 的完整阀泵切换条件; 2. `cycleValveRunForSelfCheck()` 的开关节奏; 3. `checkPressureControl()` 对压力异常的判定规则; 4. 回收泵使能 `flagOfReclaimPumEnable` 对压力控制模型的影响。