first commit

This commit is contained in:
2026-04-29 14:10:10 +08:00
commit b28556d43d
1558 changed files with 241386 additions and 0 deletions
+394
View File
@@ -0,0 +1,394 @@
# 开机 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` 对压力控制模型的影响。