Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r70ccc0b282f1dafcd1f6b95dd53f4efe2efd3b2b -rbc8403b288e167f51c9e991c2a07bb455c77c19a --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 70ccc0b282f1dafcd1f6b95dd53f4efe2efd3b2b) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision bc8403b288e167f51c9e991c2a07bb455c77c19a) @@ -47,16 +47,21 @@ #define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). +#define DIP_FLOW_RATE_SETUP_ML_MIN 100 ///< Dialysate inlet pump flow rate during the setup for wet self-test. #define DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN 100 ///< Dialysate inlet pump flow rate during the first displacement in wet self-test. #define DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 300 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. +#define WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML 1500 ///< Setup volume for reservoir one before wet self-test in ml. #define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100 ///< Target of first displacement volume in ml. #define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 300 ///< Target of second displacement volume in ml. #define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 5 ///< Tolerance on integrated volume in percentage. #define WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G 1.5 ///< Tolerance in the load cell readings of the displacement in grams. #define WET_SELF_TEST_DISPLACEMENT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Time to displace dialysate in wet self-test in ms. #define RESERVOIR_SETTLE_TIME_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time allotted for reservoir to settle in ms. +/// Multiplier to conver flow (mL/min) into volume (mL) for period of general task interval. +static const F32 SELF_TEST_FLOW_INTEGRATOR = ( ( 1.0 * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); + /// No cartridge self-tests state machine. typedef enum No_Cart_Self_Tests_State { @@ -96,13 +101,15 @@ typedef enum Wet_Self_Tests_State { WET_SELF_TESTS_START_STATE = 0, ///< Wet self-tests starting state. + WET_SELF_TESTS_SETUP_STATE, ///< Setup reservoirs for wet self-tests. WET_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors wet self-tests state. WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE, ///< Setup valve and start dialysate pump for first displacement. WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE, ///< Fill reservoir 2 with 100 mL of dialysate from reservoir 1 state. WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE, ///< After first displacement completed verify state. WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE, ///< Setup valve and start dialysate pump for second displacement. WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE, ///< Fill reservoir 1 with 300 mL of dialysate from reservoir 2 state. WET_SELF_TESTS_SECOND_DISPLACEMENT_VERIFY_STATE, ///< After first displacement completed verify state. + WET_SELF_TESTS_STOPPED_STATE, ///< Wet self-test stopped state. WET_SELF_TESTS_COMPLETE_STATE, ///< Wet self-test complete state. NUM_OF_WET_SELF_TESTS_STATES ///< Number of wet self-tests states. } WET_SELF_TESTS_STATE_T; @@ -126,13 +133,16 @@ static U32 displacementStartTime; ///< Dialysate displacement starting time. static F32 fmdIntegratedVolume; ///< FMD integrated volume over displacement time. static F32 reservoirVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Hold the current volume of all reservoirs. +static F32 setupDisplacementVolume; ///< Hold the setup displacement volume to get reservoir one to target volume. +static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been send to DG. static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. static BOOL selfTestsStopRequested; ///< Flag indicates alarm requesting to stop self-test. // ********** private function prototypes ********** static void resetSelfTestsFlags( void ); +static void setupForSelfTestsStop( void ); static void handleNoCartSelfTestsStopRequest( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ); @@ -150,13 +160,17 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); +static void handleWetSelfTestsStopRequest( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( SELF_TEST_STATUS_T *result ); static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementVerifyState( SELF_TEST_STATUS_T *result ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestStoppedState( void ); /*********************************************************************//** * @brief @@ -210,6 +224,21 @@ /*********************************************************************//** * @brief + * The setupForSelfTestsStop function sets actuators appropriately for self-tests + * states. + * @details Inputs: none + * @details Outputs: All pumps stopped + * @return none + *************************************************************************/ +static void setupForSelfTestsStop( void ) +{ + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); +} + +/*********************************************************************//** + * @brief * The transitionToNoCartSelfTests function resets anything required before * the start of no cartridge self-tests. * @details Inputs: none @@ -460,6 +489,7 @@ settleStartTime = 0; displacementStartTime = 0; fmdIntegratedVolume = 0.0; + isValvesSettingSent = FALSE; resetSelfTestsFlags(); } @@ -479,13 +509,13 @@ switch ( currentWetSelfTestsState ) { case WET_SELF_TESTS_START_STATE: -#ifdef SKIP_SELF_TESTS - currentWetSelfTestsState = WET_SELF_TESTS_COMPLETE_STATE; -#else - currentWetSelfTestsState = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; -#endif + currentWetSelfTestsState = handleWetSelfTestStartState(); break; + case WET_SELF_TESTS_SETUP_STATE: + currentWetSelfTestsState = handleWetSelfTestSetupState(); + break; + case WET_SELF_TESTS_BUBBLE_DETECTOR_STATE: currentWetSelfTestsState = handleWetSelfTestBubbleDetectorsState( &result ); break; @@ -514,6 +544,10 @@ currentWetSelfTestsState = handleWetSelfTestSecondDisplacementVerifyState( &result ); break; + case WET_SELF_TESTS_STOPPED_STATE: + currentWetSelfTestsState = handleWetSelfTestStoppedState(); + break; + case WET_SELF_TESTS_COMPLETE_STATE: wetSelfTestsResult = TRUE; break; @@ -524,6 +558,12 @@ break; } + // Transition to stopped state when alarm with stop property has been triggered + handleWetSelfTestsStopRequest(); + + // Self-tests flags should be handled by now, reset if flags not handled with current state + resetSelfTestsFlags(); + if ( SELF_TEST_STATUS_FAILED == result ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_WET_SELF_TEST_FAILURE, currentWetSelfTestsState ); @@ -550,13 +590,11 @@ * @details Outputs: none * @return the next state of no cart self-tests state machine *************************************************************************/ -static void handleNoCartSelfTestsStopRequest( void ) +static void handleNoCartSelfTestsStopRequest( void ) { if ( TRUE == selfTestsStopRequested ) { - signalBloodPumpHardStop(); - signalDialInPumpHardStop(); - signalDialOutPumpHardStop(); + setupForSelfTestsStop(); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_STOPPED_STATE; selfTestsStopRequested = FALSE; @@ -685,6 +723,7 @@ if ( TRUE == selfTestsResumeRequested ) { + selfTestsResumeRequested = FALSE; state = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } @@ -699,13 +738,11 @@ * @details Outputs: none * @return the next state of dry self-tests state machine *************************************************************************/ -static void handleDrySelfTestsStopRequest( void ) +static void handleDrySelfTestsStopRequest( void ) { if ( TRUE == selfTestsStopRequested ) { - signalBloodPumpHardStop(); - signalDialInPumpHardStop(); - signalDialOutPumpHardStop(); + setupForSelfTestsStop(); currentDrySelfTestsState = DRY_SELF_TESTS_STOPPED_STATE; selfTestsStopRequested = FALSE; @@ -883,6 +920,7 @@ if ( TRUE == selfTestsResumeRequested ) { + selfTestsResumeRequested = FALSE; state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } @@ -891,6 +929,102 @@ /*********************************************************************//** * @brief + * The handleWetSelfTestsStopRequest function handles stop request from alarm + * and transition to stopped state. + * @details Inputs: none + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static void handleWetSelfTestsStopRequest( void ) +{ + if ( TRUE == selfTestsStopRequested ) + { + setupForSelfTestsStop(); + + currentWetSelfTestsState = WET_SELF_TESTS_STOPPED_STATE; + selfTestsStopRequested = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestStartState function handles setup state for wet + * self-tests sub-mode. + * @details Inputs: reservoir one weight + * @details Outputs: setup valves and dialysate inlet pump + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_START_STATE; + DG_CMD_RESPONSE_T cmdResp; + + F32 const resOneWeight = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + setupDisplacementVolume = fabs( resOneWeight - WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML ); + + if ( FALSE == isValvesSettingSent ) + { + if ( resOneWeight > WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + cmdChangeDGValveSetting( VALVE_SETTING_R1_TO_R2 ); + } + else + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + cmdChangeDGValveSetting( VALVE_SETTING_R2_TO_R1 ); + } + + isValvesSettingSent = TRUE; + } + + if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) + { + // Re-send command if DG rejects + isValvesSettingSent = FALSE; + + if ( FALSE == cmdResp.rejected ) + { + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SETUP_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + fmdIntegratedVolume = 0; + state = WET_SELF_TESTS_SETUP_STATE; + } + } + +#ifdef SKIP_SELF_TESTS + state = WET_SELF_TESTS_COMPLETE_STATE; +#endif + + return state; +} + +/*********************************************************************//** + * @brief + * The handleWetSelfTestSetupState function setup reservoir one before + * the start of wet self-tests. + * @details Inputs: dialysate inlet flow rate + * @details Outputs: stop dialysate inlet pump + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SETUP_STATE; + + setupDisplacementVolume -= ( SELF_TEST_FLOW_INTEGRATOR * getMeasuredDialInFlowRate() ); + + if ( setupDisplacementVolume <= 0 ) + { + signalDialInPumpHardStop(); + state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleWetSelfTestBubbleDetectorsState function handles the wet self-test * for bubble detectors. * @details Inputs: Arterial and venous air bubble status @@ -929,20 +1063,31 @@ static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ) { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + DG_CMD_RESPONSE_T cmdResp; - if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + if ( ( FALSE == isValvesSettingSent ) && ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) ) { reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - // TODO: send command to DG to change VRi, VRo valve setting - setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + cmdChangeDGValveSetting( VALVE_SETTING_R1_TO_R2 ); + isValvesSettingSent = TRUE; + } - displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; - state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) + { + // Re-send command if DG rejects + isValvesSettingSent = FALSE; + + if ( FALSE == cmdResp.rejected ) + { + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0; + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; + } } return state; @@ -1017,20 +1162,31 @@ static WET_SELF_TESTS_STATE_T handleWetSelfTestSecondDisplacementSetupState( void ) { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; + DG_CMD_RESPONSE_T cmdResp; - if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + if ( ( FALSE == isValvesSettingSent ) && ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) ) { reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - // TODO: send command to DG to change VRi, VRo valve setting - setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + cmdChangeDGValveSetting( VALVE_SETTING_R1_TO_R2 ); + isValvesSettingSent = TRUE; + } - displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; - state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) + { + // Re-send command if DG rejects + isValvesSettingSent = FALSE; + + if ( FALSE == cmdResp.rejected ) + { + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + displacementStartTime = getMSTimerCount(); + fmdIntegratedVolume = 0; + state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; + } } return state; @@ -1053,6 +1209,7 @@ if ( TRUE == didTimeout( displacementStartTime, WET_SELF_TEST_DISPLACEMENT_TIME_MS ) ) { signalDialInPumpHardStop(); + // Convert flow into volume for period of general task interval fmdIntegratedVolume = ( ( fmdIntegratedVolume * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); settleStartTime = getMSTimerCount(); @@ -1094,4 +1251,25 @@ return state; } +/*********************************************************************//** + * @brief + * The handleWetSelfTestStoppedState function handles the stopped wet self-tests + * operation. + * @details Inputs: none + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestStoppedState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_STOPPED_STATE; + + if ( TRUE == selfTestsResumeRequested ) + { + selfTestsResumeRequested = FALSE; + state = WET_SELF_TESTS_START_STATE; + } + + return state; +} + /**@}*/