Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r7104ce1a12799c5a3dff10c94cb191d409bc8244 -r29a9a5dbaf87d4ae86612c7ca8c27716f20d6381 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 7104ce1a12799c5a3dff10c94cb191d409bc8244) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 29a9a5dbaf87d4ae86612c7ca8c27716f20d6381) @@ -129,19 +129,19 @@ 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. +///< 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 -static DG_OP_MODE_T lastDGOperationMode; -static DG_OP_MODE_T currentDGOperationMode; - -static PI_CONTROLLER_PROFILE_DATA_T roFlushPIProfile = { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE }; -static PI_CONTROLLER_PROFILE_DATA_T roFillPIProfile = { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE }; -static PI_CONTROLLER_PROFILE_DATA_T roDrainPIProfile = { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE }; -static PI_CONTROLLER_PROFILE_DATA_T roHeatPIProfile = { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE }; -static PI_CONTROLLER_PROFILE_DATA_T roGenIdlePIProfile = { ROP_FLOW_CONTROL_P_COEFFICIENT, ROP_FLOW_CONTROL_I_COEFFICIENT, MIN_RO_PUMP_DUTY_CYCLE, MAX_RO_PUMP_DUTY_CYCLE }; - - - // ********** private function prototypes ********** static RO_PUMP_STATE_T handleROPumpOffState( void ); @@ -150,6 +150,7 @@ static RO_PUMP_STATE_T handleROPumpControlToMaxPressureState( void ); static RO_PUMP_STATE_T handleROPumpOpenLoopState( void ); +static F32 roPumpFlowToPWM( RO_PI_FLOW_PROFILES_T profileID ); static void setROPumpTargetDutyCycle( F32 duty ); static void setROPumpControlSignalDutyCycle( F32 dutyCycle ); static void stopROPump( void ); @@ -205,6 +206,7 @@ pendingROPumpCmdTargetFlow = 0.0F; pendingROPumpCmdCountDown = 0; targetROPumpMaxPressure = 0.0F; + roPumpControlInterval = ROP_CONTROL_INTERVAL; } /*********************************************************************//** @@ -649,7 +651,7 @@ RO_PUMP_STATE_T state = RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE; // Control at set interval - if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + 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 ); @@ -661,30 +663,6 @@ } else { - if(currentDGOperationMode != lastDGOperationMode) - { - switch( currentDGOperationMode ) - { - case DG_MODE_GENE: - setPIControlerProfile( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet, roGenIdlePIProfile); - break; - case DG_MODE_FILL: - setPIControlerProfile( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet, roFillPIProfile); - break; - case DG_MODE_DRAI: - setPIControlerProfile( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet, roDrainPIProfile); - break; - case DG_MODE_FLUS: - setPIControlerProfile( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet, roFlushPIProfile); - break; - case DG_MODE_HEAT: - setPIControlerProfile( PI_CONTROLLER_ID_RO_PUMP_FLOW, roPumpDutyCyclePctSet, roHeatPIProfile); - break; - default: - // Alarm? Fault? continue running? - break; - } - } roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRateLPM(), getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) ); } @@ -712,7 +690,7 @@ F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); // Control at set interval - if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + if ( ++roControlTimerCounter >= roPumpPressureControlInterval && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) { if ( actualPressure > targetROPumpMaxPressure ) { @@ -831,7 +809,78 @@ } } +/*********************************************************************//** + * @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 + * @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 ); + } + 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 *************************************************************************/ Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r0c296cef29037819be204c45a23d4d38a52b2718 -r29a9a5dbaf87d4ae86612c7ca8c27716f20d6381 --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 0c296cef29037819be204c45a23d4d38a52b2718) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 29a9a5dbaf87d4ae86612c7ca8c27716f20d6381) @@ -34,6 +34,19 @@ #define MAX_RO_FLOWRATE_LPM 1.8F ///< Maximum target RO flow rate in L/min. #define MIN_RO_FLOWRATE_LPM 0.0F ///< Minimum target RO flow rate in L/min. + +/// Enumerations of RO pump PI controller profiles. +typedef enum +{ + RO_PI_FLOW_PROFILE_FLUSH = 0, + RO_PI_FLOW_PROFILE_GEN_IDLE, + RO_PI_FLOW_PROFILE_FILL, + RO_PI_FLOW_PROFILE_DRAIN, + RO_PI_FLOW_PROFILE_HEAT, + RO_PI_FLOW_PROFILE_OPEN_LOOP, + NUM_OF_RO_PI_FLOW_PROFILES, +}RO_PI_FLOW_PROFILES_T; + /// RO pump data struct. typedef struct { @@ -63,6 +76,7 @@ F32 getROGeneratedVolumeL( void ); void resetROGenerateVolumeL( void ); +void setROPIFlowProfile( RO_PI_FLOW_PROFILES_T profileID ); BOOL testSetROPumpDataPublishIntervalOverride( U32 value ); BOOL testResetROPumpDataPublishIntervalOverride( void ); Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r0c296cef29037819be204c45a23d4d38a52b2718 -r29a9a5dbaf87d4ae86612c7ca8c27716f20d6381 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 0c296cef29037819be204c45a23d4d38a52b2718) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 29a9a5dbaf87d4ae86612c7ca8c27716f20d6381) @@ -140,6 +140,7 @@ SW_FAULT_ID_INVALID_FPGA_ERROR_GROUP_SELECTED, SW_FAULT_ID_INVALID_LED_COLOR_SELECTED, // 110 SW_FAULT_ID_INVALID_SWITCH_SELECTED, + SW_FAULT_ID_INVALID_PI_PROFILE_SELECTED, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/PIControllers.c =================================================================== diff -u -r7104ce1a12799c5a3dff10c94cb191d409bc8244 -r29a9a5dbaf87d4ae86612c7ca8c27716f20d6381 --- firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 7104ce1a12799c5a3dff10c94cb191d409bc8244) +++ firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 29a9a5dbaf87d4ae86612c7ca8c27716f20d6381) @@ -282,15 +282,4 @@ return output; } - -/* - * reset needs to be called. - */ - -void setPIControlerProfile( PI_CONTROLLER_ID_T controllerID, F32 initialControlSignal, PI_CONTROLLER_PROFILE_DATA_T profile) -{ - initializePIController(controllerID, initialControlSignal, - profile.Kp,profile.Ki,profile.uMin,profile.uMax); -} - /**@}*/ Index: firmware/App/Services/PIControllers.h =================================================================== diff -u -r7104ce1a12799c5a3dff10c94cb191d409bc8244 -r29a9a5dbaf87d4ae86612c7ca8c27716f20d6381 --- firmware/App/Services/PIControllers.h (.../PIControllers.h) (revision 7104ce1a12799c5a3dff10c94cb191d409bc8244) +++ firmware/App/Services/PIControllers.h (.../PIControllers.h) (revision 29a9a5dbaf87d4ae86612c7ca8c27716f20d6381) @@ -53,12 +53,15 @@ NUM_OF_CONTROLLER_SIGNAL ///< Number of PI controller signals } PI_CONTROLLER_SIGNALS_ID; + +/// Data structure for PI control profiles. typedef struct ControllerProfile { - F32 Kp; ///< Proportional Value. - F32 Ki; ///< Integral Value. - F32 uMin; ///< Minimum control signal. - F32 uMax; ///< Maximum control signal. + F32 Kp; ///< Proportional Value + F32 Ki; ///< Integral Value + F32 uMin; ///< Minimum control signal + F32 uMax; ///< Maximum control signal + U32 controlInterval; ///< Control interval value } PI_CONTROLLER_PROFILE_DATA_T; @@ -69,7 +72,6 @@ void resetPIController( PI_CONTROLLER_ID_T controllerID, F32 initialControlSignal ); F32 runPIController( PI_CONTROLLER_ID_T controllerID, F32 referenceSignal, F32 measuredSignal ); F32 getPIControllerSignals( PI_CONTROLLER_ID_T controllerID, PI_CONTROLLER_SIGNALS_ID signalID ); -void setPIControlerProfile( PI_CONTROLLER_ID_T controllerID, F32 initialControlSignal, PI_CONTROLLER_PROFILE_DATA_T profile); /**@}*/