Index: firmware/App/Monitors/WaterQualityMonitor.c =================================================================== diff -u -r6f961c6e113a4076ba9d5f97e078a398a8976d7c -r830213bc6dcc1a684610caf78c79d55f2cb41e93 --- firmware/App/Monitors/WaterQualityMonitor.c (.../WaterQualityMonitor.c) (revision 6f961c6e113a4076ba9d5f97e078a398a8976d7c) +++ firmware/App/Monitors/WaterQualityMonitor.c (.../WaterQualityMonitor.c) (revision 830213bc6dcc1a684610caf78c79d55f2cb41e93) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file WaterQualityMonitor.c * -* @author (last) Sean Nash -* @date (last) 21-Nov-2024 +* @author (last) “rkallala” +* @date (last) 09-Dec-2025 * -* @author (original) Sean Nash -* @date (original) 21-Nov-2024 +* @author (original) Michael Garthwaite +* @date (original) 08-Sep-2025 * ***************************************************************************/ @@ -21,6 +21,7 @@ #include "FPOperationModes.h" #include "PersistentAlarm.h" #include "Pressure.h" +#include "ROPump.h" #include "SystemCommDD.h" #include "TaskPriority.h" #include "Temperature.h" @@ -33,28 +34,37 @@ // ********** private definitions ********** -#define INLET_TEMPERATURE_LOW_THRESHOLD_C 5.0F ///< Minimum allowed Inlet temperature in C. -#define INLET_TEMPERATURE_HIGH_THRESHOLD_C 30.0F ///< Maximum allowed Inlet temperature in C. -#define INLET_TEMPERATURE_PERSISTENCE_TIMER_MS ( 5 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Persistence timer to trigger alarm in ms. -#define INLET_TEMPERATURE_PERSISTENCE_CLEAR_MS ( 5 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Persistence timer to clear alarm in ms. +#define INLET_TEMPERATURE_LOW_THRESHOLD_C 5.0F ///< Minimum allowed Inlet temperature in C. +#define INLET_TEMPERATURE_HIGH_THRESHOLD_C 30.0F ///< Maximum allowed Inlet temperature in C. +#define INLET_TEMPERATURE_PERSISTENCE_TIMER_MS ( 5 * MS_PER_SECOND ) ///< Persistence timer to trigger alarm in ms. +#define INLET_TEMPERATURE_PERSISTENCE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence timer to clear alarm in ms. -#define MAX_INLET_RO_PUMP_PRESSURE_WARNING_PSIG 120.0F ///< Maximum allowed Input pressure to the RO membrane. -#define MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG 30.0F ///< Minimum allowed Input low pressure value in psig without boost pump. -#define MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 80.0F ///< Maximum allowed Input high pressure value in psig without boost pump. -#define MIN_INLET_WATER_PRESSURE_WARNING_BOOST_LOW_PSIG 10.0F ///< Minimum allowed Input low pressure value in psig with boost pump. -#define MAX_INLET_WATER_PRESSURE_WARNING_BOOST_HIGH_PSIG 80.0F ///< Maximum allowed Input high pressure value in psig with boost pump. -#define MIN_PRESSURE_RELIEF_WARNING_LOW_PSIG 13.0F ///< Minimum pressure relief warning in psi -#define MAX_PRESSURE_RELIEF_WARNING_HIGH_PSIG 17.0F ///< Maximum pressure relief warning in psi -#define INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error in milliseconds. -#define INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. -#define INLET_WATER_PRES_RELIEF_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error in milliseconds. -#define INLET_WATER_PRES_RELIEF_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. +#define MAX_INLET_RO_PUMP_PRESSURE_WARNING_PSIG 120.0F ///< Maximum allowed Input pressure to the RO membrane. +#define MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG 25.0F ///< Minimum allowed Input warning low pressure value in psig for RO featured. +#define MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 40.0F ///< Maximum allowed Input warning high pressure value in psig for RO featured. +#define MAX_INLET_WATER_PRESSURE_FAULT_HIGH_PSIG 75.0F ///< Maximum allowed Input fault high pressure value in psig for RO featured. +#define MIN_INLET_WATER_PRESSURE_DEFEATURED_WARNING_LOW_PSIG 5.0F ///< Minimum allowed Input warning low pressure value in psig for RO Defeatured. +#define MAX_INLET_WATER_PRESSURE_DEFEATURED_WARNING_HIGH_PSIG 10.0F ///< Maximum allowed Input warning high pressure value in psig for RO Defeatured. +#define MAX_INLET_WATER_PRESSURE_DEFEATURED_FAULT_HIGH_PSIG 40.0F ///< Maximum allowed Input fault high pressure value in psig for RO Defeatured. +#define MIN_PRESSURE_RELIEF_WARNING_LOW_PSIG 13.0F ///< Minimum pressure relief warning in psi +#define MAX_PRESSURE_RELIEF_WARNING_HIGH_PSIG 17.0F ///< Maximum pressure relief warning in psi +#define MAX_PERMEATE_FLOW_FAULT_THRESHOLD 1.25F ///< Maximum permeate flow threshold value in percentage. +#define INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error in milliseconds. +#define INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. +#define INLET_WATER_PRES_RELIEF_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error in milliseconds. +#define INLET_WATER_PRES_RELIEF_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. -#define OUTLET_CONDUCTIVITY_HIGH_THRESHOLD_US 200.0F ///< Minimum allowed inlet conductivity in uS/cm. -#define INLET_WATER_COND_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity out of range error in milliseconds. -#define INLET_WATER_COND_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity out of range clear in milliseconds. -#define INLET_CONDUCTIVITY_HIGH_THRESHOLD_US 2000.0F ///< Maximum allowed outlet conductivity in uS/cm. +#define OUTLET_CONDUCTIVITY_HIGH_THRESHOLD_US 200.0F ///< Minimum allowed inlet conductivity in uS/cm. +#define INLET_WATER_COND_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity out of range error in milliseconds. +#define INLET_WATER_COND_OUT_OF_RANGE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity out of range clear in milliseconds. +#define INLET_CONDUCTIVITY_HIGH_THRESHOLD_US 2000.0F ///< Maximum allowed outlet conductivity in uS/cm. +#define MIN_RO_REJECTION_RATIO_PCT 90.0F ///< Minimum RO rejection ration in percentage +#define PERMEATE_FLOW_OUT_RANGE_PERSISTENCE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Verify Water timer ( in ms ) +#define PERMEATE_FLOW_OUT_RANGE_PERSISTENCE_CLEAR_MS ( 5 * MS_PER_SECOND ) ///< Verify Water timer ( in ms ) +#define PERMEATE_FLOW_FAULT_MIN_THRESHOLD 200.0F ///< Permeate flow low tolerance limit +#define PERMEATE_FLOW_OUT_OF_RANGE_TIMEOUT_MS ( 12 * MS_PER_SECOND ) ///< Permeate flow low tolerance out of range timeout + // ********** private data ********** // ********** private function prototypes ********** @@ -82,44 +92,96 @@ // Conductivity Alarms initPersistentAlarm( ALARM_ID_FP_INLET_CONDUCTIVITY_OUT_HIGH_RANGE, INLET_WATER_COND_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_COND_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_FP_RO_OUTLET_CONDUCTIVITY_HIGH_RANGE, INLET_WATER_COND_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_COND_OUT_OF_RANGE_TIMEOUT_MS ); + + //Flow Alarms + initPersistentAlarm( ALARM_ID_FP_PERMEATE_FLOW_OUT_HIGH_RANGE, PERMEATE_FLOW_OUT_RANGE_PERSISTENCE_CLEAR_MS, PERMEATE_FLOW_OUT_RANGE_PERSISTENCE_TIMEOUT_MS ); + // fault , clearing timeout is not applicable + initPersistentAlarm( ALARM_ID_FP_PERMEATE_FLOW_OUT_LOW_RANGE, 0, PERMEATE_FLOW_OUT_OF_RANGE_TIMEOUT_MS ); } /*********************************************************************//** * @brief * The checkInletPressures function checks the inlet water pressure * against the pressure threshold and alarm if the pressure is out of range. - * @details \b Inputs: pressureM1 + * @details \b Inputs: pressureM3 * @details \b Outputs: none * @details \b Alarms: ALARM_ID_FP_INLET_PRESSURE_OUT_LOW_RANGE when - * M1 pressure goes beyond low pressure limit. + * M3 pressure goes beyond low pressure limit. * @details \b Alarms: ALARM_ID_FP_INLET_PRESSURE_OUT_HIGH_RANGE when - * M1 pressure goes beyond high pressure limit + * M3 pressure goes beyond high pressure limit + * @details \b Alarms: ALARM_ID_FP_INLET_PRESSURE_CRITICAL_OUT_RANGE when + * M3 pressure goes beyond fault high pressure limit * @return none *************************************************************************/ void checkInletPressures( void ) { - F32 pressureM1 = getFilteredPressure( M1_PRES ); + F32 pressureM3 = getFilteredPressure( M3_PRES ); BOOL isPresOutOfLowRange = FALSE; BOOL isPresOutOfHighRange = FALSE; + BOOL isPresOutOfHighRangeFault = FALSE; - if ( TRUE == isBoostPumpInstalled() ) + if ( TRUE == isFPDefeatured() ) { - isPresOutOfLowRange = ( ( pressureM1 < MIN_INLET_WATER_PRESSURE_WARNING_BOOST_LOW_PSIG ) ? TRUE : FALSE); - isPresOutOfHighRange = ( ( pressureM1 > MAX_INLET_WATER_PRESSURE_WARNING_BOOST_HIGH_PSIG ) ? TRUE : FALSE); - checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_LOW_RANGE, isPresOutOfLowRange, pressureM1, MIN_INLET_WATER_PRESSURE_WARNING_BOOST_LOW_PSIG ); - checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_HIGH_RANGE, isPresOutOfHighRange, pressureM1, MAX_INLET_WATER_PRESSURE_WARNING_BOOST_HIGH_PSIG ); + isPresOutOfLowRange = ( ( pressureM3 < MIN_INLET_WATER_PRESSURE_DEFEATURED_WARNING_LOW_PSIG ) ? TRUE : FALSE); + isPresOutOfHighRange = ( ( ( pressureM3 > MAX_INLET_WATER_PRESSURE_DEFEATURED_WARNING_HIGH_PSIG ) && ( pressureM3 < MAX_INLET_WATER_PRESSURE_DEFEATURED_FAULT_HIGH_PSIG ) ) ? TRUE : FALSE); + isPresOutOfHighRangeFault = ( ( pressureM3 > MAX_INLET_WATER_PRESSURE_DEFEATURED_FAULT_HIGH_PSIG ) ? TRUE : FALSE); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_LOW_RANGE, isPresOutOfLowRange, pressureM3, MIN_INLET_WATER_PRESSURE_DEFEATURED_WARNING_LOW_PSIG ); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_HIGH_RANGE, isPresOutOfHighRange, pressureM3, MAX_INLET_WATER_PRESSURE_DEFEATURED_WARNING_HIGH_PSIG ); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_CRITICAL_OUT_RANGE, isPresOutOfHighRangeFault, pressureM3, MAX_INLET_WATER_PRESSURE_DEFEATURED_FAULT_HIGH_PSIG ); } else { - isPresOutOfLowRange = ( ( pressureM1 < MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ) ? TRUE : FALSE); - isPresOutOfHighRange = ( ( pressureM1 > MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ) ? TRUE : FALSE); - checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_LOW_RANGE, isPresOutOfLowRange, pressureM1, MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ); - checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_HIGH_RANGE, isPresOutOfHighRange, pressureM1, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); + isPresOutOfLowRange = ( ( pressureM3 < MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ) ? TRUE : FALSE); + isPresOutOfHighRange = ( ( ( pressureM3 > MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ) && ( pressureM3 < MAX_INLET_WATER_PRESSURE_FAULT_HIGH_PSIG ) ) ? TRUE : FALSE); + isPresOutOfHighRangeFault = ( ( pressureM3 > MAX_INLET_WATER_PRESSURE_FAULT_HIGH_PSIG ) ? TRUE : FALSE); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_LOW_RANGE, isPresOutOfLowRange, pressureM3, MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_OUT_HIGH_RANGE, isPresOutOfHighRange, pressureM3, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); + checkPersistentAlarm( ALARM_ID_FP_INLET_PRESSURE_CRITICAL_OUT_RANGE, isPresOutOfHighRangeFault, pressureM3, MAX_INLET_WATER_PRESSURE_FAULT_HIGH_PSIG ); } } /*********************************************************************//** * @brief + * The checkPermeateHighFlow function checks the permeate flow rate from P16 + * against the set target flow rate and alarm if the flow is out of range high. + * @details \b Inputs: permeateFlow + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_FP_PERMEATE_FLOW_OUT_HIGH_RANGE when + * P16 flow goes beyond threshold limit from set target flow. + * @return none + *************************************************************************/ +void checkPermeateHighFlow( void ) +{ + F32 permeateFlow = getFilteredFlow( P16_FLOW ); + BOOL isFlowOutOfRange = FALSE; + F32 maxAllowedPermeateFlow = (F32)getTargetROPumpFlowRateMLPM() * MAX_PERMEATE_FLOW_FAULT_THRESHOLD; + + isFlowOutOfRange = ( ( permeateFlow > maxAllowedPermeateFlow ) ? TRUE : FALSE); + checkPersistentAlarm( ALARM_ID_FP_PERMEATE_FLOW_OUT_HIGH_RANGE, isFlowOutOfRange, permeateFlow, maxAllowedPermeateFlow ); +} + +/*********************************************************************//** + * @brief + * The checkPermeateLowFlow function checks the permeate low flow rate from P16 + * against the set target flow rate and alarm if the flow is out of range. + * @details \b Inputs: permeateFlow + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_FP_PERMEATE_FLOW_OUT_LOW_RANGE when + * P16 flow goes beyond threshold limit from set target flow. + * @return none + *************************************************************************/ +void checkPermeateLowFlow( void ) +{ + F32 permeateFlow = getFilteredFlow( P16_FLOW ); + BOOL isFlowOutOfRange = FALSE; + F32 minimumAllowedPermeateFlow = (F32)getTargetROPumpFlowRateMLPM() - PERMEATE_FLOW_FAULT_MIN_THRESHOLD; + + isFlowOutOfRange = ( ( permeateFlow < minimumAllowedPermeateFlow ) ? TRUE : FALSE); + checkPersistentAlarm( ALARM_ID_FP_PERMEATE_FLOW_OUT_LOW_RANGE, isFlowOutOfRange, permeateFlow, minimumAllowedPermeateFlow); +} + +/*********************************************************************//** + * @brief * The checkROPressures function checks the RO membrane pressure * against the pressure threshold and alarm if the pressure is out of range. * @details \b Inputs: pressureP13 @@ -138,7 +200,6 @@ } } - /*********************************************************************//** * @brief * The checkROPressures function checks the RO membrane outlet pressure @@ -167,18 +228,18 @@ * @brief * The checkInletTemperatures function checks the inlet water temperature * against the temperature threshold and alarm if the temperature is out of range. - * @details \b Inputs: temperatureP10, temperatureM1 + * @details \b Inputs: temperatureP10, temperatureM3 * @details \b Outputs: none * @details \b Alarms: ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE when - * P10 or M1 temperature goes beyond low temperature limit. + * P10 or M3 temperature goes beyond low temperature limit. * @details \b Alarms: ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE when - * P10 or M1 temperature goes beyond high temperature limit + * P10 or M3 temperature goes beyond high temperature limit * @return none *************************************************************************/ void checkInletTemperatures( void ) { F32 temperatureP10 = getFilteredConductivitySensorTemperature( P9_COND ); - F32 temperatureM1 = getFilteredPressureSensorTemperature( M1_PRES ); + F32 temperatureM3 = getFilteredPressureSensorTemperature( M3_PRES ); BOOL isTempOutOfLowRange = FALSE; BOOL isTempOutOfHighRange = FALSE; @@ -187,10 +248,10 @@ checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureP10, INLET_TEMPERATURE_LOW_THRESHOLD_C ); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureP10, INLET_TEMPERATURE_HIGH_THRESHOLD_C ); - isTempOutOfLowRange = ( ( temperatureM1 < INLET_TEMPERATURE_LOW_THRESHOLD_C ) ? TRUE : FALSE); - isTempOutOfHighRange = ( ( temperatureM1 > INLET_TEMPERATURE_HIGH_THRESHOLD_C ) ? TRUE : FALSE); - checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureM1, INLET_TEMPERATURE_LOW_THRESHOLD_C ); - checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureM1, INLET_TEMPERATURE_HIGH_THRESHOLD_C ); + isTempOutOfLowRange = ( ( temperatureM3 < INLET_TEMPERATURE_LOW_THRESHOLD_C ) ? TRUE : FALSE); + isTempOutOfHighRange = ( ( temperatureM3 > INLET_TEMPERATURE_HIGH_THRESHOLD_C ) ? TRUE : FALSE); + checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureM3, INLET_TEMPERATURE_LOW_THRESHOLD_C ); + checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureM3, INLET_TEMPERATURE_HIGH_THRESHOLD_C ); } /*********************************************************************//** @@ -231,7 +292,27 @@ checkPersistentAlarm( ALARM_ID_FP_RO_OUTLET_CONDUCTIVITY_HIGH_RANGE, isConductivityOutOfLowRange, conductivityP18, OUTLET_CONDUCTIVITY_HIGH_THRESHOLD_US ); } +/*********************************************************************//** + * @brief + * The checkRORejectionRatio function checks the RO rejection ratio + * alarm if the rejection ratio is out of range. + * @details \b Inputs: roRRAvg + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_FP_REJECTION_RATIO_LOW_RANGE when + * RO rejection ratio goes below allowed rejection ratio limit. + * @return none + *************************************************************************/ +void checkRORejectionRatio( void ) +{ + F32 avgRORR = getRORRAverage(); + // Alarm if the filtered average is less than allowed RO rejection limit + if ( avgRORR < MIN_RO_REJECTION_RATIO_PCT ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_REJECTION_RATIO_LOW_RANGE, avgRORR, MIN_RO_REJECTION_RATIO_PCT) + } +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/