Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -rd182ea22d168c4a6522993f8a0a362586e87e591 --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision d182ea22d168c4a6522993f8a0a362586e87e591) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 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 UVReactors.c * * @author (last) Dara Navaei -* @date (last) 06-Nov-2021 +* @date (last) 02-May-2022 * * @author (original) Dara Navaei * @date (original) 24-Nov-2020 @@ -34,41 +34,45 @@ // ********** private definitions ********** -#define INLET_UV_REACTOR_ENABLE_PIN 0 ///< Inlet UV reactor GPIO pin number (enable pin). -#define OUTLET_UV_REACTOR_ENABLE_PIN 1 ///< Outlet UV reactor GPIO pin number (enable Pin). -#define INLET_UV_REACTOR_INDICATION_PIN 0x18 ///< Inlet UV reactor N2HET1 pin number (health check). -#define OUTLET_UV_REACTOR_INDICATION_PIN 0x0B ///< Outlet UV reactor N2HET1 pin number (health check). -#define UV_REACTORS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< UV reactors data publication time interval. -/// Self test wait time after enabling the reactors and before checking for their health in ms. -#define SELF_TEST_DELAY_TIME 1000 -#define MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD MS_PER_SECOND ///< UV reactors unhealthy state period. +#define INLET_UV_REACTOR_ENABLE_PIN 0 ///< Inlet UV reactor GPIO pin number (enable pin). +#define OUTLET_UV_REACTOR_ENABLE_PIN 1 ///< Outlet UV reactor GPIO pin number (enable Pin). +#define INLET_UV_REACTOR_INDICATION_PIN 0x18 ///< Inlet UV reactor N2HET1 pin number (health check). +#define OUTLET_UV_REACTOR_INDICATION_PIN 0x0B ///< Outlet UV reactor N2HET1 pin number (health check). +#define UV_REACTORS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< UV reactors data publication time interval. +#define SELF_TEST_DELAY_TIME 1000 ///< Self test wait time after enabling the reactors and before checking for their health in ms. +#define MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD MS_PER_SECOND ///< UV reactors unhealthy state period. +#define DATA_PUBLISH_COUNTER_START_COUNT 90 ///< Data publish counter start count. +#define UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< UV reactors on with no flow time out in milliseconds. + /// UV reactors self test states typedef enum self_tests { - UV_REACTORS_SELF_TEST_OFF = 0, ///< UV reactors self test state off - UV_REACTORS_SELF_TEST_CHECK_HEALTH, ///< UV reactors self test check health - UV_REACTORS_SELF_TEST_COMPLETE, ///< UV reactors self test complete - NUM_OF_UV_REACTORS_SELF_TEST_STATES, ///< Number of UV reactors self test states + UV_REACTORS_SELF_TEST_OFF = 0, ///< UV reactors self test state off. + UV_REACTORS_SELF_TEST_CHECK_HEALTH, ///< UV reactors self test check health. + UV_REACTORS_SELF_TEST_COMPLETE, ///< UV reactors self test complete. + NUM_OF_UV_REACTORS_SELF_TEST_STATES, ///< Number of UV reactors self test states. } UV_REACTORS_SELF_TEST_STATE_T; /// UV reactors exec states typedef enum exec_states { - UV_REACTOR_STATE_OFF = 0, ///< UV reactor state off - UV_REACTOR_STATE_ON, ///< UV reactor state on - NUM_OF_UV_REACTOR_STATES, ///< Number of UV reactor states + UV_REACTOR_STATE_OFF = 0, ///< UV reactor state off. + UV_REACTOR_STATE_ON, ///< UV reactor state on. + NUM_OF_UV_REACTOR_STATES, ///< Number of UV reactor states. } UV_REACTOR_STATE_T; /// UV reactor status typedef struct { - UV_REACTOR_STATE_T execState; ///< UV reactor executive state - PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state - UV_REACTOR_STATES_T switchState; ///< UV reactor turn on/turn off state - U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A - U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1 - OVERRIDE_U32_T healthStatus; ///< UV reactor current health status + UV_REACTOR_STATE_T execState; ///< UV reactor executive state. + PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state. + UV_REACTOR_STATES_T switchState; ///< UV reactor turn on/turn off state. + U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A. + U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1. + OVERRIDE_U32_T healthStatus; ///< UV reactor current health status. + BOOL isFlowBelowMin; ///< UV reactor flag to indicate the flow is below minimum. + U32 reactorOnWithNoFlowTimer; ///< UV reactor on with no flow start time. } UV_REACTOR_STATUS_T; // ********** private data ********** @@ -80,8 +84,8 @@ static OVERRIDE_U32_T uvReactorsDataPublishInterval = { UV_REACTORS_DATA_PUB_INTERVAL, UV_REACTORS_DATA_PUB_INTERVAL, 0, 0 }; ///< UV reactors data publish interval. -static U32 dataPublishCounter = 0; ///< UV reactors data publish counter. -static U32 selfTestElapsedTime = 0; ///< UV reactors self test elapsed time. +static U32 dataPublishCounter; ///< UV reactors data publish counter. +static U32 selfTestElapsedTime; ///< UV reactors self test elapsed time. // Self test functions static UV_REACTORS_SELF_TEST_STATE_T handleUVReactorsSelfTestOff( void ); @@ -102,7 +106,7 @@ * @details Inputs: uvReactorsSelfTestResult, dataPublishCounter, * reactorsStatus, selfTestStates * @details Outputs: uvReactorsSelfTestResult, dataPublishCounter, - * reactorsStatus, selfTestStates + * reactorsStatus, selfTestStates, selfTestElapsedTime * @return none *************************************************************************/ void initUVReactors( void ) @@ -111,7 +115,8 @@ uvReactorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; uvReactorsSelfTestStates = UV_REACTORS_SELF_TEST_OFF; - dataPublishCounter = 0; + dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + selfTestElapsedTime = 0; // Initialize the UV reactors. These values are specific to the inlet and outlet reactor // so they cannot be in a for loop @@ -127,6 +132,7 @@ reactorsStatus[ reactor ].pinSignalState = PIN_SIGNAL_LOW; reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; reactorsStatus[ reactor ].switchState = TURN_OFF; + setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); } @@ -320,7 +326,7 @@ BOOL isOutletHealthy = (BOOL)getReactorHealth( OUTLET_UV_REACTOR ); // Check if both of them are healthy and if not, raise an alarm - if ( ( TRUE == isInletHealthy ) &&( TRUE == isOutletHealthy ) ) + if ( ( TRUE == isInletHealthy ) && ( TRUE == isOutletHealthy ) ) { uvReactorsSelfTestResult = SELF_TEST_STATUS_PASSED; } @@ -361,17 +367,22 @@ { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_OFF; - // Set the health status to be off. When the reactor is off, it does not report - // its health status - reactorsStatus[reactor].healthStatus.data = (U32)UV_REACTOR_OFF; + // Set the health status to be off. When the reactor is off, it does not report its health status + reactorsStatus[ reactor ].healthStatus.data = (U32)UV_REACTOR_OFF; - // If the a reactor is requested to be on and it is off, turn it on - // and change the state + // Check if the a reactor is requested to be on and it is off if ( TURN_ON == reactorsStatus[ reactor ].switchState ) { - setReactorEnableStatus( reactor, PIN_SIGNAL_HIGH ); + // Check if the flow is below minimum + reactorsStatus[ reactor ].isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); - state = UV_REACTOR_STATE_ON; + // If the flow is no longer below minimum and the reactor is requested to be on, turn it back on + if ( FALSE == reactorsStatus[ reactor ].isFlowBelowMin ) + { + setReactorEnableStatus( reactor, PIN_SIGNAL_HIGH ); + + state = UV_REACTOR_STATE_ON; + } } return state; @@ -395,19 +406,41 @@ // Get the health of the reactor (override or non-override) and decide the status BOOL isReactorUnhealthy = ( UV_REACTOR_HEALTHY == getUVReactorHealth( reactor ) ? FALSE : TRUE ); - checkPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, isReactorUnhealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_UV_REACTORS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // Check if the alarm has been active + if ( TRUE == checkPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, isReactorUnhealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ) ) + { + reactorsStatus[ reactor ].switchState = TURN_OFF; + } + } - // Check if the alarm has been active - if ( TRUE == isAlarmActive( ALARM_ID_UV_REACTOR_NOT_HEALTHY ) ) + // Check if the flow is below minimum + BOOL isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); + + if ( TRUE == isFlowBelowMin ) { - reactorsStatus[ reactor ].switchState = TURN_OFF; + // If the flow is below minimum for the first time, start the timer + if ( FALSE == reactorsStatus[ reactor ].isFlowBelowMin ) + { + reactorsStatus[ reactor ].isFlowBelowMin = TRUE; + reactorsStatus[ reactor ].reactorOnWithNoFlowTimer = getMSTimerCount(); + } + else if ( TRUE == didTimeout( reactorsStatus[ reactor ].reactorOnWithNoFlowTimer, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ) ) + { + // If the flow is below minimum and the allowed time has elapsed, set the reactor's signal to be low and set its state + // to be off. + setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); + state = UV_REACTOR_STATE_OFF; + } } // Check if it has been requested to turn off a reactor if ( TURN_OFF == reactorsStatus[ reactor ].switchState ) { setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); - state = UV_REACTOR_STATE_OFF; } @@ -458,6 +491,7 @@ if ( ++dataPublishCounter > getU32OverrideValue( &uvReactorsDataPublishInterval ) ) { UV_REACTORS_DATA_T uvReactorsData; + // Publish the reactors health status uvReactorsData.inletUVReactorHealthStatus = (U32)getUVReactorHealth( INLET_UV_REACTOR ); uvReactorsData.outletUVReactorHealthStatus = (U32)getUVReactorHealth( OUTLET_UV_REACTOR );