Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AHU-0024 — Duct static pressure reset not functioning

Statusverified — engine e2ff2f8, cxf:fnv1a128:0bc49a814c1f728a54e9a9a3ecff1244, 2026-08-17
Severity3
Methodstatistical
Phase2
CategoryEXCESS_CONSUMPTION
ConfidenceHIGH
EstimationPROXY_ESTIMATION
G36
ClustersCLU-02
Suppresses
Suppressed by
RelatedAHU-0001, AHU-0023, AHU-0031, FPB-0002
Playbooksmissing-reset
SourceHVAC FDD Reference v1.0 §9, AHU-0024; PNNL RetuningOpps A01; PNNL-25985 EEM-12
Operating statesOccupied, fan running

Preconditions (host-enforced): AHU serves multiple zones; zone damper feedback available and aggregated by the host into zone_dmpr_pos_max. When zone damper data is missing or stale, the verdict is NO_EVAL, not healthy.

Points: dsp_sp, zone_dmpr_pos_max

Outputs:

  • yFault — True while the DSP setpoint has stayed flat over the evaluation window despite all zone dampers staying well below fully open, for at least alarm_delay

Parameters:

NameDefaultUnitCXF pathDescription
evaluation_window259200.0sspRef.samplePeriod, spFlatHeld.delayTime, dmprLowHeld.delayTimeWindow over which setpoint flatness and low damper demand are assessed (3 days)
sp_flat_tolerance25.0PaspFlat.tMax deviation of DSP_SP from its sampled baseline to count as flat (half the reference’s 50 Pa min expected range)
high_damper_threshold70.0%dmprLow.tMax zone damper position below which the setpoint could safely drop
alarm_delay86400.0spersist.delayTimeFault persistence before alarm (24 h)

Description

The duct static pressure setpoint remains fixed despite varying zone demand. A functioning DSP reset (G36 §5.16.1 trim-and-respond) lowers the setpoint when zone dampers are not widely open; because fan power scales with the cube of pressure, even small reductions produce outsized savings. The other half of the “74% problem” with AHU-0023 — absent in 74% of buildings (PNNL 151-building study) — and a member of cluster CLU-02 with the same $0 desk-only fix.

Detection Logic

baseline(dsp_sp) = dsp_sp sampled and held every evaluation_window (3 days)
sp_flat          = |dsp_sp − baseline(dsp_sp)| < sp_flat_tolerance,
                   continuously for evaluation_window
low_demand       = zone_dmpr_pos_max < high_damper_threshold,
                   continuously for evaluation_window

yFault = sp_flat AND low_demand, sustained for alarm_delay

Block graph (rule.cxf.jsonld):

AHU-0024 block graph

The setpoint chain mirrors AHU-0023’s sampled-baseline flatness detector. The demand condition needs no baseline at all: the reference’s max(zone_dmpr_pos_all) < 70% over the window is exactly equivalent to “the highest zone damper stays below 70% continuously,” which is one LessThreshold plus a dwell TrueDelay on the host-aggregated maximum. Worst-case time to alarm from cold start: evaluation_window + alarm_delay (4 days).

Possible Diagnoses

  1. DSP reset never programmed in the BAS
  2. DSP reset disabled by an operator
  3. Trim-and-respond parameters misconfigured
  4. Zone damper feedback not connected to the AHU controller

Energy Impact

EXCESS_CONSUMPTION, HIGH confidence, PROXY_ESTIMATION (EEM-12). Fan energy scales with the cube of duct pressure: a 20% setpoint reduction yields ~49% fan energy savings. Savings 1–3% of site energy; climate-neutral. Prevalence: 74% of buildings.

Emissions Impact

Scope 2, PROXY_EMISSIONS, HIGH confidence; typical 400–3,000 kg CO₂e/yr (excess fan energy, cubic law). Avoided-emissions basis: MOER.

Deviations

  • zone_dmpr_pos_all (array) → host-derived zone_dmpr_pos_max (scalar). The reference consumes every zone damper position; library v1 avoids array boundary points, so the host aggregates the maximum across the zones served and feeds one scalar (flagged derived in the point dictionary). The zone-side underlying points get their semantic tags when the VAV dictionary lands.
  • Windowed range → sampled-baseline flatness on the setpoint chain, as AHU-0023 (sp_flat_tolerance = min_expected_sp_range/2; same MovingAverage ring-capacity rationale). The damper condition is an exact transformation, not an approximation: max over window < tcontinuously below t.
  • delayOnInit = true on all TrueDelays (startup conservatism per AHU-0016).

Notes

Evaluate together with AHU-0023: both fire → CLU-02 confirmed, one trim-and-respond programming visit fixes both. The reference’s PNNL-27338 AIRCx corollary — DSP > 0.2 in. w.g. during unoccupied hours — is covered separately by the after-hours rules (AHU-0018 family).

Test Vectors

5 scenarios, clock step 300 s over 432000 s.

ScenarioDescription
reset_workingReference vector: DSP_SP modulates 100 Pa with demand; no fault
fixed_sp_low_demandReference vector: DSP_SP pinned while dampers well below 70%; fault after evaluation_window (3d) + alarm_delay (24h)
fixed_sp_high_demandReference vector: DSP_SP pinned but dampers near max — setpoint cannot drop, no fault
demand_rises_resetsLow demand for 2.3 days, then dampers open past threshold before the window completes; dwell resets, never alarms
damper_at_thresholdMax damper exactly at high_damper_threshold is not low demand (strict < comparison)
vectors.json
{
  "schema": "cxf-library/vectors/v1",
  "clock": {
    "step_s": 300,
    "horizon_s": 432000
  },
  "scenarios": [
    {
      "name": "reset_working",
      "description": "Reference vector: DSP_SP modulates 100 Pa with demand; no fault",
      "inputs": {
        "dsp_sp": [
          {
            "t": 0,
            "value": 350.0
          },
          {
            "t": 21600,
            "value": 450.0
          },
          {
            "t": 43200,
            "value": 350.0
          },
          {
            "t": 64800,
            "value": 450.0
          },
          {
            "t": 86400,
            "value": 350.0
          },
          {
            "t": 108000,
            "value": 450.0
          },
          {
            "t": 129600,
            "value": 350.0
          },
          {
            "t": 151200,
            "value": 450.0
          },
          {
            "t": 172800,
            "value": 350.0
          },
          {
            "t": 194400,
            "value": 450.0
          },
          {
            "t": 216000,
            "value": 350.0
          },
          {
            "t": 237600,
            "value": 450.0
          },
          {
            "t": 259200,
            "value": 350.0
          },
          {
            "t": 280800,
            "value": 450.0
          },
          {
            "t": 302400,
            "value": 350.0
          },
          {
            "t": 324000,
            "value": 450.0
          },
          {
            "t": 345600,
            "value": 350.0
          },
          {
            "t": 367200,
            "value": 450.0
          },
          {
            "t": 388800,
            "value": 350.0
          },
          {
            "t": 410400,
            "value": 450.0
          },
          {
            "t": 432000,
            "value": 350.0
          }
        ],
        "zone_dmpr_pos_max": 85.0
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 432000,
          "equals": false
        }
      ]
    },
    {
      "name": "fixed_sp_low_demand",
      "description": "Reference vector: DSP_SP pinned while dampers well below 70%; fault after evaluation_window (3d) + alarm_delay (24h)",
      "inputs": {
        "dsp_sp": 400.0,
        "zone_dmpr_pos_max": 45.0
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 343200,
          "equals": false
        },
        {
          "output": "yFault",
          "from_s": 348000,
          "to_s": 432000,
          "equals": true
        }
      ]
    },
    {
      "name": "fixed_sp_high_demand",
      "description": "Reference vector: DSP_SP pinned but dampers near max \u2014 setpoint cannot drop, no fault",
      "inputs": {
        "dsp_sp": 400.0,
        "zone_dmpr_pos_max": 95.0
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 432000,
          "equals": false
        }
      ]
    },
    {
      "name": "demand_rises_resets",
      "description": "Low demand for 2.3 days, then dampers open past threshold before the window completes; dwell resets, never alarms",
      "inputs": {
        "dsp_sp": 400.0,
        "zone_dmpr_pos_max": [
          {
            "t": 0,
            "value": 45.0
          },
          {
            "t": 200000,
            "value": 95.0
          }
        ]
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 432000,
          "equals": false
        }
      ]
    },
    {
      "name": "damper_at_threshold",
      "description": "Max damper exactly at high_damper_threshold is not low demand (strict < comparison)",
      "inputs": {
        "dsp_sp": 400.0,
        "zone_dmpr_pos_max": 70.0
      },
      "expect": [
        {
          "output": "yFault",
          "from_s": 0,
          "to_s": 432000,
          "equals": false
        }
      ]
    }
  ]
}