Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r7a754fc23436a42e61e60f66adf1cd0cc8b32ad6 -rc48ea51c06c9d002f1b9b6a1d7b72d69756f183d --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 7a754fc23436a42e61e60f66adf1cd0cc8b32ad6) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision c48ea51c06c9d002f1b9b6a1d7b72d69756f183d) @@ -44,16 +44,18 @@ #define MAX_DIAL_OUT_FLOW_RATE 650 ///< Maximum dialysate outlet pump flow rate in mL/min. #define MIN_DIAL_OUT_FLOW_RATE 100 ///< Minimum dialysate outlet pump flow rate in mL/min. -#define DPO_FLOW_ADJ_DUE_TO_HIGHER_INLET_PRES 1.200 ///< Adjustment factor to account for higher pump inlet pressure (than DPi pump inlet). #define MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE 0.0133 ///< Maximum duty cycle change when ramping up ~ 200 mL/min/s. #define MAX_DIAL_OUT_PUMP_PWM_STEP_DN_CHANGE 0.02 ///< Maximum duty cycle change when ramping down ~ 300 mL/min/s. #define MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.89 ///< Controller will error if PWM duty cycle > 90%, so set max to 89%. #define MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.10 ///< Controller will error if PWM duty cycle < 10%, so set min to 10%. +#define MAX_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL 0.4 ///< Maximum PWM offset (added to DPi PWM duty cycle). +#define MIN_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL -0.4 ///< Minimum PWM offset (added to DPi PWM duty cycle). +#define DOP_CONTROL_INTERVAL_SEC 5 ///< Dialysate outlet pump control interval (in seconds). /// Interval (ms/task time) at which the dialysate outlet pump is controlled. -static const U32 DOP_CONTROL_INTERVAL = ( 2000 / TASK_GENERAL_INTERVAL ); -#define DOP_P_COEFFICIENT 0.0050 ///< P term for dialysate outlet pump control. +static const U32 DOP_CONTROL_INTERVAL = ( DOP_CONTROL_INTERVAL_SEC * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +#define DOP_P_COEFFICIENT 0.0010 ///< P term for dialysate outlet pump control. #define DOP_I_COEFFICIENT 0.0001 ///< I term for dialysate outlet pump control. #define DOP_HOME_RATE 100 ///< Target pump speed (in estimate mL/min) for homing. @@ -217,9 +219,8 @@ } // Initialize dialysate outlet flow PI controller - initializePIController( PI_CONTROLLER_ID_ULTRAFILTRATION, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, - DOP_P_COEFFICIENT, DOP_I_COEFFICIENT, - MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); + initializePIController( PI_CONTROLLER_ID_ULTRAFILTRATION, 0, DOP_P_COEFFICIENT, DOP_I_COEFFICIENT, + MIN_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL, MAX_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL ); } /*********************************************************************//** @@ -247,10 +248,6 @@ { F32 adjFlow = (F32)flowRate; - if ( PUMP_CONTROL_MODE_CLOSED_LOOP == mode ) - { - adjFlow *= DPO_FLOW_ADJ_DUE_TO_HIGHER_INLET_PRES; - } lastGivenRate = flowRate; dialOutPumpDirection = dir; dialOutPumpControlMode = mode; @@ -518,14 +515,18 @@ // Have we reached end of ramp up? else if ( dialOutPumpPWMDutyCyclePctSet >= dialOutPumpPWMDutyCyclePct ) { - resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); - dialOutPumpControlModeSet = dialOutPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state + dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; if ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) { - dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; - setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); } + else + { // Closed loop UF control is only controlling offset from DPi PWM + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet - getDialInPumpPWMDutyCyclePct() ); + } + dialOutPumpControlModeSet = dialOutPumpControlMode; + setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); + dopControlTimerCounter = 0; result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp up @@ -559,14 +560,18 @@ // Have we reached end of ramp down? else if ( dialOutPumpPWMDutyCyclePctSet <= dialOutPumpPWMDutyCyclePct ) { - resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); - dialOutPumpControlModeSet = dialOutPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state - if ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) + dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; + if ( ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) || ( 0 == lastGivenRate ) ) { - dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; - setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); } + else + { // Closed loop UF control is only controlling offset from DPi PWM + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet - getDialInPumpPWMDutyCyclePct() ); + } + dialOutPumpControlModeSet = dialOutPumpControlMode; + setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); + dopControlTimerCounter = 0; result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp down @@ -598,22 +603,17 @@ { F32 refVol = getTotalTargetDialOutUFVolumeInMl(); F32 totVol = getTotalMeasuredUFVolumeInMl(); - F32 newPWMDutyCyclePct; - F32 deltaPWMDutyCyclePct; + F32 offsetPWMDutyCyclePct; - // Get new PWM from PI controller - newPWMDutyCyclePct = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); - // Limit PWM change to max - deltaPWMDutyCyclePct = newPWMDutyCyclePct - dialOutPumpPWMDutyCyclePctSet; - if ( fabs( deltaPWMDutyCyclePct ) > MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ) - { - newPWMDutyCyclePct = ( deltaPWMDutyCyclePct < 0.0 ? \ - dialOutPumpPWMDutyCyclePctSet - MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE : \ - dialOutPumpPWMDutyCyclePctSet + MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ); - } - // Set new PWM - dialOutPumpPWMDutyCyclePctSet = newPWMDutyCyclePct; - setDialOutPumpControlSignalPWM( newPWMDutyCyclePct ); + // Get new PWM offset from PI controller + offsetPWMDutyCyclePct = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); + // Add PWM offset to DPi PWM mirror for our new DPo PWM + dialOutPumpPWMDutyCyclePctSet = getDialInPumpPWMDutyCyclePct() + offsetPWMDutyCyclePct; + // Limit PWM range + dialOutPumpPWMDutyCyclePctSet = MIN( dialOutPumpPWMDutyCyclePctSet, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); + dialOutPumpPWMDutyCyclePctSet = MAX( dialOutPumpPWMDutyCyclePctSet, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); + // Apply new PWM to DPo pump + setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); } dopControlTimerCounter = 0; }