Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -rd995cc12ca7e53ca9af955b25e867c19e02ea654 -r7d0fd5ed6b9db0479af90477e5108f6d3fa8df17 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision d995cc12ca7e53ca9af955b25e867c19e02ea654) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 7d0fd5ed6b9db0479af90477e5108f6d3fa8df17) @@ -1,15 +1,15 @@ /************************************************************************** * -* Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2024 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 ModeGenIdle.c * * @author (last) Dara Navaei -* @date (last) 11-May-2023 +* @date (last) 09-Apr-2024 * * @author (original) Quang Nguyen * @date (original) 06-Aug-2021 @@ -39,14 +39,15 @@ #include "Valves.h" /** - * @addtogroup DGRecirculateMode + * @addtogroup DGGenIdleMode * @{ */ // ********** private definitions ********** #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. -#define TARGET_RO_FLOW_RATE_L 0.8F //0.4F ///< Target flow rate for RO pump. +#define TARGET_RO_FLOW_RATE_L 0.8F ///< Target flow rate for RO pump. +#define MAX_IDLE_RSVR_WEIGHT_GAIN_ML 200.0F ///< Maximum fluid gain of inactive reservoir in Gen Idle mode (mL) #define HD_LOST_COMM_TIMEOUT_MS (5 * SEC_PER_MIN * MS_PER_SECOND ) ///< The time of HD lost comm before DG transition back to standby. #define BAD_FILL_SUBSTATES_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the bad fill sub-states is published on the CAN bus. #define DATA_PUBLISH_COUNTER_START_COUNT 61 ///< Data publish counter start count. @@ -58,12 +59,16 @@ // NOTE: the bad fill state must be initialized here and not in the transition function since in case of a bad fill, the transition function is called // several times to drain and fill and handle a bad fill. static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T badFillState = DG_HANDLE_BAD_FILL_STATE_START; ///< Initialize bad fill sub-state. +// NOTE: the empty bottle flag must be initialized here and not in transition function since this flag must be set to false once the empty bottle +// fill is finished. +static BOOL handleEmptyBottleFlag = FALSE; ///< Internal siganl flag to handle empty bottle flag. static U32 hdLostCommStartTime_ms; ///< Lost communication with HD start time in ms. -static U32 targetFillVolumeML; ///< Save the target fill volume before calling startFillCmd(). static BOOL handleBadFillFlag; ///< Internal signal flag to handle bad fill. static OVERRIDE_U32_T genIdleDataPublicationInterval = { BAD_FILL_SUBSTATES_PUB_INTERVAL, BAD_FILL_SUBSTATES_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish bad fill sub-states to CAN bus. +static F32 initialReservoirWeight; ///< Initial weight of inactive reservoir in Gen Idle mode. +static DG_RESERVOIR_ID_T inactiveReservoir; ///< Inactive reservoir // ********** private function prototypes ********** @@ -77,7 +82,8 @@ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleSecondDrainState( void ); static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleRefillState( DG_GEN_IDLE_MODE_STATE_T* idleState ); -static void publishGenIdleSubstates(); +static void checkInvalidReservoirFill( void ); +static void publishGenIdleSubstates( void ); /*********************************************************************//** * @brief @@ -101,9 +107,12 @@ *************************************************************************/ U32 transitionToGenIdleMode( void ) { + BOOL cp1parkStatus = ( getConcPumpIsParked( CONCENTRATEPUMPS_CP1_ACID ) != TRUE ? PARK_CONC_PUMPS : NO_PARK_CONC_PUMPS ); + BOOL cp2parkStatus = ( getConcPumpIsParked( CONCENTRATEPUMPS_CP2_BICARB ) != TRUE ? PARK_CONC_PUMPS : NO_PARK_CONC_PUMPS ); + // Re-initialize each time we transition to generation idle mode initGenIdleMode(); - + setCurrentSubState( NO_SUB_STATE ); // Set initial actuator states setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); @@ -118,8 +127,8 @@ setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR ); signalDrainPumpHardStop(); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, cp1parkStatus ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, cp2parkStatus ); // UV reactors on turnOnUVReactor( INLET_UV_REACTOR ); @@ -138,6 +147,9 @@ setCPLDCleanLEDColor( CPLD_CLEAN_LED_OFF ); + inactiveReservoir = getInactiveReservoir(); + initialReservoirWeight = getReservoirWeight( inactiveReservoir ); + return genIdleState; } @@ -188,13 +200,13 @@ * The setBadAvgConductivityDetectedFlag function sets a flag to indicate * that bad average conductivity is detected. * @details Inputs: none - * @details Outputs: none + * @details Outputs: handleBadFillFlag, badFillState * @param flag to TRUE if bad avg conductivity otherwise FALSE *************************************************************************/ void setBadAvgConductivityDetectedFlag( BOOL badAvgConducitivyflag ) { handleBadFillFlag = badAvgConducitivyflag; - badFillState = DG_HANDLE_BAD_FILL_STATE_START; // Reset bad fill state too so we start at beginning + badFillState = DG_HANDLE_BAD_FILL_STATE_START; // Reset bad fill state too so we start at beginning } /*********************************************************************//** @@ -245,6 +257,7 @@ break; } + checkInvalidReservoirFill(); publishGenIdleSubstates(); return (U32)genIdleState; @@ -254,8 +267,8 @@ * @brief * The handleIdleStartState function executes the start state of the * generation idle mode state machine. - * @details Inputs: none - * @details Outputs: none + * @details Inputs: handleEmptyBottleFlag + * @details Outputs: handleEmptyBottleFlag, handleBadFillFlag, badFillState * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleIdleStartState( void ) @@ -270,6 +283,14 @@ { badFillState = DG_HANDLE_BAD_FILL_STATE_START; result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; + + if ( ( TRUE == handleEmptyBottleFlag ) && ( DG_MODE_FILL == getPreviousOperationMode() ) ) + { + // If the previous mode was fill and the empty bottle flag was TRUE, set it to FALSE and clear the informative alarm + // Done with the empty bottle handling + handleEmptyBottleFlag = FALSE; + clearAlarmCondition( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); + } } return result; @@ -279,14 +300,28 @@ * @brief * The handleFlushWaterState function executes the flush water state * generation idle mode state machine. - * @details Inputs: none - * @details Outputs: none + * @details Inputs: handleEmptyBottleFlag + * @details Outputs: handleEmptyBottleFlag * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleFlushWaterState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; + if ( ( TRUE == isAlarmActive( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ) ) || ( TRUE == isAlarmActive( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ) ) ) + { + // The empty bottle alarms are active set the empty bottle alarm to TRUE. + handleEmptyBottleFlag = TRUE; + } + + if ( ( TRUE == handleEmptyBottleFlag ) && + ( isAlarmActive( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ) != TRUE ) && + ( isAlarmActive( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ) != TRUE ) ) + { + // User acknowledged empty conc bottle alarm(s) and so time to start a fill + startFillCmd( getTargetFillVolumeML(), getTargetFillFlowRateLPM() ); + } + return result; } @@ -301,6 +336,7 @@ static DG_GEN_IDLE_MODE_STATE_T handleBadFillState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_HANDLE_BAD_FILL; + U32 priorSubState = badFillState; // Execute current bad fill state switch ( badFillState ) @@ -331,6 +367,10 @@ break; } + if ( priorSubState != badFillState ) + { + setCurrentSubState( badFillState ); + } return result; } @@ -409,7 +449,7 @@ DG_GEN_IDLE_MODE_BAD_FILL_STATE_T state = DG_HANDLE_BAD_FILL_STATE_REFILL; // Refill to the saved target fill volume (~1500 mL) - startFillCmd( targetFillVolumeML, getTargetFillFlowRateLPM() ); + startFillCmd( getTargetFillVolumeML(), getTargetFillFlowRateLPM() ); return state; } @@ -438,6 +478,33 @@ /*********************************************************************//** * @brief + * The checkInvalidReservoirFill function checks for reservoir filling in + * generation idle mode when it should be constant. + * @details Inputs: inactiveReservoir, initialReservoirWeight + * @details Outputs: inactiveReservoir, initialReservoirWeight + * @return the next state + *************************************************************************/ +static void checkInvalidReservoirFill( void ) +{ + DG_RESERVOIR_ID_T currentInactiveReservoir = getInactiveReservoir(); + F32 reservoirWeight = getReservoirWeight( currentInactiveReservoir ); + + if ( currentInactiveReservoir != inactiveReservoir ) + { + // Inactive Reservoir changed, update the start value + inactiveReservoir = currentInactiveReservoir; + initialReservoirWeight = getReservoirWeight( inactiveReservoir ); + } + + // Check for unwanted filling unless a transfer is in progress + if ( ( FALSE == isReservoirTransferInProgress() ) && ( reservoirWeight > ( initialReservoirWeight + MAX_IDLE_RSVR_WEIGHT_GAIN_ML ) ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_INACTIVE_RESERVOIR_WEIGHT_OUT_OF_RANGE, initialReservoirWeight, reservoirWeight ); + } +} + +/*********************************************************************//** + * @brief * The publishGenIdleSubstates function publishes gen idle * sub-states at the set interval. * @details Inputs: handleBadFillFlag, badFillState, targetFillVolumeML, @@ -464,7 +531,20 @@ } } +/*********************************************************************//** + * @brief + * The getCurrentBadFillSignal function returns the current + * generation idle mode bad fill flag. + * @details Inputs: handleBadFillFlag + * @details Outputs: none + * @return the current generation idle mode bad fill flag + *************************************************************************/ +BOOL getCurrentBadFillSignal( void ) +{ + return handleBadFillFlag; +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -476,7 +556,7 @@ * bad fill sub-states publish interval. * @details Inputs: badFillSubstatesPublishInterval * @details Outputs: badFillSubstatesPublishInterval - * @param: value override bad fill sub-states publish interval with (in ms) + * @param value override bad fill sub-states publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetGenIdleSubstatesPublishIntervalOverride( U32 value )