Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -rd5b85c44743b1aaaeb61b88179de032e8ca3c6a7 -r758497628fa5839a2b6661a9d7c32fd3b11db2bd --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision d5b85c44743b1aaaeb61b88179de032e8ca3c6a7) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 758497628fa5839a2b6661a9d7c32fd3b11db2bd) @@ -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); @@ -238,6 +239,7 @@ 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 ); @@ -297,14 +299,15 @@ BOOL result = FALSE; // Direction change while pump is running is not allowed - if ( ( ( FALSE == isDialInPumpOn ) && ( dir == dialInPumpDirectionSet ) ) || ( 0 == flowRate ) ) + if ( ( FALSE == isDialInPumpOn ) || ( 0 == flowRate ) || ( dir == dialInPumpDirectionSet ) ) { S32 dirFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); // Don't interrupt pump control unless rate or mode is changing if ( ( dirFlowRate != targetDialInFlowRate ) || ( mode != dialInPumpControlMode ) ) { 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 ) ) @@ -406,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++; @@ -825,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; } @@ -1296,7 +1315,8 @@ F32 deltaMCMotorSpeed = fabs( measMCMotorSpeed - cmdMotorSpeed ); F32 measRotorSpeed = fabs( getMeasuredDialInPumpRotorSpeed() ); F32 measMotorSpeedInRotorRPM = measMotorSpeed / DIP_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 ( ( deltaMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) ) @@ -1317,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 ) ) { @@ -1370,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 ) @@ -1513,7 +1533,7 @@ * @details Inputs: isDialInPumpOn, dialInPumpPWMDutyCyclePct, dialInPumpDirectionSet, * dialInPumpState * @details Outputs: dialInPumpControlMode, dialInPumpdirection, dialInPumpPWMDutyCyclePct - * @param pwm, the new pwm value + * @param pwm the new pwm value * @return TRUE if new flow rate & dir are set, FALSE if not **************************************************************************/ static BOOL testSetDialInPumpWithPWM( F32 pwm ) @@ -1527,22 +1547,32 @@ dir = MOTOR_DIR_REVERSE; } - // Check to see if pump is on or attempting to turn off // Direction change while pump is running is not allowed unless we are turning off - if ( ( ( FALSE == isDialInPumpOn ) && ( dir == dialInPumpDirectionSet ) ) || ( MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE >= pwmFabs ) ) + 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(); - // accept direction changes only when we stop - if ( FALSE == isDialInPumpOn ) - { - dialInPumpDirection = dir; - } 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 @@ -1575,9 +1605,9 @@ break; } result = TRUE; - } } + return result; } @@ -1911,25 +1941,12 @@ if ( TRUE == isTestingActivated() ) { - // check for max of pump pwm. - // minimum will get bounded within setDialInPumpWithPWM but we want - // 0 to be acceptable as off. + // check for max of pump pwm for acceptance. if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) { - // if exactly zero, clear test flag - if ( pwmPct == 0 ) - { - isTestPWMSet = FALSE; - } - else - { - isTestPWMSet = TRUE; - } result = testSetDialInPumpWithPWM( pwmPct ); } - } - return result; }