Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r0b8f332794e830b2a9c87c7b7ba852120e1a7334 -r44e745e602377ae878e1d31f0469cdcc47248ace --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 0b8f332794e830b2a9c87c7b7ba852120e1a7334) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 44e745e602377ae878e1d31f0469cdcc47248ace) @@ -7,8 +7,8 @@ * * @file BloodFlow.c * -* @author (last) Dara Navaei -* @date (last) 18-Oct-2022 +* @author (last) Sean Nash +* @date (last) 16-Dec-2022 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -72,8 +72,9 @@ #define BP_MAX_FLOW_RATE 1320.0F ///< Maximum measured BP flow rate allowed. #define BP_MIN_FLOW_RATE -1320.0F ///< Minimum measured BP flow rate allowed. #define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0F ///< Maximum motor speed (RPM) while motor is commanded off. -#define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). +#define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 2.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0F ///< Maximum difference in speed between measured and commanded RPM. +#define BP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT 0.15F ///< Maximum motor speed vs target difference in percent. /// Persist time (in ms) for motor off error condition. static const U32 BP_OFF_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); @@ -409,7 +410,7 @@ bloodPumpRotorCounter.data++; // Calculate rotor speed (in RPM) - bloodPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; + bloodPumpRotorSpeedRPM.data = ( 1.0F / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; bpRotorRevStartTime = rotTime; // If we are supposed to stop pump at home position, stop pump now. @@ -1166,7 +1167,8 @@ F32 deltaMCMotorSpeed = fabs( measMCMotorSpeed - cmdMotorSpeed ); F32 measRotorSpeed = fabs( getMeasuredBloodPumpRotorSpeed() ); F32 measMotorSpeedInRotorRPM = fabs( measMotorSpeed / BP_GEAR_RATIO ); - F32 deltaRotorSpeed = fabs( measRotorSpeed - measMotorSpeedInRotorRPM ); + F32 deltaRotorSpeed = fabs( measRotorSpeed - measMotorSpeedInRotorRPM ); + F32 measMotorSpeedDeltaPct = fabs( deltaRotorSpeed / measMotorSpeedInRotorRPM ); // Check measured motor speed vs. commanded motor speed while controlling to target if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, @@ -1181,7 +1183,7 @@ } // Check measured rotor speed vs. measured motor speed while controlling to target - if ( deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + if ( ( deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) && ( measMotorSpeedDeltaPct > BP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT ) ) { if ( ++errorBloodRotorSpeedPersistTimerCtr >= ( getPumpRotorErrorPersistTime( measMotorSpeed, BP_GEAR_RATIO ) / TASK_PRIORITY_INTERVAL ) ) { Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r0b8f332794e830b2a9c87c7b7ba852120e1a7334 -r44e745e602377ae878e1d31f0469cdcc47248ace --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 0b8f332794e830b2a9c87c7b7ba852120e1a7334) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 44e745e602377ae878e1d31f0469cdcc47248ace) @@ -8,7 +8,7 @@ * @file DialInFlow.c * * @author (last) Sean Nash -* @date (last) 16-Nov-2022 +* @date (last) 21-Dec-2022 * * @author (original) Sean * @date (original) 16-Dec-2019 @@ -69,8 +69,9 @@ #define DIP_MIN_FLOW_RATE -1320.0F ///< Minimum measured BP flow rate allowed. #define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 350.0F ///< Maximum difference between measured motor speed and speed implied by measured flow. #define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0F ///< Maximum motor speed (RPM) while motor is commanded off. -#define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). +#define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 2.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0F ///< Maximum difference in speed between measured and commanded RPM. +#define DIP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT 0.15F ///< Maximum motor speed vs target difference in percent. /// Persist time (task intervals) for flow vs. motor speed error condition. static const U32 DIP_FLOW_VS_SPEED_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); @@ -168,15 +169,16 @@ // ********** private data ********** -static DIAL_IN_PUMP_STATE_T dialInPumpState = DIAL_IN_PUMP_OFF_STATE; ///< Current state of dialIn flow controller state machine -static U32 dialInFlowDataPublicationTimerCounter; ///< Used to schedule dialIn flow data publication to CAN bus -static BOOL isDialInPumpOn = FALSE; ///< DialIn pump is currently running -static F32 dialInPumpPWMDutyCyclePct = 0.0; ///< Initial dialIn pump PWM duty cycle -static F32 dialInPumpPWMDutyCyclePctSet = 0.0; ///< Currently set dialIn pump PWM duty cycle -static MOTOR_DIR_T dialInPumpDirection = MOTOR_DIR_FORWARD; ///< Requested dialysate flow direction -static MOTOR_DIR_T dialInPumpDirectionSet = MOTOR_DIR_FORWARD; ///< Currently set dialysate flow direction -static PUMP_CONTROL_MODE_T dialInPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Requested dialIn pump control mode. -static PUMP_CONTROL_MODE_T dialInPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP;///< Currently set dialIn pump control mode. +static DIAL_IN_PUMP_STATE_T dialInPumpState = DIAL_IN_PUMP_OFF_STATE; ///< Current state of dialIn flow controller state machine +static U32 dialInFlowDataPublicationTimerCounter; ///< Used to schedule dialIn flow data publication to CAN bus +static BOOL isDialInPumpOn = FALSE; ///< DialIn pump is currently running +static F32 dialInPumpPWMDutyCyclePct = 0.0; ///< Initial dialIn pump PWM duty cycle +static F32 dialInPumpPWMDutyCyclePctSet = 0.0; ///< Currently set dialIn pump PWM duty cycle +static MOTOR_DIR_T dialInPumpDirection = MOTOR_DIR_FORWARD; ///< Requested dialysate flow direction +static MOTOR_DIR_T dialInPumpDirectionSet = MOTOR_DIR_FORWARD; ///< Currently set dialysate flow direction +static PUMP_CONTROL_MODE_T dialInPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Requested dialIn pump control mode. +static PUMP_CONTROL_MODE_T dialInPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Currently set dialIn pump control mode. +static BOOL isTestPWMSet = FALSE; ///< Using PWM to set the rate instead of target flow. /// Interval (in ms) at which to publish dialIn flow data to CAN bus static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; @@ -237,7 +239,9 @@ static void checkDialInPumpMCCurrent( void ); static void checkDialInPumpFlowRate( void ); static F32 calcDialInFlow( void ); +static F32 dialysateInPumpRPMFromTargetFlowRate( F32 QdTarget ); static F32 dialysateInPumpPWMFromTargetFlowRate( F32 QdTarget ); +static BOOL testSetDialInPumpWithPWM( F32 pwm ); /*********************************************************************//** * @brief @@ -251,7 +255,7 @@ U32 i; dialInFlowDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - + isTestPWMSet = FALSE; signalDialInPumpHardStop(); setDialInPumpDirection( MOTOR_DIR_FORWARD ); @@ -283,7 +287,8 @@ * The setDialInPumpTargetFlowRate function sets a new target flow rate and * pump direction. * @details Inputs: isDialInPumpOn, dialInPumpDirectionSet - * @details Outputs: targetDialInFlowRate, dialInPumpdirection, dialInPumpPWMDutyCyclePct + * @details Outputs: targetDialInFlowRate, dialInPumpdirection, + * dialInPumpPWMDutyCyclePct, isTestPWMSet * @param flowRate new target dialIn flow rate * @param dir new dialIn flow direction * @param mode new control mode @@ -294,7 +299,7 @@ BOOL result = FALSE; // Direction change while pump is running is not allowed - if ( ( FALSE == isDialInPumpOn ) || ( 0 == flowRate ) || ( dir == dialInPumpDirectionSet ) ) + if ( ( FALSE == isDialInPumpOn ) || ( 0 == flowRate ) || ( dir == dialInPumpDirectionSet ) ) { S32 dirFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); @@ -303,6 +308,7 @@ { BOOL isFlowRateInRange = ( flowRate <= MAX_DIAL_IN_FLOW_RATE ? TRUE : FALSE ); + isTestPWMSet = FALSE; #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMPS_FLOW_LIMITS ) ) { @@ -403,7 +409,7 @@ U32 deltaTime = calcTimeBetween( dipRotorRevStartTime, rotTime ); // Calculate rotor speed (in RPM) - dialInPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; + dialInPumpRotorSpeedRPM.data = ( 1.0F / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; dipRotorRevStartTime = rotTime; dialysateInPumpRotorCounter.data++; @@ -577,7 +583,8 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_OFF_STATE; // If we have been given a flow rate, setup ramp up and transition to ramp up state - if ( targetDialInFlowRate != 0 ) + if ( ( targetDialInFlowRate != 0 ) || + ( TRUE == isTestPWMSet ) ) { // Set initial PWM duty cycle dialInPumpPWMDutyCyclePctSet = DIP_PWM_ZERO_OFFSET + MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE; @@ -605,7 +612,8 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_RAMPING_UP_STATE; // Have we been asked to stop the dialIn pump? - if ( 0 == targetDialInFlowRate ) + if ( ( 0 == targetDialInFlowRate ) && + ( FALSE == isTestPWMSet ) ) { // Start ramp down to stop dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE; @@ -820,23 +828,39 @@ /*********************************************************************//** * @brief - * The dialysateInPumpPWMFromTargetFlowRate function calculates a motor PWM setting + * The dialysateInPumpRPMFromTargetFlowRate function calculates a motor RPM * from the estimator based on target flow rate and tubing wear. * @details Inputs: dialInPumpRotorCounter * @details Outputs: none * @param QdTarget target dialysate flow rate - * @return Motor PWM value for given target flow rate + * @return Motor RPM value for given target flow rate *************************************************************************/ -static F32 dialysateInPumpPWMFromTargetFlowRate( F32 QdTarget ) +static F32 dialysateInPumpRPMFromTargetFlowRate( F32 QdTarget ) { U32 r = getDialInPumpRotorCount(); U32 rotCount = CAP( r, DIAL_IN_MAX_ROTOR_COUNT_FOR_WEAR ); F32 wearFactor = DIAL_IN_FLOW_WEAR_A_TERM * (F32)rotCount + DIAL_IN_FLOW_WEAR_B_TERM; F32 Pest = DIAL_IN_FLOW_PEST_A_TERM * ( QdTarget * QdTarget ) + DIAL_IN_FLOW_PEST_B_TERM * QdTarget + DIAL_IN_FLOW_PEST_C_TERM; F32 alphaTerm = wearFactor * Pest + DIAL_IN_FLOW_A_ZERO; F32 rpmTgt = QdTarget * DIAL_IN_GEAR_RATIO / ( 2 * DIAL_IN_STROKE_VOLUME * alphaTerm ); - F32 pwmDC = DIP_MOTOR_SPEED_RPM_TO_PWM( rpmTgt ); + return rpmTgt; +} + +/*********************************************************************//** + * @brief + * The dialysateInPumpPWMFromTargetFlowRate function calculates a motor PWM + * setting from a given target flow rate. + * @details Inputs: none + * @details Outputs: none + * @param QdTarget target dialysate flow rate + * @return Motor PWM value for given RPM + *************************************************************************/ +static F32 dialysateInPumpPWMFromTargetFlowRate( F32 QdTarget ) +{ + F32 rpmTgt = dialysateInPumpRPMFromTargetFlowRate( QdTarget ); + F32 pwmDC = DIP_MOTOR_SPEED_RPM_TO_PWM( rpmTgt ); + return pwmDC; } @@ -1313,7 +1337,7 @@ } // Check measured rotor speed vs. measured motor speed while controlling to target - if ( deltaRotorSpeed > DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + if ( ( deltaRotorSpeed > DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) && ( measMotorSpeedDeltaPct > DIP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT ) ) { if ( ++errorDialInRotorSpeedPersistTimerCtr >= ( getPumpRotorErrorPersistTime( measMotorSpeed, DIP_GEAR_RATIO ) / TASK_PRIORITY_INTERVAL ) ) { @@ -1366,7 +1390,7 @@ { F32 flow = (F32)targetDialInFlowRate; F32 speed = getMeasuredDialInPumpSpeed(); - F32 impliedSpeed = ( flow * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO ); + F32 impliedSpeed = dialysateInPumpRPMFromTargetFlowRate( flow ); F32 delta = fabs( speed - impliedSpeed ); if ( delta > DIP_MAX_FLOW_VS_SPEED_DIFF_RPM ) @@ -1501,6 +1525,91 @@ * TEST SUPPORT FUNCTIONS *************************************************************************/ + +/*********************************************************************//** + * @brief + * The testSetDialInPumpWithPWM function sets a new pwm value and + * pump direction. + * @details Inputs: isDialInPumpOn, dialInPumpPWMDutyCyclePct, dialInPumpDirectionSet, + * dialInPumpState + * @details Outputs: dialInPumpControlMode, dialInPumpdirection, dialInPumpPWMDutyCyclePct + * @param pwm the new pwm value + * @return TRUE if new flow rate & dir are set, FALSE if not + **************************************************************************/ +static BOOL testSetDialInPumpWithPWM( F32 pwm ) +{ + MOTOR_DIR_T dir = MOTOR_DIR_FORWARD; + BOOL result = FALSE; + F32 pwmFabs = fabs(pwm); + + if ( pwm < 0 ) + { + dir = MOTOR_DIR_REVERSE; + } + + // Direction change while pump is running is not allowed unless we are turning off + if ( ( FALSE == isDialInPumpOn ) && ( dir != dialInPumpDirectionSet ) ) + { + dialInPumpDirection = dir; + } + + // Allow pump to turn on, change rate in same direction, or turn off. + if ( ( ( FALSE == isDialInPumpOn ) || ( dir == dialInPumpDirectionSet ) ) || ( pwmFabs <= MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) ) + { + // Don't interrupt pump control unless rate is changing + if ( ( pwmFabs != dialInPumpPWMDutyCyclePct ) ) + { + resetDialInFlowMovingAverage(); + dialInPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; + dialInPumpPWMDutyCyclePct = RANGE( pwmFabs, MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ); + + // clear test flag if we are turning off the pump. + if ( pwmFabs <= MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) + { + isTestPWMSet = FALSE; + } + else + { + isTestPWMSet = TRUE; + } + + switch ( dialInPumpState ) + { + case DIAL_IN_PUMP_RAMPING_UP_STATE: // See if we need to reverse direction of ramp + if ( dialInPumpPWMDutyCyclePct < dialInPumpPWMDutyCyclePctSet ) + { + dialInPumpState = DIAL_IN_PUMP_RAMPING_DOWN_STATE; + } + break; + + case DIAL_IN_PUMP_RAMPING_DOWN_STATE: // See if we need to reverse direction of ramp + if ( dialInPumpPWMDutyCyclePct > dialInPumpPWMDutyCyclePctSet ) + { + dialInPumpState = DIAL_IN_PUMP_RAMPING_UP_STATE; + } + break; + + case DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE: // Start ramp to new target in appropriate direction + if ( dialInPumpPWMDutyCyclePctSet > dialInPumpPWMDutyCyclePct ) + { + dialInPumpState = DIAL_IN_PUMP_RAMPING_DOWN_STATE; + } + else + { + dialInPumpState = DIAL_IN_PUMP_RAMPING_UP_STATE; + } + break; + + default: + // Ok - not all states need to be handled here + break; + } + result = TRUE; + } + } + + return result; +} /*********************************************************************//** * @brief @@ -1825,16 +1934,19 @@ * @param value duty cycle of the dialysate inlet pump (as a percentage). * @return TRUE if reset successful, FALSE if not *************************************************************************/ -BOOL testSetDialInPumpTargetDutyCycle( F32 value ) +BOOL testSetDialInPumpTargetDutyCycle( F32 pwmPct ) { BOOL result = FALSE; + F32 absolutePWM = fabs( pwmPct ); if ( TRUE == isTestingActivated() ) { - setDialInPumpTargetFlowRate( (U32)DIP_ML_PER_MIN_FROM_PWM(value), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - result = TRUE; + // check for max of pump pwm for acceptance. + if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) + { + result = testSetDialInPumpWithPWM( pwmPct ); + } } - return result; } Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r0b8f332794e830b2a9c87c7b7ba852120e1a7334 -r44e745e602377ae878e1d31f0469cdcc47248ace --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 0b8f332794e830b2a9c87c7b7ba852120e1a7334) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 44e745e602377ae878e1d31f0469cdcc47248ace) @@ -8,7 +8,7 @@ * @file DialOutFlow.c * * @author (last) Sean Nash -* @date (last) 21-Nov-2022 +* @date (last) 16-Dec-2022 * * @author (original) Sean * @date (original) 24-Jan-2020 @@ -75,8 +75,9 @@ #define DOP_HALL_EDGE_COUNTS_PER_REV 48 ///< Number of hall sensor edge counts per motor revolution. #define DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0F ///< Maximum motor speed (RPM) while motor is commanded off. -#define DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). +#define DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 2.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define DOP_MAX_MOTOR_SPEED_ERROR_RPM 300.0F ///< Maximum difference in speed between measured and commanded RPM. +#define DOP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT 0.15F ///< Maximum motor speed vs target difference in percent. /// Persist time (task intervals) for motor off error condition. static const U32 DOP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); @@ -392,7 +393,7 @@ U32 deltaTime = calcTimeBetween( dopRotorRevStartTime, rotTime ); // Calculate rotor speed (in RPM) - dialOutPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; + dialOutPumpRotorSpeedRPM.data = ( 1.0F / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; dopRotorRevStartTime = rotTime; // If we are supposed to stop pump at home position, stop pump now. @@ -1052,6 +1053,7 @@ F32 measRotorSpeed = fabs( getMeasuredDialOutPumpRotorSpeed() ); F32 measMotorSpeedInRotorRPM = fabs( measMotorSpeed / DOP_GEAR_RATIO ); F32 deltaRotorSpeed = fabs( measRotorSpeed - measMotorSpeedInRotorRPM ); + F32 measMotorSpeedDeltaPct = fabs( deltaRotorSpeed / measMotorSpeedInRotorRPM ); // Check measured motor speed vs. commanded motor speed while controlling to target if ( ( deltaMotorSpeed > DOP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > DOP_MAX_MOTOR_SPEED_ERROR_RPM ) ) @@ -1072,7 +1074,7 @@ } // Check measured rotor speed vs. measured motor speed while controlling to target - if ( deltaRotorSpeed > DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + if ( ( deltaRotorSpeed > DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) && ( measMotorSpeedDeltaPct > DOP_MAX_MOTOR_SPEED_VS_TRGT_DIFF_PCT ) ) { if ( ++errorDialOutRotorSpeedPersistTimerCtr >= ( getPumpRotorErrorPersistTime( measMotorSpeed, DOP_GEAR_RATIO ) / TASK_PRIORITY_INTERVAL ) ) { Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -rcd21cbb4e733bfdf52f83bdca7a905645022c572 -r44e745e602377ae878e1d31f0469cdcc47248ace --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision cd21cbb4e733bfdf52f83bdca7a905645022c572) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 44e745e602377ae878e1d31f0469cdcc47248ace) @@ -45,11 +45,14 @@ /// Interval (ms/task time) at which the post-treatment state data is published on the CAN bus. #define POST_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) +#define DIP_DRAIN_DG_FLOW_RATE_ML_MIN 60 ///< DG drain inlet pump flow rate in mL/min. +#define DIP_DRAIN_DG_RUNTIME_MS 20000 ///< DG drain inlet pump run time in ms. /// Post-Treatment drain reservoirs state machine. typedef enum Drain_States { - DRAIN_RESERVOIR_SWITCH_STATE = 0, ///< Switch reservoir state. + DRAIN_DG_DEPRIME_STATE = 0, ///< Drain DG De-prime dialysate lines of excess fluid state. + DRAIN_RESERVOIR_SWITCH_STATE, ///< Switch reservoir state. DRAIN_RESERVOIR_START_DRAIN_STATE, ///< Drain reservoir start drain state. DRAIN_RESERVOIR_DRAIN_STATE, ///< Drain first reservoir state. DRAIN_RESERVOIR_COMPLETE_STATE, ///< Drain complete state. @@ -62,6 +65,8 @@ static BOOL disposableRemovalConfirmed; ///< Flag indicates user confirms disposable removal. static BOOL rinseConcentrateLines; ///< FLag indicates to rinse concentrate lines. static BOOL isThisFirstDrain; ///< Flag to indicate whether this is the first time the reservoir is drained. +static BOOL drainDGDePrimeActive; ///< FLag to indicate DePrime DG Dialysate lines active +static U32 drainDGDePrimeStarttime; ///< DG DePrime start time static BOOL dgCommandSent; ///< Flag indicates whether a DG command has been already sent. static HD_POST_TREATMENT_STATE_T currentPostTreatmentState; ///< Current state of post-treatment mode state machine. static DRAIN_STATE_T currentDrainReservoirState; ///< Current drain reservoir state. @@ -79,6 +84,7 @@ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ); static void execDrainReservoirs( void ); +static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ); static DRAIN_STATE_T handleDrainReservoirSwitchState( void ); static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ); static DRAIN_STATE_T handleDrainReservoirDrainState( void ); @@ -101,8 +107,10 @@ isThisFirstDrain = TRUE; dgCommandSent = FALSE; currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; - currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; + currentDrainReservoirState = DRAIN_DG_DEPRIME_STATE; postTreatmentPublishTimerCounter = 0; + drainDGDePrimeActive = FALSE; + drainDGDePrimeStarttime = 0; // Reset treatment log data memset( &treatmentLogData, 0x0, sizeof( TREATMENT_LOG_DATA_PAYLOAD_T ) ); @@ -505,6 +513,10 @@ { switch ( currentDrainReservoirState ) { + case DRAIN_DG_DEPRIME_STATE: + currentDrainReservoirState = handleDrainDePrimeDGDialysateLinesState(); + break; + case DRAIN_RESERVOIR_SWITCH_STATE: currentDrainReservoirState = handleDrainReservoirSwitchState(); break; @@ -529,6 +541,42 @@ /*********************************************************************//** * @brief + * The handleDrainDePrimeDGDialysateLinesState function waits for DG to complete + * reservoir switch. + * @details Inputs: + * @details Outputs: + * @return next state + *************************************************************************/ +static DRAIN_STATE_T handleDrainDePrimeDGDialysateLinesState( void ) +{ + DRAIN_STATE_T state = DRAIN_DG_DEPRIME_STATE; + + if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) + { + if ( FALSE == drainDGDePrimeActive ) + { + // First entry - Run DPi slow reverse, VDi, VDo closed in init, DPo Off in init. + setDialInPumpTargetFlowRate( DIP_DRAIN_DG_FLOW_RATE_ML_MIN, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); + drainDGDePrimeStarttime = getMSTimerCount(); + drainDGDePrimeActive = TRUE; + } + } + if ( TRUE == drainDGDePrimeActive ) + { + // Thereafter, check for time elapsed + if ( TRUE == didTimeout( drainDGDePrimeStarttime, DIP_DRAIN_DG_RUNTIME_MS ) ) + { + drainDGDePrimeActive = FALSE; + signalDialInPumpHardStop( ); + state = DRAIN_RESERVOIR_SWITCH_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleDrainReservoirSwitchState function waits for DG to complete * reservoir switch. * @details Inputs: isThisFirstDrain, dgCommandSent