Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r3b7059f9225a021c5c55a3cb7874bafc2ae1eb48 -rca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 3b7059f9225a021c5c55a3cb7874bafc2ae1eb48) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision ca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Dara Navaei -* @date (last) 07-Apr-2023 +* @author (last) Sean Nash +* @date (last) 17-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 08-Dec-2020 @@ -47,8 +47,8 @@ #define BLOOD_PUMP_FAST_FLOW_RATE_CIRC_BLOOD_CIRCUIT_ML_MIN 300 ///< Blood pump fast flow rate during prime recirculate blood circuit state. #define BLOOD_PUMP_FLOW_RATE_SALINE_DIALYZER_ML_MIN 300 ///< Blood pump flow rate during prime the saline dialyzer dialysate state. #define DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN 300 ///< Dialysate pump flow rate during priming fluid path. -#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump flow rate during priming fluid path. -#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 225 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. +#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump faster flow rate during priming fluid path. +#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 240 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. #define DIALYSATE_DIALYZER_TUBE_VOLUME_ML 115 ///< This total tube volume is used to calculate the Dpi & Dpo time out in the dialysate dialyzer state. #define DIALYSATE_DIALYZER_BYPASS_TUBE_VOLUME_ML 75 ///< This volume is used to calculate the DPi pump time out in the dialyzer bypass state. @@ -57,11 +57,15 @@ #define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. #define PURGE_AIR_TIME_OUT_COUNT ( 240 * MS_PER_SECOND ) ///< Time period count for purge air time out. -#define PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for prime saline dialyzer time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 8 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. -#define STEADY_VOLUME_TIME_DEADLINE_MS ( 55 * MS_PER_SECOND ) ///< Time in msec for the steady volume deadline time out. +#define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 90 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. +#define STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ( 62 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during bypass dialysate prime state. +#define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG 50.0F ///< +/- offset from start pressure that defines a range to keep PBo in during dialysate dialyzer prime state. +#define DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN 1 ///< DPo rate step to maintain pressure during dialysate dialyzer prime state. #define VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum venous pressure reading (in mmHg) for bubble clear. #define BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS ( 10 * MS_PER_SECOND ) ///< Time in msec to wait for initial bubble clear pressure. @@ -132,17 +136,21 @@ static U32 primeSalineDialyzerStartTime; ///< Starting time of priming saline dialyzer circuit. static U32 primeSalineDialyzerBubbleClearStartTime; ///< Starting time of priming saline dialyzer bubble clear. static U32 primeDialysateDialyzerStartTime; ///< Starting time of priming dialysate dialyzer circuit. +static F32 primeDialysateDialyzerStartVenPres; ///< Starting venous pressure (mmHg) for dialysate dialyzer prime state. +static U32 primeDialysateDialyzerDPoRate; ///< Record of last given DPo target rate for dialysate dialyzer prime state. static U32 primeDialysateBypassStartTime; ///< Starting time of priming dialysate bypass circuit. static U32 steadyVolumeSamplingStartTime; ///< Load cell steady volume sampling interval starting time. static F32 minimumReservoirVolume; ///< Minimum reservoir volume in mL. static U32 steadyVolumeCount; ///< Use to keep track the number of dVolume/dt < Threshold +static BOOL bubbleClearEnded; ///< Bubble clear ended boolean signal. // ********** private function prototypes ********** static void resetPrimeFlags(); static void setupForPrimePause( void ); static void broadcastPrimingStatus( void ); static void purgeAirValvesBloodPumpControl( void ); +static void handlePrimeBubbleClear( void ); static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeWaitForUserStartState( void ); static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineDialyzerSetupState( void ); @@ -172,39 +180,35 @@ primeStartTime = 0; primePauseStartTime = 0; primeStatusBroadcastTimerCounter = 0; + bubbleClearEnded = FALSE; } /*********************************************************************//** * @brief * The transitionToPrime function prepares for transition to prime sub-mode. * This function will reset anything required before the start of priming sequence. * @details Inputs: none - * @details Outputs: currentPrimeState, wetSelfTestsResult, primeStartReqReceived, reservoirFilledStatus[] + * @details Outputs: currentPrimeState, wetSelfTestsResult, primeStartReqReceived, + * reservoirFilledStatus[], bubbleClearEnded, primeDialyzerBubbleClearState * @return none *************************************************************************/ void transitionToPrime( void ) { primeStartTime = getMSTimerCount(); primeFirstPurgePass = TRUE; - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - + setCurrentSubState( (U32)currentPrimeState ); doorClosedRequired( TRUE, TRUE ); // Pumps should be off signalBloodPumpHardStop(); signalDialInPumpHardStop(); signalDialOutPumpHardStop(); stopSyringePump(); -#ifndef _RELEASE_ - if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) -#endif - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - } + setAirPumpState( AIR_PUMP_STATE_OFF ); // Set valves to default positions setValveAirTrap( STATE_CLOSED ); @@ -214,6 +218,17 @@ setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); resetPrimeFlags(); + + if ( getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) != TRUE ) + { + bubbleClearEnded = FALSE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; + } + else + { // if using a wet cartridge, we do not want to do the bubble clearing of dialyzer in blood side prime states + bubbleClearEnded = TRUE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_COMPLETE_STATE; + } } /*********************************************************************//** @@ -292,6 +307,7 @@ if ( priorSubState != currentPrimeState ) { + setCurrentSubState( (U32)currentPrimeState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentPrimeState ); } @@ -420,15 +436,20 @@ *************************************************************************/ static void broadcastPrimingStatus( void ) { - U32 const elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + U32 elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + // If the elapsed time is greater than the maximum prime time, it is capped to max prime time so the remaining time + // is a large number + elapsedPrimeTimeInSecs = CAP( elapsedPrimeTimeInSecs, MAX_PRIME_TIME ); + // timeout alarm that used to trigger when max prime time elapsed was removed. if ( ++primeStatusBroadcastTimerCounter >= PRIME_DATA_PUB_INTERVAL ) { PRIMING_DATA_PAYLOAD_T primeData; - primeData.totalTime = MAX_PRIME_TIME; - primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + primeData.totalTime = MAX_PRIME_TIME; + primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + broadcastData( MSG_ID_HD_PRIMING_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&primeData, sizeof( PRIMING_DATA_PAYLOAD_T ) ); primeStatusBroadcastTimerCounter = 0; } @@ -447,7 +468,7 @@ setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Allow fluid to get to VBA per DEN-14171 setValveAirTrap( STATE_OPEN ); signalDialOutPumpHardStop(); @@ -464,82 +485,16 @@ /*********************************************************************//** * @brief - * The handlePrimeSalineSetupState function checks user's request to start - * priming. - * @details Inputs: primeStartReqReceived - * @details Outputs: control valves to purge air - * @return current state - *************************************************************************/ -static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeWaitForUserStartState( void ) -{ - HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_WAIT_FOR_USER_START_STATE; - - // Keep updating start time until the user requested priming - primeStartTime = getMSTimerCount(); - -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) - { - primeStartRequested = TRUE; - } -#endif - -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) - { - state = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; - } - else -#endif - - if ( TRUE == primeStartRequested ) - { - primeStartRequested = FALSE; - state = HD_PRIME_SALINE_SETUP_STATE; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handlePrimeSalineSetupState function prepares the entry conditions - * before start priming the saline dialyzer fluid path. - * priming. - * @details Inputs: primeStartReqReceived - * @details Outputs: control valves to purge air, primeDialyzerBubbleClearState, - * primeSalineDialyzerBubbleClearStartTime, purgeAirTimeOutStartTime - * @return current state - *************************************************************************/ -static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineSetupState( void ) -{ - HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_SALINE_PURGE_AIR_STATE; - - purgeAirValvesBloodPumpControl(); - purgeAirTimeOutStartTime = getMSTimerCount(); - primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; - - if ( TRUE == doesAlarmStatusIndicateStop() ) - { - setupForPrimePause(); - state = HD_PRIME_PAUSE; - } - - return state; -} - -/*********************************************************************//** - * @brief * The handlePrimeBubbleClear function handles bubble clear pressurizing * of dialyzer. - * @details Inputs: air trap levels, primeDialyzerBubbleClearState, primeSalineDialyzerBubbleClearStartTime - * @details Outputs: control valves to pressurize, primeDialyzerBubbleClearState, primeSalineDialyzerBubbleClearStartTime + * @details Inputs: air trap levels, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime + * @details Outputs: control valves to pressurize, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime * @return none *************************************************************************/ static void handlePrimeBubbleClear( void ) { - static BOOL bubble_clear_ended = FALSE; U32 timeout; switch ( primeDialyzerBubbleClearState ) @@ -576,15 +531,15 @@ // Pressure max reached. or timeout, release pressure setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - bubble_clear_ended = TRUE; + bubbleClearEnded = TRUE; primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_VENT_STATE; } - else if ( ( TRUE == bubble_clear_ended ) && + else if ( ( TRUE == bubbleClearEnded ) && ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) { setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValveAirTrap( STATE_OPEN ); - bubble_clear_ended = FALSE; + bubbleClearEnded = FALSE; primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_FLOW_STATE; } break; @@ -599,6 +554,80 @@ /*********************************************************************//** * @brief + * The handlePrimeWaitForUserStartState function checks user's request to start + * priming. + * @details Inputs: primeStartReqReceived + * @details Outputs: control valves to purge air + * @return current state + *************************************************************************/ +static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeWaitForUserStartState( void ) +{ + HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_WAIT_FOR_USER_START_STATE; + + // Keep updating start time until the user requested priming + primeStartTime = getMSTimerCount(); + signalAllowDGFillRes1(); + signalAllowDGFillRes2(); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) + { + primeStartRequested = TRUE; + } +#endif + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) + { + state = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; + } + else +#endif + { + if ( TRUE == primeStartRequested ) + { + primeStartRequested = FALSE; + state = HD_PRIME_SALINE_SETUP_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePrimeSalineSetupState function prepares the entry conditions + * before start priming the saline dialyzer fluid path. + * priming. + * @details Inputs: primeStartReqReceived + * @details Outputs: control valves to purge air, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime, purgeAirTimeOutStartTime + * @return current state + *************************************************************************/ +static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineSetupState( void ) +{ + HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_SALINE_PURGE_AIR_STATE; + + purgeAirValvesBloodPumpControl(); + purgeAirTimeOutStartTime = getMSTimerCount(); + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + + if ( getTestConfigStatus( TEST_CONFIG_USE_WET_CARTRIDGE ) != TRUE ) + { + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handlePrimePurgeAirState function checks for air trap level and moves * to blood circuit circulation state if fluid is detected at upper sensor. * @details Inputs: air trap levels, primeFirstPurgePass, purgeAirTimeOutStartTime @@ -706,13 +735,15 @@ signalBloodPumpHardStop(); setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( DPO_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + primeDialysateDialyzerDPoRate = DPO_PUMP_PRIME_FLOW_RATE_ML_MIN; // Calculate the time out value that must passed prior to checking for the steady state volume in the reservoir - primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); - minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - steadyVolumeCount = 0; - steadyVolumeSamplingStartTime = getMSTimerCount(); - primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); + minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + steadyVolumeCount = 0; + steadyVolumeSamplingStartTime = getMSTimerCount(); + primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerStartVenPres = getFilteredVenousPressure(); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) @@ -742,8 +773,10 @@ * @brief * The handlePrimeDialysateDialyzerState function handles priming for * dialysate dialyzer fluid path. - * @details Inputs: reservoir 1 filtered weight - * @details Outputs: primed dialysate dialyzer fluid path + * @details Inputs: reservoir 1 filtered weight, minimumReservoirVolume, + * steadyVolumeCount + * @details Outputs: primed dialysate dialyzer fluid path, minimumReservoirVolume, + * steadyVolumeCount * @return current state *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ) @@ -755,9 +788,9 @@ { if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { - F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + F32 currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -766,19 +799,34 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; // required 10 seconds continuous steady volume to transition to next state } - - steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next dVolume/dt check + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } } } - else + + // Adjust DPo speed to maintain venous pressure if necessary (re-using 1 sec steady volume timer to do this @ 1Hz) + if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { + F32 venPres = getFilteredVenousPressure(); + + if ( venPres > ( primeDialysateDialyzerStartVenPres + PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate += DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + else if ( venPres < ( primeDialysateDialyzerStartVenPres - PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate -= DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } steadyVolumeSamplingStartTime = getMSTimerCount(); } - if ( TRUE == didTimeout( primeDialysateDialyzerStartTime, primeDialysateDialyzerTimeLimit + STEADY_VOLUME_TIME_DEADLINE_MS ) ) + if ( TRUE == didTimeout( primeDialysateDialyzerStartTime, primeDialysateDialyzerTimeLimit + STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_DIALYSATE_DIALYZER_TIME_OUT, primeDialysateDialyzerTimeLimit ); } @@ -844,11 +892,6 @@ { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; } - // TODO: Rework alarm and timeout logic here. PRIME_SALINE_DIALYZER_TIME_OUT_COUNT may not be reached. - if ( TRUE == didTimeout( primeSalineDialyzerStartTime, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_SALINE_DIALYZER_TIME_OUT, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ); // Trigger HD prime saline dialyzer time out alarm. - } if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -920,7 +963,7 @@ { F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -930,9 +973,12 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; } + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next 1 second iteration } @@ -942,7 +988,7 @@ steadyVolumeSamplingStartTime = getMSTimerCount(); } - if ( TRUE == didTimeout( primeDialysateBypassStartTime, PRIME_DIALYSATE_BYPASS_TIME_LIMIT + STEADY_VOLUME_TIME_DEADLINE_MS ) ) // allocate 55 seconds for the steady state logic to do its job before timing out + if ( TRUE == didTimeout( primeDialysateBypassStartTime, PRIME_DIALYSATE_BYPASS_TIME_LIMIT + STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ) ) // allocate 25 seconds for the steady state logic to do its job before timing out { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_DIALYSATE_BYPASS_TIME_OUT, PRIME_DIALYSATE_BYPASS_TIME_LIMIT ); } @@ -977,12 +1023,14 @@ if ( TRUE == isWetSelfTestsPassed() ) { + setCurrent4thLevelState( NO_SUB_STATE ); state = HD_PRIME_COMPLETE; } else if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForPrimePause(); state = HD_PRIME_PAUSE; + setCurrent4thLevelState( NO_SUB_STATE ); } return state;