diff --git a/PressureMonitor.cpp b/PressureMonitor.cpp index fcbd70e..2a34e02 100644 --- a/PressureMonitor.cpp +++ b/PressureMonitor.cpp @@ -2,57 +2,110 @@ #include PressureMonitor::PressureMonitor() - : m_stableTickCount(0) + : m_tickCounter(0) + , m_sampleCount(0) + , m_bufIdx(0) , m_totalTickCount(0) , m_timeout(false) { + for (int i = 0; i < BUF_SIZE; i++) { + m_buf[i] = 0.0f; + } } bool PressureMonitor::tick(float realtimePressure, float calibratedPressure) { m_totalTickCount++; - if (calibratedPressure <= 0.0f) { - m_stableTickCount = 0; - return false; - } - - float upperBound = calibratedPressure + 10.0f; - float lowerBound = calibratedPressure - 10.0f; - - if (realtimePressure >= lowerBound && realtimePressure <= upperBound) { - m_stableTickCount++; - } else { - m_stableTickCount = 0; - } - - // 5分钟超时兜底:无论压力是否稳定,都触发结束 if (m_totalTickCount >= TIMEOUT_TICKS) { m_timeout = true; return true; } - return m_stableTickCount >= REQUIRED_STABLE_TICKS; + if (m_tickCounter != 0) { + m_tickCounter = (m_tickCounter + 1) % SAMPLE_INTERVAL_TICKS; + return false; + } + m_tickCounter = (m_tickCounter + 1) % SAMPLE_INTERVAL_TICKS; + + if (calibratedPressure <= 0.0f) { + return false; + } + + m_buf[m_bufIdx] = realtimePressure; + m_bufIdx = (m_bufIdx + 1) % BUF_SIZE; + m_sampleCount++; + + if (m_sampleCount < BUF_SIZE) { + return false; + } + + float rangeMin = calibratedPressure - 10.0f; + float rangeMax = calibratedPressure + 10.0f; + + if (!checkFirst4InRange(rangeMin, rangeMax)) { + return false; + } + + float avg = computeTrimmedMean(); + return (avg >= rangeMin && avg <= rangeMax); } void PressureMonitor::reset() { - m_stableTickCount = 0; + m_tickCounter = 0; + m_sampleCount = 0; + m_bufIdx = 0; m_totalTickCount = 0; m_timeout = false; + for (int i = 0; i < BUF_SIZE; i++) { + m_buf[i] = 0.0f; + } } bool PressureMonitor::isCurrentlyInRange() const { - return m_stableTickCount > 0; + return (m_sampleCount >= BUF_SIZE); } int PressureMonitor::stableTickCount() const { - return m_stableTickCount; + return m_sampleCount; } bool PressureMonitor::wasTimeout() const { return m_timeout; +} + +const float* PressureMonitor::buffer() const +{ + return m_buf; +} + +bool PressureMonitor::checkFirst4InRange(float rangeMin, float rangeMax) const +{ + for (int i = 0; i < 4; i++) { + float val = m_buf[(m_bufIdx + i) % BUF_SIZE]; + if (val < rangeMin || val > rangeMax) { + return false; + } + } + return true; +} + +float PressureMonitor::computeTrimmedMean() const +{ + float minVal = m_buf[0]; + float maxVal = m_buf[0]; + float sum = 0.0f; + + for (int i = 0; i < BUF_SIZE; i++) { + float val = m_buf[i]; + sum += val; + if (val < minVal) minVal = val; + if (val > maxVal) maxVal = val; + } + + return (sum - minVal - maxVal) / (float)(BUF_SIZE - 2); } \ No newline at end of file diff --git a/PressureMonitor.h b/PressureMonitor.h index 1f0b754..d4f1b88 100644 --- a/PressureMonitor.h +++ b/PressureMonitor.h @@ -6,33 +6,42 @@ class PressureMonitor public: PressureMonitor(); - // 每个100ms tick 调用一次 + // 每个100ms tick 调用一次(外部调用频率不变) // realtimePressure: 实时压力 (sysPara->status.PRESSURE) // calibratedPressure: 标定压力 (sysPara->para.pressure) + // + // 内部逻辑:每500ms采样一次,维护最近12个采样的环形缓冲区。 + // 缓冲区满12个后,先检查最旧的4个采样是否各自在标定值 ±10 范围内, + // 满足后去掉全部12个中的最大值和最小值取平均,判断均值是否在 ±10 内。 + // 每次新采样入队、最旧采样出队后立即重新判定。 // 返回 true 表示: - // 1) 压力已持续稳定 3 秒(±10 范围内),或 + // 1) 前4入界且去极值均值在 ±10 范围内,或 // 2) 超过 2 分钟仍未稳定,兜底超时结束 bool tick(float realtimePressure, float calibratedPressure); - // 重置监测器状态 void reset(); - // 当前压力是否在 ±10 范围内 bool isCurrentlyInRange() const; - - // 当前连续稳定的 tick 计数 int stableTickCount() const; - - // 是否因超时而触发结束(兜底) bool wasTimeout() const; -private: - int m_stableTickCount; - int m_totalTickCount; - bool m_timeout; + // 返回环形缓冲区(12个压力值) + const float* buffer() const; - static const int REQUIRED_STABLE_TICKS = 30; // 3秒 / 100ms = 30 ticks - static const int TIMEOUT_TICKS = 1200; // 2分钟 / 100ms = 1200 ticks +private: + float computeTrimmedMean() const; + bool checkFirst4InRange(float rangeMin, float rangeMax) const; + + static const int SAMPLE_INTERVAL_TICKS = 5; // 500ms / 100ms + static const int BUF_SIZE = 12; // 缓冲区大小 + static const int TIMEOUT_TICKS = 1200; // 2分钟 / 100ms + + int m_tickCounter; // 100ms tick 计数,==0 时采样 + int m_sampleCount; // 已采集样本总数 + int m_bufIdx; // 环形缓冲区下一次写入位置 + float m_buf[12]; // 环形缓冲区 + int m_totalTickCount; // 超时用总 tick 计数 + bool m_timeout; // 是否已超时 }; #endif // PRESSUREMONITOR_H \ No newline at end of file diff --git a/mainwidget.cpp b/mainwidget.cpp index a09d6c4..42d8e8f 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -1235,19 +1235,36 @@ void MainWidget::airPushingProcess() setRunStatus(tr("等待压力稳定...")); - // 调用压力检测器,监测压力持续3秒波动范围不超过标定值的+-10% if(m_pressureMonitor->tick((float)sysPara->status.PRESSURE, (float)sysPara->para.pressure)) { reclaimTanOpen(); sysPara->status.airPushingDone = 1; sysPara->status.airPushing = 0; sysPara->status.airPushingOnTime = 0; airPushTimer->stop(); + bool isTimeout = m_pressureMonitor->wasTimeout(); + float bufCopy[12]; + memcpy(bufCopy, m_pressureMonitor->buffer(), sizeof(bufCopy)); m_pressureMonitor->reset(); setRunStatus(tr("喷嘴开启中")); - LogInfo::setRunStatusText(m_pressureMonitor->wasTimeout() + LogInfo::setRunStatusText(isTimeout ? "Pressure unstable timeout, fallback open the reclaim tank." : "Pressure has stabled, will open the reclaim tank."); + + QString pressureSet = QString("Pressure buffer: [%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12]") + .arg(bufCopy[0], 0, 'f', 1) + .arg(bufCopy[1], 0, 'f', 1) + .arg(bufCopy[2], 0, 'f', 1) + .arg(bufCopy[3], 0, 'f', 1) + .arg(bufCopy[4], 0, 'f', 1) + .arg(bufCopy[5], 0, 'f', 1) + .arg(bufCopy[6], 0, 'f', 1) + .arg(bufCopy[7], 0, 'f', 1) + .arg(bufCopy[8], 0, 'f', 1) + .arg(bufCopy[9], 0, 'f', 1) + .arg(bufCopy[10], 0, 'f', 1) + .arg(bufCopy[11], 0, 'f', 1); + LogInfo::setRunStatusText(pressureSet); } return; }