Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r1f500f8e6159a3fbab85ea68389e918a6df66400 -r62a4d7b976107f7ac4d5013ce06f38f4a0bf65bd --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 1f500f8e6159a3fbab85ea68389e918a6df66400) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 62a4d7b976107f7ac4d5013ce06f38f4a0bf65bd) @@ -45,9 +45,8 @@ #define RO_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the RO Pump data is published on the CAN bus. -#define MAX_RO_PUMP_PWM_STEP_CHANGE 0.01 ///< max duty cycle change for controller. -#define MAX_RO_PUMP_PWM_DUTY_CYCLE 0.99 ///< max duty cycle. -#define MIN_RO_PUMP_PWM_DUTY_CYCLE 0.00 ///< min duty cycle. +#define MAX_RO_PUMP_DUTY_CYCLE 0.99 ///< max duty cycle. +#define MIN_RO_PUMP_DUTY_CYCLE 0.1 ///< min duty cycle. #define ROP_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the RO pump is controlled. #define ROP_P_COEFFICIENT 0.0020 ///< P term for RO pump pressure control. @@ -66,21 +65,16 @@ #define RO_FLOW_ADC_TO_LPM_FACTOR 10909.0909 ///< conversion factor from ADC counts to LPM (liters/min) for RO flow rate (multiply this by inverse of FPGA reading). #define ROP_FLOW_TO_PWM_DC(flow) ( (F32)( flow / MAX_RO_FLOWRATE_LPM ) ) ///< Initial conversion factor from target flow rate to PWM duty cycle estimate. - -/* TODO remove -#define MAX_RO_PUMP_PWM_STEP_CHANGE 0.01 ///< Max duty cycle change for controller. -#define MAX_RO_PUMP_PWM_DUTY_CYCLE 0.99 ///< Max duty cycle. -#define MIN_RO_PUMP_PWM_DUTY_CYCLE 0.00 ///< Min duty cycle. -#define ROP_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the RO pump is controlled. -#define ROP_P_COEFFICIENT 0.0020 ///< P term for RO pump control. -#define ROP_I_COEFFICIENT 0.0015 ///< I term for RO pump control. -*/ - #define FLOW_SENSOR_ZERO_READING 0xFFFF ///< Flow sensor reading indicates zero flow (or flow lower than can be detected by sensor). #define FLOW_SAMPLES_TO_AVERAGE ( 250 / TASK_PRIORITY_INTERVAL ) ///< Averaging flow data over 250 ms intervals. -#define FLOW_AVERAGE_MULTIPLIER ( 1.0 / (F32)FLOW_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. +#define FLOW_AVERAGE_MULTIPLIER ( 1.0 / (F32)FLOW_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. +#define MAX_ALLOWED_FLOW_DEVIATION 0.1 ///< Max allowed deviation from target flow. +#define FLOW_OUT_OF_RANGE_TIME_OUT ( 5000 / TASK_PRIORITY_INTERVAL ) ///< Flow out of range time out in counts. +#define MAX_PRESSURE_TARGET_TOLERANCE 5 ///< Pressure tolerance from maximum set pressure by user in psi. +#define MAX_ALLOWED_PRESSURE_PSI 140 ///< Maximum allowed pressure that the RO pump can go to. +#define MIN_ALLOWED_PRESSURE_PSI 10 ///< Minimum allowed pressure that the RO pump can go to. // TODO - this is a place holder for real conversion #define ROP_PSI_TO_PWM_DC(p) ( 0.2 + ( (F32)((p) - 100) * 0.01 ) ) ///< conversion factor from target PSI to PWM duty cycle estimate. @@ -114,37 +108,37 @@ // ********** private data ********** -static RO_PUMP_STATE_T roPumpState = RO_PUMP_OFF_STATE; ///< current state of RO pump controller state machine -static U32 roPumpDataPublicationTimerCounter = 0; ///< used to schedule RO pump data publication to CAN bus -static BOOL isROPumpOn = FALSE; ///< RO pump is currently running -static F32 roPumpPWMDutyCyclePct = 0.0; ///< initial RO pump PWM duty cycle -static F32 roPumpPWMDutyCyclePctSet = 0.0; ///< currently set RO pump PWM duty cycle -static PUMP_CONTROL_MODE_T roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< requested RO pump control mode -static PUMP_CONTROL_MODE_T roPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< currently set RO pump control mode +static RO_PUMP_STATE_T roPumpState = RO_PUMP_OFF_STATE; ///< current state of RO pump controller state machine +static U32 roPumpDataPublicationTimerCounter = 0; ///< used to schedule RO pump data publication to CAN bus +static BOOL isROPumpOn = FALSE; ///< RO pump is currently running +static F32 roPumpPWMDutyCyclePct = 0.0; ///< initial RO pump PWM duty cycle +static F32 roPumpDutyCyclePctSet = 0.0; ///< currently set RO pump PWM duty cycle +static PUMP_CONTROL_MODE_T roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< requested RO pump control mode +static PUMP_CONTROL_MODE_T roPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< currently set RO pump control mode -static OVERRIDE_F32_T targetROPumpFlowRate = { 0, 0, 0, 0 }; ///< Target RO flow rate (in LPM) +static OVERRIDE_F32_T targetROPumpFlowRate = { 0, 0, 0, 0 }; ///< Target RO flow rate (in LPM) static OVERRIDE_U32_T roPumpDataPublishInterval = { RO_PUMP_DATA_PUB_INTERVAL, RO_PUMP_DATA_PUB_INTERVAL, - 0, 0 }; ///< Interval (in ms) at which to publish RO flow data to CAN bus -static OVERRIDE_F32_T measuredROFlowRateLPM = { 0.0, 0.0, 0.0, 0 }; ///< measured RO flow rate (in LPM) + 0, 0 }; ///< Interval (in ms) at which to publish RO flow data to CAN bus +static OVERRIDE_F32_T measuredROFlowRateLPM = { 0.0, 0.0, 0.0, 0 }; ///< measured RO flow rate (in LPM) -static U32 flowVerificationCounter = 0; ///< Counter to verify the flow is in range +static U32 flowVerificationCounter = 0; ///< Counter to verify the flow is in range -static U32 roControlTimerCounter = 0; ///< determines when to perform control on RO pump +static U32 roControlTimerCounter = 0; ///< determines when to perform control on RO pump -static F32 roPumpOpenLoopTargetPWM = 0; ///< Target RO pump open loop PWM -static F32 roPumpFlowRateRunningSum = 0; ///< RO pump flow rate running sum -static F32 roPumpPressureRunningSum = 0; ///< RO pump pressure running sum +static F32 roPumpOpenLoopTargetDutyCycle = 0; ///< Target RO pump open loop PWM +static F32 roPumpFlowRateRunningSum = 0; ///< RO pump flow rate running sum +static F32 roPumpPressureRunningSum = 0; ///< RO pump pressure running sum + +static RO_PUMP_SELF_TEST_STATE_T roPumpSelfTestState = RO_PUMP_SELF_TEST_STATE_START; ///< current ro pump self test state +static U32 roPumpSelfTestTimerCount = 0; ///< timer counter for ro pump self test -/* The variables used for POST. They are not in use yet, so they are commented out -static RO_PUMP_SELF_TEST_STATE_T roPumpSelfTestState = RO_PUMP_SELF_TEST_STATE_START; ///< current ro pump self test state -static U32 roPumpSelfTestTimerCount = 0; ///< timer counter for ro pump self test -*/ - -static OVERRIDE_U32_T targetROPumpPressure = { 0, 0, 0, 0 }; ///< Target RO pressure (in PSI). +static OVERRIDE_U32_T targetROPumpPressure = { 0, 0, 0, 0 }; ///< Target RO pressure (in PSI) -static S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging. -static U32 flowFilterCounter = 0; ///< Flow filtering counter. +static S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging +static U32 flowFilterCounter = 0; ///< Flow filtering counter +static BOOL hasTargetFlowBeenReached = FALSE; ///< Flow set flag +static U32 flowOutOfRangeCounter = 0; // ********** private function prototypes ********** @@ -154,70 +148,70 @@ static RO_PUMP_STATE_T handleROPumpControlToTargetState( void ); static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ); -static BOOL setROPumpTargetPressure( U32 roPressure, PUMP_CONTROL_MODE_T mode ); -static BOOL setROPumpTargetPWM( F32 pwm ); -static void setROPumpControlSignalPWM( F32 newPWM ); +static BOOL setROPumpTargetPressure( U32 roPressure ); +static void setROPumpTargetDutyCycle( F32 duty ); +static void setROPumpControlSignalDutyCycle( F32 newPWM ); static void stopROPump( void ); static void publishROPumpData( void ); static U32 getPublishROPumpDataInterval( void ); /*********************************************************************//** * @brief - * The initROPump function initializes the ROPump module. - * @details - * Inputs: none - * Outputs: ROPump module initialized. + * The initROPump function initializes the RO Pump module. + * @details Inputs: hasTargetFlowBeenReached, flowOutOfRangeCounter + * @details Outputs: hasTargetFlowBeenReached, flowOutOfRangeCounter * @return none *************************************************************************/ void initROPump( void ) { stopROPump(); // Initialize RO pump PI controller - initializePIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_PWM_DUTY_CYCLE, + initializePIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_DUTY_CYCLE, ROP_P_COEFFICIENT, ROP_I_COEFFICIENT, - MIN_RO_PUMP_PWM_DUTY_CYCLE, MAX_RO_PUMP_PWM_DUTY_CYCLE ); + MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE ); - // Initialize the P controller during ramp up - initializePIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE, + // Initialize the I controller during ramp up + initializePIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_DUTY_CYCLE, ROP_RAMP_UP_P_COEFFICIENT, ROP_RAMP_UP_I_COEFFICIENT, - MIN_RO_PUMP_PWM_DUTY_CYCLE, MAX_RO_PUMP_PWM_DUTY_CYCLE ); + MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE ); + + // Make sure the flow set flag has been set to FALSE until it is set + hasTargetFlowBeenReached = FALSE; + flowOutOfRangeCounter = 0; } /*********************************************************************//** * @brief - * The setROPumpTargetPWM function sets the PWM that the pump should run - * @details - * Inputs: roPumpOpenLooptargetPWM, roPumpControlMode - * Outputs: roPumpOpenLooptargetPWM, roPumpControlMode - * @param: pwm - * @return whether the value was set (TRUE) or not (FALSE) + * The setROPumpTargetDutyCycle function sets the duty cycle that the + * pump should run. + * @details Inputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, + * roPumpPWMDutyCyclePctSet, roPumpControlMode + * @details Outputs: roPumpOpenLoopTargetDutyCycle, roPumpPWMDutyCyclePct, + * roPumpPWMDutyCyclePctSet, roPumpControlMode + * @param: duty which is the duty cycle + * @return none *************************************************************************/ -static BOOL setROPumpTargetPWM( F32 pwm ) +static void setROPumpTargetDutyCycle( F32 duty ) { - BOOL result = FALSE; - - if ( pwm >= MIN_RO_PUMP_PWM_DUTY_CYCLE && pwm < MAX_RO_PUMP_PWM_DUTY_CYCLE ) - { - roPumpOpenLoopTargetPWM = pwm; - roPumpPWMDutyCyclePct = roPumpOpenLoopTargetPWM; - roPumpPWMDutyCyclePctSet = roPumpPWMDutyCyclePct; - roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; - result = TRUE; - } - - return result; + roPumpOpenLoopTargetDutyCycle = duty; + roPumpPWMDutyCyclePct = roPumpOpenLoopTargetDutyCycle; + roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; + roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; } /*********************************************************************//** * @brief - * The setROPumpTargetFlowRate function sets a new target flow rate for the \n + * The setROPumpTargetFlowRate function sets a new target flow rate for the * RO pump. - * @details - * Inputs: none - * Outputs: targetROPumpFlowRate, roPumpPWMDutyCyclePct - * @param: roFlowRate : new target RO flow rate - * @return TRUE if new target flow rate is set, FALSE if not + * @details Inputs: targetROPumpPressure, targetROPumpFlowRate, + * roPumpControlMode + * @details Outputs: targetROPumpPressure, targetROPumpFlowRate, + * roPumpControlMode + * @param roFlowRate which is target RO flow rate + * @param maxPressure which is the maximum allowed pressure that the RO pump + * can reach + * @return TRUE if new target flow rate is set successfully, FALSE if not *************************************************************************/ BOOL setROPumpTargetFlowRate( F32 roFlowRate, F32 maxPressure ) { @@ -247,31 +241,41 @@ /*********************************************************************//** * @brief - * The signalROPumpHardStop function stops the RO pump immediately. - * @details - * Inputs: none - * Outputs: RO pump stopped, set point reset, state changed to off + * The signalROPumpHardStop function stops the RO pump immediately and + * resets all the variables associated with the RO pump run. + * @details Inputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, + * roPumpOpenLoopTargetDutyCycle, roControlTimerCounter, flowVerificationCounter, + * flowVerificationCounter, isROPumpOn, hasTargetFlowBeenReached, + * flowOutOfRangeCounter + * @details Outputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, + * roPumpOpenLoopTargetDutyCycle, roControlTimerCounter, flowVerificationCounter, + * flowVerificationCounter, isROPumpOn, hasTargetFlowBeenReached, + * flowOutOfRangeCounter * @return none *************************************************************************/ void signalROPumpHardStop( void ) -{ - targetROPumpFlowRate.data = 0; - stopROPump(); - roPumpState = RO_PUMP_OFF_STATE; - roPumpPWMDutyCyclePct = 0.0; - roPumpOpenLoopTargetPWM = 0.0; - roControlTimerCounter = 0; - flowVerificationCounter = 0; - isROPumpOn = FALSE; - resetPIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_PWM_DUTY_CYCLE ); +{ + stopROPump(); + targetROPumpFlowRate.data = 0; + roPumpState = RO_PUMP_OFF_STATE; + roPumpPWMDutyCyclePct = 0.0; + roPumpOpenLoopTargetDutyCycle = 0.0; + roControlTimerCounter = 0; + flowVerificationCounter = 0; + isROPumpOn = FALSE; + hasTargetFlowBeenReached = FALSE; + flowOutOfRangeCounter = 0; + resetPIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_DUTY_CYCLE ); } /*********************************************************************//** * @brief - * The execROPumpMonitor function executes the RO Pump monitor. - * @details - * Inputs: none - * Outputs: measuredROPumpPressure, measuredROFlowRateLPM + * The execROPumpMonitor function executes the RO pump monitor. + * @details Inputs: measuredFlowReadingsSum, flowFilterCounter, + * measuredROFlowRateLPM, measuredROFlowRateLPM, hasTargetFlowBeenReached, + * flowOutOfRangeCounter, roPumpControlMode + * @details Outputs: measuredFlowReadingsSum, flowFilterCounter, + * measuredROFlowRateLPM, measuredROFlowRateLPM, flowOutOfRangeCounter * @return none *************************************************************************/ void execROPumpMonitor( void ) @@ -299,24 +303,47 @@ measuredFlowReadingsSum = 0; flowFilterCounter = 0; } + + // In order to check the flow rate deviation, the control mode must in closed loop and + // the target flow must have been set. There might be a time that the pump cannot reach to target flow + // and also it does not reach to maximum pressure. But after a certain timeout the flow will be set and the + // read flow will be checked to be in range. + if ( roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP && hasTargetFlowBeenReached ) + { + F32 currentFlow = getMeasuredROFlowRate(); + F32 targetFlow = getTargetROPumpFlowRate(); + F32 deviation = currentFlow / targetFlow; + + // If the flow is out of range for a certain amount of time in a row + if ( ++flowOutOfRangeCounter > FLOW_OUT_OF_RANGE_TIME_OUT && deviation > MAX_ALLOWED_FLOW_DEVIATION ) + { + // There are alarms for flow out of range and above the target or below the target + if ( currentFlow > targetFlow ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, currentFlow, targetFlow ) + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, currentFlow, targetFlow ) + } + + } + // If the counter is > 0 but the deviation is in range again, reset the counter + else if ( flowOutOfRangeCounter > 0 && deviation < MAX_ALLOWED_FLOW_DEVIATION ) + { + flowOutOfRangeCounter = 0; + } + } - //measuredROPumpPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); TODO what do we do with this? - - - // TODO - check pressure? - - // TODO - check flow? - // Publish RO pump data on interval publishROPumpData(); } /*********************************************************************//** * @brief - * The execROPumpController function executes the RO Pump controller. - * @details - * Inputs: roPumpState - * Outputs: roPumpState + * The execROPumpController function executes the RO pump controller. + * @details Inputs: roPumpState + * @details Outputs: roPumpState * @return none *************************************************************************/ void execROPumpController( void ) @@ -352,26 +379,45 @@ /*********************************************************************//** * @brief - * The isROPumpOn function returns the status of RO pump. - * @details - * Inputs: none - * Outputs: none - * @param: none - * @return isROPumpOn + * The isReverseOsmosisPumpOn function returns the on/off status of RO pump. + * @details Inputs: isROPumpOn + * @details Outputs: none + * @return isROPumpOn the boolean flag that is TRUE if the pump is on and + * FALSE if it is off *************************************************************************/ BOOL isReverseOsmosisPumpOn( void ) { return isROPumpOn; +} + +/*********************************************************************//** + * @brief + * The execROPumpTest function executes the state machine for the RO pump + * self-test. + * @details + * Inputs: TODO FILL UP + * Outputs: TODO FILL UP + * @return the current state of the ROPump self test. + *************************************************************************/ +SELF_TEST_STATUS_T execROPumpTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; + + // TODO - implement self-test(s) + + return result; } /*********************************************************************//** * @brief - * The handleROPumpOffState function handles the ro pump off state \n - * of the ro pump controller state machine. - * @details - * Inputs: roPumpPWMDutyCyclePctSet, isROPumpOn - * Outputs: roPumpPWMDutyCyclePctSet, isROPumpOn - * @return next state + * The handleROPumpOffState function handles the RO pump off state of the + * controller state machine. + * @details Inputs: roPumpControlMode, roPumpControlModeSet, roPumpControlMode, + * roPumpPWMDutyCyclePctSet, roPumpPWMDutyCyclePct, isROPumpOn, + * roPumpOpenLoopTargetDutyCycle + * @details Outputs: roPumpControlModeSet, roPumpPWMDutyCyclePctSet, + * roPumpPWMDutyCyclePct, isROPumpOn + * @return next state of the controller state machine *************************************************************************/ static RO_PUMP_STATE_T handleROPumpOffState( void ) { @@ -387,7 +433,7 @@ setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setROPumpTargetPressure( 120, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setROPumpTargetPressure( 120 ); #ifdef EMC_TEST_BUILD { F32 fanPWM = 0.25; @@ -401,23 +447,24 @@ #endif #endif - // If there is a flow, transition to P controller to get the corresponding pressure of that flow + // If there is a flow, transition to the PI controller to get the corresponding pressure of that flow if ( getTargetROPumpFlowRate() > 0 && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) { roPumpControlModeSet = roPumpControlMode; // Set initial PWM duty cycle - roPumpPWMDutyCyclePctSet = roPumpPWMDutyCyclePct; - setROPumpControlSignalPWM( roPumpPWMDutyCyclePctSet ); + roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); // Reset controller - resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, roPumpPWMDutyCyclePctSet ); + resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, roPumpDutyCyclePctSet ); // Set pump to on isROPumpOn = TRUE; result = RO_PUMP_RAMP_UP_STATE; } - - if ( roPumpOpenLoopTargetPWM > 0 && roPumpControlMode == PUMP_CONTROL_MODE_OPEN_LOOP ) + // If the target duty cycle is greater than zero (minimum is 10%) and the mode has been set to open + // loop, set the duty cycle + if ( roPumpOpenLoopTargetDutyCycle > 0 && roPumpControlMode == PUMP_CONTROL_MODE_OPEN_LOOP ) { - setROPumpControlSignalPWM( roPumpOpenLoopTargetPWM ); + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); isROPumpOn = TRUE; result = RO_PUMP_OPEN_LOOP_STATE; } @@ -427,12 +474,11 @@ /*********************************************************************//** * @brief - * The handleROPumpRampUpState function handles the RO pump ramp up state \n - * of the RO pump controller state machine. - * @details - * Inputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet - * Outputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet - * @return next state + * The handleROPumpRampUpState function handles the RO pump ramp up state of + * the controller state machine. + * @details Inputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet + * @details Outputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet + * @return next state of the controller state machine *************************************************************************/ static RO_PUMP_STATE_T handleROPumpRampUpState( void ) { @@ -442,14 +488,25 @@ if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL ) { F32 targetFlowRate = getTargetROPumpFlowRate(); - F32 actualFlowRate = (F32)getMeasuredROFlowRate(); - - if ( fabs( actualFlowRate - targetFlowRate ) > ROP_FLOW_TARGET_TOLERANCE ) + F32 actualFlowRate = (F32)getMeasuredROFlowRate(); + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + // If the actual pressure is greater than the target pressure or it is within the tolerance of the maximum pressure, move to set + // to target pressure straight. At the beginning the maximum pressure is set in the targetROPumpPressure override variable. + // If the flow rate was reached without reaching to maximum pressure, the pressure that was set to targetROPumpPressure override will + // be reset to the corresponding pressure of the target flow rate. + if ( actualPressure > getTargetROPumpPressure() || ( getTargetROPumpPressure() - actualPressure ) > MAX_PRESSURE_TARGET_TOLERANCE ) + { + result = RO_PUMP_CONTROL_TO_TARGET_STATE; + } + // If the actual flow is still far from target flow, update the duty cycle using the I controller and stay in this state + else if ( fabs( actualFlowRate - targetFlowRate ) > ROP_FLOW_TARGET_TOLERANCE ) { F32 newPWM = runPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, targetFlowRate, actualFlowRate ); - roPumpPWMDutyCyclePctSet = newPWM; - setROPumpControlSignalPWM( newPWM ); + roPumpDutyCyclePctSet = newPWM; + setROPumpControlSignalDutyCycle( newPWM ); } + // Reached to the target flow go to the next state else { result = RO_PUMP_VERIFY_FLOW_STATE; @@ -463,14 +520,13 @@ /*********************************************************************//** * @brief - * The handleROPumpVerifyFlowState function handles the RO pump verify \n + * The handleROPumpVerifyFlowState function handles the RO pump verify * flow state of the RO pump controller state machine. - * @details - * Inputs: flowVerificationCounter, roPumpPWMDutyCyclePctSet, \n - * tgtROPumpPressure, roPumpFlowRateRunningSum, roPumpPressureRunningSum - * Outputs: flowVerificationCounter, roPumpPWMDutyCyclePctSet, \n - * tgtROPumpPressure, roPumpFlowRateRunningSum, roPumpPressureRunningSum - * @return next state + * @details Inputs: flowVerificationCounter, hasTargetFlowBeenReached, + * targetROPumpPressure, roPumpFlowRateRunningSum, roPumpFlowRateRunningSum + * @details Outputs: flowVerificationCounter, hasTargetFlowBeenReached, + * targetROPumpPressure, roPumpFlowRateRunningSum, roPumpFlowRateRunningSum + * @return next state of the controller state machine *************************************************************************/ static RO_PUMP_STATE_T handleROPumpVerifyFlowState( void ) { @@ -495,23 +551,27 @@ F32 targetFlowRate = getTargetROPumpFlowRate(); + // Reached to target flow rate + hasTargetFlowBeenReached = TRUE; + // Calculate the flow rate deviation from the target flow rate F32 flowRateDeviation = ( targetFlowRate - avgFlowRate ) / targetFlowRate; // Use the flow rate deviation to adjust the average calculated pressure. This // pressure is used as the target pressure avgPressure = avgPressure + ( avgPressure * flowRateDeviation ); - + // Save the target pressure targetROPumpPressure.data = avgPressure; } - // Reset the P controller for the flow rate - resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE ); + // Reset the I controller for the flow rate as it is no longer needed + resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_DUTY_CYCLE ); // Set initial PWM duty cycle - setROPumpControlSignalPWM( roPumpPWMDutyCyclePctSet ); + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); // Reset controller - resetPIController( PI_CONTROLLER_ID_RO_PUMP, roPumpPWMDutyCyclePctSet ); - flowVerificationCounter = 0; + resetPIController( PI_CONTROLLER_ID_RO_PUMP, roPumpDutyCyclePctSet ); + // Reset all the variables before leaving + flowVerificationCounter = 0; roPumpFlowRateRunningSum = 0; roPumpPressureRunningSum = 0; result = RO_PUMP_CONTROL_TO_TARGET_STATE; @@ -522,32 +582,27 @@ /*********************************************************************//** * @brief - * The handleROPumpControlToTargetState function handles the "control to - * target" state of the RO pump controller state machine. - * @details - * Inputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter - * Outputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter - * @return next state + * The handleROPumpControlToTargetState function handles the control to + * target state of the RO pump controller state machine. + * @details Inputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter, + * roPumpControlModeSet + * @details Outputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter + * @return next state of the controller state machine *************************************************************************/ static RO_PUMP_STATE_T handleROPumpControlToTargetState( void ) { RO_PUMP_STATE_T result = RO_PUMP_CONTROL_TO_TARGET_STATE; - // control at set interval + // Control at set interval if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL && roPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) - { + { + // Get the pressure to use it for setting the control F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); F32 newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, getTargetROPumpPressure(), actualPressure ); - roPumpPWMDutyCyclePctSet = newPWM; - setROPumpControlSignalPWM( roPumpPWMDutyCyclePctSet ); + roPumpDutyCyclePctSet = newPWM; + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); -#ifndef EMC_TEST_BUILD - newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, tgtPres, actPres ); - roPumpPWMDutyCyclePctSet = newPWM; - setROPumpControlSignalPWM( newPWM ); -#endif - roControlTimerCounter = 0; } @@ -572,12 +627,11 @@ /*********************************************************************//** * @brief - * The handleROPumpOpenLoopState function handles the open loop state \n - * of the RO pump controller - * @details - * Inputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter - * Outputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter - * @return next state + * The handleROPumpOpenLoopState function handles the open loop state of + * the RO pump controller state machine. + * @details Inputs: none + * @details Outputs: none + * @return next state of the controller state machine *************************************************************************/ static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ) { @@ -587,75 +641,73 @@ /*********************************************************************//** * @brief * The setROPumpTargetPressure function sets a new target pressure for the RO pump. - * @details - * Inputs : none - * Outputs : targetROPumpPressure, roPumpPWMDutyCyclePct + * @details Inputs : none + * @details Outputs : targetROPumpPressure, roPumpPWMDutyCyclePct * @param roPressure new target RO pressure - * @param mode new control mode * @return TRUE if new target pressure is set, FALSE if not *************************************************************************/ -static BOOL setROPumpTargetPressure( U32 roPressure, PUMP_CONTROL_MODE_T mode ) +static BOOL setROPumpTargetPressure( U32 roPressure ) { BOOL result = FALSE; - // Verify pressure - if ( roPressure >= 10 && roPressure <= 50 ) + // Verify pressure is in the allowed range + if ( roPressure >= MIN_ALLOWED_PRESSURE_PSI && roPressure <= MAX_ALLOWED_PRESSURE_PSI ) { targetROPumpPressure.data = roPressure; - roPumpControlMode = mode; + // Set the control mode to open loop + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; // set PWM duty cycle target to an estimated initial target based on target pressure - then we'll control to pressure going forward #ifdef EMC_TEST_BUILD roPumpPWMDutyCyclePct = 1.0; #else - roPumpPWMDutyCyclePct = ROP_PSI_TO_PWM_DC( roPressure ); + roPumpPWMDutyCyclePct = ROP_PSI_TO_PWM_DC( targetROPumpPressure.data ); #endif result = TRUE; } - else // requested pressure out of range + // Invalid pressure was selected + else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, 0, roPressure ) // TODO - replace 1st param with s/w fault enum + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVAID_PRESSURE_SELECTED, roPressure ) } return result; } /*********************************************************************//** * @brief - * The setROPumpControlSignalPWM function sets the PWM duty cycle for the - * RO pump to a given %. - * @details - * Inputs: none - * Outputs: PWM duty cycle zeroed - * @param: newPWM : new duty cycle % to apply to PWM + * The setROPumpControlSignalDutyCycle function sets the duty cycle for the + * RO pump to a given duty cycle. + * @details Inputs: none + * @details Outputs: none + * @param dutyCycle which is the duty cycle * @return none *************************************************************************/ -static void setROPumpControlSignalPWM( F32 newPWM ) +static void setROPumpControlSignalDutyCycle( F32 dutyCycle ) { - etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( newPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( dutyCycle * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } /*********************************************************************//** * @brief - * The stopROPump function sets the RO pump PWM to zero. - * @details - * Inputs: none - * Outputs: PWM duty cycle zeroed + * The stopROPump function sets the RO pump duty cycle to zero. + * @details Inputs: isROPumpOn, roPumpPWMDutyCyclePctSet + * @details Outputs: isROPumpOn, roPumpPWMDutyCyclePctSet * @return none *************************************************************************/ static void stopROPump( void ) { isROPumpOn = FALSE; - roPumpPWMDutyCyclePctSet = 0.0; + roPumpDutyCyclePctSet = 0.0; etpwmSetCmpB( etpwmREG2, 0 ); } /*********************************************************************//** * @brief - * The getPublishROPumpDataInterval function gets the RO pump data publish interval. - * @details - * Inputs: roPumpDataPublishInterval - * Outputs: none + * The getPublishROPumpDataInterval function gets the RO pump data publish + * interval. + * @details Inputs: roPumpDataPublishInterval + * @details Outputs: roPumpDataPublishInterval * @return the current RO pump data publication interval (in ms). *************************************************************************/ static U32 getPublishROPumpDataInterval( void ) @@ -672,12 +724,11 @@ /*********************************************************************//** * @brief - * The getTargetROPumpFlowRate function gets the current target RO pump \n - * flow rate - * @details - * Inputs: targetROPumpFlowRate - * Outputs: targetROPumpFlowRate - * @return the current target RO flow rate (in LPM). + * The getTargetROPumpFlowRate function gets the current target RO pump + * flow rate. + * @details Inputs: targetROPumpFlowRate + * @details Outputs: targetROPumpFlowRate + * @return the current target RO flow rate (in L/min). *************************************************************************/ F32 getTargetROPumpFlowRate( void ) { @@ -694,10 +745,9 @@ /*********************************************************************//** * @brief * The getMeasuredROFlowRate function gets the measured RO pump flow rate. - * @details - * Inputs: measuredROFlowRateLPM - * Outputs: none - * @return the current RO pump flow rate (in LPM). + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM + * @return the current RO pump flow rate (in L/min). *************************************************************************/ F32 getMeasuredROFlowRate( void ) { @@ -734,9 +784,8 @@ /*********************************************************************//** * @brief * The publishROPumpData function publishes RO pump data at the set interval. - * @details - * Inputs: target pressure, measured pressure, measured RO pump speed. - * Outputs: RO pump data is published to CAN bus. + * @details Inputs: roPumpDataPublicationTimerCounter + * @details Outputs: roPumpDataPublicationTimerCounter * @return none *************************************************************************/ static void publishROPumpData( void ) @@ -747,33 +796,15 @@ RO_PUMP_DATA_T pumpData; pumpData.roPumpTgtPressure = getTargetROPumpPressure(); - pumpData.measROFlowRate = getMeasuredROFlowRate(); - pumpData.roPumpPWM = roPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; - pumpData.roPumpState = (U32)roPumpState; + pumpData.measROFlowRate = getMeasuredROFlowRate(); + pumpData.roPumpDutyCycle = roPumpDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; + pumpData.roPumpState = (U32)roPumpState; broadcastROPumpData( &pumpData ); roPumpDataPublicationTimerCounter = 0; } -} +} -/*********************************************************************//** - * @brief - * The execROPumpTest function executes the state machine for the ROPump self-test. - * @details - * Inputs: none - * Outputs: none - * @return the current state of the ROPump self test. - *************************************************************************/ -SELF_TEST_STATUS_T execROPumpTest( void ) -{ - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; - - // TODO - implement self-test(s) - - return result; -} - - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -783,9 +814,8 @@ * @brief * The testSetROPumpDataPublishIntervalOverride function overrides the * RO pump data publish interval. - * @details - * Inputs: none - * Outputs: roPumpDataPublishInterval + * @details Inputs: roPumpDataPublishInterval + * @details Outputs: roPumpDataPublishInterval * @param: value : override RO pump data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -796,22 +826,21 @@ if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; - + roPumpDataPublishInterval.ovData = intvl; + roPumpDataPublishInterval.override = OVERRIDE_KEY; + result = TRUE; - roPumpDataPublishInterval.ovData = intvl; - roPumpDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief - * The testResetROPumpDataPublishIntervalOverride function resets the override - * of the RO pump data publish interval. - * @details - * Inputs: none - * Outputs: roPumpDataPublishInterval + * The testResetROPumpDataPublishIntervalOverride function resets the + * override of the RO pump data publish interval. + * @details Inputs: roPumpDataPublishInterval + * @details Outputs: roPumpDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetROPumpDataPublishIntervalOverride( void ) @@ -820,22 +849,22 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; roPumpDataPublishInterval.override = OVERRIDE_RESET; - roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; + roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; + + result = TRUE; } return result; } /*********************************************************************//** * @brief - * The testSetTargetROPumpFlowRateOverride function overrides the target \n - * RO flow rate. \n - * @details - * Inputs: targetROPumpFlowRate - * Outputs: targetROPumpPressure - * @param: value : override target RO flow rate (in LPM) + * The testSetTargetROPumpFlowRateOverride function overrides the target + * flow rate. + * @details Inputs: targetROPumpFlowRate + * @details Outputs: targetROPumpFlowRate + * @param: value which is override target RO flow rate (in L/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTargetROPumpFlowRateOverride( F32 value ) @@ -844,22 +873,21 @@ if ( TRUE == isTestingActivated() ) { - targetROPumpFlowRate.ovInitData = targetROPumpFlowRate.data; // backup current target pressure - targetROPumpFlowRate.ovData = value; - targetROPumpFlowRate.override = OVERRIDE_KEY; - //result = setROPumpTargetFlowRate( value ); + targetROPumpFlowRate.ovInitData = targetROPumpFlowRate.data; + targetROPumpFlowRate.ovData = value; + targetROPumpFlowRate.override = OVERRIDE_KEY; + //result = setROPumpTargetFlowRate( value ); TODO what should be pressure here? } return result; } /*********************************************************************//** * @brief - * The testResetTargetROPumpPressureOverride function resets the override of the - * target RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure + * The testResetTargetROPumpFlowRateOverride function resets the override + * of the target RO flow rate. + * @details Inputs: targetROPumpFlowRate + * @details Outputs: targetROPumpFlowRate * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTargetROPumpFlowRateOverride( void ) @@ -868,11 +896,13 @@ if ( TRUE == isTestingActivated() ) { - targetROPumpFlowRate.data = targetROPumpFlowRate.ovInitData; // restore pre-override target pressure - targetROPumpFlowRate.override = OVERRIDE_RESET; + // Reset the override + targetROPumpFlowRate.data = targetROPumpFlowRate.ovInitData; + targetROPumpFlowRate.override = OVERRIDE_RESET; targetROPumpFlowRate.ovInitData = 0; - targetROPumpFlowRate.ovData = 0; - //result = setROPumpTargetFlowRate( targetROPumpFlowRate.data ); + targetROPumpFlowRate.ovData = 0; + // Set the flow rate back to its original as well as the pressure + result = setROPumpTargetFlowRate( targetROPumpFlowRate.data, getTargetROPumpPressure() ); } return result; @@ -882,10 +912,9 @@ * @brief * The testSetTargetROPumpPressureOverride function overrides the target * RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure - * @param value override target RO pressure (in PSI) + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure + * @param value override target RO pressure (in psi) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTargetROPumpPressureOverride( U32 value ) @@ -894,22 +923,21 @@ if ( TRUE == isTestingActivated() ) { - targetROPumpPressure.ovInitData = targetROPumpPressure.data; // backup current target pressure - targetROPumpPressure.ovData = value; - targetROPumpPressure.override = OVERRIDE_KEY; - result = setROPumpTargetPressure( value, roPumpControlMode ); + targetROPumpPressure.ovInitData = targetROPumpPressure.data; + targetROPumpPressure.ovData = value; + targetROPumpPressure.override = OVERRIDE_KEY; + result = setROPumpTargetPressure( value ); } return result; } /*********************************************************************//** * @brief - * The testResetTargetROPumpPressureOverride function resets the override of the - * target RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure + * The testResetTargetROPumpPressureOverride function resets the override + * of the target RO pressure. + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTargetROPumpPressureOverride( void ) @@ -918,11 +946,11 @@ if ( TRUE == isTestingActivated() ) { - targetROPumpPressure.data = targetROPumpPressure.ovInitData; // restore pre-override target pressure - targetROPumpPressure.override = OVERRIDE_RESET; + targetROPumpPressure.data = targetROPumpPressure.ovInitData; + targetROPumpPressure.override = OVERRIDE_RESET; targetROPumpPressure.ovInitData = 0; - targetROPumpPressure.ovData = 0; - result = setROPumpTargetPressure( targetROPumpPressure.data, roPumpControlMode ); + targetROPumpPressure.ovData = 0; + result = setROPumpTargetPressure( targetROPumpPressure.data ); } return result; @@ -932,10 +960,9 @@ * @brief * The testSetMeasuredROFlowRateOverride function overrides the measured * RO flow rate. - * @details - * Inputs: none - * Outputs: measuredROFlowRateLPM - * @param: value : override measured RO pump motor speed (in LPM) + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM + * @param: value : override measured RO pump motor speed (in L/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetMeasuredROFlowRateOverride( F32 value ) @@ -944,37 +971,89 @@ if ( TRUE == isTestingActivated() ) { + measuredROFlowRateLPM.ovInitData = measuredROFlowRateLPM.data; + measuredROFlowRateLPM.ovData = value; + measuredROFlowRateLPM.override = OVERRIDE_KEY; + result = TRUE; - measuredROFlowRateLPM.ovData = value; - measuredROFlowRateLPM.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief - * The testResetMeasuredROFlowRateOverride function resets the override of the - * measured RO flow rate. - * @details - * Inputs: none - * Outputs: measuredROFlowRateLPM - * @param: none - + * The testResetMeasuredROFlowRateOverride function resets the override + * of the measured RO flow rate. + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredROFlowRateOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) - { + { + measuredROFlowRateLPM.data = measuredROFlowRateLPM.ovInitData; + measuredROFlowRateLPM.override = OVERRIDE_RESET; + measuredROFlowRateLPM.ovInitData = 0.0; + measuredROFlowRateLPM.ovData = 0.0; + result = TRUE; - measuredROFlowRateLPM.override = OVERRIDE_RESET; - measuredROFlowRateLPM.ovData = measuredROFlowRateLPM.ovInitData; } return result; -} +} +/*********************************************************************//** + * @brief + * The testSetTargetDutyCycleOverride function overrides the target duty + * cycle of the RO pump. + * @details Inputs: none + * @details Outputs: none + * @param value which is the duty cycle to be set + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetTargetDutyCycleOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Check if duty cycle is within ranges + if ( value >= MIN_RO_PUMP_DUTY_CYCLE && value <= MAX_RO_PUMP_DUTY_CYCLE ) + { + setROPumpTargetDutyCycle( value ); + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetTargetDutyCyceOverride function resets and turns off the + * RO pump that was running at a certain duty cycle. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetTargetDutyCyceOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Reset of the duty cycle override means stop the pump and + // reset all its variables + signalROPumpHardStop(); + + result = TRUE; + } + + return result; +} + /**@}*/