[Challenge] - Demand-Controlled Ventilation (DCV) Challenge

Objective

Your task is to design a demand-controlled ventilation system in Niagara 4 (N4) using primitive logic blocks. The system must vary the supply fan speed based on CO₂ concentration and occupancy, ensuring good indoor air quality while minimizing energy consumption.

:woman_technologist: This challenge tests your ability to translate functional requirements into a reliable control strategy using Niagara’s primitive logic blocks. It simulates the type of workflow you’d encounter when implementing a DCV strategy in a building management system.


Instructions

Setup

  • Inputs
    1. CO2Sensor (numeric): Measured CO₂ level in parts per million (ppm).
    2. OccupancySensor (boolean): Indicates whether the space is occupied (true) or unoccupied (false).
    3. TimeSchedule (boolean): Active (true) during building operating hours.
    4. ManualOverride (boolean): Forces the fan to a user-defined speed.
  • Parameters
    1. CO2Setpoint (numeric): Desired maximum CO₂ level (e.g., 800 ppm).
    2. UnoccupiedFanSpeed (numeric): Minimum fan speed when unoccupied (e.g., 20%).
    3. OccupiedMinFanSpeed (numeric): Minimum fan speed when the zone is occupied (e.g., 50%).
    4. OccupiedMaxFanSpeed (numeric): Maximum fan speed when the zone is occupied (e.g., 100%).
    5. AlarmCO2Level (numeric): CO₂ level that triggers an alarm condition (e.g., 1200 ppm).
    6. OverrideFanSpeed (numeric): Fan speed to apply when ManualOverride is true (e.g., 100%).
  • Outputs
    1. FanSpeed (numeric): The commanded fan speed (0–100%).
    2. HighCO2Alarm (boolean): Alarm indicator if CO₂ exceeds AlarmCO2Level.

Logic Requirements

  1. Occupied vs. Unoccupied Operation
  • When TimeSchedule is active and OccupancySensor is true:
    • The fan speed must at least be OccupiedMinFanSpeed.
    • As CO₂ approaches the CO2Setpoint, the fan speed should increase proportionally, up to OccupiedMaxFanSpeed.
  • When TimeSchedule is inactive or OccupancySensor is false:
    • The fan speed should revert to UnoccupiedFanSpeed.
  1. Proportional Control (Demand-Controlled Ventilation)
  • If CO2Sensor is below CO2Setpoint, maintain the fan at the minimum speed for occupied mode (OccupiedMinFanSpeed).
  • If CO2Sensor rises above CO2Setpoint, ramp up the fan speed linearly until it reaches OccupiedMaxFanSpeed at or above the AlarmCO2Level.
  • Use a deadband or hysteresis around the CO2Setpoint to avoid frequent adjustments in fan speed due to minor CO₂ fluctuations.
  1. Alarm Condition
  • If CO2Sensor exceeds AlarmCO2Level, set HighCO2Alarm to true.
  • While in alarm, the fan should run at the maximum speed (OccupiedMaxFanSpeed) if the system is in occupied mode.
  • Once CO2Sensor falls back below the AlarmCO2Level minus a small deadband, clear the alarm.
  1. Manual Override
  • If ManualOverride is true, the FanSpeed should be forced to OverrideFanSpeed regardless of CO₂ or occupancy conditions.
  • The manual override resets (returns to automatic control) at the start of the next active TimeSchedule period.
  1. Fail-Safe / Minimum Constraints
  • In all cases, ensure FanSpeed never goes below 0% or above 100%.
  • Prevent rapid oscillations by applying a small delay or rate-limiting logic if necessary.

Tools

Leverage Niagara 4’s primitive logic blocks (comparators, numeric ranges, latches, hysteresis blocks, etc.) and methods such as:

  • Comparators (Greater Than, Less Than) to evaluate CO₂ levels vs. setpoints.
  • Math blocks (Add, Subtract, Multiply, Divide) for scaling or linear interpolation between OccupiedMinFanSpeed and OccupiedMaxFanSpeed.
  • Hysteresis or Deadband blocks to prevent rapid toggling around the setpoint or alarm threshold.
  • Boolean Logic blocks (And, Or, Not) to handle occupancy and scheduling conditions.
  • Timer or Delay blocks (optional) to smooth out transitions if needed.

Testing

  1. CO₂ Ramping
  • Gradually increase the CO2Sensor value from well below the setpoint to above the alarm threshold.
  • Verify that the FanSpeed transitions from minimum to maximum appropriately.
  • Confirm that HighCO2Alarm is set when crossing AlarmCO2Level and cleared after falling below it (with deadband).
  1. Occupancy & Schedule
  • Toggle OccupancySensor between true and false while TimeSchedule is active.
  • Ensure the system moves from UnoccupiedFanSpeed to at least OccupiedMinFanSpeed when occupied, and vice versa.
  • Set TimeSchedule inactive and confirm fan speed reverts to UnoccupiedFanSpeed.
  1. Manual Override
  • Enable ManualOverride and verify FanSpeed is forced to OverrideFanSpeed.
  • Simulate the next schedule period transition and confirm the system returns to normal automatic logic.
  1. Alarm Handling
  • Drive CO2Sensor above the AlarmCO2Level.
  • Ensure HighCO2Alarm is triggered and FanSpeed is at OccupiedMaxFanSpeed (if occupied).
  • Drop CO2Sensor below the alarm threshold minus deadband; confirm alarm is cleared.

Submission

  1. File: Save and submit your completed Niagara 4 station (.bog file) as a reply to this post.
  2. Documentation: Include a brief explanation of how your logic blocks interconnect and how they fulfill the requirements (hysteresis usage, manual override, scaling for fan speed, etc.).

:no_entry: Real-world conditions, hardware constraints, and site-specific guidelines may influence your actual implementation—this exercise is for educational purposes.

Good luck, and happy engineering! :rocket:

2 Likes

This is a nice one. And to those that are without too much experience, this is pretty much how you do it in real life too. Looking forward to seeing the submissions!

Great job @Giantsbane

2 Likes

I feel like a kid in a candy store when you guys put these out! It’s such good training, and with feedback it’s such a good learning experience. Hoping to have a solution posted maybe Monday, end of day!

1 Like

I don’t know if anyone has the time to look at this, but I’m a bit stalled out. With your help I was able to get most of the Override logic to work. It seems to work OK, except for the fact that the Override is deactivated when the Schedule is driven Active OR Inactive. It should only resume normal operation when the Schedule goes to Active? I know this probably should be fixed by a latch, but I’ve gone into to what Giantsbane has affectionately termed: “Total Mind Fuckery” (excuse the language, but in this case it is warranted!). This is a work in progress, as I have not introduced hysteresis or alarms, etc. I also would take any criticism/advice on how to lay this out more logically, cause I’m just winging it at this point!

Thanks all!

DemandControlledVentilation_Lee.bog (8.9 KB)

2 Likes

Hey all,
First post of mine. Happy to be here.
The occupied fan speed is determined by taking the CO2 reading and dividing by the 1200ppm alarm setpoint, then multiplying by max fan speed 100% – This gives a proportional value from 0-100% as it reaches the alarm setpoint. Unoccupied speed is 20% unless over 800ppm then it changes to the Occupied minimum of 50%. The override is controlled by an Xor latch which can be reset by refiring override or when the schedule is enabled


DCV.bog (199 Bytes)

1 Like

Lol, I’m just a novice, not even in the industry yet, but this is a lot cleaner and simpler than my mess of spaghetti! I’ll be looking more closely to see how/if this works. Cheers.

Haha I’m technically also a novice — just started controls in November. But I have a background in CS so I came in with a good understanding of this sort of logic

1 Like

Overrides (latches in particular) seem to be my cryptonite. I see you use the “xor” for your override latches, and this may help me as I’ve never used the “xor”. I’ll look more closely at this.