Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r5aee05d242962c2f9294577c3ba5015f9342fb83 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 5aee05d242962c2f9294577c3ba5015f9342fb83) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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. @@ -284,11 +284,9 @@ /*********************************************************************//** * @brief * The checkInletWaterConductivity function checks inlet water conductivity value - * and triggers an alarm when conductivity value is not within the specified - * values. + * and triggers an alarm when conductivity value is out of allowed range. * @details Inputs: CPi sensor conductivity - * @details Outputs: Trigger warning alarm if conductivity is in the warning - * range. Trigger alarm if conductivity is below minimum conductivity. + * @details Outputs: Trigger alarms when conductivity is out of allowed range * @return none *************************************************************************/ void checkInletWaterConductivity( void ) Index: firmware/App/Controllers/ConductivitySensors.h =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -46,14 +46,16 @@ // ********** public definitions ********** +#define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0F ///< Out of range value for RO rejection ratio when CPi conductivity is zero. + /// Enumeration of conductivity sensors. typedef enum ConductivitySensors { - CONDUCTIVITYSENSORS_CPI_SENSOR = 0, ///< Inlet water conductivity sensor - CONDUCTIVITYSENSORS_CPO_SENSOR, ///< Outlet water conductivity sensor - CONDUCTIVITYSENSORS_CD1_SENSOR, ///< Post-acid concentrate conductivity sensor - CONDUCTIVITYSENSORS_CD2_SENSOR, ///< Post-bicarbonate concentrate conductivity sensor - NUM_OF_CONDUCTIVITY_SENSORS ///< Number of conductivity sensors + CONDUCTIVITYSENSORS_CPI_SENSOR = 0, ///< Inlet water conductivity sensor + CONDUCTIVITYSENSORS_CPO_SENSOR, ///< Outlet water conductivity sensor + CONDUCTIVITYSENSORS_CD1_SENSOR, ///< Post-acid concentrate conductivity sensor + CONDUCTIVITYSENSORS_CD2_SENSOR, ///< Post-bicarbonate concentrate conductivity sensor + NUM_OF_CONDUCTIVITY_SENSORS ///< Number of conductivity sensors } CONDUCTIVITY_SENSORS_T; /// Conductivity data struct. @@ -82,7 +84,6 @@ SELF_TEST_STATUS_T execConductivitySensorsSelfTest( void ); void checkInletWaterConductivity( void ); -void checkRORejectionRatio( void ); F32 getConductivityValue( U32 sensorId ); Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -21,13 +21,15 @@ #include "mibspi.h" #include "DrainPump.h" +#include "FlowSensors.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" #include "Pressures.h" +#include "ROPump.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -48,7 +50,13 @@ #define DRAIN_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the Drain Pump data is published on the CAN bus. -#define DRP_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the Drain pump is controlled. +#define DRP_CONTROL_INTERVAL ( 200 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the Drain pump is controlled. +#define DRP_CONTROL_MAX_ALLOWED_PPO_PSI 30.0F ///< Drain pump maximum allowed PPo pressure in psi. +#define DRP_CONTROL_MAX_ALLOWED_PDR_PSI 40.0F ///< Drain pump maximum allowed PDr pressure in psi. +#define DRP_CONTROL_PSI_TO_DAC_P_TERM 0.2F ///< Drain pump psi to DAC conversion. +#define DRP_CONTROL_FLOW_TO_DAC_P_TERM 100.0F ///< Drain pump flow (L/min) to DAC conversion. +#define DRP_CONTROL_PRES_TO_MAX_THRESHOLD_PSI 1.0F ///< Drain pump pressure to maximum pressure threshold in psi. +#define DRP_CONTROL_MIN_DAC_CHANGE 1 ///< Drain pump minimum DAC change #define RPM_2_DAC_SLOPE 0.0547F ///< RPM to DAC conversion slope. #define RPM_2_DAC_INTERCEPT 2.9968F ///< RPM to DAC conversion intercept. @@ -58,12 +66,9 @@ #define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.000005F ///< Toggle period to resolution in seconds. #define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4.0F ///< Rotational to toggle period conversion coefficient. -#define DRAIN_PUMP_P_COEFFICIENT 0.5F ///< P term for drain pump delta pressure control. +#define DRAIN_PUMP_P_COEFFICIENT 100.0F //0.5F ///< P term for drain pump delta pressure control. #define DRAIN_PUMP_I_COEFFICIENT 1.0F ///< I term for drain pump delta pressure control. -#define MIN_ALLOWED_TARGET_OUTLET_PRESSURE -15.0F ///< Minimum allowed outlet pressure for closed loop control. -#define MAX_ALLOWED_TARGET_OUTLET_PRESSURE 15.0F ///< Maximum allowed outlet pressure for closed loop control. - #define MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE 100 ///< Maximum allowed RPM out of range from target RPM in open loop. #define OPEN_LOOP_RPM_OUT_OF_RANGE_TIME_OUT ( 10 * MS_PER_SECOND ) ///< Open loop RPM out of range time out in ms. @@ -114,8 +119,8 @@ DRAIN_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish drain pump data to CAN bus. static U32 targetDrainPumpRPM; ///< Target drain pump RPM. -static F32 targetDrainPumpOutletPressure; ///< Target outlet pressure for the drain pump. -static U32 drainControlTimerCounter; ///< Determines when to perform control on drain pump. +static F32 targetDrainPumpOutletFlowLPM; ///< Target outlet pressure for the drain pump. +static U32 drainControlTimerCtr; ///< Determines when to perform control on drain pump. static BOOL hasClosedLoopBeenRequested; ///< Closed loop pump control flag. static OVERRIDE_U32_T drainPumpMeasuredRPM = { 0, 0, 0, 0 }; ///< Measured drain pump RPM from feedback. static OVERRIDE_F32_T drainPumpMeasuredCurrentA = { 0.0F, 0.0F, 0.0F, 0 }; ///< Measured drain pump current feedback. @@ -126,6 +131,7 @@ static U32 pendingDrainPumpCmdCountDown; ///< Delayed (pending) drain pump command count down timer (in task intervals). static DG_DRAIN_LINE_VOLUME_T drainLineVolumeRecord; ///< Drain line volume record. static DG_DRAIN_PUMP_CAL_RECORD_T drainPumpCalRecord; ///< Drain pump calibration record. +static BOOL isDrainPumpControlInFlowMode; ///< Drain pump flag to indicate whether the drain pump in flow control or not. /// ADC to RPM conversion coefficient or RPM to ADC conversion. static const F32 RPM_CONVERSION_COEFF = (F32) SEC_PER_MIN / ( 2.0F * TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); @@ -147,10 +153,10 @@ * @details Inputs: none * @details Outputs: drainPumpState, drainPumpDAC, drainPumpDACSet, * drainPumpControlMode, drainPumpControlModeSet, targetDrainPumpRPM, - * targetDrainPumpOutletPressure, drainControlTimerCounter, + * targetDrainPumpOutletFlowLPM, drainControlTimerCtr, * pendingDrainPumpCmd, pendingDrainPumpCmdTarget, pendingDrainPumpCmdCountDown, * hasClosedLoopBeenRequested, signalNewRPMRequest, - * drainPumpDataPublicationTimerCounter, + * drainPumpDataPublicationTimerCounter, isDrainPumpControlInFlowMode * @return none *************************************************************************/ void initDrainPump( void ) @@ -163,14 +169,15 @@ drainPumpControlMode = NUM_OF_PUMP_CONTROL_MODES; drainPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; targetDrainPumpRPM = 0; - targetDrainPumpOutletPressure = 0.0F; - drainControlTimerCounter = 0; + targetDrainPumpOutletFlowLPM = 0.0F; + drainControlTimerCtr = 0; pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; pendingDrainPumpCmdTarget = 0.0F; pendingDrainPumpCmdCountDown = 0; hasClosedLoopBeenRequested = FALSE; signalNewRPMRequest = FALSE; drainPumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + isDrainPumpControlInFlowMode = TRUE; // Initialize the drain pump PI controller initializePIController( PI_CONTROLLER_ID_DRAIN_PUMP, DRAIN_PUMP_MIN_DAC, DRAIN_PUMP_P_COEFFICIENT, DRAIN_PUMP_I_COEFFICIENT, @@ -252,72 +259,41 @@ /*********************************************************************//** * @brief - * The setDrainPumpTargetOutletPressure function sets the drain pump to start - * with given target PDr pressure. - * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, - * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet - * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, - * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet - * @param pressure new target drain pump outlet pressure + * The setDrainPumpTargetOutletFlowLPM function sets the drain pump target flow + * rate in L/min. + * @details Inputs: none + * @details Outputs: targetDrainPumpOutletFlowFMP, hasClosedLoopBeenRequested, + * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet, + * isDrainPumpControlInFlowMode + * @param flow new target flow in L/min * @return TRUE if new target speed is set, FALSE if not *************************************************************************/ -BOOL setDrainPumpTargetOutletPressure( F32 pressure ) +BOOL setDrainPumpTargetOutletFlowLPM( F32 flow ) { BOOL result = FALSE; // Check the delta pressure is in range - if ( ( pressure >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( pressure <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) + if ( ( flow >= MIN_RO_FLOWRATE_LPM ) && ( flow <= MAX_RO_FLOWRATE_LPM ) ) { // Set all the variables for closed loop mode - targetDrainPumpOutletPressure = pressure; - hasClosedLoopBeenRequested = TRUE; - drainPumpDAC = DRAIN_PUMP_MIN_DAC; - drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; - drainPumpControlModeSet = drainPumpControlMode; - result = TRUE; + targetDrainPumpOutletFlowLPM = flow; + hasClosedLoopBeenRequested = TRUE; + drainPumpDAC = DRAIN_PUMP_MIN_DAC; + drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + drainPumpControlModeSet = drainPumpControlMode; + result = TRUE; + isDrainPumpControlInFlowMode = TRUE; } else { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, pressure ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_TARGET_FLOW_LPM_SELECTED, flow ) } return result; } /*********************************************************************//** * @brief - * The setDrainPumpTargetOutletPressureDelayed function sets the drain pump - * to start with given target PDr pressure after given delay. - * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, - * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet - * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, - * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet - * @param pressure new target drain pump outlet pressure - * @param delayMS delay duration (in ms) before drain pump started - * @return TRUE if new target speed is set, FALSE if not - *************************************************************************/ -BOOL setDrainPumpTargetOutletPressureDelayed( F32 pressure, U32 delayMs ) -{ - BOOL result = FALSE; - - // Check the delta pressure is in range - if ( ( pressure >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( pressure <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) - { - pendingDrainPumpCmd = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; - pendingDrainPumpCmdTarget = pressure; - pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; - result = TRUE; - } - else - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, pressure ) - } - - return result; -} - -/*********************************************************************//** - * @brief * The signalDrainPumpHardStop function stops the Drain pump immediately. * @details Inputs: none * @details Outputs: targetDrainPumpRPM, drainPumpState, drainPumpControlMode, @@ -334,7 +310,7 @@ hasClosedLoopBeenRequested = FALSE; drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; drainPumpControlModeSet = drainPumpControlMode; - drainControlTimerCounter = 0; + drainControlTimerCtr = 0; pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; pendingDrainPumpCmdTarget = 0.0; pendingDrainPumpCmdCountDown = 0; @@ -480,11 +456,11 @@ { if ( DRAIN_PUMP_CONTROL_TO_TARGET_STATE == pendingDrainPumpCmd ) { - targetDrainPumpOutletPressure = pendingDrainPumpCmdTarget; - hasClosedLoopBeenRequested = TRUE; - drainPumpDAC = DRAIN_PUMP_MIN_DAC; - drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; - drainPumpControlModeSet = drainPumpControlMode; + targetDrainPumpOutletFlowLPM = pendingDrainPumpCmdTarget; + hasClosedLoopBeenRequested = TRUE; + drainPumpDAC = DRAIN_PUMP_MIN_DAC; + drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + drainPumpControlModeSet = drainPumpControlMode; } else if ( DRAIN_PUMP_OPEN_LOOP_STATE == pendingDrainPumpCmd ) { @@ -583,15 +559,15 @@ /*********************************************************************//** * @brief - * The getTargetDrainPumpOutletPressure function gets the current target - * drain pump delta pressure. + * The targetDrainPumpOutletFlowLPM function gets the current target + * drain pump flow in L/min. * @details Inputs: targetDrainPumpOutletPressure * @details Outputs: none - * @return the current target drain pump outlet pressure. + * @return the current target drain pump flow in L/min *************************************************************************/ -F32 getDrainPumpTargetOutletPressure( void ) +F32 getDrainPumpTargetOutletFlowLPM( void ) { - return targetDrainPumpOutletPressure; + return targetDrainPumpOutletFlowLPM; } /*********************************************************************//** @@ -667,25 +643,74 @@ * @brief * The handleDrainPumpControlToTargetState function handles the control to * target state of the drain pump controller state machine. - * @details Inputs: drainControlTimerCounter, drainPumpDACSet - * @details Outputs: drainControlTimerCounter, drainPumpDACSet + * @details Inputs: drainControlTimerCtr + * @details Outputs: drainControlTimerCtr, drainPumpDACSet * @return next state of the controller state machine *************************************************************************/ static DRAIN_PUMP_STATE_T handleDrainPumpControlToTargetState( void ) { DRAIN_PUMP_STATE_T state = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; // control at set interval - if ( ++drainControlTimerCounter >= DRP_CONTROL_INTERVAL ) + if ( ++drainControlTimerCtr >= DRP_CONTROL_INTERVAL ) { - F32 outletDrainPressure = getMeasuredDGPressure( PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ); - F32 dac = runPIController( PI_CONTROLLER_ID_DRAIN_PUMP, getDrainPumpTargetOutletPressure(), outletDrainPressure ); + U32 tempDACSet; + F32 drainPumpOutletPressurePSI = getMeasuredDGPressure( PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ); + F32 roPumpOutletPressurePSI = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + F32 targetROFlowLPM = getDrainPumpTargetOutletFlowLPM(); + F32 msrdROFlowLPM = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + F32 flowSubLPM = msrdROFlowLPM - targetROFlowLPM; - // The PI controller sends the DAC out and it is rounded to the nearest offset and is fed to the FPGA - drainPumpDACSet = (U32)( dac + FLOAT_TO_INT_ROUNDUP_OFFSET ); - setFPGADrainPumpSpeed( drainPumpDACSet ); + if ( TRUE == isDrainPumpControlInFlowMode ) + { + F32 dac = runPIController( PI_CONTROLLER_ID_DRAIN_PUMP, targetROFlowLPM, msrdROFlowLPM ); + drainPumpDACSet = (U32)( dac + FLOAT_TO_INT_ROUNDUP_OFFSET ); - drainControlTimerCounter = 0; + if ( ( drainPumpOutletPressurePSI > DRP_CONTROL_MAX_ALLOWED_PDR_PSI ) || ( roPumpOutletPressurePSI > DRP_CONTROL_MAX_ALLOWED_PPO_PSI ) ) + { + // If either of the pressure sensors are above range, transition to control to pressure + isDrainPumpControlInFlowMode = FALSE; + } + } + else if ( flowSubLPM > NEARLY_ZERO ) + { + // If measured flow if greater than the target flow, adjust the DAC to lower the flow rate + tempDACSet = (U32)( ( flowSubLPM * DRP_CONTROL_FLOW_TO_DAC_P_TERM ) + FLOAT_TO_INT_ROUNDUP_OFFSET ); + drainPumpDACSet -= ( tempDACSet > 0.0F ? tempDACSet : DRP_CONTROL_MIN_DAC_CHANGE ); + } + else + { + // Get the status of the current pressure readings with respect to their maximum pressures + // Get the maximum of the pressure difference of PPo and PDr + F32 pdrSubPSI = drainPumpOutletPressurePSI - DRP_CONTROL_MAX_ALLOWED_PDR_PSI; + F32 ppoSubPSI = roPumpOutletPressurePSI - DRP_CONTROL_MAX_ALLOWED_PPO_PSI; + F32 maxPresPSI = MAX( pdrSubPSI, ppoSubPSI ); + + if ( ( pdrSubPSI > NEARLY_ZERO ) || ( ppoSubPSI > NEARLY_ZERO ) ) + { + // If either of the pressure values are greater than the maximum pressure, recalculate the DAC by the maximum pressure difference + // If the calculated DAC value turned out to be 0, set it to 1 so it changes at least by 1 DAC + tempDACSet = (U32)( ( maxPresPSI * DRP_CONTROL_PSI_TO_DAC_P_TERM ) + FLOAT_TO_INT_ROUNDUP_OFFSET ); + drainPumpDACSet -= ( tempDACSet > 0.0F ? tempDACSet : DRP_CONTROL_MIN_DAC_CHANGE ); + } + else if ( ( fabs(pdrSubPSI) > DRP_CONTROL_PRES_TO_MAX_THRESHOLD_PSI ) && ( fabs(ppoSubPSI) > DRP_CONTROL_PRES_TO_MAX_THRESHOLD_PSI ) ) + { + // If both of the DACs turned out to be less than their maximum pressure limits by more than the specified value, recalculate the + // DAC. Using fabs for the subtraction means both pressure subtractions are negative so they are below their limits. + // In the calculations use fabs for max pressure because it is negative so it will end of subtracting DAC but it should be adding + tempDACSet = (U32)( ( fabs(maxPresPSI) * DRP_CONTROL_PSI_TO_DAC_P_TERM ) + FLOAT_TO_INT_ROUNDUP_OFFSET ); + drainPumpDACSet += ( tempDACSet > 0.0F ? tempDACSet : DRP_CONTROL_MIN_DAC_CHANGE ); + } + } + + // Check the DAC to make sure it is not out the min and max ranges of the drain pump + tempDACSet = drainPumpDACSet; + tempDACSet = MIN( tempDACSet, DRAIN_PUMP_MAX_DAC ); + tempDACSet = MAX( tempDACSet, DRAIN_PUMP_MIN_DAC ); + drainPumpDACSet = tempDACSet; + + drainControlTimerCtr = 0; + setFPGADrainPumpSpeed( drainPumpDACSet ); } return state; @@ -750,7 +775,7 @@ drainPumpData.pumpDACSet = drainPumpDACSet; drainPumpData.drainPumpState = (U32)drainPumpState; drainPumpData.drainPumpRPM = getDrainPumpMeasuredRPM(); - drainPumpData.trgtOutletPrsr = targetDrainPumpOutletPressure; + drainPumpData.trgtOutletFlowLPM = targetDrainPumpOutletFlowLPM; drainPumpData.drainPumpCurrentA = getDrainPumpMeasuredCurrentA(); drainPumpData.drainPumpDirection = getDrainPumpMeasuredDirection(); @@ -815,7 +840,7 @@ drainPumpDataPublishInterval.ovData = intvl; drainPumpDataPublishInterval.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -837,7 +862,7 @@ { drainPumpDataPublishInterval.override = OVERRIDE_RESET; drainPumpDataPublishInterval.ovData = drainPumpDataPublishInterval.ovInitData; - result = TRUE; + result = TRUE; } return result; @@ -874,23 +899,23 @@ /*********************************************************************//** * @brief - * The testSetTargetDrainPumpDeltaPressureOverride function overrides - * the target drain pump delta pressure. + * The testSetTargetDrainPumpOutletFlowLPM function overrides + * the target drain pump outlet flow in L/min/ * @details Inputs: none * @details Outputs: none - * @param value override target drain pump delta pressure + * @param value of flow in L/min * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetTargetDrainPumpOutletPressure( F32 value ) +BOOL testSetTargetDrainPumpOutletFlowLPM( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { // Check if delta pressure is in range - if ( ( value >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( value <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) + if ( ( value >= MIN_RO_FLOWRATE_LPM ) && ( value <= MAX_RO_FLOWRATE_LPM ) ) { - result = setDrainPumpTargetOutletPressure( value ); + result = setDrainPumpTargetOutletFlowLPM( value ); } } Index: firmware/App/Controllers/DrainPump.h =================================================================== diff -u -r5aee05d242962c2f9294577c3ba5015f9342fb83 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision 5aee05d242962c2f9294577c3ba5015f9342fb83) +++ firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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 DrainPump.h * * @author (last) Dara Navaei -* @date (last) 28-Oct-2022 +* @date (last) 02-Jan-2023 * * @author (original) Sean * @date (original) 08-Apr-2020 Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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. @@ -184,6 +184,7 @@ if( heater < NUM_OF_DG_HEATERS ) { +#ifndef DISABLE_HEATERS_AND_TEMPS // Assume the target temperature has not changed heatersStatus[ heater ].hasTargetTempChanged = FALSE; @@ -194,6 +195,7 @@ heatersStatus[ heater ].hasTargetTempChanged = TRUE; result = TRUE; } +#endif } else { @@ -227,6 +229,7 @@ { BOOL status = FALSE; + if( heater < NUM_OF_DG_HEATERS ) { if ( HEATER_EXEC_STATE_OFF == heatersStatus[ heater ].state ) Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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. Index: firmware/App/Controllers/Pressures.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -62,7 +62,8 @@ #define MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 80.0F ///< Maximum allowed high pressure value in psig. #define MIN_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 78.0F ///< Minimum allowed high pressure value in psig. -#define INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error. +#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 ( 1 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. #define PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Pressure out of range persistence period in milliseconds. #define PRESSURES_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the pressures data is published on the CAN bus. #define DATA_PUBLISH_COUNTER_START_COUNT 10 ///< Data publish counter start count. @@ -150,12 +151,12 @@ msrdPressureSum[ i ] = 0; } - initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_HIGH_RANGE, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_HIGH_RANGE, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS ); initPersistentAlarm( ALARM_ID_DG_PRESSURE_OUT_OF_RANGE, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_BARO_PRESSURE_OUT_OF_RANGE, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); } /*********************************************************************//** @@ -182,20 +183,29 @@ case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: - isPressureTooHigh = ( pressure <= MIN_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ? FALSE : TRUE ); - isPressureTooLow = ( pressure >= MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ? FALSE : TRUE ); - // Per PRS 841 - checkPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_HIGH_RANGE, isPressureTooHigh, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); + if ( ( pressure >= MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE ) ) ) + { + isPressureTooLow = FALSE; + } + // Per PRS 401 checkPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE, isPressureTooLow, pressure, MAX_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ); + + if ( ( pressure <= MIN_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_PRESSURE_IN_HIGH_RANGE ) ) ) + { + isPressureTooHigh = FALSE; + } + + // Per PRS 841 + checkPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_IN_HIGH_RANGE, isPressureTooHigh, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); break; - // TODO add chem flush and heat disinfect cooling modes once they are created case DG_MODE_INIT: case DG_MODE_STAN: case DG_MODE_FLUS: case DG_MODE_HEAT: case DG_MODE_CHEM: + case DG_MODE_CHFL: if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) { // TODO define the PRS Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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. Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 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. @@ -22,7 +22,7 @@ /** * @defgroup ROPump ROPump - * @brief RO Pump monitor and controller module. Controls and monitors the RO pump. + * @brief RO Pump monitor and controller module. Controls and monitors the RO pump and the flow meter. * The flow meter is manufactured by SwissFlow, PN: 82015311. * The diaphragm (RO) pump is manufactured by Aquatec, PN: 5889-2MM1-V724DY. * Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -60,6 +60,7 @@ #define SHIFT_BITS_BY_2 2U ///< Shift bits by 2 to create a 4 for averaging 4 samples. #define SHIFT_BITS_BY_2_FOR_AVERAGING 2U ///< Shift the ADCs of the temperature sensors by 2 to average them. #define INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Inlet water temperature sensors timeout in milliseconds. +#define INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ( 1 * MS_PER_SECOND ) ///< Inlet water temperature sensors out of range clear in milliseconds. #define MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE 24.0F ///< Low range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE 26.0F ///< Low range maximum water input temperature. @@ -323,8 +324,8 @@ tempSensors[ TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Persistent alarms for inlet water high/low temperature - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); @@ -434,10 +435,19 @@ case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: - isWaterTempInHighRange = ( temperature <= MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? FALSE : TRUE ); - isWaterTempInLowRange = ( temperature >= MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ? FALSE : TRUE ); + if ( ( temperature <= MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) ) + { + isWaterTempInHighRange = FALSE; + } + // Per PRS 406 checkPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, isWaterTempInHighRange, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); + + if ( ( temperature >= MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) ) + { + isWaterTempInLowRange = FALSE; + } + // Per PRS 405 checkPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, isWaterTempInLowRange, temperature, MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); break; @@ -447,6 +457,7 @@ case DG_MODE_CHEM: case DG_MODE_INIT: case DG_MODE_STAN: + case DG_MODE_CHFL: if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) { // Per PRS 557 Index: firmware/App/Drivers/CPLD.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Drivers/CPLD.h (.../CPLD.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Drivers/CPLD.h (.../CPLD.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2023 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. Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -28,6 +28,7 @@ #include "ModeStandby.h" #include "NVDataMgmt.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" @@ -50,14 +51,6 @@ // General defines #define CHEM_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. -// Inlet water check defines -#define MIN_INLET_PRESSURE_PSI 14.0F ///< Minimum water inlet pressure in psi. -#define MAX_INLET_PRESSURE_PSI 80.0F ///< Maximum water inlet pressure in psi. -#define MIN_INLET_TEMPERATURE_C 18.0F ///< Minimum water inlet temperature in C. -#define MAX_INLET_TEMPERATURE_C 37.0F ///< Maximum water inlet temperature in C. -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm -#define MIN_INLET_CONDUCTIVITY_US_PER_CM 100.0F ///< Minimum water inlet conductivity in us/cm - // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. #define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. @@ -66,8 +59,6 @@ // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MAX_ALLOWED_FLUSH_DRAIN_PERIODS 2 ///< Number of flush drain periods to wait for inlet water to come into range -#define INLET_WATER_CHECK_FAILURE_TASK_INT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Task interval counter for inlet water check failures before alarm // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. @@ -103,16 +94,17 @@ #define DISINFECTANT_MIX_RATIO_FILL 65.67F ///< Disinfectant mixing ratio during fill, water/disinfectant. #define RO_PUMP_FILL_DISINECTANT_FLOW_RATE_LPM 0.4F ///< ROP flow rate for disinfectant prime #define MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI 130.0F ///< ROP max pressure for disinfectant fill -#define FLUSH_DISINFECTANT_INITIAL_WAIT_TIME ( 30 * MS_PER_SECOND ) ///< Initial time to wait for temperature and conductivity to reach target in disinfectant flush state -#define FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME ( 60 * MS_PER_SECOND ) ///< Additional time to wait for temperature and conductivity to reach target in disinfectant flush state +#define FLUSH_DISINFECTANT_INITIAL_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Initial time to wait for temperature and conductivity to reach target in disinfectant flush state in milliseconds. +#define FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Additional time to wait for temperature and conductivity to reach target in disinfectant flush state // Parameters during disinfect defines #define CHEM_DISINFECT_TARGET_RO_FLOW_LPM 0.5F ///< Chemical disinfect target RO flow rate in L/min. #define CHEM_DISINFECT_MAX_RO_PRESSURE_PSI 130 ///< Chemical disinfect maximum RO pressure in psi. #define MIN_DISINFECT_CONDUCTIVITY_US_PER_CM 150.0F ///< Minimum conductivity for mixed disinfect fluid in us/cm #define MAX_DISINFECT_CONDUCTIVITY_US_PER_CM 650.0F ///< Maximum conductivity for mixed disinfect fluid in us/cm #define MAX_DISINFECT_TPO_TEMPERATURE_C 55.0F ///< Maximum temperature for mixed disinfect fluid at outlet of heater in dec C -#define MIN_MAX_CONDUCTIVITY_WAIT_TASK_INT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Number of task intervals to wait for conductivity and temperature to stabilize +#define DISINFECT_COND_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Chemical disinfect conductivity out of range in milliseconds. +#define DISINFECT_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Chemical disinfect temperature out of range in milliseconds. // Initial disinfectant fill of R1 and R2 #define RSRVRS_FULL_VOL_ML 1800.0F ///< Reservoirs 1 & 2 full volume in mL. @@ -121,7 +113,7 @@ // Parameters controlling chemical disinfect #define TARGET_CHEM_DISINFECT_TIME_MS ( 12 * SEC_PER_MIN * MS_PER_SECOND ) ///< Expected chemical disinfect time in ms. -#define CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ( 6 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. +#define CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. #define CHEM_DISINFECT_TARGET_TEMPERATURE_C 37.0F ///< Chemical disinfect target water temperature in C. #define CHEM_DISINFECT_MINIMUM_TEMPERATURE_C 35.0F ///< Chemical disinfect target water temperature in C. #define CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C 45.0F ///< Chemical disinfect heater control water temperature in C. @@ -156,36 +148,33 @@ // ********** private data ********** -static DG_CHEM_DISINFECT_STATE_T chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; ///< Currently active chemical disinfect state. -static DG_CHEM_DISINFECT_STATE_T prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; ///< Previous active heat disinfect state before alarm. -static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect UI state. -static U32 overallChemDisinfectTimer = 0; ///< Chemical disinfect cycle total timer. -static U32 stateTimer = 0; ///< Chemical disinfect state timer to be used in different states. -static U32 stateTrialCounter = 0; ///< Chemical disinfect state trial counter to be used for retries in different states. -static BOOL isThisLastDrain = FALSE; ///< Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect cycle or in the beginning. -static BOOL haveInletWaterChecksPassed = FALSE; ///< Chemical disinfect inlet water checks flag. -static U32 inletWaterChecksFailCounter = 0; ///< Timer/counter for inlet water check failures. -static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. -static BOOL isRsrvrLeaking = FALSE; ///< Flag used to determine if reservoir is leaking. -static U32 rsrvrsVolMonitorCounter = 0; ///< Timer/counter used to determine if reservoir is leaking. -static U32 chemDisinfectReservoirTime = 0; ///< Chemical disinfect accumulated time in ms above the temperature target in one cycle for reservoir 1 or reservoir 2. -static BOOL ischemDisinfectWarmupTargetReached = FALSE; ///< Flag that indicates whether the disinfect warmup target has been reached. -static BOOL isChemDisinfectTemperatureAboveTarget = FALSE; ///< Flag that indicates if the disinfect temperature is currently above the target. -static U32 DisinfectCycleCounter = 0; ///< Counter for disinfect cycles. -static U32 drpControlTimerCounter = 0; ///< Timer/counter for reservoir volume control of DRP. -static U32 dataPublishCounter = 0; ///< Chemical Disinfect data publish timer/counter. -static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static DG_CHEM_DISINFECT_STATE_T chemDisinfectState; ///< Currently active chemical disinfect state. +static DG_CHEM_DISINFECT_STATE_T prevChemDisinfectState; ///< Previous active heat disinfect state before alarm. +static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectUIState; ///< Currently active chemical disinfect UI state. +static U32 overallChemDisinfectTimer; ///< Chemical disinfect cycle total timer. +static U32 stateTimer; ///< Chemical disinfect state timer to be used in different states. +static U32 stateTrialCounter; ///< Chemical disinfect state trial counter to be used for retries in different states. +static BOOL isThisLastDrain; ///< Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect cycle or in the beginning. +static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. +static BOOL isRsrvrLeaking; ///< Flag used to determine if reservoir is leaking. +static U32 rsrvrsVolMonitorCounter; ///< Timer/counter used to determine if reservoir is leaking. +static U32 chemDisinfectReservoirTime; ///< Chemical disinfect accumulated time in ms above the temperature target in one cycle for reservoir 1 or reservoir 2. +static BOOL ischemDisinfectWarmupTargetReached; ///< Flag that indicates whether the disinfect warmup target has been reached. +static BOOL isChemDisinfectTempAboveTarget; ///< Flag that indicates if the disinfect temperature is currently above the target. +static U32 DisinfectCycleCounter; ///< Counter for disinfect cycles. +static U32 drpControlTimerCounter; ///< Timer/counter for reservoir volume control of DRP. +static U32 dataPublishCounter; ///< Chemical Disinfect data publish timer/counter. +static CANCELLATION_MODE_T cancellationMode; ///< Cancellation mode. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. static U32 flushCircWaitTime; ///< Variable time period in ms to wait in flush circulation state to check sensor values. static U32 flushDisinfectantWaitTime; ///< Variable time period in ms to wait in disinfectant flush state to check sensor values. -static U32 primeAcidSteadyStateCounter = 0; ///< Prime acid steady state counter. -static U32 minMaxConductivityWaitCounter = 0; ///< Timer/counter for the disinfect conductivity check. -static U32 rsrvrFillStableTimeCounter = 0; ///< Task interval timer/counter for determining if reservoir has reached fill target. -static U32 rsrvrFillToFullStableTimeCounter = 0; ///< Task interval timer/counter for determining if reservoir is full. -static F32 R1FullVolume = 0.0; ///< R1 volume determined by fill to full function. -static F32 R2FullVolume = 0.0; ///< R2 volume determined by fill to full function. -static F32 disinfectantMixRatio = 0.0; ///< Current disinfectant mixing ratio. +static U32 primeAcidSteadyStateCounter; ///< Prime acid steady state counter. +static U32 rsrvrFillStableTimeCounter; ///< Task interval timer/counter for determining if reservoir has reached fill target. +static U32 rsrvrFillToFullStableTimeCounter; ///< Task interval timer/counter for determining if reservoir is full. +static F32 R1FullVolume; ///< R1 volume determined by fill to full function. +static F32 R2FullVolume; ///< R2 volume determined by fill to full function. +static F32 disinfectantMixRatio ; ///< Current disinfectant mixing ratio. static DISINFECT_NV_OPS_T disinfectNVOps; ///< Disinfect non-volatile memory operations. // ********** private function prototypes ********** @@ -215,8 +204,9 @@ static void chemicalDisinfectTimerUpdate( void ); static void publishChemicalDisinfectData( void ); static void monitorModeChemicalDisinfect( void ); -static void writeDisinfectDataToNV( void ); +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); + /*********************************************************************//** * @brief * The initChemicalDisinfectMode function initializes the chemical @@ -233,24 +223,41 @@ *************************************************************************/ void initChemicalDisinfectMode( void ) { - chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - overallChemDisinfectTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillToFullStableTimeCounter = 0; - primeAcidSteadyStateCounter = 0; - disinfectantMixRatio = 0.0; - isRsrvrLeaking = FALSE; - chemDisinfectReservoirTime = 0; - ischemDisinfectWarmupTargetReached = FALSE; - isChemDisinfectTemperatureAboveTarget = FALSE; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; - disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + stateTimer = 0; + isThisLastDrain = FALSE; + stateTrialCounter = 0; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + overallChemDisinfectTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillToFullStableTimeCounter = 0; + primeAcidSteadyStateCounter = 0; + disinfectantMixRatio = 0.0F; + isRsrvrLeaking = FALSE; + chemDisinfectReservoirTime = 0; + ischemDisinfectWarmupTargetReached = FALSE; + isChemDisinfectTempAboveTarget = FALSE; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; + disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; + isRsrvrLeaking = FALSE; + rsrvrsVolMonitorCounter = 0; + DisinfectCycleCounter = 0; + drpControlTimerCounter = 0; + dataPublishCounter = 0; + alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; + flushCircWaitTime = 0; + flushDisinfectantWaitTime = 0; + primeAcidSteadyStateCounter = 0; + rsrvrFillStableTimeCounter = 0; + rsrvrFillToFullStableTimeCounter = 0; + R1FullVolume = 0.0F; + R2FullVolume = 0.0F; + disinfectantMixRatio = 0.0F; + + initPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE, DISINFECT_TEMP_OUT_OF_RANGE_TIMEOUT_MS, DISINFECT_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_COND_OUT_OF_RANGE, DISINFECT_COND_OUT_OF_RANGE_TIMEOUT_MS, DISINFECT_COND_OUT_OF_RANGE_TIMEOUT_MS ); } /*********************************************************************//** @@ -283,6 +290,17 @@ *************************************************************************/ U32 execChemicalDisinfectMode( void ) { + // The inlet pressure shall be checked all the time as long as VPi is open + checkInletWaterPressure(); + + if ( chemDisinfectState != DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN ) + { + // Do not check on the inlet water temperature and conductivity until the inlet filters have been flushed + // The initial states are drain reservoirs but in those states VPi is closed so these alarms are not checked + checkInletWaterTemperature(); + checkInletWaterConductivity(); + } + monitorModeChemicalDisinfect(); switch ( chemDisinfectState ) @@ -386,6 +404,9 @@ // Check if the current operation mode is chemical disinfect if ( DG_MODE_CHEM == getCurrentOperationMode() ) { + // Reset all the actuators + deenergizeActuators( NO_PARK_CONC_PUMPS ); + // Transition to mode standby requestNewOperationMode( DG_MODE_STAN ); @@ -451,6 +472,11 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; + if ( TRUE == isThisLastDrain ) + { + writeDisinfectDataToNV( USAGE_INFO_CHEM_DIS ); + } + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); @@ -472,7 +498,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -512,7 +538,7 @@ tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); @@ -526,7 +552,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -552,35 +578,17 @@ // Check if flush time has elapsed if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - // haveInletWaterChecksPassed is set in the monitor function - if ( TRUE == haveInletWaterChecksPassed ) - { - // set pumps and valves for next state, flush circulation - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Start heating the water while we are flushing - setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C ); - startHeater( DG_PRIMARY_HEATER ); - // The UV reactors will be on for the entire disinfect cycle - turnOnUVReactor( OUTLET_UV_REACTOR ); - flushCircWaitTime = FLUSH_CICRCULATION_INITIAL_WAIT_TIME_MS; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; - } - else - { // The inlet water checks failed - // If the number of failures have not exceeded the limit, try again. - if ( ++stateTrialCounter < MAX_ALLOWED_FLUSH_DRAIN_PERIODS ) - { - stateTimer = getMSTimerCount(); - } - else - { // Couldn't get a good water sample after a couple of trials so the disinfect flush drain cycle failed - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; // TODO: ALARM_ID_DG_NEW_WAT; - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - } + // set pumps and valves for next state, flush circulation + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + // Start heating the water while we are flushing + setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C ); + startHeater( DG_PRIMARY_HEATER ); + // The UV reactors will be on for the entire disinfect cycle + turnOnUVReactor( OUTLET_UV_REACTOR ); + flushCircWaitTime = FLUSH_CICRCULATION_INITIAL_WAIT_TIME_MS; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; } return state; @@ -606,18 +614,18 @@ // Check if the flush circulation time has elapsed and the temperature sensors are not in range yet if ( TRUE == didTimeout( stateTimer, flushCircWaitTime ) ) { - F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 TD2Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); - F32 avgTemp = ( TPoTemp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 cpoConductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + F32 TD2Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); + F32 avgTemp = ( TPoTemp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; + F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 cpoConductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CPO_SENSOR ); // Check if any of the temperature sensors deviate for more than the defined value from the average of all // of the temperature sensors BOOL isTPoOut = FALSE; BOOL isTD2Out = FALSE; - BOOL isCD2Out = ( cd2Conductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); - BOOL isCPoOut = ( cpoConductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); + BOOL isCD2Out = ( cd2Conductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); + BOOL isCPoOut = ( cpoConductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) @@ -642,14 +650,15 @@ // determine which alarm it is, temperature or conductivity, one of them has to take precedence if ( ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) ) { - alarmDetectedPendingTrigger = ALARM_ID_DG_TEMP_SENSORS_DIFF_OUT_OF_RANGE; + alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_TEMP_SENSORS_DIFF_OUT_OF_RANGE; } else { - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //TODO: ALARM_ID_DG_NEW_CON; + alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_COND_SENSORS_OUT_OF_RANGE; } - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } else @@ -658,10 +667,11 @@ // Set the acid dispense pump speed at the priming rate setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_PRIME_SPEED_ML_PER_MIN ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - disinfectantMixRatio = DISINFECTANT_MIX_RATIO_PRIME; - primeAcidSteadyStateCounter = 0; - state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; - stateTimer = getMSTimerCount(); + + disinfectantMixRatio = DISINFECTANT_MIX_RATIO_PRIME; + primeAcidSteadyStateCounter = 0; + state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; + stateTimer = getMSTimerCount(); } } @@ -685,16 +695,14 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - - // Set the chemical disinfect state that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); #ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE != getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) - { + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { if ( cd2Conductivity < MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM ) { primeAcidSteadyStateCounter = 0; @@ -706,18 +714,18 @@ // Turn off the concentrate pump requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // Turn on the RO pump and concentrate pump to the disinfectant fill rates - setROPumpTargetFlowRateLPM( RO_PUMP_FILL_DISINECTANT_FLOW_RATE_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - disinfectantMixRatio = DISINFECTANT_MIX_RATIO_FILL; - flushDisinfectantWaitTime = FLUSH_DISINFECTANT_INITIAL_WAIT_TIME; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; + disinfectantMixRatio = DISINFECTANT_MIX_RATIO_FILL; + flushDisinfectantWaitTime = FLUSH_DISINFECTANT_INITIAL_WAIT_TIME_MS; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; } if ( TRUE == didTimeout( stateTimer, PRIME_ACID_LINE_TIMEOUT_MS ) ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_PRIME_ACID_LINE_TIME_OUT; } @@ -742,46 +750,35 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectantFlushState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; - // Set the chemical disinfect state that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; - + writeDisinfectDataToNV( USAGE_INFO_CHEM_DIS_START ); handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); if ( TRUE == didTimeout( stateTimer, flushDisinfectantWaitTime ) ) { - F32 TdiTemp = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - F32 cd2Conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - BOOL isCD2OutofRange = ( cd2Conductivity < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Conductivity > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ); - BOOL isTPoOutofRange = ( TPoTemp > MAX_DISINFECT_TPO_TEMPERATURE_C ); + F32 cd2Cond = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + BOOL isCD2OutOfRange = ( ( cd2Cond < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Cond > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ) ? TRUE : FALSE ); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) { - isCD2OutofRange = FALSE; + isCD2OutOfRange = FALSE; } #endif - if ( ( TRUE == isCD2OutofRange ) || ( TRUE == isTPoOutofRange ) ) - { // The conditions have not been met + if ( TRUE == isCD2OutOfRange ) + { + // The conditions have not been met // Check if we have exceeded the number of trials. If not, try another time - if (++stateTrialCounter < MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS ) + if ( ++stateTrialCounter < MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS ) { - stateTimer = getMSTimerCount(); - flushDisinfectantWaitTime = FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME; + stateTimer = getMSTimerCount(); + flushDisinfectantWaitTime = FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME_MS; } else { - if ( ( TRUE == isTPoOutofRange ) ) - { - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; - } - else - { - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //TODO: ALARM_ID_DG_NEW_CON - } - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; } } else @@ -793,13 +790,13 @@ setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - chemDisinfectReservoirTime = 0; - rsrvrFillStableTimeCounter = 0; - isChemDisinfectTemperatureAboveTarget = FALSE; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + chemDisinfectReservoirTime = 0; + rsrvrFillStableTimeCounter = 0; + isChemDisinfectTempAboveTarget = FALSE; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; } } @@ -823,10 +820,8 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectFillWithDisinfectantState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - // Set the chemical disinfect state that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); // First reservoir 1 must be full @@ -840,7 +835,7 @@ { // Once R1 is full, keep monitoring for R2 level and timeout rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_PARTIAL_FILL_UP_TIMEOUT_MS ); - chemicalDisinfectTimerUpdate( ); + chemicalDisinfectTimerUpdate(); // Once R2 is full, transition to the next state if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) @@ -851,21 +846,21 @@ // Set the drain pump to control mode controlDRPByReservoirVolume( DG_RESERVOIR_2, TRUE ); //Initialize the PI controller for DRP - isRsrvrLeaking = FALSE; - ischemDisinfectWarmupTargetReached = FALSE; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; + isRsrvrLeaking = FALSE; + ischemDisinfectWarmupTargetReached = FALSE; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -887,28 +882,26 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectR1ToR2State( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - // Set the chemical disinfect that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); - chemicalDisinfectTimerUpdate( ); + chemicalDisinfectTimerUpdate(); - if ( (TRUE != ischemDisinfectWarmupTargetReached ) && ( TRUE == didTimeout( stateTimer, CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ) ) ) + if ( ( FALSE == ischemDisinfectWarmupTargetReached ) && ( TRUE == didTimeout( stateTimer, CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ) ) ) { // Heating up to minimum temperature for chemical disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE; chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } if ( TRUE == didTimeout( stateTimer, MAX_DISINFECT_STATE_TIME_MS ) ) { // Heating up to minimum temperature for chemical disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE; chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } - if ( chemDisinfectReservoirTime >= DISINFECT_CYCLE_PERIOD_MS ) + if ( chemDisinfectReservoirTime >= DISINFECT_CYCLE_PERIOD_MS ) { // Set the actuators to fill R2 and drain R1 state setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -955,17 +948,17 @@ } if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - isRsrvrLeaking = FALSE; - chemDisinfectReservoirTime = 0; - isChemDisinfectTemperatureAboveTarget = FALSE; - ischemDisinfectWarmupTargetReached = FALSE; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1; + isRsrvrLeaking = FALSE; + chemDisinfectReservoirTime = 0; + isChemDisinfectTempAboveTarget = FALSE; + ischemDisinfectWarmupTargetReached = FALSE; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } else { @@ -990,28 +983,26 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectR2ToR1State( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1; - - // Set the chemical disinfect that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); - chemicalDisinfectTimerUpdate( ); + chemicalDisinfectTimerUpdate(); if ( (TRUE != ischemDisinfectWarmupTargetReached ) && ( TRUE == didTimeout( stateTimer, CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ) ) ) { // Heating up to minimum temperature for chemical disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE; chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } if ( TRUE == didTimeout( stateTimer, MAX_DISINFECT_STATE_TIME_MS ) ) { // Heating up to minimum temperature for chemical disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE; chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } - if ( chemDisinfectReservoirTime >= DISINFECT_CYCLE_PERIOD_MS ) + if ( chemDisinfectReservoirTime >= DISINFECT_CYCLE_PERIOD_MS ) { if ( REQUIRED_DISINFECT_CYCLES == ++DisinfectCycleCounter ) { @@ -1036,12 +1027,10 @@ initDrainParameters( DG_RESERVOIR_2 ); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - isThisLastDrain = TRUE; - // Set the chemical disinfect state that is published on the UI + isThisLastDrain = TRUE; chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; - writeDisinfectDataToNV(); - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; } else { @@ -1090,17 +1079,17 @@ } if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - chemDisinfectReservoirTime = 0; - isChemDisinfectTemperatureAboveTarget = FALSE; - ischemDisinfectWarmupTargetReached = FALSE; - isRsrvrLeaking = FALSE; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; + chemDisinfectReservoirTime = 0; + isChemDisinfectTempAboveTarget = FALSE; + ischemDisinfectWarmupTargetReached = FALSE; + isRsrvrLeaking = FALSE; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } else { @@ -1122,13 +1111,9 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeBasicPathState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; + cancellationMode = CANCELLATION_MODE_BASIC; - // Set the chemical disinfect that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; - - // Set the cancellation mode - cancellationMode = CANCELLATION_MODE_BASIC; - failChemicalDisinfect(); return state; @@ -1147,10 +1132,8 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeWaterPathState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; - // Set the chemical disinfect that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; - if ( CANCELLATION_MODE_NONE == cancellationMode ) { // Stop all the actuators first then decide who should run next @@ -1220,11 +1203,9 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCompleteState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_COMPLETE; - - // Set the chemical disinfect that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_COMPLETE; - stopChemicalDisinfect(); + requestNewOperationMode( DG_MODE_CHFL ); return state; } @@ -1257,7 +1238,7 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; - F32 volume = 0.0; + F32 volume = 0.0F; if ( DG_RESERVOIR_1 == r ) { @@ -1286,9 +1267,9 @@ else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to fill ontime. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectState = chemDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevChemDisinfectState = chemDisinfectState; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -1445,7 +1426,7 @@ resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP_VOLUME, MIN_DRP_VOLUME_CONTROL_RPM ); setDrainPumpTargetRPM( MIN_DRP_VOLUME_CONTROL_RPM ); //set the initial pump speed to the minimum } - else if ( TRUE == didTimeout( drpControlTimerCounter, DRP_VOLUME_CONTROL_INTERVAL_TASK_INT) ) + else if ( TRUE == didTimeout( drpControlTimerCounter, DRP_VOLUME_CONTROL_INTERVAL_TASK_INT ) ) { // Control at set interval F32 tgtVolume = (F32)DRP_VOLUME_CONTROL_TARGET_VOLUME_ML; // this is the default if no full volume is available F32 actVolume; @@ -1499,15 +1480,15 @@ // reset the chemical disinfect timers and check whether heating up has timed out if ( TdiTemp >= CHEM_DISINFECT_TARGET_TEMPERATURE_C ) { - isChemDisinfectTemperatureAboveTarget = TRUE; + isChemDisinfectTempAboveTarget = TRUE; ischemDisinfectWarmupTargetReached = TRUE; } - else if ( TdiTemp < CHEM_DISINFECT_MINIMUM_TEMPERATURE_C ) + else if ( TdiTemp < CHEM_DISINFECT_MINIMUM_TEMPERATURE_C ) { - isChemDisinfectTemperatureAboveTarget = FALSE; + isChemDisinfectTempAboveTarget = FALSE; } - if ( TRUE == isChemDisinfectTemperatureAboveTarget ) + if ( TRUE == isChemDisinfectTempAboveTarget ) { chemDisinfectReservoirTime += TASK_GENERAL_INTERVAL; } @@ -1579,23 +1560,16 @@ *************************************************************************/ static void monitorModeChemicalDisinfect( void ) { - BOOL hasConductivityFailed = TRUE; - BOOL hasInletPressureFailed = TRUE; - BOOL hasInletTemperatureFailed = TRUE; + BOOL areInletWaterAlarmsActive = FALSE; // Reservoir leak detection. if ( ( DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2 == chemDisinfectState ) || ( DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1 == chemDisinfectState ) ) { BOOL isRsrvrVolumeOutOfRange = FALSE; + isRsrvrLeaking = FALSE; + isRsrvrVolumeOutOfRange |= fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1FullVolume ) > RSRVRS_MAX_LEAK_VOL_CHANGE_ML; + isRsrvrVolumeOutOfRange |= fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2FullVolume ) > RSRVRS_MAX_LEAK_VOL_CHANGE_ML; - if ( DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2 == chemDisinfectState ) - { - isRsrvrVolumeOutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1FullVolume ) > RSRVRS_MAX_LEAK_VOL_CHANGE_ML; - } - else if ( DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1 == chemDisinfectState ) - { - isRsrvrVolumeOutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2FullVolume ) > RSRVRS_MAX_LEAK_VOL_CHANGE_ML; - } if ( ( TRUE == isRsrvrVolumeOutOfRange ) ) { // If the leak is the first time after a while, set the flag and start the timer @@ -1612,11 +1586,6 @@ chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } - // Reservoirs are in range - else - { - isRsrvrLeaking = FALSE; - } } #ifndef _RELEASE_ @@ -1636,91 +1605,45 @@ } } - // In all states, check inlet temperature, inlet pressure, and inlet conductivity. - haveInletWaterChecksPassed= TRUE; + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE ); - hasConductivityFailed = ( ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) > MAX_INLET_CONDUCTIVITY_US_PER_CM ) || - ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) < MIN_INLET_CONDUCTIVITY_US_PER_CM ) ); - hasInletPressureFailed = ( ( getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) < MIN_INLET_PRESSURE_PSI ) || - ( getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) > MAX_INLET_PRESSURE_PSI ) ); - hasInletTemperatureFailed = ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) < MIN_INLET_TEMPERATURE_C ) || - ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MAX_INLET_TEMPERATURE_C ) ); - -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) ) + if ( TRUE == areInletWaterAlarmsActive ) { - hasConductivityFailed = FALSE; + prevChemDisinfectState = chemDisinfectState; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } -#endif - if ( hasInletTemperatureFailed || hasConductivityFailed || hasInletPressureFailed ) - { // Inlet check failed, - haveInletWaterChecksPassed= FALSE; // set flag for flush drain state - // increment timer/counter and check for timeout - if ( ++inletWaterChecksFailCounter >= INLET_WATER_CHECK_FAILURE_TASK_INT ) - { - // alarm unless in the start, drain, or flush drain states - switch( chemDisinfectState ) - { - case DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION: - case DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT: - case DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH: - prevChemDisinfectState = chemDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_NEW_WAT; - chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; - break; - - case DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT: - case DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2: - case DG_CHEM_DISINFECT_STATE_PARTIAL_DRAIN_R1_FILL_R2_TO_R1: - case DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1: - case DG_CHEM_DISINFECT_STATE_PARTIAL_DRAIN_R2_FILL_R1_TO_R2: - prevChemDisinfectState = chemDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_NEW_WAT; - chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - break; - - default: - // In all other states, it is not necessary to monitor inlet water conditions - break; - } - } - } - else - { // inlet water checks passed, reset water check fail timer - inletWaterChecksFailCounter = 0; - } - // Check the temperature and conductivity of the diluted disinfectant - if ( chemDisinfectState > DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT ) + if ( ( chemDisinfectState >= DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH ) && ( chemDisinfectState <= DG_CHEM_DISINFECT_STATE_PARTIAL_DRAIN_R2_FILL_R1_TO_R2 ) ) { // Disinfect conditions check - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - BOOL isCD2OutofRange = ( cd2Conductivity < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Conductivity > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ); + F32 cd2CondUSCM = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + BOOL isCD2OutofRange = ( ( cd2CondUSCM < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM ) || ( cd2CondUSCM > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ) ? TRUE : FALSE ); + BOOL isTPoOutofRange = ( TPoTemp > MAX_DISINFECT_TPO_TEMPERATURE_C ); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) { isCD2OutofRange = FALSE; } #endif - BOOL isTPoOutofRange = ( TPoTemp > MAX_DISINFECT_TPO_TEMPERATURE_C ); - if ( TRUE != isCD2OutofRange ) + checkPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_COND_OUT_OF_RANGE, isCD2OutofRange, cd2CondUSCM, MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE, isTPoOutofRange, TPoTemp, MAX_DISINFECT_TPO_TEMPERATURE_C ); + + if ( ( TRUE == isAlarmActive( ALARM_ID_DG_CHEM_DISINFECT_TARGET_COND_OUT_OF_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE ) ) ) { - minMaxConductivityWaitCounter = 0; + prevChemDisinfectState = chemDisinfectState; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } - else if ( ++minMaxConductivityWaitCounter >= MIN_MAX_CONDUCTIVITY_WAIT_TASK_INT ) - { - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //ALARM_ID_DG_NEW_CON; TODO - chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - } - else if ( ( TRUE == isTPoOutofRange ) ) - { - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; - chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - } } } @@ -1730,14 +1653,15 @@ * non-volatile memory. * @details Inputs: disinfectNVOps * @details Outputs: disinfectNVOps + * @param info the type disinfect data to write to the memory (i.e. heat + * disinfect start time) * @return: none *************************************************************************/ -// TODO: this may conflict with heat disinfect? -static void writeDisinfectDataToNV( void ) +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ) { if ( FALSE == disinfectNVOps.hasDisStatusBeenWrittenToNV ) { - disinfectNVOps.hasDisStatusBeenWrittenToNV = setLastDisinfectDate( USAGE_INFO_CHEM_DIS, getRTCTimestamp() ); + disinfectNVOps.hasDisStatusBeenWrittenToNV = setLastDisinfectDate( info, getRTCTimestamp() ); } } Index: firmware/App/Modes/ModeChemicalDisinfectFlush.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -55,17 +55,8 @@ #define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. #define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. -// Inlet water checks defines -#define MIN_INLET_TEMPERATURE_C 24.0F ///< Minimum water inlet temperature in C. -#define MAX_INLET_TEMPERATURE_C 37.0F ///< Maximum water inlet temperature in C. -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm -#define MIN_INLET_CONDUCTIVITY_US_PER_CM 100.0F ///< Minimum water inlet conductivity in us/cm -#define MIN_INLET_PRESSURE_PSI 10.0F ///< Minimum water inlet pressure in psi. -#define MAX_INLET_PRESSURE_PSI 80.0F ///< Maximum water inlet pressure in psi. - // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MAX_ALLOWED_FLUSH_DRAIN_PERIODS 2 ///< Number of flush drain periods to wait for inlet water to come in range // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. @@ -87,11 +78,14 @@ #define RSRVRS_FILL_TO_FULL_STABLE_TASK_INT ( ( 2 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in task intervals. // Flush disinfectant lines and flush UF defines -#define CONC_PUMP_CP1_FLUSH_SPEED_ML_PER_MIN 40.0 ///< Concentrate pump CP1 speed for flush -#define CONC_PUMP_CP2_FLUSH_SPEED_ML_PER_MIN 40.8 ///< Concentrate pump CP2 speed for flush +#define CONC_PUMP_CP1_FLUSH_SPEED_ML_PER_MIN -40.0F ///< Concentrate pump CP1 speed for flush +#define CONC_PUMP_CP2_FLUSH_SPEED_ML_PER_MIN 40.8F ///< Concentrate pump CP2 speed for flush #define FLUSH_DISINFECTANT_LINE_WAIT_TIME_MS ( 2.5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush disinfectant line in milliseconds. #define FLUSH_UF_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush UF in milliseconds. +// Sample flush R1 to R2 drain R2 defines +#define SAMPLE_FLUSH_WAIT_TIME_MS ( 2.5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to wait for sampling flush R1 to R2 drain R2 in milliseconds. + /// Cancellation paths typedef enum Cancellation_modes { @@ -104,34 +98,30 @@ /// Non-volatile write structure typedef struct { - BOOL hasDisFlushStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush status been written to NV or not. - BOOL hasDisFlushCompleteDateBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush complete date been written to NV or not. -} DISINFECT_FLUSH_NV_OPS_T; + BOOL hasDisStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect status been written to NV or not. +} DISINFECT_NV_OPS_T; // ********** private data ********** -static DG_CHEM_DISINFECT_FLUSH_STATE_T chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Currently active chemical disinfect flush state. -static DG_CHEM_DISINFECT_FLUSH_STATE_T prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Previous active chemical disinfect flush state before alarm. -static DG_CHEM_DISINFECT_FLUSH_UI_STATE_T chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect flush UI state. -static U32 overallChemDisinfectFlushTimer = 0; ///< Chemical disinfect flush cycle total timer. -static U32 stateTimer = 0; ///< Chemical disinfect flush state timer to be used in different states. -static U32 stateTrialCounter = 0; ///< Chemical disinfect flush state trial counter to be used for retries in different states. -static BOOL haveInletWaterChecksPassed = TRUE; ///< Inlet water pressure, temperature, and pressure in range flag -static BOOL isThisLastDrain = FALSE; /// Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect flush cycle or in the beginning. -static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. -static U32 waitTimer = 0; ///< Wait timer for reservoir flushing. -static U32 drainTimer = 0; ///< Timer for reservoir draining during flush states -static U32 dataPublishCounter = 0; ///< Chemical disinfect flush data publish counter. -static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. -static U32 rsrvrFillToFullStableTimerCounter = 0; ///< Task interval counter for determining if reservoir is full +static DG_CHEM_DISINFECT_FLUSH_STATE_T chemDisinfectFlushState; ///< Currently active chemical disinfect flush state. +static DG_CHEM_DISINFECT_FLUSH_STATE_T prevChemDisinfectFlushState; ///< Previous active chemical disinfect flush state before alarm. +static DG_CHEM_DISINFECT_FLUSH_UI_STATE_T chemDisinfectFlushUIState; ///< Currently active chemical disinfect flush UI state. +static U32 overallChemDisinfectFlushTimer; ///< Chemical disinfect flush cycle total timer. +static U32 stateTimer; ///< Chemical disinfect flush state timer to be used in different states. +static BOOL isThisLastDrain; ///< Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect flush cycle or in the beginning. +static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. +static U32 waitTimer; ///< Wait timer for reservoir flushing. +static U32 drainTimer; ///< Timer for reservoir draining during flush states +static U32 dataPublishCounter; ///< Chemical disinfect flush data publish counter. +static CANCELLATION_MODE_T cancellationMode; ///< Cancellation mode. +static U32 rsrvrFillToFullStableTimerCounter; ///< Task interval counter for determining if reservoir is full static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect flush alarm to raise. static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect flush. -static DISINFECT_FLUSH_NV_OPS_T disinfectFlushNVOps; ///< Disinfect flush non-volatile memory operations. +static DISINFECT_NV_OPS_T disinfectNVOps; ///< Disinfect non-volatile memory operations. // ********** private function prototypes ********** -//static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushRemoveAcidBottleFromUIState( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ); @@ -140,6 +130,7 @@ static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushSampleFlushR1ToR2DrainR2State( void ); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState(void); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState(void); static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ); @@ -149,7 +140,7 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillToFullStatus( DG_RESERVOIR_ID_T r, U32 timeout ); static void publishChemicalDisinfectFlushData( void ); static void monitorModeChemicalDisinfectFlush( void ); -static void writeDisinfectFlushDataToNV( void ); +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); /*********************************************************************//** * @brief @@ -167,21 +158,22 @@ *************************************************************************/ void initChemicalDisinfectFlushMode( void ) { - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - haveInletWaterChecksPassed = TRUE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - overallChemDisinfectFlushTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillToFullStableTimerCounter = 0; - numberOfPostDisinfectRinses = 0; - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; - disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV = FALSE; - disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV = FALSE; + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + stateTimer = 0; + isThisLastDrain = FALSE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + overallChemDisinfectFlushTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillToFullStableTimerCounter = 0; + numberOfPostDisinfectRinses = 0; + alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; + waitTimer = 0; + drainTimer = 0; + dataPublishCounter = 0; + disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; } /*********************************************************************//** @@ -213,6 +205,17 @@ *************************************************************************/ U32 execChemicalDisinfectFlushMode( void ) { + // The inlet pressure shall be checked all the time as long as VPi is open + checkInletWaterPressure(); + + if ( chemDisinfectFlushState != DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN ) + { + // Do not check on the inlet water temperature and conductivity until the inlet filters have been flushed + // The initial states are drain reservoirs but in those states VPi is closed so these alarms are not checked + checkInletWaterTemperature(); + checkInletWaterConductivity(); + } + monitorModeChemicalDisinfectFlush(); switch ( chemDisinfectFlushState ) @@ -249,6 +252,10 @@ chemDisinfectFlushState = handleChemicalDisinfectFlushFlushR1ToR2DrainR2State(); break; + case DG_CHEM_DISINFECT_FLUSH_STATE_SAMPLE_FLUSH_R1_TO_R2_DRAIN_R2: + chemDisinfectFlushState = handleChemicalDisinfectFlushSampleFlushR1ToR2DrainR2State(); + break; + case DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH: chemDisinfectFlushState = handleChemicalDisinfectFlushCancelModeBasicPathState(); break; @@ -324,11 +331,7 @@ static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DRAIN_R1; - - // Set the chemical disinfect flush state that is published on the UI chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_FLUSH_AFTER_DISINFECT; - - // Start overall chemical disinfect timer overallChemDisinfectFlushTimer = getMSTimerCount(); // Close VPi to prevent wasting water @@ -338,8 +341,8 @@ setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); return state; } @@ -363,22 +366,23 @@ rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { // Done with draining R1 + { + // Done with draining R1 if ( FALSE == isThisLastDrain ) { tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); } setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_FLUSH_STATE_DRAIN_R2; - stateTimer = getMSTimerCount(); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_FLUSH_STATE_DRAIN_R2; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } return state; @@ -405,9 +409,10 @@ else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { signalDrainPumpHardStop(); // Done with draining + if ( TRUE == isThisLastDrain ) { - state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; + state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; } else { @@ -419,15 +424,14 @@ setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); turnOnUVReactor( INLET_UV_REACTOR ); - stateTrialCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } return state; @@ -452,34 +456,18 @@ // Check if flush time has elapsed if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - if (haveInletWaterChecksPassed) - { - // set pumps and valves for next state, flush disinfectant line - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Set the acid concentrate pump to run at a constant speed during flushing in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, -1.0 * CONC_PUMP_CP1_FLUSH_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - // Turn on the bicarb line pump with forward direction, to flush the line that contains acid from the disinfect - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_CP2_FLUSH_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - turnOnUVReactor( OUTLET_UV_REACTOR ); - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; - } - else - { // If the number of failures have not exceeded the limit, try again. - if ( ++stateTrialCounter < MAX_ALLOWED_FLUSH_DRAIN_PERIODS ) - { - stateTimer = getMSTimerCount(); - } - else - { // Couldn't get a good water sample after a couple of trials and the disinfect flush cycle failed - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //TODO: ALARM_ID_DG_NEW_WAT; - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - } - } + // set pumps and valves for next state, flush disinfectant line + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + // Set the acid concentrate pump to run at a constant speed during flushing in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONC_PUMP_CP1_FLUSH_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + // Turn on the bicarb line pump with forward direction, to flush the line that contains acid from the disinfect + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_CP2_FLUSH_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; } return state; @@ -537,13 +525,13 @@ setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - drainTimer = getMSTimerCount(); - numberOfPostDisinfectRinses = 0; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + drainTimer = getMSTimerCount(); + numberOfPostDisinfectRinses = 0; rsrvrFillToFullStableTimerCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; } return state; @@ -569,7 +557,8 @@ // Check whether draining R1 has timed out if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) - { // Do not use the standard drain status function because we are filling and draining at the same time + { + // Do not use the standard drain status function because we are filling and draining at the same time if ( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) < RSRVRS_DRAIN_TARGET_VOLUME_ML ) { rsrvr1Status = DG_RESERVOIR_REACHED_TARGET; @@ -600,7 +589,7 @@ } // Overflow R2 to R1 for an additional period - if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( TRUE == didTimeout( waitTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( TRUE == didTimeout( waitTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { // Set the valves to flush R1 to R2 and drain R2 setValveState( VRD2, VALVE_STATE_OPEN ); @@ -639,7 +628,8 @@ // Check whether draining R2 has timed out if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { // Do not use the standard drain status function because we are filling and draining at the same time + { + // Do not use the standard drain status function because we are filling and draining at the same time if ( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) < RSRVRS_DRAIN_TARGET_VOLUME_ML ) { rsrvr2Status = DG_RESERVOIR_REACHED_TARGET; @@ -688,31 +678,21 @@ state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; } else - { // number of rinse cycles complete + { + // number of rinse cycles complete // Set the valves to drain R1 - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - // Because this is the second reservoir drain in this mode, the drain parameters must be reset - initDrainParameters( DG_RESERVOIR_1 ); - initDrainParameters( DG_RESERVOIR_2 ); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - // Turn off CP1 and CP2 and ROP - signalROPumpHardStop(); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - //Turn off UV reactors - turnOffUVReactor( INLET_UV_REACTOR ); - turnOffUVReactor( OUTLET_UV_REACTOR ); - isThisLastDrain = TRUE; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_DRAIN_R1; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_FLUSH_STATE_SAMPLE_FLUSH_R1_TO_R2_DRAIN_R2; } } @@ -721,6 +701,27 @@ /*********************************************************************//** * @brief + * The handleChemicalDisinfectFlushSampleFlushR1ToR2DrainR2State function + * handles the chemical disinfect flush sample flush R1 to R2 and drain R2 + * state. + * @details Inputs: stateTimer, TODO fill up + * @details Outputs: TODO fill up + * @return next state of the chemical disinfect flush state machine + *************************************************************************/ +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushSampleFlushR1ToR2DrainR2State( void ) +{ + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_SAMPLE_FLUSH_R1_TO_R2_DRAIN_R2; + + if ( TRUE == didTimeout( stateTimer, SAMPLE_FLUSH_WAIT_TIME_MS ) ) + { + + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleChemicalDisinfectFlushCancelModeBasicPathState function handles the * chemical disinfect flush cancel mode basic path state. The state sets the state * to complete and raises an alarm. @@ -731,13 +732,9 @@ static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + cancellationMode = CANCELLATION_MODE_BASIC; - // Set the chemical disinfect flush that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; - - // Set the cancellation mode - cancellationMode = CANCELLATION_MODE_BASIC; - failChemicalDisinfectFlush(); return state; @@ -755,10 +752,8 @@ static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; - // Set the chemical disinfect flush state that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; - if ( CANCELLATION_MODE_NONE == cancellationMode ) { // Stop all the actuators first then decide who should run next @@ -829,12 +824,10 @@ static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; - // Set the chemical disinfect flush state that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; + writeDisinfectDataToNV( USAGE_INFO_CHEM_FLUSH ); - writeDisinfectFlushDataToNV(); //TODO: is this needed? - stopChemicalDisinfectFlush(); return state; @@ -869,20 +862,20 @@ static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; - BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); + BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); - status = DG_RESERVOIR_REACHED_TARGET; + stateTimer = getMSTimerCount(); + status = DG_RESERVOIR_REACHED_TARGET; } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to drain on time. Update the previous chemical disinfect state - prevChemDisinfectFlushState = chemDisinfectFlushState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevChemDisinfectFlushState = chemDisinfectFlushState; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -902,17 +895,17 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillToFullStatus( DG_RESERVOIR_ID_T r, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; - F32 currentVolume = 0.0; - F32 filteredVolume = 0.0; + F32 currentVolume = 0.0F; + F32 filteredVolume = 0.0F; if ( DG_RESERVOIR_1 == r ) { - currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); filteredVolume = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); } else if ( DG_RESERVOIR_2 == r ) { - currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); filteredVolume = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); } else @@ -934,9 +927,9 @@ else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to fill on time. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectFlushState = chemDisinfectFlushState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevChemDisinfectFlushState = chemDisinfectFlushState; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } else { @@ -991,9 +984,7 @@ *************************************************************************/ static void monitorModeChemicalDisinfectFlush( void ) { - BOOL hasConductivityFailed = TRUE; - BOOL hasInletPressureFailed = TRUE; - BOOL hasInletTemperatureFailed = TRUE; + BOOL areInletWaterAlarmsActive = FALSE; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) @@ -1006,68 +997,41 @@ // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function U32 ConcCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); U32 DialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); - prevChemDisinfectFlushState = chemDisinfectFlushState; + prevChemDisinfectFlushState = chemDisinfectFlushState; chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; } } - // In some states, check inlet temperature, inlet pressure, and inlet conductivity. - haveInletWaterChecksPassed= TRUE; + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW ); + areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE ); - hasConductivityFailed = ( ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) > MAX_INLET_CONDUCTIVITY_US_PER_CM ) || - ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) < MIN_INLET_CONDUCTIVITY_US_PER_CM ) ); - hasInletPressureFailed = ( ( getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) < MIN_INLET_PRESSURE_PSI ) || - ( getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) > MAX_INLET_PRESSURE_PSI ) ); - hasInletTemperatureFailed = ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) < MIN_INLET_TEMPERATURE_C ) || - ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MAX_INLET_TEMPERATURE_C ) ); -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) ) + if ( ( TRUE == areInletWaterAlarmsActive ) ) { - hasConductivityFailed = FALSE; + prevChemDisinfectFlushState = chemDisinfectFlushState; + chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } -#endif - if ( hasInletTemperatureFailed || hasConductivityFailed || hasInletPressureFailed ) - { // Inlet check failed, alarm unless in the start, drain, or flush drain states - haveInletWaterChecksPassed= FALSE; // set flag for flush drain state - switch( chemDisinfectFlushState ) - { - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2: - prevChemDisinfectFlushState = chemDisinfectFlushState; - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //TODO: ALARM_ID_NEW_WAT; - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - break; - - default: - // The inlet water checks do not apply for other states - break; - } - } } /*********************************************************************//** * @brief * The writeDisinfectDataToNV function writes the disinfect flush data to the * non-volatile memory. - * @details Inputs: disinfectFlushNVOps + * @details Inputs: disFlushNVOps * @details Outputs: disinfectFlushNVOps * @return: none *************************************************************************/ -static void writeDisinfectFlushDataToNV( void ) +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ) { - // TODO update in the next branch - /*if ( FALSE == disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV ) + if ( FALSE == disinfectNVOps.hasDisStatusBeenWrittenToNV ) { - disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV = setDisinfectStatus( TRUE ); + disinfectNVOps.hasDisStatusBeenWrittenToNV = setLastDisinfectDate( info, getRTCTimestamp() ); } - - if ( FALSE == disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV ) - { - disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV = setLastDisinfectDate( USAGE_INFO_CHEMICAL_DISINFECT, getRTCTimestamp() ); - }*/ } /**@}*/ Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -143,7 +143,6 @@ checkInletWaterConductivity(); checkInletWaterTemperature(); checkInletWaterPressure(); - checkRORejectionRatio(); // execute current drain state switch ( drainState ) Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -74,6 +74,9 @@ #define CONCENTRATE_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. #define DELAY_FMP_CHECK_START_BY_MS ( 10 * MS_PER_SECOND ) ///< Delay start of FMP check during dialysate deliver state by this amount of time (in ms). +#define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. +#define MAX_CPO_CONDUCTIVITY_ALLOW 100.0F ///< Maximum CPo sensor conductivity value. + // 2m long tubing to cap = 19.5 mL (acid line) + 7.92 mL/m * 2 m (tubing to cap) + 20.82 mL (straw) = 56.15 mL // Prime time in seconds = ( 56.15 mL / 48 mL/min ) x 60 second/min + 25 seconds margin time = 95 seconds. #define PRIME_CONCENTRATE_LINES_TIME_OUT_MS ( 95 * MS_PER_SECOND ) ///< Time required to prime the concentrate lines. @@ -129,6 +132,10 @@ static F32 totalBicarbConductivity; ///< Total bicarb conductivity over 30 seconds. static F32 totalAcidConductivity; ///< Total acid conductivity over 30 seconds. +static F32 sumFillCPoConductivity; ///< Sum of CPo conductivity readings over course of a fill to calculate an average at end of fill. +static F32 sumFillRejRatio; ///< Sum of Rejection Ratio values over course of a fill to calculate an average at end of fill. +static U32 fillCPoConductivitySampleCnt; ///< Number of samples in sum of CPo and Rej. Ratio conductivity readings for fill. + static U32 pumpSpeedIndex; ///< Index used to access the desired pump speed in roPumpFlushBubblesSpeed table. static BOOL havePauseActuatorsBeenSet; ///< Flag to indicate the actuators have been set to pause for the first time. static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. @@ -186,6 +193,9 @@ totalBicarbConductivity = 0.0F; totalAcidConductivity = 0.0F; havePauseActuatorsBeenSet = FALSE; + sumFillCPoConductivity = 0.0F; + sumFillRejRatio = 0.0F; + fillCPoConductivitySampleCnt = 0; } /*********************************************************************//** @@ -226,7 +236,6 @@ *************************************************************************/ U32 execFillMode( void ) { - checkRORejectionRatio(); checkDialysateTemperatureSensors(); setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); @@ -722,10 +731,10 @@ { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - dialysateFillStartTime = getMSTimerCount(); + dialysateFillStartTime = getMSTimerCount(); - fillStatus.isThisFirstFill = FALSE; - result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + fillStatus.isThisFirstFill = FALSE; + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; } return result; @@ -750,6 +759,9 @@ F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); + F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 rejRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; // default 1:1 before calculation in case can't divide by zero. #ifndef _RELEASE_ if ( ( HW_CONFIG_BETA == getHardwareConfigStatus() ) || @@ -768,6 +780,15 @@ // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); + // Sum conductivity readings for CPo and RR checks + if ( fabs(cpi) >= NEARLY_ZERO ) + { + rejRatio = cpo / cpi; + } + sumFillCPoConductivity += cpo; + sumFillRejRatio += rejRatio; + fillCPoConductivitySampleCnt++; + // Delay start of FMP check, then begin integrating flow to a volume if ( TRUE == didTimeout( dialysateFillStartTime, DELAY_FMP_CHECK_START_BY_MS ) ) { @@ -808,7 +829,28 @@ F32 acidNormalConductivity = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConductivityUSPerCM; F32 bicarbNormalConductivity = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConductivityUSPerCM; + // Check RO filter #ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + F32 avgCPo = sumFillCPoConductivity / (F32)fillCPoConductivitySampleCnt; // sample count incremented above w/o condition so no need for divide by zero checks + F32 avgRR = sumFillRejRatio / (F32)fillCPoConductivitySampleCnt; + + if ( avgCPo > MAX_CPO_CONDUCTIVITY_ALLOW ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, avgCPo, MAX_CPO_CONDUCTIVITY_ALLOW ); + } + if ( avgRR > MAX_RO_REJECTION_RATIO_ALLOW ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, avgRR, MAX_RO_REJECTION_RATIO_ALLOW ); + } + } + + // Check FMP vs. LC +#ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_FLOW_VS_LOAD_CELL_CHECK_IN_FILL ) != SW_CONFIG_ENABLE_VALUE ) #endif { @@ -818,6 +860,7 @@ } } + // Check mixing via avg. conductivities #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MIXING_IN_FILL ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -907,10 +950,12 @@ checkInletWaterPressure(); // Check if any of the alarms are active - if ( ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) || + if ( ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ) ) || ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE ) ) ) { status = TRUE; @@ -1184,7 +1229,7 @@ { integratedVolumeML.ovData = value; integratedVolumeML.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -1206,7 +1251,7 @@ { integratedVolumeML.override = OVERRIDE_RESET; integratedVolumeML.ovData = integratedVolumeML.ovInitData; - result = TRUE; + result = TRUE; } return result; Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -191,7 +191,6 @@ checkInletWaterConductivity(); checkInletWaterTemperature(); checkInletWaterPressure(); - checkRORejectionRatio(); // Transition to standby mode when HD is not communicating if ( TRUE == isHDCommunicating() ) Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -58,8 +58,6 @@ // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MIN_INLET_TEMPERATURE_C 24.0F ///< Minimum water inlet temperature in C. -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. @@ -82,21 +80,21 @@ // Fill and heat water #define HEAT_DISINFECT_TARGET_TEMPERATURE_C 82.0F ///< Heat disinfect target water temperature in C. -#define HEAT_DISINFECT_START_TEMPERATURE_C 81.00F ///< Heat disinfect minimum acceptable temperature in C. +#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0F ///< Heat disinfect minimum acceptable temperature in C. // R1 to R2 & R2 to R1 heat disinfect circulation #define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 1.3F ///< Heat disinfect target RO flow rate in L/min. #define HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM 0.8F ///< Heat disinfect target RO flow rate in L/min when transferring between reservoirs. #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. -#define HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI 12.0F ///< Heat disinfect target drain outlet pressure in psi. -#define HEAT_DISINFECT_TARGET_DRAIN_FILL_R2_PSI 9.0F ///< Heat disinfect target drain R2 fill outplet pressure in PSI #define HEAT_DISINFECT_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. #define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. #define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. TODO change this to 5 seconds #define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 250.0F // TODO temporary change. Change back to 100 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. #define HEAT_DISINFECT_MAX_TEMP_GRADIENT_C 15.0F ///< Heat disinfect maximum allowed temperature gradient in between hottest and coldest sensors. #define HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ( 0.16 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect temperature gradient out of range timeout in milliseconds. +#define HEAT_DISINFECT_TARGET_RO_PUMP_DC 0.4F ///< Heat disinfect target RO pump duty cycle. +#define HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Heat disinfect getting reference reservoirs value timeout in milliseconds. // Mix drain R1 and R2 #define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. @@ -145,8 +143,8 @@ static U32 concentratePumpsPrimeTimer; ///< Concentrate pumps prime timer. static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. -static F32 R1HeatDisinfectVol; ///< Reservoir 1 full volume during heat disinfect. -static F32 R2HeatDisinfectVol; ///< Reservoir 2 full volume during heat disinfect. +static F32 rsrvr1RefVolML; ///< Reservoir 1 reference volume in heat disinfect in milliliters. +static F32 rsrvr2RefVolML; ///< Reservoir 2 reference volume in heat disinfect in milliliters. static U32 heatDisinfectTimer; ///< Heat disinfect timer. static BOOL isPartialDisinfectInProgress; ///< Heat disinfect partial complete/in progess flag. static U32 rsrvrsVolMonitorTimer; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. @@ -198,7 +196,7 @@ * @details Inputs: none * @details Outputs: heatDisinfectState, stateTimer, * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, - * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, + * rsrvr1RefVolML, rsrvr2RefVolML, overallHeatDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, heatDisinfectTimer * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime @@ -217,8 +215,8 @@ areTempSensorsInRange = FALSE; rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - R1HeatDisinfectVol = 0.0F; - R2HeatDisinfectVol = 0.0F; + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; overallHeatDisinfectTimer = 0; cancellationMode = CANCELLATION_MODE_NONE; rsrvrFillStableTimeCounter = 0; @@ -608,7 +606,7 @@ // State failed. Cancel heat disinfect mode else { - alarmDetectedPendingTrigger = ALARM_ID_DG_TEMP_SENSORS_DIFF_OUT_OF_RANGE; + alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_TEMP_SENSORS_DIFF_OUT_OF_RANGE; prevHeatDisinfectState = state; state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } @@ -929,10 +927,8 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; - // First reservoir 1 must be full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -953,37 +949,28 @@ setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - + signalROPumpHardStop(); // Set the drain pump to control mode - setDrainPumpTargetOutletPressure( HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter - // at inlet temperature > 45 C - setROPumpTargetFlowRateLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // Start the trimmer heater since we are recirculating water and there is flow in the shunt line setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); startHeater( DG_TRIMMER_HEATER ); - // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' - // volume does not change more than a certain amount during the actual heat disinfect cycle - R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvrsVolMonitorTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; + state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1006,6 +993,22 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); + if ( FALSE == isROPumpRunning() ) + { + setROPumpTargetDutyCycle( HEAT_DISINFECT_TARGET_RO_PUMP_DC ); + } + + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ) ) + { + if ( ( rsrvr1RefVolML < NEARLY_ZERO ) && ( rsrvr2RefVolML < NEARLY_ZERO ) ) + { + // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' + // volume does not change more than a certain amount during the actual heat disinfect cycle + rsrvr1RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + rsrvr2RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + } + } + switch ( status ) { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: @@ -1028,12 +1031,8 @@ setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter - // at inlet temperature > 45 C - setROPumpTargetFlowRateLPM( HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // Set the drain pump to control mode - setDrainPumpTargetOutletPressure( HEAT_DISINFECT_TARGET_DRAIN_FILL_R2_PSI ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM ); // Turn off trimmer heater for transition stopHeater( DG_TRIMMER_HEATER ); @@ -1043,6 +1042,8 @@ rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; stateTimer = getMSTimerCount(); + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; // Reset the timer for the next disinfect state tempGradOutOfRangeTimer = 0; state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; @@ -1073,10 +1074,8 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWaterState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; - // First reservoir 1 must be partially full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1088,33 +1087,26 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Get the current volumes to be monitored during R2 to R1 heat disinfect state - R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - // Set the drain pump to control mode - setDrainPumpTargetOutletPressure( HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter - // at inlet temperature > 45 C - setROPumpTargetFlowRateLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // Start the trimmer heater since we are recirculating water and there is flow in the shunt line setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); startHeater( DG_TRIMMER_HEATER ); - state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1137,6 +1129,17 @@ HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ) ) + { + if ( ( rsrvr1RefVolML < NEARLY_ZERO ) && ( rsrvr2RefVolML < NEARLY_ZERO ) ) + { + // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' + // volume does not change more than a certain amount during the actual heat disinfect cycle + rsrvr1RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + rsrvr2RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + } + } + switch ( status ) { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: @@ -1334,7 +1337,7 @@ // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_CANCEL_DISINFECT; - U32 drainTimeoutMS = RSRVRS_INITIAL_DRAIN_TIME_OUT_MS; + U32 drainTimeoutMS = ( CANCELLATION_MODE_COLD == cancellationMode ? RSRVRS_INITIAL_DRAIN_TIME_OUT_MS : RSRVRS_MIX_DRAIN_TIMEOUT_MS ); if ( CANCELLATION_MODE_NONE == cancellationMode ) { @@ -1438,10 +1441,8 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCompleteState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COMPLETE; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; - requestNewOperationMode( DG_MODE_HCOL ); return state; @@ -1609,8 +1610,8 @@ F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); F32 loadCellA1 = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); F32 loadCellB1 = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - BOOL isR1OutOfRange = ( fabs( loadCellA1 - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); - BOOL isR2OutOfRange = ( fabs( loadCellB1 - R2HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); + BOOL isR1OutOfRange = ( fabs( loadCellA1 - rsrvr1RefVolML ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); + BOOL isR2OutOfRange = ( fabs( loadCellB1 - rsrvr2RefVolML ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); BOOL isGradientOutOfRange = ( fabs( TPoTemp - ThdTemp ) > HEAT_DISINFECT_MAX_TEMP_GRADIENT_C ? TRUE : FALSE ); // Perform check if no pending alarm @@ -1634,22 +1635,25 @@ // Perform check if no pending alarm if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume - if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) + if ( ( rsrvr1RefVolML > NEARLY_ZERO ) && ( rsrvr2RefVolML > NEARLY_ZERO ) ) { - // If the leak is the first time after a while, set the flag and start the timer - if ( FALSE == areRsrvrsLeaking ) + // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume + if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) { - areRsrvrsLeaking = TRUE; - rsrvrsVolMonitorTimer = getMSTimerCount(); + // If the leak is the first time after a while, set the flag and start the timer + if ( FALSE == areRsrvrsLeaking ) + { + areRsrvrsLeaking = TRUE; + rsrvrsVolMonitorTimer = getMSTimerCount(); + } + // If the volume is out of range and it has timed out, exit + else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) + { + areRsrvrsLeaking = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; + status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; + } } - // If the volume is out of range and it has timed out, exit - else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) - { - areRsrvrsLeaking = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; - status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; - } } // Reservoirs are in range else @@ -1745,8 +1749,8 @@ uiData.heatDisinfectTargetTime = targetDisinfectTime; uiData.heatDisinfectCountdownTime = countDown / 1000; // The count down is converted into seconds since the UI does not work with milliseconds - data.R1FillLevel = R1HeatDisinfectVol; - data.R2FillLevel = R2HeatDisinfectVol; + data.R1FillLevel = rsrvr1RefVolML; + data.R2FillLevel = rsrvr2RefVolML; } else { @@ -1815,6 +1819,8 @@ * non-volatile memory. * @details Inputs: disinfectNVOps * @details Outputs: disinfectNVOps + * @param info the type disinfect data to write to the memory (i.e. heat + * disinfect start time) * @return: none *************************************************************************/ static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ) Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -378,6 +378,8 @@ case DG_MODE_HEAT: case DG_MODE_CHEM: case DG_MODE_SERV: + case DG_MODE_CHFL: + case DG_MODE_HCOL: status = FALSE; break; Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2021-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2023 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. @@ -85,8 +85,8 @@ SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, // 55 SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, - SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, SW_FAULT_ID_SERVICE_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, SW_FAULT_ID_UV_REACTORS_INVALID_EXEC_STATE, SW_FAULT_ID_UV_REACTORS_INVALID_SELF_TEST_STATE, SW_FAULT_ID_THERMISTORS_INVALID_EXEC_STATE, // 60 Index: firmware/App/Services/PIControllers.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -169,7 +169,7 @@ if ( controller->direction == CONTROLLER_UNIDIRECTIONAL ) { // Control should always be positive - controller->errorSignal = fabs( referenceSignal ) - ( referenceSignal < 0.0 ? ( measuredSignal * -1.0 ) : measuredSignal ); + controller->errorSignal = fabs( referenceSignal ) - ( referenceSignal < 0.0F ? ( measuredSignal * -1.0F ) : measuredSignal ); } else { @@ -179,9 +179,9 @@ // Limit error sum step size if ( fabs( controller->errorSignal ) > controller->maxErrorSumStep ) { - if ( controller->errorSignal < 0.0 ) + if ( controller->errorSignal < 0.0F ) { - controller->errorSum += ( controller->maxErrorSumStep * -1.0 ); + controller->errorSum += ( controller->maxErrorSumStep * -1.0F ); } else { Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2023 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 SystemComm.c * * @author (last) Dara Navaei -* @date (last) 21-Dec-2022 +* @date (last) 02-Jan-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -897,14 +897,15 @@ handleDGSendConcentrateMixingRatios( message ); break; - case MSG_ID_HD_REQUEST_DG_USAGE_INFO: - handleHDRequestDGUsageInfo( message ); - break; case MSG_ID_HD_REQUEST_DG_SERVICE_MODE: handleServiceModeRequest( message ); break; + case MSG_ID_HD_REQUEST_DG_USAGE_INFO: + handleHDRequestDGUsageInfo( message ); + break; + case MSG_ID_DG_SET_SERVICE_TIME: handleSetDGServiceTime( message ); break; @@ -1149,11 +1150,11 @@ break; case MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE: - handleFilterFlushTimePeriodOverride( message ); + handleFilterFlushTimePeriodOverride(message); break; - case MSG_ID_DG_FANS_RPM_OVERRIDE: - handleFansRPMOverride( message ); + case MSG_ID_DG_BLOCK_MESSAGE_TRANSMISSION: + handleTestBlockMessagesRequest( message ); break; case MSG_ID_DG_STOP_RTC_CLOCK: @@ -1164,10 +1165,6 @@ handleSetDrainPumpMeasuredRPMOverrideRequest( message ); break; - case MSG_ID_DG_BLOCK_MESSAGE_TRANSMISSION: - handleTestBlockMessagesRequest( message ); - break; - case MSG_ID_DG_SUPER_CLEAR_ALARMS_CMD: handleTestSuperClearAlarmsRequest( message ); break; @@ -1180,6 +1177,10 @@ handleTestFansRPMAlarmStartTimeOffsetRequest( message ); break; + case MSG_ID_DG_FANS_RPM_OVERRIDE: + handleFansRPMOverride( message ); + break; + case MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE: handleTestUsedAcidVolumeMLOverrideRequest( message ); break; @@ -1224,6 +1225,10 @@ handleTestTareReservoirRequest( message ); break; + case MSG_ID_DG_GEN_IDLE_PUBLISH_INTERVAL_OVERRIDE: + handleTestGenIdlePublishIntervalOverride( message ); + break; + case MSG_ID_DG_DRAIN_PUMP_CURRENT_OVERRIDE: handleTestDGDrainPumpCurrentOverrideRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2023 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 SystemCommMessages.c * * @author (last) Dara Navaei -* @date (last) 21-Dec-2022 +* @date (last) 02-Jan-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -373,7 +373,6 @@ return result; } - // *********************************************************************** // **************** Message Handling Helper Functions ******************** // *********************************************************************** @@ -3367,37 +3366,6 @@ } /*********************************************************************//** - * @brief - * The handleFansRPMOverride function handles a request to override a fans RPM value. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleFansRPMOverride( MESSAGE_T *message ) -{ - TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; - BOOL result = FALSE; - - // verify payload length - if ( sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) == message->hdr.payloadLen ) - { - memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); - if ( FALSE == payload.reset ) - { - result = testSetFanRPMOverride( payload.index, payload.state.f32 ); - } - else - { - result = testResetFanRPMOverride( payload.index ); - } - } - - // respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** * @brief * The handleStopDGRTCClock function handles a request to stop the RTC clock. * @details Inputs: none @@ -3536,10 +3504,41 @@ /*********************************************************************//** * @brief - * The handleTestFansRPMAlarmStartTimeOffsetRequest function handles a - * request to set the fans RPM alarm start time offset. + * The handleFansRPMOverride function handles a request to override a fans RPM value. * @details Inputs: none * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleFansRPMOverride( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); + if ( FALSE == payload.reset ) + { + result = testSetFanRPMOverride( payload.index, payload.state.f32 ); + } + else + { + result = testResetFanRPMOverride( payload.index ); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestFansRPMAlarmStartTimeOverrideRequest function handles a + * request to override the fan RPM alarm start time. + * @details Inputs: none + * @details Outputs: message handled * @param message : a pointer to the message to handle * @return none *************************************************************************/ @@ -3562,7 +3561,6 @@ } /*********************************************************************//** - * @brief * The handleTestUsedAcidVolumeMLOverrideRequest function handles a * request to override the acid volume. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2023 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. @@ -160,6 +160,12 @@ // MSG_ID_DG_RESPONSE_SERVICE_MODE_REQUEST BOOL sendServiceModeResponse( BOOL accepted, U32 rejCode ); +// MSG_ID_HD_OP_MODE +BOOL handleSetHDOperationMode( MESSAGE_T *message ); + +// MSG_ID_HD_REQUEST_DG_USAGE_INFO +void handleHDRequestDGUsageInfo( MESSAGE_T * message ); + // MSG_ID_DG_SET_SERVICE_TIME void handleSetDGServiceTime( MESSAGE_T *message ); @@ -370,6 +376,12 @@ // MSG_ID_DG_DRAIN_PUMP_MEASURED_RPM_OVERRIDE void handleSetDrainPumpMeasuredRPMOverrideRequest( MESSAGE_T *message ); +// MSG_ID_DG_ALARM_INFO_SEND_INTERVAL_OVERRIDE +void handleTestAlarmInfoSendIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DG_SUPER_CLEAR_ALARMS_CMD +void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ); + // MSG_ID_DG_SET_FANS_RPM_ALARM_START_TIME_OFFSET void handleTestFansRPMAlarmStartTimeOffsetRequest( MESSAGE_T *message ); @@ -388,21 +400,27 @@ // MSG_ID_DG_SET_SW_CONFIG_RECORD void handleSetDGSoftwareConfigRecord( MESSAGE_T *message ); +// MSG_ID_HD_REQUEST_DG_ALARMS +void handleResendAllAlarmsCommand( MESSAGE_T *message ); + // MSG_ID_DG_HD_COMMUNICATION_STATUS void handleTestHDCommunicationStatusOverrideRequest( MESSAGE_T *message ); // MSG_ID_DG_SET_PRIMARY_AND_TRIMMER_HEATERS_TARGET_TEMP void handleSetPrimaryAndTrimmerHeatersTargetTemperature( MESSAGE_T *message ); +// MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE +void handleTestUsedAcidVolumeMLOverrideRequest(MESSAGE_T *message); + +// MSG_ID_DG_USED_BICARB_VOLUME_ML_OVERRIDE +void handleTestUsedBicarbVolumeMLOverrideRequest(MESSAGE_T *message); + // MSG_ID_DG_GET_USAGE_INFO_RECORD void handleGetDGUsageInfoRecord( MESSAGE_T *message ); // MSG_ID_DG_SET_USAGE_INFO_RECORD void handleSetDGUsageInfoRecord( MESSAGE_T *message ); -// MSG_ID_HD_REQUEST_DG_ALARMS -void handleResendAllAlarmsCommand( MESSAGE_T *message ); - // MSG_ID_DG_SET_OP_MODE_REQUEST void handleTestSetOpModeRequest( MESSAGE_T *message );