Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -56,12 +56,9 @@ #define MAX_CONDUCTIVITY_SENSOR_FAILURES 5 ///< maximum number of conductivity sensor errors within window period before alarm. #define MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ( 60 * MS_PER_SECOND ) ///< Conductivity sensor error window. -#define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0F ///< Out of range value for RO rejection ratio when CPi conductivity is zero. -#define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. -#define MAX_CPO_CONDUCTIVITY_ALLOW 30.0F ///< Maximum CPo sensor conductivity value. - #define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. -#define RO_REJECTION_RATIO_PERSISTENCE_PERIOD ( 10 * MS_PER_SECOND ) ///< Persistence period for RO rejection ratio. +#define INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Inlet water conductivity sensor out of range timeout in milliseconds. +#define INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS ( 1 * MS_PER_SECOND ) ///< Inlet water conductivity sensor out of range clear in milliseconds. #define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Emstat measurement offset. // The below Emstat status values come from the MethodScript-v1_2-1.pdf. See page 10 table 4 for further information @@ -197,16 +194,14 @@ setFPGACPiProbeType( COND_CPI_SENSOR_PROBE_TYPE ); setFPGACPoProbeType( COND_CPO_SENSOR_PROBE_TYPE ); - initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); - initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, RO_REJECTION_RATIO_PERSISTENCE_PERIOD, RO_REJECTION_RATIO_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_CPI_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); - initPersistentAlarm( ALARM_ID_DG_CPO_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); - initPersistentAlarm( ALARM_ID_DG_CD1_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); - initPersistentAlarm( ALARM_ID_DG_CD2_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS ); + initPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CPI_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CPO_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CD1_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CD2_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); @@ -302,34 +297,43 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - DG_OP_MODE_T opMode = getCurrentOperationMode(); - F32 conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - BOOL isConductTooLow = ( conductivity < MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? TRUE : FALSE ); - BOOL isConductInWarningRange = ( conductivity > MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? TRUE : FALSE ); + DG_OP_MODE_T opMode = getCurrentOperationMode(); + F32 conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + BOOL isConductTooLow = ( conductivity < MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? TRUE : FALSE ); + BOOL isConductTooHigh = ( conductivity > MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? TRUE : FALSE ); switch( opMode ) { case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: - isConductTooLow = ( conductivity >= MIN_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? FALSE: TRUE ); - isConductInWarningRange = ( conductivity <= MIN_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? FALSE : TRUE ); + if ( ( conductivity >= MIN_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE ) ) ) + { + isConductTooLow = FALSE; + } + // Per PRS 403 checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + + if ( ( conductivity <= MIN_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) ) + { + isConductTooHigh = FALSE; + } + // Per PRS 404 - checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductInWarningRange, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductTooHigh, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); 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 ) ) { // Per PRS 403 - checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, isConductInWarningRange, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, isConductTooHigh, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); // Per PRS 404 checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); } @@ -344,33 +348,6 @@ /*********************************************************************//** * @brief - * The checkRORejectionRatio function checks RO rejection ratio and outlet water - * conductivity. The function triggers an alarm when RO rejection ratio or - * outlet water conductivity is out of allowed range for period of time. - * @details Inputs: roRejectionRatio, CPo sensor conductivity - * @details Outputs: Triggered alarm - * @return none - *************************************************************************/ -void checkRORejectionRatio( void ) -{ -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - BOOL isRORejectionOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ? TRUE : FALSE ); - BOOL isCPoOutOfRange = ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ? TRUE : FALSE ); - - // Fault alarm per PRS 483 - checkPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, isCPoOutOfRange, cpo, MAX_CPO_CONDUCTIVITY_ALLOW ); - - // Fault alarm per PRS 483 - checkPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORejectionOutOfRange, roRejectionRatio, MAX_RO_REJECTION_RATIO_ALLOW ); - } -} - -/*********************************************************************//** - * @brief * The getConductivityValue function gets the compensated conductivity * value for a given conductivity sensor id. * @details Inputs: compensatedConductivityValues[] Index: firmware/App/Controllers/ConductivitySensors.h =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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_ONLY_TERM 0.2F ///< Drain pump psi to DAC conversion. +#define DRP_CONTROL_FLOW_TO_DAC_P_ONLY_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_I_COEFFICIENT 1.0F ///< I term for drain pump delta pressure control. +#define DRAIN_PUMP_P_COEFFICIENT 20.0F ///< P term for drain pump delta pressure control. +#define DRAIN_PUMP_I_COEFFICIENT 80.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,76 +259,47 @@ /*********************************************************************//** * @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, - * hasClosedLoopBeenRequested, drainControlTimerCounter, drainPumpControlModeSet + * hasClosedLoopBeenRequested, drainControlTimerCounter, drainPumpControlModeSet, + * drainControlTimerCtr, pendingDrainPumpCmd, pendingDrainPumpCmdTarget, + * pendingDrainPumpCmdCountDown * @return none *************************************************************************/ void signalDrainPumpHardStop( void ) @@ -334,9 +312,9 @@ hasClosedLoopBeenRequested = FALSE; drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; drainPumpControlModeSet = drainPumpControlMode; - drainControlTimerCounter = 0; + drainControlTimerCtr = 0; pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; - pendingDrainPumpCmdTarget = 0.0; + pendingDrainPumpCmdTarget = 0.0F; pendingDrainPumpCmdCountDown = 0; } @@ -458,8 +436,11 @@ /*********************************************************************//** * @brief * The execDrainPumpController function executes the drain pump controller. - * @details Inputs: drainPumpState - * @details Outputs: drainPumpState + * @details Inputs: drainPumpState, pendingDrainPumpCmdCountDown, + * pendingDrainPumpCmd + * @details Outputs: drainPumpState, pendingDrainPumpCmdCountDown, + * pendingDrainPumpCmd, targetDrainPumpOutletFlowLPM, drainPumpDAC, + * hasClosedLoopBeenRequested, drainPumpControlMode, drainPumpControlModeSet * @return none *************************************************************************/ void execDrainPumpController( void ) @@ -480,11 +461,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 +564,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 +648,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_ONLY_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_ONLY_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_ONLY_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 +780,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 +845,7 @@ drainPumpDataPublishInterval.ovData = intvl; drainPumpDataPublishInterval.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -837,7 +867,7 @@ { drainPumpDataPublishInterval.override = OVERRIDE_RESET; drainPumpDataPublishInterval.ovData = drainPumpDataPublishInterval.ovInitData; - result = TRUE; + result = TRUE; } return result; @@ -874,23 +904,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 -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -43,7 +43,7 @@ U32 pumpDACSet; ///< Drain pump DAC set value. U32 drainPumpState; ///< Drain pump state machine state. U32 drainPumpRPM; ///< Drain pump current RPM. - F32 trgtOutletPrsr; ///< Drain pump target outlet pressure. + F32 trgtOutletFlowLPM; ///< Drain pump target outlet flow in L/min. F32 drainPumpCurrentA; ///< Drain pump current in amps. U32 drainPumpDirection; ///< Drain pump direction. } DRAIN_PUMP_DATA_T; @@ -59,14 +59,13 @@ BOOL setDrainPumpTargetRPM( U32 rpm ); BOOL setDrainPumpTargetRPMDelayed( U32 rpm, U32 delayMs ); -BOOL setDrainPumpTargetOutletPressure( F32 pressure ); -BOOL setDrainPumpTargetOutletPressureDelayed( F32 pressure, U32 delayMs ); +BOOL setDrainPumpTargetOutletFlowLPM( F32 flow ); +F32 getDrainPumpTargetOutletFlowLPM( void ); void signalDrainPumpHardStop( void ); U32 getDrainPumpTargetRPM( void ); U32 getDrainPumpMeasuredRPM( void ); -F32 getDrainPumpTargetOutletPressure( void ); BOOL isDrainPumpOn( void ); @@ -76,7 +75,7 @@ BOOL testResetDrainPumpDataPublishIntervalOverride( void ); BOOL testSetTargetDrainPumpRPM( U32 value ); -BOOL testSetTargetDrainPumpOutletPressure( F32 value ); +BOOL testSetTargetDrainPumpOutletFlowLPM( F32 value ); BOOL testSetDrainPumpMeasuredRPMOverride( U32 value ); BOOL testResetDrainPumpMeasuredRPMOverride( void ); Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -88,7 +88,7 @@ HEATERS_STATE_T state; ///< Heater state. BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. - F32 dutyCycle; ///< Heater duty cycle. + OVERRIDE_F32_T dutyCycle; ///< Heater duty cycle. F32 targetFlow; ///< Heater target flow. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. F32 heaterEstGain; ///< Heater estimation gain during the run. @@ -116,6 +116,7 @@ static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ); static F32 calculateTrimmerHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ); static BOOL haveHeaterControlConditionsChanged( DG_HEATERS_T heater ); +static F32 getHeaterDutyCycle( DG_HEATERS_T heater ); static void setMainPrimaryHeaterPWM( F32 pwm ); static void setSmallPrimaryHeaterPWM( F32 pwm ); @@ -142,7 +143,10 @@ heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].isHeaterOn = FALSE; - heatersStatus[ heater ].dutyCycle = 0.0F; + heatersStatus[ heater ].dutyCycle.data = 0.0F; + heatersStatus[ heater ].dutyCycle.ovData = 0.0F; + heatersStatus[ heater ].dutyCycle.ovInitData = 0.0F; + heatersStatus[ heater ].dutyCycle.override = 0; heatersStatus[ heater ].targetFlow = 0.0F; heatersStatus[ heater ].hasTargetTempChanged = FALSE; heatersStatus[ heater ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; @@ -413,7 +417,7 @@ #endif { F32 heaterEstGain = heatersStatus[ heater ].heaterEstGain; - F32 heaterDutyCycle = heatersStatus[ heater ].dutyCycle; + F32 heaterDutyCycle = heatersStatus[ heater ].dutyCycle.data; F32 lastFillTemperature = getAvgFillTemperature(); F32 primaryTargetTemperature = heatersStatus[ heater ].targetTemp; BOOL isTempUnderTarget = ( lastFillTemperature < primaryTargetTemperature ? TRUE : FALSE ); @@ -630,7 +634,7 @@ } else { - dutyCycle = heatersStatus[ heater ].dutyCycle; + dutyCycle = heatersStatus[ heater ].dutyCycle.data; } state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; @@ -702,7 +706,7 @@ F32 targetFlowLPM = heatersStatus[ heater ].targetFlow; F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, outletRedundantTemperature, targetFlowLPM, TRUE ); - tempDutyCycle = heatersStatus[ heater ].dutyCycle + dutyCycle; + tempDutyCycle = heatersStatus[ heater ].dutyCycle.data + dutyCycle; tempDutyCycle = MIN( tempDutyCycle, HEATERS_MAX_DUTY_CYCLE ); tempDutyCycle = MAX( tempDutyCycle, HEATERS_MIN_DUTY_CYCLE ); @@ -725,17 +729,20 @@ { if ( heater < NUM_OF_DG_HEATERS ) { + F32 duty; + + heatersStatus[ heater ].dutyCycle.data = pwm; + duty = getHeaterDutyCycle( heater ); + if ( DG_PRIMARY_HEATER == heater ) { - setMainPrimaryHeaterPWM( pwm ); - setSmallPrimaryHeaterPWM( pwm ); + setMainPrimaryHeaterPWM( duty ); + setSmallPrimaryHeaterPWM( duty ); } else if ( DG_TRIMMER_HEATER == heater ) { - setTrimmerHeaterPWM( pwm ); + setTrimmerHeaterPWM( duty ); } - - heatersStatus[ heater ].dutyCycle = pwm; } else { @@ -831,6 +838,20 @@ /*********************************************************************//** * @brief + * The getHeaterDutyCycle function returns the heater's duty cycle. + * @details Inputs: heaterStatus + * @param heater: The heater Id that its on state is handled + * @return duty cycle + *************************************************************************/ +static F32 getHeaterDutyCycle( DG_HEATERS_T heater ) +{ + F32 duty = getF32OverrideValue( &heatersStatus[ heater ].dutyCycle ); + + return duty; +} + +/*********************************************************************//** + * @brief * The setMainPrimaryHeaterPWM function sets the PWM of the main primary heater. * @details Inputs: none * @details Outputs: Sets the PWM duty cycle for the main primary heater @@ -894,7 +915,7 @@ /*********************************************************************//** * @brief - * The publishTemperatureData function publishes the heaters data into + * The publishHeatersData function publishes the heaters data info * at the defined time interval. * @details Inputs: dataPublicationTimerCounter * @details Outputs: dataPublicationTimerCounter @@ -908,9 +929,9 @@ // The duty cycle of the primary heater is divided into 2 parts and is applied to main // and small primary heaters. So they are always the same. - data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; - data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; - data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle * FRACTION_TO_PERCENT_FACTOR; + data.mainPrimayHeaterDC = getHeaterDutyCycle( DG_PRIMARY_HEATER ) * FRACTION_TO_PERCENT_FACTOR; + data.smallPrimaryHeaterDC = getHeaterDutyCycle( DG_PRIMARY_HEATER ) * FRACTION_TO_PERCENT_FACTOR; + data.trimmerHeaterDC = getHeaterDutyCycle( DG_TRIMMER_HEATER ) * FRACTION_TO_PERCENT_FACTOR; data.primaryTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; @@ -939,9 +960,9 @@ F32 trimmerVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_TRIM_HTR_V ); // Voltage to PWM is reverse. If PWM = 0 -> V = 24V - F32 mainPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; - F32 smallPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; - F32 trimmerDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle; + F32 mainPriDC = getHeaterDutyCycle( DG_PRIMARY_HEATER ); + F32 smallPriDC = getHeaterDutyCycle( DG_PRIMARY_HEATER ); + F32 trimmerDC = getHeaterDutyCycle( DG_TRIMMER_HEATER ); // The expected voltage is the inverse of the duty cycle F32 mainPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - mainPriDC ); @@ -997,11 +1018,58 @@ /*********************************************************************//** * @brief + * The testSetHeaterDutyCycleOverride function overrides the specified heater's + * duty cycle. + * @details Inputs: heatersStatus + * @details Outputs: heatersStatus + * @return TRUE if the override was successful otherwise FALSE + *************************************************************************/ +BOOL testSetHeaterDutyCycleOverride( U32 heater, F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( ( value >= HEATERS_MIN_DUTY_CYCLE ) && ( value <= HEATERS_MAX_DUTY_CYCLE ) ) + { + result = TRUE; + heatersStatus[ (DG_HEATERS_T)heater ].dutyCycle.ovData = value; + heatersStatus[ (DG_HEATERS_T)heater ].dutyCycle.override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeaterDutyCycleOverride function resets the heater's + * duty cycle overridden value. + * @details Inputs: heatersStatus + * @details Outputs: heatersStatus + * @return TRUE if the reset was successful otherwise, FALSE + *************************************************************************/ +BOOL testResetHeaterDutyCycleOverride( U32 heater ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + heatersStatus[ (DG_HEATERS_T)heater ].dutyCycle.override = OVERRIDE_RESET; + heatersStatus[ (DG_HEATERS_T)heater ].dutyCycle.ovData = heatersStatus[ (DG_HEATERS_T)heater ].dutyCycle.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testSetHeatersPublishIntervalOverride function overrides the heaters * publish data time interval. * @details Inputs: heatersDataPublishInterval * @details Outputs: heatersDataPublishInterval - * @return result + * @return TRUE if the override was successful otherwise *************************************************************************/ BOOL testSetHeatersPublishIntervalOverride( U32 value ) { @@ -1025,7 +1093,7 @@ * publish time interval to its previous time interval. * @details Inputs: heatersDataPublishInterval * @details Outputs: heatersDataPublishInterval - * @return result + * @return TRUE if the reset was successful otherwise, FALSE *************************************************************************/ BOOL testResetHeatersPublishIntervalOverride( void ) { Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -155,7 +155,6 @@ static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ); static F32 roPumpFlowToPWM( RO_PI_FLOW_PROFILES_T profileID, F32 targetFlow ); -static void setROPumpTargetDutyCycle( F32 duty ); static void setROPumpControlSignalDutyCycle( F32 dutyCycle ); static void stopROPump( void ); static void publishROPumpData( void ); @@ -309,11 +308,45 @@ /*********************************************************************//** * @brief + * The setROPumpTargetDutyCycle function sets the duty cycle that the + * pump should run. + * @details Inputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, + * roPumpPWMDutyCyclePctSet, roPumpControlMode + * @details Outputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, + * roPumpPWMDutyCyclePctSet, roPumpControlMode + * @param: duty which is the duty cycle + * @return none + *************************************************************************/ +BOOL setROPumpTargetDutyCycle( F32 duty ) +{ + BOOL status = FALSE; + + if ( ( duty >= MIN_RO_PUMP_DUTY_CYCLE ) && ( duty <= MAX_RO_PUMP_DUTY_CYCLE ) ) + { + roPumpOpenLoopTargetDutyCycle = duty; + roPumpPWMDutyCyclePct = roPumpOpenLoopTargetDutyCycle; + roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; + roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; + status = TRUE; + + // Set the new duty cycle of the pump + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_RO_PUMP_DUTY_CYCLE_SELECTED, duty ) + } + + return status; +} + +/*********************************************************************//** + * @brief * The signalROPumpHardStop function stops the RO pump immediately and * resets all the variables associated with the RO pump run. * @details Inputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, * roPumpOpenLoopTargetDutyCycle, roControlTimerCounter, flowVerificationCounter, - * flowVerificationCounter, isROPumpOn, rampUp2FlowTimeoutCounter + * flowVerificationCounter, rampUp2FlowTimeoutCounter * @details Outputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, * roPumpOpenLoopTargetDutyCycle, roControlTimerCounter, * flowVerificationCounter, isROPumpOn, rampUp2FlowTimeoutCounter @@ -327,7 +360,6 @@ roPumpPWMDutyCyclePct = 0.0F; roPumpOpenLoopTargetDutyCycle = 0.0F; roControlTimerCounter = 0; - isROPumpOn = FALSE; targetROPumpMaxPressure = 0; pendingROPumpCmdMaxPressure = 0.0F; pendingROPumpCmdTargetFlow = 0.0F; @@ -577,6 +609,7 @@ static RO_PUMP_STATE_T handleROPumpOffState( void ) { RO_PUMP_STATE_T state = RO_PUMP_OFF_STATE; + isROPumpOn = FALSE; // If there is a flow, transition to the PI controller to get the corresponding pressure of that flow if ( ( getTargetROPumpFlowRateLPM() > 0.0F ) && ( PUMP_CONTROL_MODE_CLOSED_LOOP == roPumpControlMode ) ) @@ -713,28 +746,6 @@ /*********************************************************************//** * @brief - * The setROPumpTargetDutyCycle function sets the duty cycle that the - * pump should run. - * @details Inputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, - * roPumpPWMDutyCyclePctSet, roPumpControlMode - * @details Outputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, - * roPumpPWMDutyCyclePctSet, roPumpControlMode - * @param: duty which is the duty cycle - * @return none - *************************************************************************/ -static void setROPumpTargetDutyCycle( F32 duty ) -{ - roPumpOpenLoopTargetDutyCycle = duty; - roPumpPWMDutyCyclePct = roPumpOpenLoopTargetDutyCycle; - roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; - roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; - - // Set the new duty cycle of the pump - setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); -} - -/*********************************************************************//** - * @brief * The setROPumpControlSignalDutyCycle function sets the duty cycle for the * RO pump to a given duty cycle. * @details Inputs: none @@ -988,7 +999,7 @@ if ( TRUE == isTestingActivated() ) { // Check if duty cycle is within range - if ( value >= MIN_RO_PUMP_DUTY_CYCLE && value <= MAX_RO_PUMP_DUTY_CYCLE ) + if ( ( value >= MIN_RO_PUMP_DUTY_CYCLE ) && ( value <= MAX_RO_PUMP_DUTY_CYCLE ) ) { setROPumpTargetDutyCycle( value ); result = TRUE; Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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/TemperatureSensors.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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/Controllers/Voltages.h =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -34,7 +34,7 @@ /// Enumeration of voltages monitored by this module. typedef enum Voltages { - MONITORED_LINE_24V_MAIN = 0, ///< Main voltage (24V) + MONITORED_LINE_24V_MAIN = 0, ///< Main voltage (24V) (non-isolated) MONITORED_LINE_1_8V_FPGA, ///< FPGA logic voltage (1.8V) MONITORED_LINE_1V_FPGA, ///< FPGA reference voltage (1V) MONITORED_LINE_3_3V_SENSORS, ///< Sensors voltage (3.3V) @@ -51,7 +51,7 @@ MONITORED_LINE_FPGA_VPVN_V, ///< FPGA VPVN voltage (1V) MONITORED_LINE_PS_GATE_DRIVER_V, ///< P/S gate driver voltage (5V) MONITORED_LINE_LAST_RANGE_CHECKED_LINE = MONITORED_LINE_PS_GATE_DRIVER_V, ///< The last monitored line that is checked per fixed range. - MONITORED_LINE_24V_POWER_PRIM_HTR_V, ///< Primary heater voltage (24V) + MONITORED_LINE_24V_POWER_PRIM_HTR_V, ///< Primary heater voltage (24V) (isolated) MONITORED_LINE_24V_GND_MAIN_PRIM_HTR_V, ///< Main primary heater ground voltage (24V when off, <5V when on) MONITORED_LINE_24V_GND_SMALL_PRIM_HTR_V, ///< Small primary heater voltage (24V) MONITORED_LINE_24V_GND_TRIM_HTR_V, ///< Trimmer heater voltage (24V) Index: firmware/App/Drivers/CPLD.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Drivers/CPLD.h (.../CPLD.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Drivers/CPLD.h (.../CPLD.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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,7 +204,7 @@ 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 @@ -233,24 +222,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 +289,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 +403,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 +471,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 +497,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 +537,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 +551,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 +577,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 +613,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 +649,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 +666,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(); } } @@ -686,15 +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; + 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; } @@ -743,45 +751,35 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; - // 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 +791,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; } } @@ -824,7 +822,6 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; - // 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 ); @@ -840,7 +837,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 +848,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; @@ -888,27 +885,26 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; - // 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 +951,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 { @@ -991,27 +987,26 @@ { 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; + 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 +1031,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 +1083,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 { @@ -1123,10 +1116,7 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; - // 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(); @@ -1148,7 +1138,6 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - // Set the chemical disinfect that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; if ( CANCELLATION_MODE_NONE == cancellationMode ) @@ -1221,10 +1210,9 @@ { 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; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_COMPLETE; - stopChemicalDisinfect(); + requestNewOperationMode( DG_MODE_CHFL ); return state; } @@ -1257,7 +1245,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 +1274,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 +1433,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 +1487,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 +1567,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 +1593,6 @@ chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } - // Reservoirs are in range - else - { - isRsrvrLeaking = FALSE; - } } #ifndef _RELEASE_ @@ -1636,91 +1612,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 +1660,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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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; @@ -325,21 +332,18 @@ { 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; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_FLUSH_AFTER_DISINFECT; + overallChemDisinfectFlushTimer = getMSTimerCount(); - // Start overall chemical disinfect timer - overallChemDisinfectFlushTimer = getMSTimerCount(); - // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); // Set the actuators to drain R1 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 +367,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 +410,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 +425,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 +457,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 +526,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 +558,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 +590,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 +629,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 +679,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 +702,30 @@ /*********************************************************************//** * @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; + + state = DG_CHEM_DISINFECT_FLUSH_STATE_DRAIN_R1; // TODO remove once this state is implemented + // TODO add a 30 min timeout if the user did not hit complete and update the SRS + + if ( TRUE == didTimeout( stateTimer, SAMPLE_FLUSH_WAIT_TIME_MS ) ) + { + // TODO complete this if statement + } + + 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. @@ -732,12 +737,9 @@ { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - // Set the chemical disinfect flush that is published on the UI chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + cancellationMode = CANCELLATION_MODE_BASIC; - // Set the cancellation mode - cancellationMode = CANCELLATION_MODE_BASIC; - failChemicalDisinfectFlush(); return state; @@ -756,7 +758,6 @@ { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - // 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 ) @@ -830,10 +831,9 @@ { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; - // Set the chemical disinfect flush state that is published on the UI chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; - writeDisinfectFlushDataToNV(); //TODO: is this needed? + writeDisinfectDataToNV( USAGE_INFO_CHEM_FLUSH ); stopChemicalDisinfectFlush(); @@ -869,20 +869,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 +902,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 +934,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 +991,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 +1004,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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -143,7 +143,6 @@ checkInletWaterConductivity(); checkInletWaterTemperature(); checkInletWaterPressure(); - checkRORejectionRatio(); // execute current drain state switch ( drainState ) Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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; } @@ -930,7 +928,6 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; - // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; // First reservoir 1 must be full @@ -953,37 +950,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 +994,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 +1032,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 +1043,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; @@ -1074,7 +1076,6 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; - // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; // First reservoir 1 must be partially full @@ -1088,33 +1089,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; @@ -1135,8 +1129,20 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + 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: @@ -1176,8 +1182,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + writeDisinfectDataToNV( USAGE_INFO_HEAT_DIS ); if ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) @@ -1216,8 +1223,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + if ( ( TRUE == didTimeout( stateTimer, DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ) ) && ( FALSE == isDrainPumpInMixDrainOn ) ) { isDrainPumpInMixDrainOn = TRUE; @@ -1334,7 +1342,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 ) { @@ -1439,7 +1447,6 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COMPLETE; - // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; requestNewOperationMode( DG_MODE_HCOL ); @@ -1609,8 +1616,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 +1641,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 +1755,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 +1825,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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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. Index: firmware/App/Services/PIControllers.c =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 @@ -1225,9 +1225,13 @@ break; case MSG_ID_DG_DRAIN_PUMP_CURRENT_OVERRIDE: - handleTestDGDrainPumpCurrentOverrideRequest( message ); + handleTestDrainPumpMeasuredCurrentOverride( message ); break; + case MSG_ID_DG_GEN_IDLE_PUBLISH_INTERVAL_OVERRIDE: + handleTestGenIdlePublishIntervalOverride( message ); + break; + case MSG_ID_DG_DRAIN_PUMP_DIRECTION_OVERRIDE: handleTestDGDrainPumpDirectionOverrideRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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 Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7 -r5c430c3ac17fc8ad836fd70b8a3b8a12af44319e --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 4b9ae4e44d44ee6577fec4c8b75aa160fea04cc7) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5c430c3ac17fc8ad836fd70b8a3b8a12af44319e) @@ -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.