Index: firmware/App/Modes/BloodPrime.c =================================================================== diff -u -r8466e63f95f65a3ffb18c3af85ac99328e41167b -rb03a3ed91ebe15cfb419e34018f8fe600e744b4b --- firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision 8466e63f95f65a3ffb18c3af85ac99328e41167b) +++ firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision b03a3ed91ebe15cfb419e34018f8fe600e744b4b) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2022 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 TreatmentEnd.c +* @file BloodPrime.c * -* @author (last) Sean Nash -* @date (last) 04-Feb-2021 +* @author (last) Dara Navaei +* @date (last) 04-Jan-2022 * -* @author (original) Sean -* @date (original) 04-Feb-2021 +* @author (original) Sean Nash +* @date (original) 06-Feb-2021 * ***************************************************************************/ @@ -36,22 +36,15 @@ // ********** private definitiions *********** -// TODO - get from Systems when available -#define TARGET_BLOOD_PRIME_VOLUME_ML 300.0 ///< Target blood prime volume to prime the blood side circuit (in mL). -#define MIN_RAMP_TIME_SEC 60 ///< Minimum ramp time for blood prime (in seconds). +#define TUBING_BLOOD_PRIME_VOLUME_ML 80.0 ///< Target blood prime volume to prime the blood side circuit (in mL). +#define MAX_BLOOD_PRIME_VOLUME_ERROR_ML 60.0 ///< Maximum error in total additional blood prime volume (20% of total). +#define MIN_RAMP_TIME_SEC 60 ///< Minimum ramp time for blood prime (in seconds). -#ifndef DISABLE_PUMP_FLOW_CHECKS -/// Maximum blood prime volume measured by independent means (as % of target). -static const F32 MAX_BLOOD_PRIME_SAFETY_VOLUME_ML = ( TARGET_BLOOD_PRIME_VOLUME_ML * 1.2 ); -/// Minimum blood prime volume measured by independent means (as % of target). -static const F32 MIN_BLOOD_PRIME_SAFETY_VOLUME_ML = ( TARGET_BLOOD_PRIME_VOLUME_ML * 0.8 ); -#endif - /// Initial flow rate for blood pump when starting blood prime operation. #define BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN 100 /// Interval at which blood prime ramping is controlled. -static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Interval at which blood prime progress is to be published to UI. #define BLOOD_PRIME_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) @@ -65,29 +58,28 @@ 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 = 300.0; ///< Calculated target blood prime volume (based on selected dialyzer and fixed tubing 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. /// 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 }; -static OVERRIDE_F32_T cumulativeBloodPrimeVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative blood prime volume (in mL). -static OVERRIDE_F32_T bloodPrimeVolumeDelivered_Safety = { 0.0, 0.0, 0.0, 0 }; ///< The cumulative independent blood prime volume (in mL) calculated so far. -static S32 bloodPrimeMotorCount; ///< The cumulative sum of BP motor encoder counts used for independent blood prime volume check. -static U32 bloodPrimeLastMotorCount; ///< The last BP motor encoder count read for independent blood prime volume check. +static OVERRIDE_F32_T cumulativeBloodPrimeVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative blood prime volume (in mL) from measured blood flow rate. +static F32 expectedBloodPrimeVolume_mL = 0.0; ///< Total cumulative blood prime volume (in mL) expected based on target blood flow rate. // ********** private function prototypes ********** static void resetBloodPrimeFlags( void ); static F32 getBloodPrimeVolume( void ); -static F32 getBloodPrimeSafetyVolume( void ); static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ); static void publishBloodPrimeData( void ); /*********************************************************************//** * @brief * The initBloodPrime function initializes the Blood Prime sub-mode - * module. + * module. Calling this function will reset blood prime and therefore should + * only be called when a new blood prime is due to begin. * @details Inputs: none * @details Outputs: Blood prime sub-mode module initialized. * @return none @@ -98,13 +90,12 @@ bloodPrimeState = BLOOD_PRIME_RAMP_STATE; bloodPrimeRampControlTimerCtr = 0; - bloodPrimePublishTimerCtr = 0; + bloodPrimePublishTimerCtr = BLOOD_PRIME_DATA_PUBLISH_INTERVAL; cumulativeBloodPrimeVolume_mL.data = 0.0; - bloodPrimeVolumeDelivered_Safety.data = 0.0; - bloodPrimeMotorCount = 0; - bloodPrimeLastMotorCount = getBloodPumpMotorCount(); + expectedBloodPrimeVolume_mL = 0.0; resetBloodPrimeFlags(); + bloodPrimeTargetVolume_mL = (F32)TUBING_BLOOD_PRIME_VOLUME_ML + (F32)getDialyzerBloodVolume(); bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; // Calculate BP ramp step size if ( setBPRate <= BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) @@ -114,7 +105,7 @@ else { F32 rampRateSpan = (F32)( setBPRate - BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ); - F32 estRampSeconds = ( ( TARGET_BLOOD_PRIME_VOLUME_ML / (F32)setBPRate + TARGET_BLOOD_PRIME_VOLUME_ML / (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) / 2.0 ) * (F32)SEC_PER_MIN; + F32 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 ) { @@ -127,15 +118,15 @@ /*********************************************************************//** * @brief * The transitionToBloodPrime function prepares for transition to blood prime - * sub-mode. + * sub-mode. This function will reset only what is required for resuming a + * blood prime that was paused (alarm) so if a blood prime is being restarted, + * call the initialize function first to reset everything. * @details Inputs: none * @details Outputs: actuators set for initial state of blood prime sub-mode * @return none *************************************************************************/ void transitionToBloodPrime( void ) { - initBloodPrime(); - // Set valves setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); @@ -147,7 +138,7 @@ stopSyringePump(); // start blood and dialysate inlet pumps - setBloodPumpTargetFlowRate( BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); cmdStartDGTrimmerHeater(); @@ -194,26 +185,6 @@ /*********************************************************************//** * @brief - * The getBloodPrimeSafetyVolume function gets the calculated independent - * blood prime volume delivered. - * @details Inputs: bloodPrimeVolumeDelivered_Safety - * @details Outputs: none - * @return the current blood prime safety volume delivered (in mL). - *************************************************************************/ -static F32 getBloodPrimeSafetyVolume( void ) -{ - F32 result = bloodPrimeVolumeDelivered_Safety.data; - - if ( OVERRIDE_KEY == bloodPrimeVolumeDelivered_Safety.override ) - { - result = bloodPrimeVolumeDelivered_Safety.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The execBloodPrime function executes the Blood Prime sub-mode state machine. * @details Inputs: bloodPrimeState * @details Outputs: bloodPrimeState @@ -253,32 +224,22 @@ // Update blood prime volume delivered so far cumulativeBloodPrimeVolume_mL.data += ( getMeasuredBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); - // Update independent calculated safety volume delivered so far - bloodPrimeMotorCount = u32BiDiffWithWrap( bloodPrimeLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - bloodPrimeVolumeDelivered_Safety.data = ( (F32)bloodPrimeMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc + expectedBloodPrimeVolume_mL += ( (F32)getTargetBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); // Has blood prime completed? - if ( getBloodPrimeVolume() >= TARGET_BLOOD_PRIME_VOLUME_ML ) + if ( getBloodPrimeVolume() >= bloodPrimeTargetVolume_mL ) { -#ifndef DISABLE_PUMP_FLOW_CHECKS - // check for under-delivery - if ( getBloodPrimeSafetyVolume() < MIN_BLOOD_PRIME_SAFETY_VOLUME_ML ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE, TARGET_BLOOD_PRIME_VOLUME_ML, getBloodPrimeSafetyVolume() ); - } - else -#endif - { - setBloodIsPrimed( TRUE ); - signalDialInPumpHardStop(); - signalBloodPrimeToDialysis(); - } + initBloodPrime(); // Reset blood prime so that we start anew next time we transition to this sub-mode + setBloodIsPrimed( TRUE ); // Signal treatment mode that blood prime is completed + signalDialInPumpHardStop(); // Stop dialysate recirculation - dialysis sub-mode will restart dialysate pumps + signalBloodPrimeToDialysis(); // Signal treatment mode that it's time to start dialysis + cmdStopDGTrimmerHeater(); // Stop trimmer heater - dialysis sub-mode will restart as appropriate } #ifndef DISABLE_PUMP_FLOW_CHECKS - // Has independent safety volume exceeded safety limit? - else if ( getBloodPrimeSafetyVolume() > MAX_BLOOD_PRIME_SAFETY_VOLUME_ML ) + // Is blood prime taking too long based on set BP rate? + else if ( fabs( expectedBloodPrimeVolume_mL - getBloodPrimeVolume() ) > MAX_BLOOD_PRIME_VOLUME_ERROR_ML ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE, TARGET_BLOOD_PRIME_VOLUME_ML, getBloodPrimeSafetyVolume() ); + activateAlarmNoData( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE ); } #endif else @@ -328,10 +289,10 @@ BLOOD_PRIME_DATA_PAYLOAD_T data; bloodPrimePublishTimerCtr = 0; - data.targetBloodPrimeVolumeMl = TARGET_BLOOD_PRIME_VOLUME_ML; + data.targetBloodPrimeVolumeMl = bloodPrimeTargetVolume_mL; data.deliveredBloodPrimeVolumeMl = getBloodPrimeVolume(); - data.indDeliveredBloodPrimeVolumeMl = getBloodPrimeSafetyVolume(); - broadcastBloodPrimeData( data ); + data.unused = 0.0; // TODO - remove later when UI no longer looking for this field. + broadcastData( MSG_ID_HD_BLOOD_PRIME_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); } } @@ -388,51 +349,6 @@ /*********************************************************************//** * @brief - * The testSetBloodPrimeSafetyVolumeOverride function overrides the calculated - * blood prime volume. - * @details Inputs: none - * @details Outputs: bloodPrimeVolumeDelivered_Safety - * @param vol override calculated blood prime safety volume (in mL) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetBloodPrimeSafetyVolumeOverride( F32 vol ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - bloodPrimeVolumeDelivered_Safety.ovData = vol; - bloodPrimeVolumeDelivered_Safety.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetBloodPrimeSafetyVolumeOverride function resets the override of the - * calculated blood prime safety volume. - * @details Inputs: none - * @details Outputs: bloodPrimeVolumeDelivered_Safety - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetBloodPrimeSafetyVolumeOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - bloodPrimeVolumeDelivered_Safety.override = OVERRIDE_RESET; - bloodPrimeVolumeDelivered_Safety.ovData = bloodPrimeVolumeDelivered_Safety.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The testSetBloodPrimePublishIntervalOverride function sets the override of the * blood prime data publication interval. * @details Inputs: none