Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -ra7bf3ca23ea37a61000379facae628a31b3ecc59 -rf9b3862d01ce6c64bd05b8649e69b44fa155b8e0 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision a7bf3ca23ea37a61000379facae628a31b3ecc59) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision f9b3862d01ce6c64bd05b8649e69b44fa155b8e0) @@ -7,30 +7,29 @@ * * @file ROPump.c * -* @author (last) Sean Nash -* @date (last) 08-Jul-2020 +* @author (last) Quang Nguyen +* @date (last) 14-Sep-2020 * * @author (original) Sean * @date (original) 04-Apr-2020 * ***************************************************************************/ -#ifndef _VECTORCAST_ - #include -#endif +#include #include "etpwm.h" #include "mibspi.h" #include "FPGA.h" #include "OperationModes.h" -#include "PIControllers.h" +#include "PIControllers.h" +#include "PersistentAlarm.h" #include "Pressures.h" +#include "ROPump.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" -#include "ROPump.h" #ifdef EMC_TEST_BUILD #include "Heaters.h" #endif @@ -45,201 +44,328 @@ // ********** private definitions ********** -#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 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.0 ///< 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 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. +#define ROP_I_COEFFICIENT 0.0015 ///< I term for RO pump pressure control. + +#define ROP_RAMP_UP_P_COEFFICIENT 0.0 ///< P term for RO pump flow control. +#define ROP_RAMP_UP_I_COEFFICIENT 0.1 ///< I term for RO pump flow control. +#define ROP_FLOW_TARGET_TOLERANCE 0.05 ///< Tolerance in between the target flow rate and the actual flow rate in liter. -#define FLOW_SENSOR_ZERO_READING 0xFFFF ///< Flow sensor reading indicates zero flow (or flow lower than can be detected by sensor) +#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_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_VERIFICATION_COUNTER_TARGET 40U ///< The time in counts to check the flow and make sure it is in range. -#define ROP_PSI_TO_PWM_DC(p) ( 0.2 + ( (F32)((p) - 100) * 0.01 ) ) ///< conversion factor from target PSI to PWM duty cycle estimate TODO - this is a place holder for real conversion +#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. -#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 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 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 130 ///< 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. +#define MAX_ALLOWED_MEASURED_PRESSURE_PSI 135 ///< Maximum allowed pressure that the sensor measures. RO pump shut off pressure is 140psi. +#define MAX_PRESSURE_OUT_OF_RANGE_TIME_OUT ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Maximum allowed time that the pressure can be very high. +#define MAX_ALLOWED_RAMP_UP_TIME ( 30 * MS_PER_SECOND ) ///< Maximum allowed ramp up time to a flow rate in ms. +#define RAMP_UP_TIME_OUT_COUNT ( MAX_ALLOWED_RAMP_UP_TIME / \ + TASK_GENERAL_INTERVAL ) ///< Ramp up time out in counts. + +// 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. TODO remove? + /// Enumeration of RO pump states. typedef enum ROPump_States { - RO_PUMP_OFF_STATE = 0, ///< RO pump off state. - RO_PUMP_CONTROL_TO_TARGET_STATE, ///< RO pump control to target pressure state. - NUM_OF_RO_PUMP_STATES ///< Number of RO pump states. + RO_PUMP_OFF_STATE = 0, ///< RO pump off state + RO_PUMP_RAMP_UP_STATE, ///< RO pump ramp up to target flow rate state + RO_PUMP_VERIFY_FLOW_STATE, ///< RO pump maintain the flow rate for a set period of time + RO_PUMP_CONTROL_TO_TARGET_STATE, ///< RO pump control to target pressure state + RO_PUMP_OPEN_LOOP_STATE, ///< RO pump open loop state + NUM_OF_RO_PUMP_STATES ///< Number of RO pump states } RO_PUMP_STATE_T; -/// Enumeration of RO pump self test states. +/// Enumeration of RO pump self-test states. typedef enum ROPump_Self_Test_States { - RO_PUMP_SELF_TEST_STATE_START = 0, ///< RO pump self test start state. - RO_PUMP_TEST_STATE_IN_PROGRESS, ///< RO pump self tests in progress state. - RO_PUMP_TEST_STATE_COMPLETE, ///< RO pump self tests completed state. - NUM_OF_RO_PUMP_SELF_TEST_STATES ///< Number of RO pump self test states. + RO_PUMP_SELF_TEST_STATE_START = 0, ///< RO pump self-test start state + RO_PUMP_TEST_STATE_IN_PROGRESS, ///< RO pump self-tests in progress state + RO_PUMP_TEST_STATE_COMPLETE, ///< RO pump self-tests completed state + NUM_OF_RO_PUMP_SELF_TEST_STATES ///< Number of RO pump self-test states } RO_PUMP_SELF_TEST_STATE_T; // TODO - test code - remove later // pin assignments for pump test DIP switch 0 #define RO_PUMP_TEST_SPI5_PORT_MASK 0x00000100 // (ENA - re-purposed as input GPIO) // dialIn pump stop and direction macros -#define GET_DIP_SW0_TEST() ( ( mibspiREG5->PC2 & RO_PUMP_TEST_SPI5_PORT_MASK ) != 0 ) +#define GET_DIP_SW0_TEST() ( ( mibspiREG5->PC2 & RO_PUMP_TEST_SPI5_PORT_MASK ) != 0 ) // ********** 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_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_U32_T targetROPumpPressure = { 0, 0, 0, 0 }; ///< Target RO pressure (in PSI). -static OVERRIDE_F32_T measuredROFlowRateLPM = { 0.0, 0.0, 0.0, 0 }; ///< measured RO flow rate (in LPM). -static F32 measuredROPumpPressure = 0.0; ///< measured RO pressure (in PSI). +static F32 targetROPumpFlowRate = 0.0; ///< Target RO flow rate (in L/min) +static U32 targetROPumpPressure = 0; ///< Target RO pressure (in PSI) -static S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging. -static U32 flowFilterCounter = 0; ///< used to schedule flow filtering. +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 L/min) -static U32 roControlTimerCounter = 0; ///< determines when to perform control on ro pump +static U32 flowVerificationCounter = 0; ///< Counter to verify the flow is in range -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 U32 roControlTimerCounter = 0; ///< determines when to perform control on RO pump + +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 + +/* These variables are used for POST. POST has not been implemented yet +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 S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging +static U32 flowFilterCounter = 0; ///< Flow filtering counter +static U32 rampUp2FlowTimeoutCounter = 0; ///< Counter for ramping up to flow time // ********** private function prototypes ********** static RO_PUMP_STATE_T handleROPumpOffState( void ); -static RO_PUMP_STATE_T handleROPumpControlToTargetState( void ); -static void setROPumpControlSignalPWM( F32 newPWM ); +static RO_PUMP_STATE_T handleROPumpRampUpState( void ); +static RO_PUMP_STATE_T handleROPumpVerifyFlowState( void ); +static RO_PUMP_STATE_T handleROPumpControlToTargetState( void ); +static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ); + +static void setROPumpTargetDutyCycle( F32 duty ); +static void setROPumpControlSignalDutyCycle( F32 dutyCycle ); static void stopROPump( void ); static void publishROPumpData( void ); -static DATA_GET_PROTOTYPE( U32, getPublishROPumpDataInterval ); +static U32 getPublishROPumpDataInterval( void ); /*********************************************************************//** - * @brief initROPump - * The initROPump function initializes the ROPump module. - * @details - * Inputs : none - * Outputs : ROPump module initialized. + * @brief + * The initROPump function initializes the RO Pump module. + * @details Inputs: rampUp2FlowTimeoutCounter + * @details Outputs: rampUp2FlowTimeoutCounter * @return none *************************************************************************/ void initROPump( void ) { stopROPump(); - // initialize RO pump PI controller - initializePIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_PWM_DUTY_CYCLE, - ROP_P_COEFFICIENT, ROP_I_COEFFICIENT, - MIN_RO_PUMP_PWM_DUTY_CYCLE, MAX_RO_PUMP_PWM_DUTY_CYCLE ); + // Initialize RO pump PI controller + initializePIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_DUTY_CYCLE, ROP_P_COEFFICIENT, ROP_I_COEFFICIENT, + MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_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_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE ); + + // Initialize the persistent alarm for flow out of upper and lower range + initPersistentAlarm( PERSISTENT_ALARM_RO_FLOW_RATE_OUT_OF_UPPER_RANGE, ALARM_ID_FLOW_RATE_OUT_OF_RANGE, TRUE, + FLOW_OUT_OF_RANGE_TIME_OUT, FLOW_OUT_OF_RANGE_TIME_OUT ); + + initPersistentAlarm( PERSISTENT_ALARM_RO_FLOW_RATE_OUT_OF_LOWER_RANGE, ALARM_ID_FLOW_RATE_OUT_OF_RANGE, TRUE, + FLOW_OUT_OF_RANGE_TIME_OUT, FLOW_OUT_OF_RANGE_TIME_OUT ); + + // Initialize the persistent alarm for max allowed pressure out of range + initPersistentAlarm( PERSISTENT_ALARM_RO_PUMP_PRESSURE_OUT_OF_RANGE, ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, TRUE, + MAX_PRESSURE_OUT_OF_RANGE_TIME_OUT, MAX_PRESSURE_OUT_OF_RANGE_TIME_OUT ); + + rampUp2FlowTimeoutCounter = 0; +} + +/*********************************************************************//** + * @brief + * 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 void setROPumpTargetDutyCycle( F32 duty ) +{ + roPumpOpenLoopTargetDutyCycle = duty; + roPumpPWMDutyCyclePct = roPumpOpenLoopTargetDutyCycle; + roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; + roPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; } /*********************************************************************//** * @brief - * The setROPumpTargetPressure function sets a new target pressure for the \n + * The setROPumpTargetFlowRate function sets a new target flow rate for the * RO pump. - * @details - * Inputs : none - * 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 + * @details Inputs: targetROPumpPressure, targetROPumpFlowRate, + * roPumpControlMode, rampUp2FlowTimeoutCounter + * @details Outputs: targetROPumpPressure, targetROPumpFlowRate, + * roPumpControlMode, rampUp2FlowTimeoutCounter + * @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 setROPumpTargetPressure( U32 roPressure, PUMP_CONTROL_MODE_T mode ) +BOOL setROPumpTargetFlowRate( F32 roFlowRate, U32 maxPressure ) { BOOL result = FALSE; - - // verify pressure - if ( roPressure >= MIN_RO_PRESSURE && roPressure <= MAX_RO_PRESSURE ) + + // First of all, the flow rate must be in range + if ( ( roFlowRate < MAX_RO_FLOWRATE_LPM ) && ( roFlowRate >= MIN_RO_FLOWRATE_LPM ) ) + { + // Then the max pressure that we are allowed to reach must be in range + if ( ( maxPressure >= MIN_ALLOWED_PRESSURE_PSI ) && ( maxPressure <= MAX_ALLOWED_PRESSURE_PSI ) ) + { + // For now maximum allowed pressure is inserted into the target pressure override + // if the target flow rate exceeded the max pressure, it will set the maximum pressure + targetROPumpPressure = maxPressure; + targetROPumpFlowRate = roFlowRate; + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + // Get the initial guess of the duty cycle + roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( roFlowRate ); + rampUp2FlowTimeoutCounter = 0; + result = TRUE; + } + // Requested max pressure is out of range + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, maxPressure ) + } + +/*#ifdef EMC_TEST_BUILD + roPumpPWMDutyCyclePct = 1.0; +#else + roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( roFlowRate ); +#endif*/ + } + // Requested flow rate is out of range + else { - targetROPumpPressure.data = roPressure; - roPumpControlMode = mode; - // 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 ); -#endif - - result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, roFlowRate ) } - else // requested pressure out of range - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, 0, roPressure ) // TODO - replace 1st param with s/w fault enum - } return result; } /*********************************************************************//** * @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, rampUp2FlowTimeoutCounter + * @details Outputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, + * roPumpOpenLoopTargetDutyCycle, roControlTimerCounter, + * flowVerificationCounter, isROPumpOn, rampUp2FlowTimeoutCounter * @return none *************************************************************************/ void signalROPumpHardStop( void ) -{ - targetROPumpPressure.data = 0; - stopROPump(); - roPumpState = RO_PUMP_OFF_STATE; - roPumpPWMDutyCyclePct = 0.0; - roControlTimerCounter = 0; - resetPIController( PI_CONTROLLER_ID_RO_PUMP, MIN_RO_PUMP_PWM_DUTY_CYCLE ); +{ + stopROPump(); + targetROPumpFlowRate = 0; + roPumpState = RO_PUMP_OFF_STATE; + roPumpPWMDutyCyclePct = 0.0; + roPumpOpenLoopTargetDutyCycle = 0.0; + roControlTimerCounter = 0; + flowVerificationCounter = 0; + isROPumpOn = FALSE; + rampUp2FlowTimeoutCounter = 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, roPumpState, + * flowOutOfRangeCounter, roPumpControlMode + * @details Outputs: measuredFlowReadingsSum, flowFilterCounter, + * measuredROFlowRateLPM, measuredROFlowRateLPM * @return none *************************************************************************/ void execROPumpMonitor( void ) { U16 roFlowReading = getFPGAROPumpFlowRate(); S32 roFlow = (S32)roFlowReading; + // Update sum for flow average calculation + measuredFlowReadingsSum += roFlow; + + // Read the pressure at the sensor. The pump cannot be more that the maximum allowed pressure + // to make sure the hardware (especially the ROF) is not damaged. If it is the case, we need to + // stop immediately + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + BOOL isPressureMax = actualPressure >= MAX_ALLOWED_MEASURED_PRESSURE_PSI; + checkPersistentAlarm( PERSISTENT_ALARM_RO_PUMP_PRESSURE_OUT_OF_RANGE, isPressureMax, actualPressure ); - // update sum for flow average calculation - measuredFlowReadingsSum += roFlow; - // filter every 250ms + // Read flow at the control set if ( ++flowFilterCounter >= FLOW_SAMPLES_TO_AVERAGE ) { F32 avgROFlow = (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER; - - if ( ( avgROFlow == FLOW_SENSOR_ZERO_READING ) || ( measuredFlowReadingsSum == 0 ) ) + + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that + // the flow is 0. Otherwise, convert the count to flow rate in mL/min + if ( ( roFlowReading == FLOW_SENSOR_ZERO_READING ) || ( roFlowReading == 0 ) ) { - measuredROFlowRateLPM.data = 0.0; + measuredROFlowRateLPM.data = 0.0; } else { measuredROFlowRateLPM.data = RO_FLOW_ADC_TO_LPM_FACTOR / avgROFlow; - } + } + measuredFlowReadingsSum = 0; flowFilterCounter = 0; } + + // To monitor the flow, the control mode must be in closed loop and the pump should be control to target state, + // meaning, it is controlling to a certain pressure + if ( roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP && roPumpState == RO_PUMP_CONTROL_TO_TARGET_STATE ) + { + F32 currentFlow = getMeasuredROFlowRate(); + F32 targetFlow = getTargetROPumpFlowRate(); + F32 error = 1.0 - ( currentFlow / targetFlow ); + BOOL isFlowOutOfRange = error > MAX_ALLOWED_FLOW_DEVIATION; + + // Figure out whether flow is out of range from which side + if ( isFlowOutOfRange ) + { + BOOL isFlowOutOfUpperRange = currentFlow > targetFlow; + BOOL isFlowOutOfLowerRange = currentFlow < targetFlow; + + // Check for flow out of range + checkPersistentAlarm( PERSISTENT_ALARM_RO_FLOW_RATE_OUT_OF_UPPER_RANGE, isFlowOutOfUpperRange, currentFlow ); + checkPersistentAlarm( PERSISTENT_ALARM_RO_FLOW_RATE_OUT_OF_LOWER_RANGE, isFlowOutOfLowerRange, currentFlow ); + } + } - measuredROPumpPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); - - // TODO - check pressure? - - // TODO - check flow? - - // publish RO pump data on interval + // 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 ) @@ -250,39 +376,70 @@ roPumpState = handleROPumpOffState(); break; + case RO_PUMP_RAMP_UP_STATE: + roPumpState = handleROPumpRampUpState(); + break; + + case RO_PUMP_VERIFY_FLOW_STATE: + roPumpState = handleROPumpVerifyFlowState(); + break; + case RO_PUMP_CONTROL_TO_TARGET_STATE: roPumpState = handleROPumpControlToTargetState(); + break; + + case RO_PUMP_OPEN_LOOP_STATE: + roPumpState = handleROPumpOpenLoopState(); break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, 0, roPumpState ) // 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_INVALID_EXEC_STATE, roPumpState ) roPumpState = RO_PUMP_OFF_STATE; break; - } + } } /*********************************************************************//** * @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 : targetROPumpPressure - * 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 ) { @@ -298,7 +455,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; @@ -310,53 +467,171 @@ #endif } #endif -#endif +#endif - // if we've been given a pressure, transition to control to target state - if ( getTargetROPumpPressure() > 0 ) + // 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 ); - // reset controller - resetPIController( PI_CONTROLLER_ID_RO_PUMP, roPumpPWMDutyCyclePctSet ); - // set pump to on + roPumpControlModeSet = roPumpControlMode; + // Set initial PWM duty cycle + roPumpDutyCyclePctSet = roPumpPWMDutyCyclePct; + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + // Reset controller + resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, roPumpDutyCyclePctSet ); + // Set pump to on isROPumpOn = TRUE; - result = RO_PUMP_CONTROL_TO_TARGET_STATE; + result = RO_PUMP_RAMP_UP_STATE; + } + // 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 ) + { + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); + isROPumpOn = TRUE; + result = RO_PUMP_OPEN_LOOP_STATE; } return result; } + +/*********************************************************************//** + * @brief + * The handleROPumpRampUpState function handles the RO pump ramp up state + * of the controller state machine. + * @details Inputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet, + * rampUp2FlowTimeoutCounter + * @details Outputs: roControlTimerCounter, roPumpPWMDutyCyclePctSet, + * rampUp2FlowTimeoutCounter + * @return next state of the controller state machine + *************************************************************************/ +static RO_PUMP_STATE_T handleROPumpRampUpState( void ) +{ + RO_PUMP_STATE_T result = RO_PUMP_RAMP_UP_STATE; + + // Get the current pressure from the sensor + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + // If we are still in the ramp up mode after the specified time, get the current pressure + // and control from this + if ( ++rampUp2FlowTimeoutCounter > RAMP_UP_TIME_OUT_COUNT ) + { + targetROPumpPressure = actualPressure; + rampUp2FlowTimeoutCounter = 0; + result = RO_PUMP_CONTROL_TO_TARGET_STATE; + } + // Control at set interval + else if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL ) + { + F32 targetFlowRate = getTargetROPumpFlowRate(); + F32 actualFlowRate = (F32)getMeasuredROFlowRate(); + + // 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 ) + { + roPumpDutyCyclePctSet = runPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, targetFlowRate, actualFlowRate ); + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + } + // Reached to the target flow go to the next state + else + { + result = RO_PUMP_VERIFY_FLOW_STATE; + } + + roControlTimerCounter = 0; + } + return result; +} + +/*********************************************************************//** + * @brief + * The handleROPumpVerifyFlowState function handles the RO pump verify + * flow state of the RO pump controller state machine. + * @details Inputs: flowVerificationCounter, targetROPumpPressure, + * roPumpFlowRateRunningSum, roPumpFlowRateRunningSum + * @details Outputs: flowVerificationCounter, targetROPumpPressure, + * roPumpFlowRateRunningSum, roPumpFlowRateRunningSum + * @return next state of the controller state machine + *************************************************************************/ +static RO_PUMP_STATE_T handleROPumpVerifyFlowState( void ) +{ + RO_PUMP_STATE_T result = RO_PUMP_VERIFY_FLOW_STATE; + + // Calculate the running sum of the flow rate and RO pump outlet pressure + roPumpFlowRateRunningSum = roPumpFlowRateRunningSum + (F32)getMeasuredROFlowRate(); + roPumpPressureRunningSum = roPumpPressureRunningSum + getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + // Check if the time for flow verification has elapsed + if ( ++flowVerificationCounter >= FLOW_VERIFICATION_COUNTER_TARGET ) + { + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + // If the flow has been achieved without reaching to the maximum pressure, set the new pressure + // otherwise, stay with the maximum allowed pressure as target pressure + if ( actualPressure < getTargetROPumpPressure() ) + { + // Calculate the average pressure and flow rate + F32 avgPressure = roPumpPressureRunningSum / flowVerificationCounter; + F32 avgFlowRate = roPumpFlowRateRunningSum / flowVerificationCounter; + + F32 targetFlowRate = getTargetROPumpFlowRate(); + + // 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 = avgPressure; + } + + // 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 + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + // Reset controller + 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; + } + + return result; +} + /*********************************************************************//** * @brief - * The handleROPumpControlToTargetState function handles the "control to \n - * target" state of the ro pump controller state machine. - * @details - * Inputs : none - * Outputs : roPumpState - * @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 - if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL ) - { - if ( roPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) - { - F32 tgtPres = (F32)getTargetROPumpPressure(); - F32 actPres = measuredROPumpPressure; - F32 newPWM; + // 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 ); -#ifndef EMC_TEST_BUILD - newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, tgtPres, actPres ); - roPumpPWMDutyCyclePctSet = newPWM; - setROPumpControlSignalPWM( newPWM ); -#endif - } + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP, getTargetROPumpPressure(), actualPressure ); + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + roControlTimerCounter = 0; } @@ -377,48 +652,58 @@ #endif return result; +} + +/*********************************************************************//** + * @brief + * 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 ) +{ + return RO_PUMP_OPEN_LOOP_STATE; } /*********************************************************************//** * @brief - * The setROPumpControlSignalPWM function sets the PWM duty cycle for \n - * 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 \n - * publication 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). *************************************************************************/ -U32 getPublishROPumpDataInterval( void ) +static U32 getPublishROPumpDataInterval( void ) { U32 result = roPumpDataPublishInterval.data; @@ -432,33 +717,23 @@ /*********************************************************************//** * @brief - * The getTargetROPumpPressure function gets the current target RO pump \n - * pressure. - * @details - * Inputs : targetROPumpPressure - * Outputs : none - * @return the current target RO pressure (in PSI). + * 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). *************************************************************************/ -U32 getTargetROPumpPressure( void ) +F32 getTargetROPumpFlowRate( void ) { - U32 result = targetROPumpPressure.data; - - if ( OVERRIDE_KEY == targetROPumpPressure.override ) - { - result = targetROPumpPressure.ovData; - } - - return result; + return targetROPumpFlowRate; } /*********************************************************************//** * @brief - * The getMeasuredROFlowRate function gets the measured RO pump \n - * flow rate. - * @details - * Inputs : measuredROFlowRateLPM - * Outputs : none - * @return the current RO pump flow rate (in LPM). + * The getMeasuredROFlowRate function gets the measured RO pump flow rate. + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM + * @return the current RO pump flow rate (in L/min). *************************************************************************/ F32 getMeasuredROFlowRate( void ) { @@ -470,63 +745,57 @@ } return result; +} + +/*********************************************************************//** + * @brief + * The getTargetROPumpPressure function gets the current target RO pump + * pressure. + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure + * @return the current target RO targetROPumpPressure in psi. + *************************************************************************/ +F32 getTargetROPumpPressure( void ) +{ + return targetROPumpPressure; } /*********************************************************************//** * @brief - * The publishROPumpData function publishes RO pump data at the set \n - * interval. - * @details - * Inputs : target pressure, measured pressure, measured RO pump speed. - * Outputs : RO pump data is published to CAN bus. + * The publishROPumpData function publishes RO pump data at the set interval. + * @details Inputs: roPumpDataPublicationTimerCounter + * @details Outputs: roPumpDataPublicationTimerCounter * @return none *************************************************************************/ static void publishROPumpData( void ) { // publish RO pump data on interval if ( ++roPumpDataPublicationTimerCounter >= getPublishROPumpDataInterval() ) { - U32 presStPt = getTargetROPumpPressure(); - F32 measFlow = getMeasuredROFlowRate(); - F32 pumpPWMPctDutyCycle = roPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; - broadcastROPumpData( presStPt, measFlow, pumpPWMPctDutyCycle ); + RO_PUMP_DATA_T pumpData; + + pumpData.roPumpTgtPressure = getTargetROPumpPressure(); + 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 *************************************************************************/ + - /*********************************************************************//** * @brief - * The testSetROPumpDataPublishIntervalOverride function overrides the \n + * The testSetROPumpDataPublishIntervalOverride function overrides the * RO pump data publish interval. - * @details - * Inputs : none - * Outputs : roPumpDataPublishInterval - * @param value : override RO pump data publish interval with (in ms) + * @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 *************************************************************************/ BOOL testSetROPumpDataPublishIntervalOverride( U32 value ) @@ -536,22 +805,20 @@ 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 \n - * 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 ) @@ -560,73 +827,75 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; roPumpDataPublishInterval.override = OVERRIDE_RESET; - roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; + roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; + result = TRUE; } return result; } /*********************************************************************//** * @brief - * The testSetTargetROPumpPressureOverride function overrides the target \n - * RO pressure. \n - * @details - * Inputs : none - * Outputs : targetROPumpPressure - * @param value : override target RO pressure (in PSI) + * The testSetTargetROPumpFlowRateOverride function overrides the target + * flow rate. + * @details Inputs: none + * @details Outputs: none + * @param value which is override target RO flow rate (in L/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetTargetROPumpPressureOverride( U32 value ) +BOOL testSetTargetROPumpFlowAndPressure( F32 flow, U32 pressure ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) - { - targetROPumpPressure.ovInitData = targetROPumpPressure.data; // backup current target pressure - targetROPumpPressure.ovData = value; - targetROPumpPressure.override = OVERRIDE_KEY; - result = setROPumpTargetPressure( value, roPumpControlMode ); + { + // The flow rate and pressure must be in range + if ( flow < MAX_RO_FLOWRATE_LPM && flow >= MIN_RO_FLOWRATE_LPM ) + { + if ( pressure >= MIN_ALLOWED_PRESSURE_PSI && pressure <= MAX_ALLOWED_PRESSURE_PSI ) + { + result = setROPumpTargetFlowRate( flow, pressure ); + } + } } return result; -} +} + +/*********************************************************************//** + * @brief + * The testSetTargetROPumpPressureOverride function overrides the target + * RO pressure. + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure + * @param value override target RO pressure (in psi) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetTargetROPumpPressure( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Make sure the requested pressure is in range + if ( value >= MIN_ALLOWED_PRESSURE_PSI && value <= MAX_ALLOWED_PRESSURE_PSI ) + { + targetROPumpPressure = value; + result = TRUE; + } + } + + return result; +} /*********************************************************************//** * @brief - * The testResetTargetROPumpPressureOverride function resets the override of the \n - * target RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure - * @param none - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetROPumpPressureOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - targetROPumpPressure.data = targetROPumpPressure.ovInitData; // restore pre-override target pressure - targetROPumpPressure.override = OVERRIDE_RESET; - targetROPumpPressure.ovInitData = 0; - targetROPumpPressure.ovData = 0; - result = setROPumpTargetPressure( targetROPumpPressure.data, roPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetMeasuredROFlowRateOverride function overrides the measured \n + * 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 ) @@ -635,34 +904,63 @@ 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 \n - * 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 testSetTargetDutyCycle( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Check if duty cycle is within range + if ( value >= MIN_RO_PUMP_DUTY_CYCLE && value <= MAX_RO_PUMP_DUTY_CYCLE ) + { + setROPumpTargetDutyCycle( value ); + result = TRUE; + } + } + + return result; +} + +/**@}*/