Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r9a9d04b84f4345fca87fb14d26f09d497b08aae8 -ra74a984a7059f75d86ad87d6d9499bd8f94cc976 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 9a9d04b84f4345fca87fb14d26f09d497b08aae8) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision a74a984a7059f75d86ad87d6d9499bd8f94cc976) @@ -46,8 +46,6 @@ #define BP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) // interval (ms/task time) at which the blood pump is controlled #define BP_P_COEFFICIENT 0.00005 // P term for blood pump control #define BP_I_COEFFICIENT 0.00015 // I term for blood pump control -#define BP_MAX_PWM_DC_DELTA 0.01 // prevents large steps in PWM duty cycle while controlling -#define BP_MIN_PWM_DC_DELTA -0.01 #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 // motor controller current should not exceed this when pump should be stopped #define BP_MIN_CURR_WHEN_RUNNING_MA 150.0 // motor controller current should always exceed this when pump should be running @@ -100,13 +98,15 @@ // ********** private data ********** -static BLOOD_PUMP_STATE_T bloodPumpState = BLOOD_PUMP_OFF_STATE; // current state of blood flow controller state machine -static U32 bloodFlowDataPublicationTimerCounter = 0; // used to schedule blood flow data publication to CAN bus -static BOOL isBloodPumpOn = FALSE; // blood pump is currently running -static F32 bloodPumpPWMDutyCyclePct = 0.0; // initial blood pump PWM duty cycle -static F32 bloodPumpPWMDutyCyclePctSet = 0.0; // currently set blood pump PWM duty cycle -static MOTOR_DIR_T bloodPumpDirection = MOTOR_DIR_FORWARD; // requested blood flow direction -static MOTOR_DIR_T bloodPumpDirectionSet = MOTOR_DIR_FORWARD; // currently set blood flow direction +static BLOOD_PUMP_STATE_T bloodPumpState = BLOOD_PUMP_OFF_STATE; // current state of blood flow controller state machine +static U32 bloodFlowDataPublicationTimerCounter = 0; // used to schedule blood flow data publication to CAN bus +static BOOL isBloodPumpOn = FALSE; // blood pump is currently running +static F32 bloodPumpPWMDutyCyclePct = 0.0; // initial blood pump PWM duty cycle +static F32 bloodPumpPWMDutyCyclePctSet = 0.0; // currently set blood pump PWM duty cycle +static MOTOR_DIR_T bloodPumpDirection = MOTOR_DIR_FORWARD; // requested blood flow direction +static MOTOR_DIR_T bloodPumpDirectionSet = MOTOR_DIR_FORWARD; // currently set blood flow direction +static PUMP_CONTROL_MODE_T bloodPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< requested blood pump control mode. +static PUMP_CONTROL_MODE_T bloodPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< currently set blood pump control mode. DATA_DECL( U32, BloodFlowDataPub, bloodFlowDataPublishInterval, BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL ); // interval (in ms) at which to publish blood flow data to CAN bus DATA_DECL( S32, TargetBloodFlowRate, targetBloodFlowRate, 0, 0 ); // requested blood flow rate @@ -178,9 +178,10 @@ * Outputs : targetBloodFlowRate, bloodPumpdirection, bloodPumpPWMDutyCyclePct * @param flowRate : new target blood flow rate * @param dir : new blood flow direction + * @param mode : new control mode * @return TRUE if new flow rate & dir are set, FALSE if not *************************************************************************/ -BOOL setBloodPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir ) +BOOL setBloodPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir, PUMP_CONTROL_MODE_T mode ) { BOOL result = FALSE; @@ -193,6 +194,7 @@ resetBloodFlowMovingAverage(); targetBloodFlowRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); bloodPumpDirection = dir; + bloodPumpControlMode = mode; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed bloodPumpPWMDutyCyclePct = BP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) @@ -377,6 +379,13 @@ { resetBloodFlowMovingAverage(); resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); + bloodPumpControlModeSet = bloodPumpControlMode; + // if open loop mode, set PWM to requested duty cycle where it will stay during control state + if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) + { + bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; + setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); + } result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp up @@ -414,6 +423,13 @@ { resetBloodFlowMovingAverage(); resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); + bloodPumpControlModeSet = bloodPumpControlMode; + // if open loop mode, set PWM to requested duty cycle where it will stay during control state + if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) + { + bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; + setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); + } result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp down @@ -439,16 +455,20 @@ static BLOOD_PUMP_STATE_T handleBloodPumpControlToTargetState( void ) { BLOOD_PUMP_STATE_T result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; - F32 tgtFlow = (F32)getTargetBloodFlowRate(); - F32 actFlow = getMeasuredBloodFlowRate(); - F32 newPWM; // control at set interval if ( ++bpControlTimerCounter >= BP_CONTROL_INTERVAL ) { - newPWM = runPIController( PI_CONTROLLER_ID_BLOOD_FLOW, tgtFlow, actFlow ); - bloodPumpPWMDutyCyclePctSet = newPWM; - setBloodPumpControlSignalPWM( newPWM ); + if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) + { + F32 tgtFlow = (F32)getTargetBloodFlowRate(); + F32 actFlow = getMeasuredBloodFlowRate(); + F32 newPWM; + + newPWM = runPIController( PI_CONTROLLER_ID_BLOOD_FLOW, tgtFlow, actFlow ); + bloodPumpPWMDutyCyclePctSet = newPWM; + setBloodPumpControlSignalPWM( newPWM ); + } bpControlTimerCounter = 0; }