Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r54f45c387430e440ab4607451fc84dea61f273f1 -r036a11ec6f48682b47e67ddcc7a7772d81647f4b --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 54f45c387430e440ab4607451fc84dea61f273f1) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 036a11ec6f48682b47e67ddcc7a7772d81647f4b) @@ -1,658 +1,1088 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file ROPump.c +* @file ROPump.c * -* @author (last) Quang Nguyen -* @date (last) 26-Aug-2020 +* @author (last) Bill Bracken +* @date (last) 24-Oct-2022 * -* @author (original) Sean -* @date (original) 04-Apr-2020 +* @author (original) Sean +* @date (original) 04-Apr-2020 * ***************************************************************************/ - -#include - -#include "etpwm.h" -#include "mibspi.h" - -#include "FPGA.h" -#include "OperationModes.h" -#include "PIControllers.h" -#include "Pressures.h" -#include "ROPump.h" -#include "SystemCommMessages.h" -#include "TaskGeneral.h" -#include "TaskPriority.h" -#include "Timers.h" -#ifdef EMC_TEST_BUILD -#include "Heaters.h" -#endif -#ifdef ENABLE_DIP_SWITCHES -#include "Valves.h" -#endif - -/** - * @addtogroup ROPump - * @{ - */ - -// ********** 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 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. -// 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. -#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). - -/// 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_STATE_T; - -/// 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_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 ) - -// ********** private data ********** - -static RO_PUMP_STATE_T roPumpState = RO_PUMP_OFF_STATE; ///< Current state of RO pump controller state machine. -static U32 roPumpDataPublicationTimerCounter = 0; ///< RO pump data publication timer counter. -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. - +#include + +#include "etpwm.h" +#include "mibspi.h" + +#include "ConcentratePumps.h" +#include "FlowSensors.h" +#include "FPGA.h" +#include "InternalADC.h" +#include "NVDataMgmt.h" +#include "MessageSupport.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" +#include "PIControllers.h" +#include "Pressures.h" +#include "ROPump.h" +#include "SafetyShutdown.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "TaskPriority.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup ROPump + * @{ + */ + +// ********** 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 MAX_RO_PUMP_DUTY_CYCLE 0.99F ///< Max duty cycle. +#define MIN_RO_PUMP_DUTY_CYCLE 0.0F ///< 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_RAMP_UP_CONTROL_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the RO pump is controlled. +#define ROP_RAMP_UP_P_COEFFICIENT 0.22F ///< P term for RO pump ramp up to flow control. +#define ROP_FLOW_CONTROL_P_COEFFICIENT 0.4F ///< P term for RO pump flow control. +#define ROP_FLOW_CONTROL_I_COEFFICIENT 0.3F ///< I term for RO pump flow control. +#define ROP_MAX_PRESSURE_P_COEFFICIENT 0.01F ///< P term for RO pump max pressure control. +#define ROP_MAX_PRESSURE_I_COEFFICIENT 0.01F ///< I term for RO pump max pressure control. + +#define ROP_FLOW_TARGET_TOLERANCE 0.03F ///< Tolerance in between the target flow rate and the actual flow rate in percentage. +#define ROP_RAMP_DOWN_DUTY_CYCLE_RATIO 0.03F ///< Pump ramp down duty cycle ratio when the pressure higher than max defined. + +#define FLOW_SENSOR_ZERO_READING 0xFFFF ///< Flow sensor reading indicates zero flow (or flow lower than can be detected by sensor). + +#define FLOW_AVERAGE_MULTIPLIER ( 1.0F / (F32)FLOW_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. + +// The ADC to LPM factor is calculated using the following steps: +// 0.1 to 2 LPM range +// 110000 pulses/liter +// For 2 LPM => 2LPM x 110000 pulses/liter * 1 edges/pulse * 1 min/60 seconds = 3666.66 counts/sec => 272.72 microseconds => for 1 LPM = 136.36 counts +#define RO_FLOW_ADC_TO_LPM_FACTOR 272.72F ///< 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_SLOPE 0.1F ///< Slope of flow to PWM line equation. +#define ROP_FLOW_TO_PWM_INTERCEPT 0.0F ///< Intercept of flow to PWM line equation. + + /// Initial conversion factor from target flow rate to PWM duty cycle estimate. +#define ROP_FLOW_TO_PWM_DC(flow) ( ROP_FLOW_TO_PWM_SLOPE * flow + ROP_FLOW_TO_PWM_INTERCEPT ) +#define MAX_ALLOWED_FLOW_DEVIATION 0.1F ///< Max allowed deviation from target flow. +#define FLOW_OUT_OF_RANGE_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Flow out of range time out in counts. // TODO - changed to prevent alarms (initial value 12) +#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_PERSISTENT_INTERVAL MS_PER_SECOND ///< Maximum allowed time that the pressure can be very high. +#define MAX_ALLOWED_RAMP_UP_TIME ( 10 * MS_PER_SECOND ) ///< Maximum allowed ramp up time to a flow rate in ms. +#define ROP_PSI_TO_PWM_DC(p) ( 0.2F + ( (F32)((p) - 100) * 0.01F ) ) ///< Conversion factor from target PSI to PWM duty cycle estimate. +#define SAFETY_SHUTDOWN_TIMEOUT ( 3 * MS_PER_SECOND ) ///< RO pump safety shutdown activation timeout in ms. + +#define ROP_FEEDBACK_0_PCT_DUTY_CYCLE_VOLTAGE 2.51F ///< RO pump 0% duty cycle feedback voltage. +#define ROP_DUTY_CYCLE_OUT_OF_RANGE_TOLERANCE 0.05F ///< RO pump duty cycle out of range tolerance. +#define DATA_PUBLISH_COUNTER_START_COUNT 50 ///< Data publish counter start count. + +/// Enumeration of RO pump states. +typedef enum ROPump_States +{ + RO_PUMP_OFF_STATE = 0, ///< RO pump off state. + RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE, ///< RO pump ramp up to target flow rate state. + RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE, ///< RO pump control to target flow state. + RO_PUMP_CONTROL_TO_MAX_PRESSURE_STATE, ///< RO pump control to max 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. +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_T; + +// ********** private data ********** + +static RO_PUMP_STATE_T roPumpState; ///< Current state of RO pump controller state machine. +static U32 roPumpDataPublicationTimerCounter; ///< Used to schedule RO pump data publication to CAN bus. +static BOOL isROPumpOn; ///< RO pump is currently running. +static F32 roPumpPWMDutyCyclePct; ///< Initial RO pump PWM duty cycle. +static F32 roPumpDutyCyclePctSet; ///< Currently set RO pump PWM duty cycle. +static OVERRIDE_F32_T roPumpFeedbackDutyCyclePct = { 0, 0, 0, 0 }; ///< RO pump feedback duty cycle in percent. +static PUMP_CONTROL_MODE_T roPumpControlMode; ///< Requested RO pump control mode. +static F32 pendingROPumpCmdMaxPressure; ///< Delayed (pending) RO pump max pressure (in PSI) setting. +static F32 pendingROPumpCmdTargetFlow; ///< Delayed (pending) RO pump target flow rate (in mL/min) setting. +static U32 pendingROPumpCmdCountDown; ///< Delayed (pending) RO pump command count down timer (in task intervals). +static F32 targetROPumpFlowRateLPM; ///< Target RO flow rate (in L/min). +static F32 targetROPumpMaxPressure; ///< Target RO max allowed pressure (in PSI). 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 S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging. -static U32 flowFilterCounter = 0; ///< Flow filtering counter. - -static U32 roControlTimerCounter = 0; ///< Timer counter for perform control on RO pump. - -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. - -// ********** private function prototypes ********** - -static RO_PUMP_STATE_T handleROPumpOffState( void ); -static RO_PUMP_STATE_T handleROPumpControlToTargetState( void ); -static void setROPumpControlSignalPWM( 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. - * @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 ); -} - -/*********************************************************************//** - * @brief - * The setROPumpTargetPressure function sets a new target pressure 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 - *************************************************************************/ -BOOL setROPumpTargetPressure( U32 roPressure, PUMP_CONTROL_MODE_T mode ) -{ - BOOL result = FALSE; - - // verify pressure - if ( roPressure >= MIN_RO_PRESSURE && roPressure <= MAX_RO_PRESSURE ) - { - 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; - } - else // requested pressure out of range - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_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 - * @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 ); -} - -/*********************************************************************//** - * @brief - * The execROPumpMonitor function executes the RO Pump monitor. - * @details - * Inputs : flowFilterCounter - * Outputs : measuredROPumpPressure, measuredROFlowRateLPM - * @return none - *************************************************************************/ -void execROPumpMonitor( void ) -{ - U16 roFlowReading = getFPGAROPumpFlowRate(); - S32 roFlow = (S32)roFlowReading; - - // update sum for flow average calculation - measuredFlowReadingsSum += roFlow; - // filter every 250ms - if ( ++flowFilterCounter >= FLOW_SAMPLES_TO_AVERAGE ) - { - F32 avgROFlow = (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER; - - if ( ( avgROFlow == FLOW_SENSOR_ZERO_READING ) || ( measuredFlowReadingsSum == 0 ) ) - { - measuredROFlowRateLPM.data = 0.0; - } - else - { - measuredROFlowRateLPM.data = RO_FLOW_ADC_TO_LPM_FACTOR / avgROFlow; - } - measuredFlowReadingsSum = 0; - flowFilterCounter = 0; - } - - measuredROPumpPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); - - // 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 - * @return none - *************************************************************************/ -void execROPumpController( void ) -{ - switch ( roPumpState ) - { - case RO_PUMP_OFF_STATE: - roPumpState = handleROPumpOffState(); - break; - - case RO_PUMP_CONTROL_TO_TARGET_STATE: - roPumpState = handleROPumpControlToTargetState(); - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, 0, roPumpState ) // TODO - replace 1st param with s/w fault enum - roPumpState = RO_PUMP_OFF_STATE; - break; - } -} - -/*********************************************************************//** - * @brief - * The isROPumpOn function returns the status of RO pump. - * @details - * Inputs : none - * Outputs : none - * @return isROPumpOn - *************************************************************************/ -BOOL isReverseOsmosisPumpOn( void ) -{ - return isROPumpOn; -} - -/*********************************************************************//** - * @brief + RO_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish RO flow data to CAN bus. +static U32 roControlTimerCounter; ///< Determines when to perform control on RO pump. +static F32 roPumpOpenLoopTargetDutyCycle; ///< Target RO pump open loop PWM. +static F32 roVolumeL; ///< RO water generated in liters. +static U32 roPumpControlInterval; ///< RO pump Control interval. +static RO_PI_FLOW_PROFILES_T currentROPumpProfile; + +///< RO Pump flow profile table. +static PI_CONTROLLER_PROFILE_DATA_T roPIFlowProfiles[ NUM_OF_RO_PI_FLOW_PROFILES ] = +{ // Kp Ki uMin uMax Control Interval + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_FLUSH + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_GEN_IDLE + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_FILL + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_DRAIN + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_HEAT + { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE, ROP_CONTROL_INTERVAL }, ///< RO_PI_FLOW_PROFILE_OPEN_LOOP +};// Kp Ki uMin uMax Control Interval + +// ********** private function prototypes ********** + +static RO_PUMP_STATE_T handleROPumpOffState( void ); +static RO_PUMP_STATE_T handleROPumpRampUpToTargetFlowState( void ); +static RO_PUMP_STATE_T handleROPumpControlToTargetFlowState( void ); +static RO_PUMP_STATE_T handleROPumpControlToMaxPressureState( void ); +static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ); + +static F32 roPumpFlowToPWM( RO_PI_FLOW_PROFILES_T profileID, F32 targetFlow ); +static void setROPumpTargetDutyCycle( F32 duty ); +static void setROPumpControlSignalDutyCycle( F32 dutyCycle ); +static void stopROPump( void ); +static void publishROPumpData( void ); +static F32 getROFeedbackVoltage( void ); + +/*********************************************************************//** + * @brief + * The initROPump function initializes the RO Pump module. + * @details Inputs: roControlTimerCounter,roPumpOpenLoopTargetDutyCycle, + * roPumpPressureRunningSum, flowFilterCounter, flowVerificationCounter, + * roPumpState, roPumpControlMode, roPumpDataPublicationTimerCounter, rawFlowLP, + * roPumpPWMDutyCyclePct, roPumpDutyCyclePctSet, pendingROPumpCmdMaxPressure, + * pendingROPumpCmdTargetFlow, pendingROPumpCmdCountDown, targetROPumpMaxPressure, + * @details Outputs: none + * @return none + *************************************************************************/ +void initROPump( void ) +{ + stopROPump(); + + // Initialize RO pump PI controller to flow + initializePIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, MIN_RO_PUMP_DUTY_CYCLE, ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, + MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE ); + + // Initialize RO pump PI controller t maximum pressure + initializePIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, MIN_RO_PUMP_DUTY_CYCLE, ROP_MAX_PRESSURE_P_COEFFICIENT, ROP_MAX_PRESSURE_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( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, FLOW_OUT_OF_RANGE_TIME_OUT_MS, FLOW_OUT_OF_RANGE_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, FLOW_OUT_OF_RANGE_TIME_OUT_MS, FLOW_OUT_OF_RANGE_TIME_OUT_MS ); + + // Initialize the persistent alarm for max allowed pressure out of range + initPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL, + MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL ); + + // Initialize the persistent alarm for not turning off the pump + initPersistentAlarm( ALARM_ID_RO_PUMP_DUTY_CYCLE_OUT_OF_RANGE, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); + + // Initialize the variables + roControlTimerCounter = 0; + roPumpOpenLoopTargetDutyCycle = 0; + roPumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + roPumpState = RO_PUMP_OFF_STATE; + roPumpControlMode = NUM_OF_PUMP_CONTROL_MODES; + isROPumpOn = FALSE; + roPumpFeedbackDutyCyclePct.data = 0.0F; + roVolumeL = 0.0F; + targetROPumpFlowRateLPM = 0.0F; + roPumpPWMDutyCyclePct = 0.0F; + roPumpDutyCyclePctSet = 0.0F; + pendingROPumpCmdMaxPressure = 0.0F; + pendingROPumpCmdTargetFlow = 0.0F; + pendingROPumpCmdCountDown = 0; + targetROPumpMaxPressure = 0.0F; + roPumpControlInterval = ROP_CONTROL_INTERVAL; + currentROPumpProfile = RO_PI_FLOW_PROFILE_GEN_IDLE; +} + +/*********************************************************************//** + * @brief + * The setROPumpTargetFlowRate function sets a new target flow rate for the + * RO pump. + * @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 setROPumpTargetFlowRateLPM( F32 roFlowRate, U32 maxPressure ) +{ + BOOL result = FALSE; + + // 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 + targetROPumpMaxPressure = maxPressure; + targetROPumpFlowRateLPM = roFlowRate; + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + roPumpState = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; + // Get the initial guess of the duty cycle + roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( roFlowRate ); + roControlTimerCounter = 0; + isROPumpOn = TRUE; + 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_PRESSURE_SELECTED, maxPressure ) + } + } + // Requested flow rate is out of range + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, roFlowRate ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setROPumpTargetFlowRateDelayed function sets a new target flow rate for the + * RO pump to be set after given delay. + * @details Inputs: none + * @details Outputs: pendingROPumpCmdMaxPressure, pendingROPumpCmdTargetFlow, + * pendingROPumpCmdCountDown + * @param roFlowRate which is target RO flow rate + * @param maxPressure which is the maximum allowed pressure that the RO pump + * can reach + * @param delayMs delay duration (in ms) before RO pump started + * @return TRUE if new target flow rate is set successfully, FALSE if not + *************************************************************************/ +BOOL setROPumpTargetFlowRateDelayed( F32 roFlowRate, U32 maxPressure, U32 delayMs ) +{ + BOOL result = FALSE; + + // 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 ) ) + { + pendingROPumpCmdMaxPressure = (F32)maxPressure; + pendingROPumpCmdTargetFlow = roFlowRate; + pendingROPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; + 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_PRESSURE_SELECTED, maxPressure ) + } + } + // Requested flow rate is out of range + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, roFlowRate ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * 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 ) +{ + stopROPump(); + targetROPumpFlowRateLPM = 0.0F; + roPumpState = RO_PUMP_OFF_STATE; + roPumpPWMDutyCyclePct = 0.0F; + roPumpOpenLoopTargetDutyCycle = 0.0F; + roControlTimerCounter = 0; + isROPumpOn = FALSE; + targetROPumpMaxPressure = 0; + pendingROPumpCmdMaxPressure = 0.0F; + pendingROPumpCmdTargetFlow = 0.0F; + pendingROPumpCmdCountDown = 0; + resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, MIN_RO_PUMP_DUTY_CYCLE ); +} + +/*********************************************************************//** + * @brief + * The execROPumpMonitor function executes the RO pump monitor. The RO flow + * sensor is read, filtered, converted to L/min and calibrated. + * @details Inputs: measuredFlowReadingsSum, flowFilterCounter, + * measuredROFlowRateLPM, measuredROFlowRateLPM, roPumpState, + * flowOutOfRangeCounter, roPumpControlMode + * @details Outputs: measuredFlowReadingsSum, flowFilterCounter, + * measuredROFlowRateLPM, measuredROFlowRateLPM + * @return none + *************************************************************************/ +void execROPumpMonitor( void ) +{ + U32 roFlowReading = (U32)getFPGAROPumpFlowRate(); + F32 roFeedbackVoltage = getIntADCVoltageConverted( INT_ADC_RO_PUMP_FEEDBACK_DUTY_CYCLE ); + // 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 ? TRUE : FALSE ); + BOOL isDutyCylceOutOfRange = FALSE; + + checkPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, isPressureMax, actualPressure, MAX_ALLOWED_MEASURED_PRESSURE_PSI ); + + if ( ( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) > NEARLY_ZERO ) && ( VALVE_STATE_CLOSED == getValveStateName( VBF ) ) ) + { + // If the RO pump's flow is greater than zero, and the VBf valve is not open (like heat disinfect) it means RO water is being generated + // Add that water to the variable + roVolumeL += ( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) / ( SEC_PER_MIN * MS_PER_SECOND ) ) * TASK_PRIORITY_INTERVAL; + } + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_PUMP_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // To monitor the flow, the control mode must be in closed loop mode and the pump should be control to flow state + // If the pump is controlled to the maximum pressure, the flow might be different from the target flow for more than 10% + // but the pump is not able to achieve the flow. + if ( ( PUMP_CONTROL_MODE_CLOSED_LOOP == roPumpControlMode ) && ( RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE == roPumpState ) ) + { + F32 currentFlow = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + F32 targetFlow = getTargetROPumpFlowRateLPM(); + // The flow cannot be out of range for than 10% of the target flow + BOOL isFlowOutOfRange = ( fabs( 1.0F - ( currentFlow / targetFlow ) ) > MAX_ALLOWED_FLOW_DEVIATION ? TRUE : FALSE ); + // Figure out whether flow is out of range from which side + BOOL isFlowOutOfUpperRange = ( isFlowOutOfRange && ( currentFlow > targetFlow ) ? TRUE : FALSE ); + BOOL isFlowOutOfLowerRange = ( isFlowOutOfRange && ( currentFlow < targetFlow ) ? TRUE : FALSE ); + + checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, isFlowOutOfUpperRange, currentFlow, targetFlow ); + checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, isFlowOutOfLowerRange, currentFlow, targetFlow ); + } + else + { + checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, FALSE, 0.0F, 0.0F ); + checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, FALSE, 0.0F, 0.0F ); + } + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // The feedback voltage is on the 0V line so when the duty cycle is 0, the feedback is 2.5V + // The duty cycle is calculated by getting the 1 - (ratio of feedback / to the voltage at 0 percent duty cycle). + roPumpFeedbackDutyCyclePct.data = 1.0F - ( roFeedbackVoltage / ROP_FEEDBACK_0_PCT_DUTY_CYCLE_VOLTAGE ); + isDutyCylceOutOfRange = ( fabs( getROFeedbackVoltage() - roPumpDutyCyclePctSet ) > ROP_DUTY_CYCLE_OUT_OF_RANGE_TOLERANCE ? TRUE : FALSE ); + + checkPersistentAlarm( ALARM_ID_RO_PUMP_DUTY_CYCLE_OUT_OF_RANGE, isDutyCylceOutOfRange, getROFeedbackVoltage(), roPumpDutyCyclePctSet ); + + // Check if it the alarm has timed out and if the pump is supposed to be off but it is still on, activate the safety shutdown + if ( ( TRUE == isAlarmActive( ALARM_ID_RO_PUMP_DUTY_CYCLE_OUT_OF_RANGE ) ) && ( FALSE == isROPumpOn ) ) + { + activateSafetyShutdown(); + } + } + } + + // Publish RO pump data on interval + publishROPumpData(); +} + +/*********************************************************************//** + * @brief + * The execROPumpController function executes the RO pump controller. + * @details Inputs: roPumpState + * @details Outputs: roPumpState + * @return none + *************************************************************************/ +void execROPumpController( void ) +{ + // Handle pending delayed RO pump command + if ( pendingROPumpCmdCountDown > 0 ) + { + pendingROPumpCmdCountDown--; + if ( 0 == pendingROPumpCmdCountDown ) + { + targetROPumpMaxPressure = pendingROPumpCmdMaxPressure; + targetROPumpFlowRateLPM = pendingROPumpCmdTargetFlow; + pendingROPumpCmdMaxPressure = 0.0F; + pendingROPumpCmdTargetFlow = 0.0F; + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + roPumpState = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; + // Get the initial guess of the duty cycle + roPumpPWMDutyCyclePct = roPumpFlowToPWM( currentROPumpProfile, targetROPumpFlowRateLPM ); + roControlTimerCounter = 0; + isROPumpOn = TRUE; + } + } + + // Execute RO pump control state machine + switch ( roPumpState ) + { + case RO_PUMP_OFF_STATE: + roPumpState = handleROPumpOffState(); + break; + + case RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE: + roPumpState = handleROPumpRampUpToTargetFlowState(); + break; + + case RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE: + roPumpState = handleROPumpControlToTargetFlowState(); + break; + + case RO_PUMP_CONTROL_TO_MAX_PRESSURE_STATE: + roPumpState = handleROPumpControlToMaxPressureState(); + break; + + case RO_PUMP_OPEN_LOOP_STATE: + roPumpState = handleROPumpOpenLoopState(); + break; + + default: + 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 execROPumpSelfTest function executes the RO pump's self-test. + * @details Inputs: none + * @details Outputs: none + * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execROPumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + // TODO is there anything else needed in POST for the RO pump? + + return result; +} + +/*********************************************************************//** + * @brief + * The isROPumpRunning 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 isROPumpRunning( void ) +{ + return isROPumpOn; +} + +/*********************************************************************//** + * @brief + * The getTargetROPumpFlowRateLPM function gets the current target RO pump + * flow rate. + * @details Inputs: targetROPumpFlowRateLPM + * @details Outputs: none + * @return the current target RO flow rate (in L/min). + *************************************************************************/ +F32 getTargetROPumpFlowRateLPM( void ) +{ + return targetROPumpFlowRateLPM; +} + +/*********************************************************************//** + * @brief + * The getTargetROPumpPressurePSI function gets the current target RO pump + * pressure. + * @details Inputs: none + * @details Outputs: targetROPumpMaxPressure + * @return the current target RO pump pressure in psi. + *************************************************************************/ +F32 getTargetROPumpPressurePSI( void ) +{ + return targetROPumpMaxPressure; +} + +/*********************************************************************//** + * @brief + * The getROGeneratedVolumeL function returns the RO generated volume in liters. + * @details Inputs: none + * @details Outputs: roVolumeL + * @return the RO generated volume in liters + *************************************************************************/ +F32 getROGeneratedVolumeL( void ) +{ + return roVolumeL; +} + +/*********************************************************************//** + * @brief + * The getROFeedbackVoltage function returns the RO pump feedback + * voltage. + * @details Inputs: roPumpFeedbackDutyCyclePct + * @details Outputs: none + * @return ro pump voltage feedback + *************************************************************************/ +static F32 getROFeedbackVoltage( void ) +{ + F32 feedbackVotlage = getF32OverrideValue( &roPumpFeedbackDutyCyclePct ); + + return feedbackVotlage; +} + +/*********************************************************************//** + * @brief + * The resetROGenerateVolumeL function resets the RO generated volume in liters. + * @details Inputs: none + * @details Outputs: roVolumeL + * @return none + *************************************************************************/ +void resetROGenerateVolumeL( void ) +{ + roVolumeL = 0.0F; +} + +/*********************************************************************//** + * @brief * The handleROPumpOffState function handles the RO pump off state of the - * RO pump controller state machine. - * @details - * Inputs : targetROPumpPressure - * Outputs : roPumpPWMDutyCyclePctSet, isROPumpOn - * @return next state - *************************************************************************/ -static RO_PUMP_STATE_T handleROPumpOffState( void ) -{ - RO_PUMP_STATE_T result = RO_PUMP_OFF_STATE; - -#ifdef DEBUG_ENABLED -#ifdef ENABLE_DIP_SWITCHES - // TODO - test code - remove later - if ( GET_DIP_SW0_TEST() ) - { - setValveState( VSP, VALVE_STATE_CLOSED ); - setValveState( VPI, VALVE_STATE_OPEN ); - 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 ); -#ifdef EMC_TEST_BUILD - { - F32 fanPWM = 0.25; - etpwmSetCmpA( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); - etpwmSetCmpB( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); - setPrimaryHeaterTargetTemperature( 50.0 ); - startPrimaryHeater(); - } -#endif - } -#endif -#endif - - // if we've been given a pressure, transition to control to target state - if ( getTargetROPumpPressure() > 0 ) - { - roPumpControlModeSet = roPumpControlMode; - // set initial PWM duty cycle - roPumpPWMDutyCyclePctSet = roPumpPWMDutyCyclePct; - setROPumpControlSignalPWM( roPumpPWMDutyCyclePctSet ); - // reset controller - resetPIController( PI_CONTROLLER_ID_RO_PUMP, roPumpPWMDutyCyclePctSet ); - // set pump to on - isROPumpOn = TRUE; - result = RO_PUMP_CONTROL_TO_TARGET_STATE; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleROPumpControlToTargetState function handles the "control to - * target" state of the RO pump controller state machine. - * @details - * Inputs : none - * Outputs : roPumpState - * @return next state - *************************************************************************/ -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; - -#ifndef EMC_TEST_BUILD - newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, tgtPres, actPres ); - roPumpPWMDutyCyclePctSet = newPWM; - setROPumpControlSignalPWM( newPWM ); -#endif - } - roControlTimerCounter = 0; - } - -#ifdef DEBUG_ENABLED -#ifdef ENABLE_DIP_SWITCHES - // TODO - test code - remove later - if ( !GET_DIP_SW0_TEST() ) - { - signalROPumpHardStop(); - result = RO_PUMP_OFF_STATE; -#ifdef EMC_TEST_BUILD - etpwmSetCmpA( etpwmREG6, 0 ); - etpwmSetCmpB( etpwmREG6, 0 ); - stopPrimaryHeater(); -#endif - } -#endif -#endif - - 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 - * @return none - *************************************************************************/ -static void setROPumpControlSignalPWM( F32 newPWM ) -{ - etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( newPWM * (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 - * @return none - *************************************************************************/ -static void stopROPump( void ) -{ - isROPumpOn = FALSE; - roPumpPWMDutyCyclePctSet = 0.0; - etpwmSetCmpB( etpwmREG2, 0 ); -} - -/*********************************************************************//** - * @brief - * The getPublishROPumpDataInterval function gets the RO pump data publish interval. - * @details - * Inputs : roPumpDataPublishInterval - * Outputs : none - * @return the current RO pump data publication interval (in ms). - *************************************************************************/ -static U32 getPublishROPumpDataInterval( void ) -{ - U32 result = roPumpDataPublishInterval.data; - - if ( OVERRIDE_KEY == roPumpDataPublishInterval.override ) - { - result = roPumpDataPublishInterval.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The getTargetROPumpPressure function gets the current target RO pump pressure. - * @details - * Inputs : targetROPumpPressure - * Outputs : none - * @return the current target RO pressure (in PSI). - *************************************************************************/ -U32 getTargetROPumpPressure( void ) -{ - U32 result = targetROPumpPressure.data; - - if ( OVERRIDE_KEY == targetROPumpPressure.override ) - { - result = targetROPumpPressure.ovData; - } - - return result; -} - -/*********************************************************************//** - * @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). - *************************************************************************/ -F32 getMeasuredROFlowRate( void ) -{ - F32 result = measuredROFlowRateLPM.data; - - if ( OVERRIDE_KEY == measuredROFlowRateLPM.override ) - { - result = measuredROFlowRateLPM.ovData; - } - - return result; -} - -/*********************************************************************//** - * @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. - * @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 ); - 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 - *************************************************************************/ + * controller state machine. + * @details Inputs: roPumpControlMode, roPumpPWMDutyCyclePctSet, + * roPumpOpenLoopTargetDutyCycle + * @details Outputs: roPumpPWMDutyCyclePct, setupROPumpControl, isROPumpOn + * @return next state of the controller state machine + *************************************************************************/ +static RO_PUMP_STATE_T handleROPumpOffState( void ) +{ + RO_PUMP_STATE_T state = RO_PUMP_OFF_STATE; - -/*********************************************************************//** - * @brief - * 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) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetROPumpDataPublishIntervalOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - U32 intvl = value / TASK_PRIORITY_INTERVAL; - - 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 - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetROPumpDataPublishIntervalOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - roPumpDataPublishInterval.override = OVERRIDE_RESET; - roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetTargetROPumpPressureOverride function overrides the target - * RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure - * @param value override target RO pressure (in PSI) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetTargetROPumpPressureOverride( U32 value ) -{ - 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 ); - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetTargetROPumpPressureOverride function resets the override of the - * target RO pressure. - * @details - * Inputs : none - * Outputs : targetROPumpPressure - * @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 - * RO flow rate. - * @details - * Inputs : none - * Outputs : measuredROFlowRateLPM - * @param value override measured RO pump motor speed (in LPM) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetMeasuredROFlowRateOverride( F32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - 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 - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testResetMeasuredROFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - measuredROFlowRateLPM.override = OVERRIDE_RESET; - measuredROFlowRateLPM.ovData = measuredROFlowRateLPM.ovInitData; - } - - return result; -} + // If there is a flow, transition to the PI controller to get the corresponding pressure of that flow + if ( getTargetROPumpFlowRateLPM() > 0.0F && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + { + // Set pump to on + isROPumpOn = TRUE; + roPumpDutyCyclePctSet = roPumpFlowToPWM( currentROPumpProfile, getTargetROPumpFlowRateLPM() ); + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + state = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_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.0F && roPumpControlMode == PUMP_CONTROL_MODE_OPEN_LOOP ) + { + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); + isROPumpOn = TRUE; + state = RO_PUMP_OPEN_LOOP_STATE; + } + return state; +} + +/*********************************************************************//** + * @brief + * The handleROPumpRampUpToTargetFlowState function handles the RO pump + * ramp up to flow 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 handleROPumpRampUpToTargetFlowState( void ) +{ + RO_PUMP_STATE_T state = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; + + // Get the current pressure from the sensor + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + F32 targetFlowRate = getTargetROPumpFlowRateLPM(); + F32 actualFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + F32 flowRateDeviation = fabs( targetFlowRate - actualFlowRate ) / targetFlowRate; + BOOL isFlowOutOfRange = flowRateDeviation > ROP_FLOW_TARGET_TOLERANCE; + F32 targetPressure = getTargetROPumpPressurePSI(); + + if ( ++roControlTimerCounter >= ROP_RAMP_UP_CONTROL_INTERVAL ) + { + // 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 > targetPressure ) || ( ( targetPressure - actualPressure ) < MAX_PRESSURE_TARGET_TOLERANCE ) ) + { + resetPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, roPumpDutyCyclePctSet ); + state = RO_PUMP_CONTROL_TO_MAX_PRESSURE_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 ( TRUE == isFlowOutOfRange ) + { + roPumpDutyCyclePctSet += ( targetFlowRate - actualFlowRate ) * ROP_RAMP_UP_P_COEFFICIENT; + // If the duty cycle is out of the define range for the RO pump, set the boundaries + roPumpDutyCyclePctSet = roPumpDutyCyclePctSet < MIN_RO_PUMP_DUTY_CYCLE ? MIN_RO_PUMP_DUTY_CYCLE : roPumpDutyCyclePctSet; + roPumpDutyCyclePctSet = roPumpDutyCyclePctSet > MAX_RO_PUMP_DUTY_CYCLE ? MAX_RO_PUMP_DUTY_CYCLE : roPumpDutyCyclePctSet; + + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + } + // Reached to the target flow go to the next state + else + { + resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet ); + state = RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE; + } + + roControlTimerCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleROPumpControlToTargetFlowState function handles the control to + * target flow state of the RO pump controller state machine. + * @details Inputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter + * @details Outputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter + * @return next state of the controller state machine + *************************************************************************/ +static RO_PUMP_STATE_T handleROPumpControlToTargetFlowState( void ) +{ + RO_PUMP_STATE_T state = RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE; + + // Control at set interval + if ( ++roControlTimerCounter >= roPumpControlInterval && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + { + // Get the pressure to use it for setting the control + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + if ( actualPressure >= targetROPumpMaxPressure ) + { + resetPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, roPumpDutyCyclePctSet ); + state = RO_PUMP_CONTROL_TO_MAX_PRESSURE_STATE; + } + else + { + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRateLPM(), getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) ); + } + + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + + roControlTimerCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleROPumpControlToMaxPressureState function handles the control + * to max pressure state of the RO pump controller state machine. + * @details Inputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter + * @details Outputs: roPumpPWMDutyCyclePctSet, roControlTimerCounter + * @return next state of the controller state machine + *************************************************************************/ +static RO_PUMP_STATE_T handleROPumpControlToMaxPressureState( void ) +{ + RO_PUMP_STATE_T state = RO_PUMP_CONTROL_TO_MAX_PRESSURE_STATE; + + // Get the pressure to use it for setting the control + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + // Control at set interval + if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + { + if ( actualPressure > targetROPumpMaxPressure ) + { + roPumpDutyCyclePctSet -= ROP_RAMP_DOWN_DUTY_CYCLE_RATIO; + resetPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, roPumpDutyCyclePctSet ); + } + else + { + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, getTargetROPumpFlowRateLPM(), getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) ); + } + + setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); + + roControlTimerCounter = 0; + } + + // Check if the actual pressure is out of tolerance from max pressure. + // If it is out, go back to ramp up state and to try to reach to target flow again + if ( ( targetROPumpMaxPressure - actualPressure ) > MAX_PRESSURE_TARGET_TOLERANCE ) + { + resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet ); + state = RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE; + + roControlTimerCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @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 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; + + // Set the new duty cycle of the pump + setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); +} + +/*********************************************************************//** + * @brief + * 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 setROPumpControlSignalDutyCycle( F32 dutyCycle ) +{ + etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( dutyCycle * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); +} + +/*********************************************************************//** + * @brief + * 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; + roPumpDutyCyclePctSet = 0.0; + etpwmSetCmpB( etpwmREG2, 0 ); +} + +/*********************************************************************//** + * @brief + * 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 >= getU32OverrideValue( &roPumpDataPublishInterval ) ) + { + RO_PUMP_DATA_T pumpData; + + pumpData.roPumpTgtFlowRateLPM = getTargetROPumpFlowRateLPM(); + pumpData.roPumpTgtPressurePSI = getTargetROPumpPressurePSI(); + pumpData.roPumpDutyCycle = roPumpDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; + pumpData.roMeasFlowRateLPM = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + pumpData.roPumpState = (U32)roPumpState; + pumpData.roPumpFBDutyCycle = getROFeedbackVoltage() * FRACTION_TO_PERCENT_FACTOR; + + broadcastData( MSG_ID_RO_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&pumpData, sizeof( RO_PUMP_DATA_T ) ); + roPumpDataPublicationTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The setROPIFlowProfile function sets the RO flow PI controller to new coefficients + * and calculates the initial duty cycle. + * @details Inputs: targetROPumpFlowRateLPM + * @details Outputs: roPumpControlInterval, currentROPumpProfile + * @param profileID the ID for which flow profile to be used + * @return none + *************************************************************************/ +void setROPIFlowProfile( RO_PI_FLOW_PROFILES_T profileID ) +{ + F32 initialControlDutyCycle; + + if ( profileID < NUM_OF_RO_PI_FLOW_PROFILES ) + { + roPumpControlInterval = roPIFlowProfiles[ profileID ].controlInterval; + initialControlDutyCycle = roPumpFlowToPWM( profileID, (getTargetROPumpFlowRateLPM()) ); + + initializePIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, initialControlDutyCycle, + roPIFlowProfiles[ profileID ].Kp, roPIFlowProfiles[ profileID ].Ki, + roPIFlowProfiles[ profileID ].uMin, roPIFlowProfiles[ profileID ].uMax ); + + currentROPumpProfile = profileID; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PI_PROFILE_SELECTED, profileID ) + } +} + +/*********************************************************************//** + * @brief + * The roPumpFlowToPWM function calculates the duty cycle for the given target + * flow in relation to which PI profile has been selected. + * @details Inputs: none + * @details Outputs: dutyCyclePct + * @param profileID the ID for which flow profile to be used + * targetFlow the flow as a parameter for the conversion calculation + * @return dutyCyclePct, the duty cycle for the given flow + *************************************************************************/ +static F32 roPumpFlowToPWM( RO_PI_FLOW_PROFILES_T profileID, F32 targetFlow ) +{ + F32 dutyCyclePct = 0; + if ( profileID < NUM_OF_RO_PI_FLOW_PROFILES ) + { + switch( profileID ) + { + case RO_PI_FLOW_PROFILE_FLUSH: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + case RO_PI_FLOW_PROFILE_GEN_IDLE: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + case RO_PI_FLOW_PROFILE_FILL: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + case RO_PI_FLOW_PROFILE_DRAIN: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + case RO_PI_FLOW_PROFILE_HEAT: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + default: + dutyCyclePct = ROP_FLOW_TO_PWM_DC( targetFlow ); + break; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PI_PROFILE_SELECTED, profileID ) + } + return dutyCyclePct; +} + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetROPumpDataPublishIntervalOverride function overrides the + * RO pump data publish interval. + * @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 ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_PRIORITY_INTERVAL; + roPumpDataPublishInterval.ovData = intvl; + roPumpDataPublishInterval.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * 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 ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + roPumpDataPublishInterval.override = OVERRIDE_RESET; + roPumpDataPublishInterval.ovData = roPumpDataPublishInterval.ovInitData; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetTargetROPumpFlow 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 testSetTargetROPumpFlow( F32 flow ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // The flow rate and pressure must be in range + if ( ( flow <= MAX_RO_FLOWRATE_LPM ) && ( flow >= MIN_RO_FLOWRATE_LPM ) ) + { + result = setROPumpTargetFlowRateLPM( flow, MAX_ALLOWED_PRESSURE_PSI ); + } + + // If the flow is less than a very small number, it means 0 LPM flow rate has been requested + // and this is coming from Dialin so the user requested the pump to stop + if ( fabs( flow ) < NEARLY_ZERO ) + { + signalROPumpHardStop(); + result = TRUE; + } + } + + 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 ) + { + targetROPumpMaxPressure = value; + result = TRUE; + } + } + + 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; +} + +/*********************************************************************//** + * @brief + * The testSetDrainPumpMeasuredRPMOverride function overrides the drain pump + * measured RPM data. + * @details Inputs: none + * @details Outputs: drainPumpMeasuredRPM + * @param value override drain pump measured data + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetROPumpMeasuredFeedbackVoltageOverride( F32 value ) +{ + BOOL status = FALSE; + + // Check if the requested drain pump RPM is within range + if ( ( value >= MIN_RO_PUMP_DUTY_CYCLE ) && ( value <= MAX_RO_PUMP_DUTY_CYCLE ) ) + { + // Check if the user is logged in + if ( TRUE == isTestingActivated() ) + { + roPumpFeedbackDutyCyclePct.ovData = value; + roPumpFeedbackDutyCyclePct.override = OVERRIDE_KEY; + status = TRUE; + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The testResetDrainPumpMeasuredRPMOverride function resets the drain pump + * measured RPM data. + * @details Inputs: none + * @details Outputs: drainPumpMeasuredRPM + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetROPumpMeasuredFeedbackVoltageOverride( void ) +{ + BOOL status = FALSE; + + // Check if the user is logged in + if ( TRUE == isTestingActivated() ) + { + roPumpFeedbackDutyCyclePct.ovData = roPumpFeedbackDutyCyclePct.ovInitData; + roPumpFeedbackDutyCyclePct.override = OVERRIDE_RESET; + status = TRUE; + } + + return status; +} + /**@}*/