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 *************************************************************************/