Index: firmware/App/Modes/ModeGenPermeate.c =================================================================== diff -u -r6a318f2db61c3567fceea2c1963e0b02d90c8aee -r3475e61837973cd54b99c24fce8e6085d340aad2 --- firmware/App/Modes/ModeGenPermeate.c (.../ModeGenPermeate.c) (revision 6a318f2db61c3567fceea2c1963e0b02d90c8aee) +++ firmware/App/Modes/ModeGenPermeate.c (.../ModeGenPermeate.c) (revision 3475e61837973cd54b99c24fce8e6085d340aad2) @@ -25,6 +25,7 @@ #include "ModeGenPermeate.h" #include "ModePreGenPermeate.h" #include "PermeateTank.h" +#include "PIControllers.h" #include "ROPump.h" #include "TaskGeneral.h" #include "Timers.h" @@ -40,12 +41,23 @@ #define PRE_GEN_PERMEATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen permeate mode data published. #define GEN_PERMEATE_BOOST_PUMP_TGT_PSI 25.0F ///< Pressure target in PSI for the boost pump during generate permeate mode. #define GEN_PERMEATE_RO_PUMP_TGT_ML 750 ///< Flow target in ml/min for the ro pump during generate permeate mode. +#define PUMP_REST_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< Verify Water timer ( in ms ) // ********** private data ********** static FP_GENP_MODE_STATE_T genPermeateState; ///< Currently active generate Permeate state. static U32 genPermeateDataPublicationTimerCounter; ///< Used to schedule generate Permeate data publication to CAN bus. static OVERRIDE_U32_T genPermeateDataPublishInterval; ///< Generate permeate mode data publish interval. +static F32 fillDutySum; ///< Sum of duty cycle values for one fill cycle. +static U32 fillDutyCount; ///< Sample counts for one fill cycle. +static F32 prevFillAvgDutyCycle; ///< Average vale of duty cycle during previous fill state. +static BOOL isFillAvgValid; ///< Flag to check if the average fill duty cycle value is valid or not. +static F32 fullDutySum; ///< Sum of duty cycle values for one full cycle. +static U32 fullDutyCount; ///< Sample counts for one full cycle. +static F32 prevFullAvgDutyCycle; ///< Average vale of duty cycle during previous full state. +static BOOL isFullAvgValid; ///< Flag to check if the average full duty cycle value is valid or not. +static U32 waitTimeAfterReset; ///< Time to wait after reset before starting close loop control (temporary) +static BOOL stateTransitioned; ///< // ********** private function prototypes ********** @@ -54,6 +66,10 @@ static FP_GENP_MODE_STATE_T handleGenPTankFillState( void ); static void setModeGenPTransition( FP_GENP_MODE_STATE_T state ); static U32 getGenPermeateDataPublishInterval( void ); +//static void startTankFillState( void ); +//static void startTankFullState( void ); +static void updateDutyCycleAvg( FP_GENP_MODE_STATE_T state ); +static void calculateDutyCycleAvg( FP_GENP_MODE_STATE_T state ); /*********************************************************************//** * @brief @@ -70,6 +86,17 @@ genPermeateDataPublishInterval.ovInitData = 0; genPermeateDataPublishInterval.override = OVERRIDE_RESET; genPermeateDataPublicationTimerCounter = 0; + fillDutySum = 0.0F; + fillDutyCount = 0; + prevFillAvgDutyCycle = 0.0F; + isFillAvgValid = FALSE; + fullDutySum = 0.0F; + fullDutyCount = 0; + prevFullAvgDutyCycle = 0.0F; + isFullAvgValid = FALSE; + waitTimeAfterReset = 0; + stateTransitioned = FALSE; + } /*********************************************************************//** @@ -107,10 +134,12 @@ switch ( genPermeateState ) { case FP_GENP_TANK_FILL_STATE: + updateDutyCycleAvg( FP_GENP_TANK_FILL_STATE ); genPermeateState = handleGenPTankFillState(); break; case FP_GENP_TANK_FULL_STATE: + updateDutyCycleAvg( FP_GENP_TANK_FULL_STATE ); genPermeateState = handleGenPTankFullState(); break; @@ -122,6 +151,8 @@ if ( prevState != genPermeateState ) { + stateTransitioned = TRUE; + calculateDutyCycleAvg( prevState ); setModeGenPTransition( genPermeateState ); SEND_EVENT_WITH_2_U32_DATA( FP_EVENT_GENP_CHANGE, genPermeateState, prevState ) } @@ -142,17 +173,24 @@ *************************************************************************/ static void setModeGenPTransition( FP_GENP_MODE_STATE_T state ) { + F32 initDutyCycle = 0.0F; // Execute on running state switch( state ) { case FP_GENP_TANK_FILL_STATE: + initDutyCycle = isFillAvgValid ? prevFillAvgDutyCycle : 0.70F; + setROPumpTargetDutyCycle( initDutyCycle, TRUE ); + waitTimeAfterReset = getMSTimerCount(); if ( TRUE == isBoostPumpInstalled() ) { setBoostPumpTargetPressure( GEN_PERMEATE_BOOST_PUMP_TGT_PSI ); } break; case FP_GENP_TANK_FULL_STATE: + initDutyCycle = isFullAvgValid ? prevFullAvgDutyCycle : getTargetROPumpDutyCyclePCT(); + setROPumpTargetDutyCycle( initDutyCycle, TRUE ); + waitTimeAfterReset = getMSTimerCount(); if ( TRUE == isBoostPumpInstalled() ) { signalBoostPumpHardStop(); @@ -176,7 +214,13 @@ { FP_GENP_MODE_STATE_T state = FP_GENP_TANK_FILL_STATE; PERMEATE_TANK_STATE_T permemeateTankState = getPermeateTankState(); - + F32 initDutyCycle = isFillAvgValid ? prevFillAvgDutyCycle : 0.70F; // TODO - what value to start in initial cycle + if ( TRUE == didTimeout( waitTimeAfterReset, PUMP_REST_TIMEOUT_MS ) && stateTransitioned == TRUE ) + { + stateTransitioned = FALSE; + resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, initDutyCycle, 0.0F ); + setROPumpTargetFlowRateMLPM( GEN_PERMEATE_RO_PUMP_TGT_ML, TRUE ); + } if ( permemeateTankState == PERMEATE_TANK_FULL_STATE ) { state = FP_GENP_TANK_FULL_STATE; @@ -195,6 +239,13 @@ static FP_GENP_MODE_STATE_T handleGenPTankFullState( void ) { FP_GENP_MODE_STATE_T state = FP_GENP_TANK_FULL_STATE; + F32 initDutyCycle = isFullAvgValid ? prevFullAvgDutyCycle : getTargetROPumpDutyCyclePCT(); + if ( TRUE == didTimeout( waitTimeAfterReset, PUMP_REST_TIMEOUT_MS ) && stateTransitioned == TRUE ) + { + stateTransitioned = FALSE; + resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, initDutyCycle, 0.0F ); + setROPumpTargetFlowRateMLPM( GEN_PERMEATE_RO_PUMP_TGT_ML, TRUE ); + } PERMEATE_TANK_STATE_T permemeateTankState = getPermeateTankState(); if ( permemeateTankState == PERMEATE_TANK_FILL_STATE ) @@ -207,6 +258,59 @@ /*********************************************************************//** * @brief + * The updateDutyCycleAvg function accumulates duty cycle samples for + * states in generate permeate mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @param state genPermeateState enum + * @return none + *************************************************************************/ +static void updateDutyCycleAvg( FP_GENP_MODE_STATE_T state ) +{ + F32 duty = getCurrentROPumpDutyCyclePCT(); + if ( state == FP_GENP_TANK_FILL_STATE ) + { + fillDutySum += duty; + fillDutyCount++; + } + else if ( state == FP_GENP_TANK_FULL_STATE ) + { + fullDutySum += duty; + fullDutyCount++; + } + +} + +/*********************************************************************//** + * @brief + * The calculateDutyCycleAvg function computes the average duty cycle + * from the accumulated samples collected using updateDutyCyle. + * @details \b Inputs: none + * @details \b Outputs: none + * @param state genPermeateState enum + * @return none + *************************************************************************/ +static void calculateDutyCycleAvg( FP_GENP_MODE_STATE_T state ) +{ + if ( state == FP_GENP_TANK_FILL_STATE && fillDutyCount > 0) + { + prevFillAvgDutyCycle = fillDutySum / (F32)fillDutyCount; + isFillAvgValid = TRUE; + fillDutySum = 0.0F; + fillDutyCount = 0; + } + else if ( state == FP_GENP_TANK_FULL_STATE && fullDutyCount > 0 ) + { + prevFullAvgDutyCycle = fullDutySum / (F32)fullDutyCount; + isFullAvgValid = TRUE; + fullDutySum = 0.0F; + fullDutyCount = 0; + } + +} + +/*********************************************************************//** + * @brief * The getCurrentGenPermeateState function returns the current state of the * gen permeate mode. * @details \b Inputs: genPermeateState