Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r497e638f3a9b45c0e9081db7e4f48f2ea879ba07 -r1a7b3fdc8c9b47ae713a7ec37670a96df7d73818 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 497e638f3a9b45c0e9081db7e4f48f2ea879ba07) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 1a7b3fdc8c9b47ae713a7ec37670a96df7d73818) @@ -332,6 +332,7 @@ checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, isFlowOutOfUpperRange, currentFlow, targetFlow ); checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, isFlowOutOfLowerRange, currentFlow, targetFlow ); } +#endif // If the pump is off and PPi + 5psi < PPo for a certain period of time, activate safety shutdown if ( FALSE == isROPumpOn ) @@ -347,7 +348,6 @@ activateSafetyShutdown(); } } -#endif // Publish RO pump data on interval publishROPumpData(); Index: firmware/App/DGCommon.h =================================================================== diff -u -rebbb1f85550a1f9b8f946655f7b2b63f76fbf67d -r1a7b3fdc8c9b47ae713a7ec37670a96df7d73818 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision ebbb1f85550a1f9b8f946655f7b2b63f76fbf67d) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision 1a7b3fdc8c9b47ae713a7ec37670a96df7d73818) @@ -48,7 +48,7 @@ #define DISABLE_DIALYSATE_CHECK 1 #define IGNORE_DRAIN_PUMP_MONITOR 1 #define IGNORE_HEATERS_MONITOR 1 -// #define IGNORE_RO_PUMP_MONITOR 1 + #define IGNORE_RO_PUMP_MONITOR 1 #define IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT 1 #define DISABLE_RO_RATIO_CHECK 1 #define DISABLE_COND_SENSOR_CHECK 1 Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -rd7926685f2fe3086bab183166119f0965a192a69 -r1a7b3fdc8c9b47ae713a7ec37670a96df7d73818 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision d7926685f2fe3086bab183166119f0965a192a69) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 1a7b3fdc8c9b47ae713a7ec37670a96df7d73818) @@ -64,8 +64,9 @@ #define RSRVRS_DRAIN_TIMEOUT_MS ( 3 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. TODO original value was 2 minutes #define FINAL_DRAIN_RO_PUMP_FLOW_LPM 0.6 ///< Final drain RO pump flow rate in L/min. This is used to flush the drain line during drain. -// Flush drain line state define -#define FLUSH_LINES_VOLUME_L 0.1 ///< Water volume to flush in liters. +// Flush drain line state defines +#define FLUSH_DRAIN_LINE_VOLUME_L 0.1 ///< Water volume to flush in liters. +#define FLUSH_DRAIN_LINE_TIMEOUT_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush drain lines timeout in milliseconds. // Flush circulation state defines #define FLUSH_CIRCULATION_WAIT_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush circulation wait time in milliseconds. @@ -98,7 +99,7 @@ static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ); static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ); static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ); -static DG_FLUSH_STATE_T handleFlushModeFlushDrainLineState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ); static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ); static DG_FLUSH_STATE_T handleFlushModeFlushWithFreshWaterState( void ); static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ); @@ -116,7 +117,8 @@ * @details Inputs: none * @details Outputs: flushState, prevFlushState, rsrvrFillStableTimeCounter, * overallFlushElapsedTime, isThisInitialDrain, dataPublishCounter, - * rsrvr1Status, rsrvr2Status, hasWaterCancellationBeenSet + * rsrvr1Status, rsrvr2Status, hasWaterCancellationBeenSet, + * flushLinesVolumeL * @return none *************************************************************************/ void initFlushMode( void ) @@ -131,6 +133,7 @@ rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; hasWaterCancellationBeenSet = FALSE; + flushLinesVolumeL = 0.0; } /*********************************************************************//** @@ -151,8 +154,8 @@ /*********************************************************************//** * @brief * The execFlushMode function executes the flush mode state machine. - * @details Inputs: none - * @details Outputs: Flush mode state machine executed + * @details Inputs: flushState + * @details Outputs: flushState * @return current state *************************************************************************/ U32 execFlushMode( void ) @@ -192,8 +195,8 @@ flushState = handleFlushModeFlushR2AndDrainR1State(); break; - case DG_FLUSH_STATE_FLUSH_DRAIN_LINE: - flushState = handleFlushModeFlushDrainLineState(); + case DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE: + flushState = handleFlushModeFlushCirculationDrainLineState(); break; case DG_FLUSH_STATE_FLUSH_CIRCULATION: @@ -225,7 +228,7 @@ // Publish the data publishFlushData(); - return flushState; + return (U32)flushState; } /*********************************************************************//** @@ -234,7 +237,7 @@ * mode. * @details Inputs: flushState * @details Outputs: none - * @return current state of flush mode. + * @return flushState which is the current state of flush mode. *************************************************************************/ DG_FLUSH_STATE_T getCurrentFlushState( void ) { @@ -243,16 +246,17 @@ /*********************************************************************//** * @brief - * The stopDGFlush function stops flush mode. + * The stopDGFlush function stops flush mode if the current operation mode + * is flush mode. * @details Inputs: none * @details Outputs: none - * @return none + * @return TRUE if the current mode is flush otherwise, FALSE *************************************************************************/ BOOL stopDGFlush( void ) { BOOL status = FALSE; - // Check if the current operation mode is heat disinfect + // Check if the current operation mode is flush if ( DG_MODE_FLUS == getCurrentOperationMode() ) { // Reset all the actuators @@ -307,8 +311,8 @@ * The handleFlushModeDrainR1State function handles the drain reservoir 1. * If the drain is completed within the defined time, it transitions to the * next state, otherwise, it transitions to basic cancellation state. - * @details Inputs: stateTimer, rsrvr2Status, isThisInitialDrain - * @details Outputs: stateTimer, rsrvr2Status + * @details Inputs: stateTimer, rsrvr1Status,rsrvr2Status, isThisInitialDrain + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status * @return next state of the flush state machine *************************************************************************/ static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ) @@ -348,8 +352,8 @@ * The handleFlushModeDrainR2State function handles the drain reservoir 2. * If the drain is completed within the defined time, it transitions to the * next state, otherwise, it transitions to basic cancellation state. - * @details Inputs: stateTimer, rsrvr2Status, isThisInitialDrain - * @details Outputs: none + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisInitialDrain + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status * @return next state of the flush state machine *************************************************************************/ static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ) @@ -375,7 +379,14 @@ } else { - state = DG_FLUSH_STATE_FLUSH_DRAIN_LINE; + // Set the actuators to pull fresh water in to drain the circulation line + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setROPumpTargetFlowRate( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + + state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; } stateTimerStart = getMSTimerCount(); @@ -400,7 +411,7 @@ { DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN; - if ( didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) + if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); @@ -420,9 +431,8 @@ /*********************************************************************//** * @brief * The handleFlushModeFlushDialysateState function handles the flush - * dialysate state. - * Once the flush dialysate time has elapsed, it transitions to the next - * state. + * dialysate state. Once the flush dialysate time has elapsed, it + * transitions to the next state. * @details Inputs: stateTimer * @details Outputs: stateTimer * @return next state of the flush state machine @@ -431,7 +441,7 @@ { DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DIALYSATE; - if ( didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) + if ( TRUE == didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) { // TODO turn on the concentrate pumps stateTimerStart = getMSTimerCount(); @@ -455,7 +465,7 @@ { DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; - if ( didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) + if ( TRUE == didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) { // TODO turn off the concentrate pumps setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); @@ -476,50 +486,65 @@ * The handleFlushModeFlushR1ToR2State function handles the flush * reservoir 1 to reservoir 2 state. If any of the reservoirs flush within * the defined period of time, it transitions to the next state, otherwise, - * it transitions to water cancellation state. + * it transitions to water cancellation state. If reservoir 2 is filled to + * 500 mL before reservoir 1 is filled, it transitions to water cancellation + * state. * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer, prevFlushState, + * alarmDetectedPendingTrigger * @return next state of the flush state machine *************************************************************************/ static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ) { DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) - { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) - { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - // Set the actuators to flush R2 and drain R1 state - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - stateTimerStart = getMSTimerCount(); + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - // Set both reservoirs' status - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } + // Keep monitoring the status of reservoir 2 as the same time + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already + // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue + // until reservoir 2 is filled up and the tubing might expand or leak. + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + prevFlushState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) + { + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + // Set the actuators to flush R2 and drain R1 state + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + stateTimerStart = getMSTimerCount(); + // Set both reservoirs' status + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } + return state; } @@ -530,9 +555,12 @@ * the defined period of time and reservoir 1 drains within the defined * period of time, it transitions to the next state. If the flush times out, * the function transitions to water cancellation state. If the drain times - * out the function transitions to basic cancellation state. + * out the function transitions to basic cancellation state. If reservoir 1 + * is filled to 500 mL before reservoir 2 is filled, it transitions to + * water cancellation state. * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer, prevFlushState, + * alarmDetectedPendingTrigger, isThisInitialDrain * @return next state of the flush state machine *************************************************************************/ static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ) @@ -559,6 +587,21 @@ if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + U32 drainPumpRPM = getTargetDrainPumpRPM(); + // Keep monitoring the status of reservoir 1 as the same time + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + // Reservoir 1 cannot be filled before reservoir 2 is filled and is overflowing to reservoir 1. If reservoir 1 has already + // reached to target volume, it means reservoir 2's load cell might be reading incorrect values. This situation might continue + // until reservoir 1 is filled up and the tubing might expand or leak. + // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make + // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) && ( 0 == drainPumpRPM ) ) + { + prevFlushState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } } // Once reservoir 2 is full, reservoir 1 must be partially full else if( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) @@ -594,25 +637,27 @@ /*********************************************************************//** * @brief - * The handleFlushModeFlushDrainLineState function handles the flush - * drain line state. Once the drain line was flushed with sufficient water, - * it transitions to the next state. + * The handleFlushModeFlushCirculationDrainLineState function handles the + * flush drain line state. Once the drain line was flushed with sufficient + * water, it transitions to the next state. If the line is not drained + * within the defined time, it transitions to water cancellation state. * @details Inputs: stateTimerStart, flushLinesVolumeL - * @details Outputs: stateTimerStart, flushLinesVolumeL + * @details Outputs: stateTimerStart, flushLinesVolumeL, + * alarmDetectedPendingTrigger * @return next state of the flush state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushDrainLineState( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN_LINE; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; F32 waterFlowRate = getMeasuredROFlowRate(); F32 waterVolume = ( ( waterFlowRate / SEC_PER_MIN ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - // integrate volume of water moved through line + // Integrate volume of water moved through line flushLinesVolumeL += waterVolume; - // when enough water volume has flowed to flush the lines, transition to re-circ state - if ( flushLinesVolumeL >= FLUSH_LINES_VOLUME_L ) + // When enough water volume has flowed to flush the lines, transition to flush circulation state + if ( flushLinesVolumeL >= FLUSH_DRAIN_LINE_VOLUME_L ) { // Set the actuators to transition to flush circulation // The valves are set to do flush drain and flush circulation @@ -625,6 +670,12 @@ state = DG_FLUSH_STATE_FLUSH_CIRCULATION; } + else if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_LINE_TIMEOUT_MS ) ) + { + alarmDetectedPendingTrigger = ALARM_ID_DG_DRAIN_CIRCULATION_LINE_TIMEOUT; + // Could not reach to the defined drain line on time + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } return state; } @@ -661,7 +712,7 @@ * The handleFlushModeFlushWithFreshWaterState function handles the * flush with fresh water state. It runs the circulation state with fresh * water for the defined period of time. - * @details Inputs: none + * @details Inputs: stateTimerStart * @details Outputs: none * @return next state of the flush state machine *************************************************************************/ @@ -682,8 +733,8 @@ /*********************************************************************//** * @brief * The handleFlushModeCancelBasicPathState function handles the flush - * cancel mode basic path state. The state sets the state - * to complete and raises an alarm. + * cancel mode basic path state. The state sets the state to complete and + * raises an alarm. * @details Inputs: none * @details Outputs: none * @return next state of the flush state machine @@ -692,7 +743,8 @@ { DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - // Once the fault alarm is raised, the DG Software will de-energize all the actuators + // Once the fault alarm is raised, the DG Software will + // deenergize all the actuators failFlushMode(); return state; @@ -703,8 +755,10 @@ * The handleFlushModeCancelWaterPathState function handles the flush mode * cancel water path state. The state drains the 2 reservoirs. If the drain * times out, it transitions to basic cancellation path. - * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer - * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer + * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer, + * hasWaterCancellationBeenSet + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer, + * hasWaterCancellationBeenSet * @return next state of the flush state machine *************************************************************************/ static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ) @@ -806,8 +860,7 @@ * not reach to target. * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, flushState, * prevFlushState - * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer, - * prevFlushState + * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param targetVol is the target fill volume * @param timeout is the fill up time out that is checked against @@ -854,8 +907,7 @@ * The getRsrvrDrainStatus function returns the status of draining a * reservoir. If the drain times out, it set the status to did not reach * target. - * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, - * flushState, prevFlushState + * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer, * prevFlushState * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 @@ -905,6 +957,7 @@ data.flushState = (U32)flushState; data.overallElapsedTime = calcTimeSince( overallFlushElapsedTimeStart ); data.stateElapsedTime = calcTimeSince( stateTimerStart ); + data.drainLineVolume = flushLinesVolumeL; broadcastFlushData( &data );