Index: firmware/App/Modes/StateTxBloodPrime.c =================================================================== diff -u -ra1f14a4e422f94b6bc25d1b91839761e7e1196d7 -r949ea2ef6be9b80854d9912df16d558dbd529998 --- firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision a1f14a4e422f94b6bc25d1b91839761e7e1196d7) +++ firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 949ea2ef6be9b80854d9912df16d558dbd529998) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include "AirPump.h" #include "AirTrap.h" #include "BloodFlow.h" #include "Buttons.h" @@ -39,52 +40,53 @@ // ********** private definitiions *********** -///< Minimum ramp time for blood prime (in seconds) -#define MIN_RAMP_TIME_SEC 60 +/// Initial blood flow rate used during Blood Prime ramp. +#define BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN 100 -/// Initial flow rate for blood pump when starting blood prime operation. -#define BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN 250 +/// Blood Prime initial ramp duration in seconds. +#define BLOOD_PRIME_RAMP_TIME_SEC 30 -/// Interval at which blood prime ramping is controlled. -static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +/// Blood Prime flow rate used after the initial ramp period when the +/// treatment blood flow rate is greater than or equal to 200 mL/min. +#define BLOOD_PRIME_RAMP_MAX_FLOW_RATE_ML_MIN 200 -/// Interval at which blood prime progress is to be published to UI. -#define BLOOD_PRIME_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) - -/// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. -static const F32 BLOOD_PRIME_FLOW_INTEGRATOR = 1.0F / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - /// Tubing portion of blood prime volume to prime the blood side circuit (in mL). #define TUBING_BLOOD_PRIME_VOLUME_ML 126 /// Timeout duration for Blood Prime pause state. -#define BLOOD_PRIME_PAUSE_TIMEOUT_SEC ( 5 * SEC_PER_MIN ) +#define BLOOD_PRIME_PAUSE_TIMEOUT_SEC ( 5 * SEC_PER_MIN ) -// Warning threshold before timeout (1 minute remaining) -#define BLOOD_PRIME_WARNING_SEC ( 1 * SEC_PER_MIN ) +/// Warning threshold before Blood Prime pause timeout. +#define BLOOD_PRIME_WARNING_SEC ( 1 * SEC_PER_MIN ) +/// Interval at which blood prime progress is to be published to UI. +#define BLOOD_PRIME_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +/// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. +static const F32 BLOOD_PRIME_FLOW_INTEGRATOR = 1.0F / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + // ********** private data ********** static BLOOD_PRIME_STATE_T bloodPrimeState; ///< Current state of the blood prime sub-mode. static BLOOD_PRIME_STATE_T bloodPrimeResumeState; ///< Blood prime sub-state prior to pause. static BLOOD_PRIME_STATE_T bolusCallingState; ///< Fluid Bolus calling state. static BOOL pendingPauseRequest; ///< Flag indicating UI has requested blood prime pause. static BOOL pendingResumeRequest; ///< Flag indicating UI has requested blood prime resume. -static BOOL pendingFlowChangeRequest; ///< Flag indicating UI has requested blood prime flow change +static BOOL pendingFlowChangeRequest; ///< Flag indicating UI has requested blood prime flow change. static BOOL fluidBolusRequested; ///< Flag indicating fluid bolus has been requested by user. -static F32 bloodPrimeRampFlowRate_mL_min; ///< Current blood pump ramp flow rate. -static F32 bloodPrimeRampStep_mL; ///< Blood pump volume step size for ramping. -static F32 bloodPrimeTargetVolume_mL; ///< Calculated target blood prime volume (based on selected dialyzer and fixed tubing volume). +static F32 bloodPrimeRampFlowRate_mL_min; ///< Current Blood Prime flow rate. +static F32 bloodPrimeTargetVolume_mL; ///< Calculated target blood prime volume (based on blood tubing set volume and maximum dialyzer blood volume). -static U32 bloodPrimeRampControlTimerCtr; ///< Timer counter for determining interval for controlling BP ramp. -static U32 bloodPrimePublishTimerCtr; ///< Timer counter for determining interval for blood prime status to be published. -static U32 lastBloodPrimeFlowRate_mL_min; ///< Flow rate prior to pausing blood prime. -static U32 requestedBloodFlowRate_mL_min; ///< Requested blood flow rate from UI. -static U32 bloodPrimeStartMS; ///< Start time of Blood Prime (ms timer count) -static U32 bloodPrimeTimeoutSec; ///< Blood prime pause timeout duration (broadcast to UI) -static U32 bloodPrimeCountdownSec; ///< Blood prime pause countdown remaining time (broadcast to UI) -static U32 pausedElapsedMS; ///< Elapsed pause time saved when fluid bolus starts from paused state. +static U32 bloodPrimePublishTimerCtr; ///< Timer counter for determining interval for blood prime status to be published. +static U32 lastBloodPrimeFlowRate_mL_min; ///< Flow rate prior to pausing blood prime. +static U32 requestedBloodFlowRate_mL_min; ///< Requested blood flow rate from UI. +static U32 bloodPrimeRampStartMS; ///< Start time of Blood Prime ramp. +static U32 bloodPrimeRampElapsedMS; ///< Elapsed Blood Prime ramp time saved during pause/bolus. +static U32 bloodPrimeStartMS; ///< Start time of Blood Prime pause. +static U32 bloodPrimeTimeoutSec; ///< Blood Prime pause timeout duration. +static U32 bloodPrimeCountdownSec; ///< Blood Prime pause countdown remaining time. +static U32 pausedElapsedMS; ///< Elapsed pause time saved when fluid bolus starts from paused state. /// Interval (in task intervals) at which to publish blood prime data to CAN bus. static OVERRIDE_U32_T bloodPrimePublishInterval = { BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, 0 }; @@ -111,35 +113,32 @@ *************************************************************************/ void initBloodPrime( void ) { - S32 setBPRate = (S32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); - F32 rampRateSpan = 0.0F; - F32 estRampSeconds = 0.0F; + U32 setBPRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); bloodPrimeState = BLOOD_PRIME_RAMP_STATE; bloodPrimeResumeState = BLOOD_PRIME_RAMP_STATE; bolusCallingState = BLOOD_PRIME_RAMP_STATE; - bloodPrimeRampControlTimerCtr = 0; bloodPrimePublishTimerCtr = BLOOD_PRIME_DATA_PUBLISH_INTERVAL - 2; // setup so publish will occur time after next cumulativeBloodPrimeVolume_mL.data = 0.0; resetBloodPrimeFlags(); bloodPrimeTargetVolume_mL = (F32)TUBING_BLOOD_PRIME_VOLUME_ML + (F32)( getDialyzerBloodVolume( (DIALYZER_TYPE_T)getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ) ); - bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; - // Calculate BP ramp step size - rampRateSpan = (F32)( setBPRate - BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ); - estRampSeconds = ( ( bloodPrimeTargetVolume_mL / (F32)setBPRate + bloodPrimeTargetVolume_mL / (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) / 2.0 ) * (F32)SEC_PER_MIN; - - if ( estRampSeconds < (F32)MIN_RAMP_TIME_SEC ) + if ( setBPRate <= BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) { - estRampSeconds = (F32)MIN_RAMP_TIME_SEC; + bloodPrimeRampFlowRate_mL_min = (F32)setBPRate; } - bloodPrimeRampStep_mL = rampRateSpan / estRampSeconds; - bloodPrimeStartMS = 0; - bloodPrimeTimeoutSec = 0; - bloodPrimeCountdownSec = 0; - pausedElapsedMS = 0; - fluidBolusRequested = FALSE; + else + { + bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; + } + bloodPrimeRampStartMS = getMSTimerCount(); + bloodPrimeRampElapsedMS = 0; + bloodPrimeStartMS = 0; + bloodPrimeTimeoutSec = 0; + bloodPrimeCountdownSec = 0; + pausedElapsedMS = 0; + fluidBolusRequested = FALSE; } /*********************************************************************//** @@ -274,23 +273,28 @@ * @brief * The handleBloodPrimeRampState function handles the blood prime ramp * state operations. - * @details \b Inputs: flags - * @details \b Outputs: flags handled + * @details \b Inputs: bloodPrimeTargetVolume_mL, pendingPauseRequest, + * pendingFlowChangeRequest, fluidBolusRequested, requestedBloodFlowRate_mL_min, + * bloodPrimeRampStartMS + * @details \b Outputs: cumulativeBloodPrimeVolume_mL, + * bloodPrimeRampFlowRate_mL_min, bloodPrimeResumeState, bloodPrimeStartMS * @return next blood prime state *************************************************************************/ static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ) { BLOOD_PRIME_STATE_T result = BLOOD_PRIME_RAMP_STATE; + U32 setBPRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); + U32 elapsedSec = calcTimeSince( bloodPrimeRampStartMS ) / MS_PER_SECOND; - //Update blood prime volume delivered so far + // Update blood prime volume delivered so far cumulativeBloodPrimeVolume_mL.data += ( getMeasuredBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); if ( TRUE == getTestConfigStatus( TEST_CONFIG_SKIP_BLOOD_PRIME ) ) { cumulativeBloodPrimeVolume_mL.data = bloodPrimeTargetVolume_mL; } - // Volume reached to Dialysis + // When volume reached transition to Dialysis if ( getBloodPrimeVolume() >= bloodPrimeTargetVolume_mL ) { initBloodPrime(); @@ -300,56 +304,81 @@ // Soft pause from UI else if ( TRUE == pendingPauseRequest ) { - pendingPauseRequest = FALSE; - bloodPrimeResumeState = BLOOD_PRIME_RAMP_STATE; - lastBloodPrimeFlowRate_mL_min = (F32)getTargetBloodFlowRate(); + pendingPauseRequest = FALSE; + bloodPrimeResumeState = BLOOD_PRIME_RAMP_STATE; + lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); + bloodPrimeRampElapsedMS = calcTimeSince( bloodPrimeRampStartMS ); + setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - // Close art/ven pinch valves - setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + // Stop Air Trap Control during pause + endAirTrapControl(); + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + // Set Blood Prime pause valve configuration + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); - result = BLOOD_PRIME_PAUSED_STATE; + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); bloodPrimeStartMS = getMSTimerCount(); + result = BLOOD_PRIME_PAUSED_STATE; } // When UI changes blood flow rate else if ( TRUE == pendingFlowChangeRequest ) { pendingFlowChangeRequest = FALSE; + + // Cancel Blood Prime ramp and continue at adjusted blood flow rate bloodPrimeRampFlowRate_mL_min = (F32)requestedBloodFlowRate_mL_min; - // To ensure resume returns to RUN state + setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, requestedBloodFlowRate_mL_min ); + setBloodPumpTargetFlowRate( requestedBloodFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); bloodPrimeResumeState = BLOOD_PRIME_RUN_STATE; - result = BLOOD_PRIME_RUN_STATE; + result = BLOOD_PRIME_RUN_STATE; } // When UI requests fluid bolus else if ( TRUE == fluidBolusRequested ) { - fluidBolusRequested = FALSE; - bloodPrimeResumeState = bloodPrimeState; - bolusCallingState = bloodPrimeState; + fluidBolusRequested = FALSE; + bloodPrimeResumeState = bloodPrimeState; + bolusCallingState = bloodPrimeState; lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); - // Start bolus and transition to bolus state + // Save elapsed ramp time while bolus is active + bloodPrimeRampElapsedMS = calcTimeSince( bloodPrimeRampStartMS ); signalStartFluidBolus( lastBloodPrimeFlowRate_mL_min ); result = BLOOD_PRIME_FLUID_BOLUS_STATE; } else { - // Continue ramping - if ( ++bloodPrimeRampControlTimerCtr >= BLOOD_PRIME_RAMPING_INTERVAL ) + if ( setBPRate <= BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) { - bloodPrimeRampControlTimerCtr = 0; - bloodPrimeRampFlowRate_mL_min += bloodPrimeRampStep_mL; - setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + bloodPrimeRampFlowRate_mL_min = (F32)setBPRate; + setBloodPumpTargetFlowRate( setBPRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } + else if ( elapsedSec >= BLOOD_PRIME_RAMP_TIME_SEC ) + { + if ( setBPRate >= BLOOD_PRIME_RAMP_MAX_FLOW_RATE_ML_MIN ) + { + bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_RAMP_MAX_FLOW_RATE_ML_MIN; + } + else + { + bloodPrimeRampFlowRate_mL_min = (F32)setBPRate; + } + setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + bloodPrimeResumeState = BLOOD_PRIME_RUN_STATE; + result = BLOOD_PRIME_RUN_STATE; + } } - return result; + return result; } /*********************************************************************//** * @brief * The handleBloodPrimeRunState function handles the blood prime run * state operations. - * @details \b Inputs: cumulativeBloodPrimevolume_mL - * @details \b Outputs: cumulativeBloodPrimevolume_mL + * @details \b Inputs: bloodPrimeTargetVolume_mL, pendingPauseRequest, + * pendingFlowChangeRequest, fluidBolusRequested + * @details \b Outputs: cumulativeBloodPrimeVolume_mL, + * bloodPrimeResumeState, bloodPrimeStartMS * @return next blood prime state *************************************************************************/ static BLOOD_PRIME_STATE_T handleBloodPrimeRunState( void ) @@ -373,24 +402,31 @@ bloodPrimeResumeState = BLOOD_PRIME_RUN_STATE; lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - // Close art/ven pinch valves - setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); + // Stop Air Trap Control during pause + endAirTrapControl(); + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + // Set Blood Prime pause pinch valve positions + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); - result = BLOOD_PRIME_PAUSED_STATE; + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); bloodPrimeStartMS = getMSTimerCount(); + result = BLOOD_PRIME_PAUSED_STATE; } // When UI changes blood flow rate else if ( TRUE == pendingFlowChangeRequest ) { pendingFlowChangeRequest = FALSE; + setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, requestedBloodFlowRate_mL_min ); setBloodPumpTargetFlowRate( requestedBloodFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } // When UI requests fluid bolus else if ( TRUE == fluidBolusRequested ) { - fluidBolusRequested = FALSE; - bloodPrimeResumeState = bloodPrimeState; - bolusCallingState = bloodPrimeState; + fluidBolusRequested = FALSE; + bloodPrimeResumeState = bloodPrimeState; + bolusCallingState = bloodPrimeState; lastBloodPrimeFlowRate_mL_min = getTargetBloodFlowRate(); // Start bolus and transition to bolus state signalStartFluidBolus( lastBloodPrimeFlowRate_mL_min ); @@ -408,9 +444,10 @@ * @brief * The handleBloodPrimePausedState function handles the blood prime paused * state operations. - * @details \b Inputs: getCurrentOperationMode - * @details \b Outputs: flags handled - * @return none + * @details \b Inputs: pendingResumeRequest, fluidBolusRequested, + * bloodPrimeResumeState + * @details \b Outputs: bloodPrimeRampStartMS, pausedElapsedMS + * @return next blood prime state *************************************************************************/ static BLOOD_PRIME_STATE_T handleBloodPrimePausedState( void ) { @@ -421,10 +458,18 @@ { pendingResumeRequest = FALSE; bolusCallingState = bloodPrimeResumeState; - setBloodPumpTargetFlowRate( (U32)lastBloodPrimeFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); // Open art/ven pinch valves setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + // Start Air Trap Control before restarting blood pump + startAirTrapControl(); + + if ( BLOOD_PRIME_RAMP_STATE == bloodPrimeResumeState ) + { + bloodPrimeRampStartMS = getMSTimerCount() - bloodPrimeRampElapsedMS; + bloodPrimeRampElapsedMS = 0; + } + setBloodPumpTargetFlowRate( (U32)lastBloodPrimeFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); // Return to state prior to pause result = bloodPrimeResumeState; } @@ -447,13 +492,14 @@ return result; } + /*********************************************************************//** * @brief * The handleBloodPrimeFluidBolusState function handles the fluid bolus * state of the blood prime sub-mode. * @details \b Inputs: bolusCallingState, lastBloodPrimeFlowRate_mL_min, - * bloodPrimeStartMS, pausedElapsedMS - * @details \b Outputs: bolusCallingState + * bloodPrimeStartMS, pausedElapsedMS, bloodPrimeRampElapsedMS + * @details \b Outputs: bloodPrimeStartMS, bloodPrimeRampStartMS * @return next blood prime state *************************************************************************/ static BLOOD_PRIME_STATE_T handleBloodPrimeFluidBolusState( void ) @@ -468,17 +514,26 @@ // Resume from saved elapsed bloodPrimeStartMS = getMSTimerCount() - pausedElapsedMS; pausedElapsedMS = 0; - // Arterial valve is open to saline, not required here + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_C_CLOSE ); + endAirTrapControl(); + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } else { setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); + startAirTrapControl(); + if ( BLOOD_PRIME_RAMP_STATE == bolusCallingState ) + { + bloodPrimeRampStartMS = getMSTimerCount() - bloodPrimeRampElapsedMS; + bloodPrimeRampElapsedMS = 0; + } setBloodPumpTargetFlowRate( lastBloodPrimeFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } - result = bolusCallingState; }