Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r0339d8357ff90e6540ec4420b536336e8c2bc6ea -raa5566f8a93214d1408ae361e4d80210b453187c --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 0339d8357ff90e6540ec4420b536336e8c2bc6ea) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision aa5566f8a93214d1408ae361e4d80210b453187c) @@ -54,14 +54,18 @@ #define DIALYZER_VOLUME_SCALE_FACTOR 0.5F ///< Half of the dialyzer total volume. #define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. -#define PURGE_AIR_TIME_OUT_COUNT ( 120 * MS_PER_SECOND ) ///< Time period count for purge air time out. +#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 ( 15 * 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 VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum arterial pressure reading (in mmHg) for bubble clear. +#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. +#define BUBBLE_CLEAR_WAIT_TIME_MS ( 2 * MS_PER_SECOND ) ///< Time in msec to wait for bubble clear pressure. +#define BUBBLE_CLEAR_MAX_TIME_MS ( 10 * MS_PER_SECOND ) ///< Time in msec maximum for bubble clear pressure. +#define BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ( 90 ) ///< Time in msec between VDi and VBT valve open /// States of the treatment reservoir management state machine. typedef enum PrimeReservoirMgmt_States @@ -78,6 +82,17 @@ NUM_OF_PRIME_RESERVOIR_MGMT_STATES ///< Number of prime reservoir mgmt. states. } PRIME_RESERVOIR_MGMT_STATE_T; +/// States of the prime dialyzer bubble clear state machine. +typedef enum PrimeSalineDialyzerBubbleClear_States +{ + PRIME_BUBBLE_CLEAR_READY_STATE = 0, ///< Bubble clear initial / ready state. + PRIME_BUBBLE_CLEAR_PRESSURE_STATE, ///< Bubble clear pressurized / active state. + PRIME_BUBBLE_CLEAR_VENT_STATE, ///< BUbble clear vent to reservoir state. + PRIME_BUBBLE_CLEAR_FLOW_STATE, ///< Bubble clear flow state. + PRIME_BUBBLE_CLEAR_COMPLETE_STATE, ///< Bubble clear complete. + NUM_OF_PRIME_BUBBLE_CLEAR_STATES ///< Number of bubble clear states. +} PRIME_BUBBLE_CLEAR_STATE_T; + typedef struct { U32 bloodVolume; ///< Blood volume of the dialyzer in mL. U32 dialysateVolume; ///< Dialysate volume of the dialyzer in mL. @@ -100,6 +115,7 @@ static HD_PRE_TREATMENT_PRIME_STATE_T currentPrimeState; ///< Current state of the prime sub-mode state machine. static HD_PRE_TREATMENT_PRIME_STATE_T previousPrimeState; ///< Previous state of the prime sub-mode, to use when resuming from pause. static PRIME_RESERVOIR_MGMT_STATE_T currentReservoirMgmtState; ///< Current reservoir management state. +static PRIME_BUBBLE_CLEAR_STATE_T primeDialyzerBubbleClearState;///< Priming saline dialyzer bubble clear state. static U32 primeStartTime; ///< Starting time of priming (in ms). static U32 primePauseStartTime; ///< Priming pause start time (in ms). @@ -169,6 +185,7 @@ { primeStartTime = getMSTimerCount(); primeFirstPurgePass = TRUE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); @@ -481,7 +498,8 @@ * before start priming the saline dialyzer fluid path. * priming. * @details Inputs: primeStartReqReceived - * @details Outputs: control valves to purge air + * @details Outputs: control valves to purge air, primeDialyzerBubbleClearState, + * primeSalineDialyzerBubbleClearStartTime, purgeAirTimeOutStartTime * @return current state *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineSetupState( void ) @@ -490,6 +508,8 @@ purgeAirValvesBloodPumpControl(); purgeAirTimeOutStartTime = getMSTimerCount(); + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_READY_STATE; if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -502,6 +522,74 @@ /*********************************************************************//** * @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 + * @return none + *************************************************************************/ +static void handlePrimeBubbleClear( void ) +{ + static BOOL bubble_clear_ended = FALSE; + U32 timeout; + + switch ( primeDialyzerBubbleClearState ) + { + case PRIME_BUBBLE_CLEAR_READY_STATE: + case PRIME_BUBBLE_CLEAR_FLOW_STATE: + if ( PRIME_BUBBLE_CLEAR_READY_STATE == primeDialyzerBubbleClearState ) + { + timeout = BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS; + } + else + { + timeout = BUBBLE_CLEAR_WAIT_TIME_MS; + } + + if ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, timeout ) ) + { + // Close valve to create pressure to clear Dialyzer bubbles + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + if ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_PRESSURE_STATE; + } + } + break; + + case PRIME_BUBBLE_CLEAR_PRESSURE_STATE: + case PRIME_BUBBLE_CLEAR_VENT_STATE: + if ( ( getMeasuredVenousPressure() > VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ) || + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_MAX_TIME_MS ) ) ) + { + // Pressure max reached. or timeout, release pressure + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); + bubble_clear_ended = TRUE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_VENT_STATE; + } + else if ( ( TRUE == bubble_clear_ended ) && + ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, BUBBLE_CLEAR_VALVE_WAIT_TIME_MS ) ) ) + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_OPEN ); + bubble_clear_ended = FALSE; + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_FLOW_STATE; + } + break; + + case PRIME_BUBBLE_CLEAR_COMPLETE_STATE: + default: + // do nothing + break; + + } // end switch +} + +/*********************************************************************//** + * @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 @@ -518,6 +606,8 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_SALINE_PURGE_AIR_TIME_OUT, PURGE_AIR_TIME_OUT_COUNT ); } + handlePrimeBubbleClear(); + if ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) { setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); @@ -532,6 +622,7 @@ // until we are in a new priming state. primeFirstPurgePass = FALSE; noAirDetectedStartTime = getMSTimerCount(); + primeDialyzerBubbleClearState = PRIME_BUBBLE_CLEAR_COMPLETE_STATE; state = HD_PRIME_SALINE_CIRC_BLOOD_CIRCUIT_STATE; } @@ -722,7 +813,6 @@ primeSalineDialyzerTimeLimit = (U32)( ( ( dialyzerDialysateVolume * DIALYZER_VOLUME_SCALE_FACTOR + DIALYZER_DVI_PATH_VOLUME_ML ) * SEC_PER_MIN * MS_PER_SECOND ) / BLOOD_PUMP_FLOW_RATE_SALINE_DIALYZER_ML_MIN ); primeSalineDialyzerStartTime = getMSTimerCount(); - primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -743,24 +833,8 @@ *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineDialyzerState( void ) { - static BOOL bubbleClearActive = FALSE; - HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_SALINE_DIALYZER_STATE; - // Close valve 4-5 times to create pressure to clear Dialyzer bubbles - if ( TRUE == didTimeout( primeSalineDialyzerBubbleClearStartTime, ( primeSalineDialyzerTimeLimit / 5 ) ) ) - { - primeSalineDialyzerBubbleClearStartTime = getMSTimerCount(); - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - bubbleClearActive = TRUE; - } - // TODO - could also check for valve closed too long here (maybe > 2sec) in case not opening based on pressure - if ( ( TRUE == bubbleClearActive ) && ( getMeasuredVenousPressure() > VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ) ) - { - // Pressure max reached, release pressure - setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); - bubbleClearActive = FALSE; - } if ( TRUE == didTimeout( primeSalineDialyzerStartTime, primeSalineDialyzerTimeLimit ) ) { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE;