Index: firmware/App/Modes/FlushConcentrate.c =================================================================== diff -u -r410afd26b3ae5e372310c696c82f58c59235e10d -r8d272582cbd2cb5fc0c6af0fead2867ce02658b0 --- firmware/App/Modes/FlushConcentrate.c (.../FlushConcentrate.c) (revision 410afd26b3ae5e372310c696c82f58c59235e10d) +++ firmware/App/Modes/FlushConcentrate.c (.../FlushConcentrate.c) (revision 8d272582cbd2cb5fc0c6af0fead2867ce02658b0) @@ -1 +1,395 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 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 FlushConcentrate.c +* +* @author (last) Michael Garthwaite +* @date (last) 28-Feb-2025 +* +* @author (original) Michael Garthwaite +* @date (original) 28-Feb-2025 +* +***************************************************************************/ + +#include + +#include "Conductivity.h" +#include "BoostPump.h" +#include "FlowSensor.h" +#include "FlushConcentrate.h" +#include "MessageSupport.h" +#include "Messaging.h" +#include "OperationModes.h" +#include "Pressure.h" +#include "ROPump.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup FPConcentrateFlush + * @{ + */ + +// ********** private definitions ********** + +#define CONCENTRATE_FLUSH_MAX_TIMEOUT ( 600 * MS_PER_SECOND ) ///< Max override timeout for 10 minutes +#define CONCENTRATE_FLUSH_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen water mode data published. +#define CONCENTRATE_FLUSH_TIMEOUT ( 30 * MS_PER_SECOND ) ///< Concentrate flush timer (in ms) +#define CONCENTRATE_FLUSH_RO_PUMP_TGT_PWM 0.8F ///< target in PWM % for the RO pump during concentrate flush. +#define CONCENTRATE_FLUSH_BOOST_PUMP_TGT_PSI 25 ///< Pressure target in PSI for the boost pump during concentrate flush. +#define CONCENTRATE_FLUSH_VOLUME_THRESHOLD_ML 1000.0F ///< Integrated volume threshold in ml +#define CONCENTRATE_FLUSH_VOLUME_THRESHOLD_PCT 0.9F ///< Integrated volume threshold percentage +#define CONCENTRATE_FLUSH_VOLUME_THRESHOLD CONCENTRATE_FLUSH_VOLUME_THRESHOLD_ML * CONCENTRATE_FLUSH_VOLUME_THRESHOLD_PCT ///< alarm threshold for integrated volume + +// ********** private data ********** +/// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. +static const F32 CONCENTRATE_FLOW_INTEGRATOR = 1.0F / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); +static FP_CONC_FLUSH_STATE_T concentrateFlushState; ///< Currently active Concentrate flush state. +static U32 concentrateFlushDataPublicationTimerCounter; ///< Used to schedule Concentrate flush data publication to CAN bus. +static OVERRIDE_U32_T concentrateFlushDataPublishInterval; ///< Concentrate Flush mode data publish interval. +static OVERRIDE_U32_T concentrateFlushTimeout; ///< Concentrate Flush timeout value +static U32 concentrateFlushTimer; ///< Concentrate Flush timeout timer +static BOOL pendingStartConcentrateFlushRequest; ///< signal to start flushing. +static BOOL isFlushComplete; ///< Concentrate Flush complete BOOL +static F32 cumulativeConcentrateVolume_mL; + +// ********** private function prototypes ********** + +static void publishConcentrateFlushData( void ); +static FP_CONC_FLUSH_STATE_T handleConcentrateFlushProgressState( void ); +static FP_CONC_FLUSH_STATE_T handleConcentrateFlushPausedState( void ); +static void setConcentrateFlushTransition( FP_CONC_FLUSH_STATE_T state ); +static U32 getConcentrateFlushTimeout( void ); +static U32 getConcentrateFlushPublishInterval( void ); + +/*********************************************************************//** + * @brief + * The initConcentrateFlush function initializes the Concentrate flush unit. + * @details \b Inputs: none + * @details \b Outputs: Concentrate flush unit initialized + * @return none + *************************************************************************/ +void initConcentrateFlush( void ) +{ + concentrateFlushState = CONC_FLUSH_PAUSED; + concentrateFlushDataPublishInterval.data = CONCENTRATE_FLUSH_DATA_PUBLISH_INTERVAL; + concentrateFlushDataPublishInterval.ovData = CONCENTRATE_FLUSH_DATA_PUBLISH_INTERVAL; + concentrateFlushDataPublishInterval.ovInitData = 0; + concentrateFlushDataPublishInterval.override = OVERRIDE_RESET; + concentrateFlushTimeout.data = CONCENTRATE_FLUSH_TIMEOUT; + concentrateFlushTimeout.ovData = CONCENTRATE_FLUSH_TIMEOUT; + concentrateFlushTimeout.ovInitData = 0; + concentrateFlushTimeout.override = OVERRIDE_RESET; + concentrateFlushDataPublicationTimerCounter = 0; + concentrateFlushTimer = 0; + isFlushComplete = FALSE; + pendingStartConcentrateFlushRequest = FALSE; + cumulativeConcentrateVolume_mL = 0.0F; +} + +/*********************************************************************//** + * @brief + * The execConcentrateFlush function executes the Concentrate flush state machine + * and publishes Concentrate flush data. + * @details \b Inputs: concentrateFlushState + * @details \b Outputs: concentrateFlushState + * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if in invalid flush state + * @return none + *************************************************************************/ +void execConcentrateFlush( void ) +{ + switch ( concentrateFlushState ) + { + case CONC_FLUSH_IN_PROGRESS: + concentrateFlushState = handleConcentrateFlushProgressState(); + break; + + case CONC_FLUSH_PAUSED: + concentrateFlushState = handleConcentrateFlushPausedState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_CONCENTRATE_FLUSH_STATE, (U32)concentrateFlushState ) + concentrateFlushState = CONC_FLUSH_PAUSED; + break; + } + + // publish Concentrate flush data on interval + publishConcentrateFlushData(); +} + +/*********************************************************************//** + * @brief + * The handleConcentrateFlushProgressState handles the in progress state of Concentrate flush + * @details \b Inputs: none + * @details \b Outputs: none + * @return the next state of Concentrate flush state + *************************************************************************/ +static FP_CONC_FLUSH_STATE_T handleConcentrateFlushProgressState( void ) +{ + FP_CONC_FLUSH_STATE_T state = CONC_FLUSH_IN_PROGRESS; + BOOL isVolumeOutOfRange = FALSE; + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setConcentrateFlushTransition( CONC_FLUSH_PAUSED ); + state = CONC_FLUSH_PAUSED; + } + + cumulativeConcentrateVolume_mL = getFlowRate(P7_FLOW) * CONCENTRATE_FLOW_INTEGRATOR; + + if( TRUE == didTimeout( concentrateFlushTimer, getConcentrateFlushTimeout() ) ) + { + + isVolumeOutOfRange = ( cumulativeConcentrateVolume_mL >= CONCENTRATE_FLUSH_VOLUME_THRESHOLD ? TRUE : FALSE ); + + if( FALSE == isVolumeOutOfRange ) + { + isFlushComplete = TRUE; + setConcentrateFlushTransition( CONC_FLUSH_PAUSED ); + state = CONC_FLUSH_PAUSED; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_CONCENTRATE_FLUSH_VOLUME_OUT_OF_RANGE, CONCENTRATE_FLUSH_VOLUME_THRESHOLD, cumulativeConcentrateVolume_mL) + setConcentrateFlushTransition( CONC_FLUSH_PAUSED ); + state = CONC_FLUSH_PAUSED; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleConcentrateFlushProgressState handles the in progress state of Concentrate flush + * @details \b Inputs: none + * @details \b Outputs: none + * @return the next state of Concentrate flush state + *************************************************************************/ +static FP_CONC_FLUSH_STATE_T handleConcentrateFlushPausedState( void ) +{ + FP_CONC_FLUSH_STATE_T state = CONC_FLUSH_PAUSED; + + if ( TRUE == pendingStartConcentrateFlushRequest ) + { + isFlushComplete = FALSE; + pendingStartConcentrateFlushRequest = FALSE; + setConcentrateFlushTransition( CONC_FLUSH_IN_PROGRESS ); + state = CONC_FLUSH_IN_PROGRESS; + } + return state; +} + +/*********************************************************************//** + * @brief + * The setConcentrateFlushTransition function sets the actuators and variables + * for the state transition in Concentrate flush mode. + * @details Inputs: Valve states, Pump speed + * @details Outputs: Actuate valves, pumps as desired. + * @param state Concentrate flush state enum + * @return none + *************************************************************************/ +static void setConcentrateFlushTransition( FP_CONC_FLUSH_STATE_T state ) +{ + // Execute on running state + switch( state ) + { + case CONC_FLUSH_IN_PROGRESS: + setValveState( M4_VALV, VALVE_STATE_OPEN ); + setValveState( P6_VALV, VALVE_STATE_CLOSED ); + setValveState( P11_VALV, VALVE_STATE_OPEN ); + setValveState( P33_VALV, VALVE_STATE_CLOSED ); + setValveState( P34_VALV, VALVE_STATE_CLOSED ); + setValveState( P37_VALV, VALVE_STATE_OPEN ); + setValveState( P39_VALV, VALVE_STATE_OPEN ); + + if ( TRUE == isBoostPumpInstalled() ) + { + setBoostPumpTargetPressure( CONCENTRATE_FLUSH_BOOST_PUMP_TGT_PSI ); + } + setROPumpTargetDutyCycle( CONCENTRATE_FLUSH_RO_PUMP_TGT_PWM ); + concentrateFlushTimer = getMSTimerCount(); + cumulativeConcentrateVolume_mL = 0; + break; + + case CONC_FLUSH_PAUSED: + + // Stop pumps and close only if we alarm ( pause ) during flush. + if ( FALSE == isConcentrateFlushComplete() ) + { + setValveState( M4_VALV, VALVE_STATE_CLOSED ); + setValveState( P6_VALV, VALVE_STATE_CLOSED ); + setValveState( P11_VALV, VALVE_STATE_CLOSED ); + setValveState( P33_VALV, VALVE_STATE_CLOSED ); + setValveState( P34_VALV, VALVE_STATE_CLOSED ); + setValveState( P37_VALV, VALVE_STATE_CLOSED ); + setValveState( P39_VALV, VALVE_STATE_CLOSED ); + + if ( TRUE == isBoostPumpInstalled() ) + { + signalBoostPumpHardStop(); + } + signalROPumpHardStop(); + } + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_CONCENTRATE_FLUSH_STATE, state ) + break; + } +} + +/*********************************************************************//** + * @brief + * The signalStartConcentrateFlush function signals the FP to start Concentrate flush. + * @details \b Inputs: none + * @details \b Outputs: pendingStartConcentrateFlushRequest + * @return the current state of Concentrate flush + *************************************************************************/ +void signalStartConcentrateFlush( void ) +{ + if ( CONC_FLUSH_PAUSED == getCurrentConcentrateFlushState() ) + { + pendingStartConcentrateFlushRequest = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The resetFilterFlushSignals function resets the signal values for + * FP filter flush. + * @details \b Inputs: none + * @details \b Outputs: pendingStartFilterFlushRequest, isFlushComplete + * @return none + *************************************************************************/ +void resetConcentrateFlushSignals( void ) +{ + pendingStartConcentrateFlushRequest = FALSE; + isFlushComplete = FALSE; +} + +/*********************************************************************//** + * @brief + * The getCurrentConcentrateFlushState function returns the current state of + * Concentrate flush. + * @details \b Inputs: concentrateFlushState + * @details \b Outputs: concentrateFlushState + * @return the current state of Concentrate flush + *************************************************************************/ +FP_CONC_FLUSH_STATE_T getCurrentConcentrateFlushState( void ) +{ + return concentrateFlushState; +} + +/*********************************************************************//** + * @brief + * The isConcentrateFlushComplete function returns isConcentrateFlushComplete. + * @details \b Inputs: none + * @details \b Outputs: none + * @return the complete boolean for Concentrate flush. + *************************************************************************/ +BOOL isConcentrateFlushComplete( void ) +{ + return isFlushComplete; +} + +/*********************************************************************//** + * @brief + * The getConcentrateFlushTimeout function gets the generate water + * mode data publish interval. + * @details \b Inputs: ConcentrateFlushTimeOut + * @details \b Outputs: none + * @return the timeout timer for Concentrate flush. + *************************************************************************/ +static U32 getConcentrateFlushTimeout( void ) +{ + U32 result = getU32OverrideValue( &concentrateFlushTimeout ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getConcentrateFlushPublishInterval function gets the Concentrate flush + * mode data publish interval. + * @details \b Inputs: concentrateFlushDataPublishInterval + * @details \b Outputs: none + * @return the interval at Concentrate flush mode data being published. + *************************************************************************/ +static U32 getConcentrateFlushPublishInterval( void ) +{ + U32 result = getU32OverrideValue( &concentrateFlushDataPublishInterval ); + + return result; +} + +/*********************************************************************//** + * @brief + * The publishConcentrateFlushData function broadcasts the Concentrate flush + * mode data at defined interval. + * @details \b Inputs: concentrateFlushDataPublicationTimerCounter + * @details \b Outputs: fp Concentrate flush data broadcast message sent + * @details \b Message \Sent: MSG_ID_FP_CONCENTRATE_FLUSH_DATA to publish the + * Concentrate flush mode data. + * @return none + *************************************************************************/ +static void publishConcentrateFlushData( void ) +{ + if ( ++concentrateFlushDataPublicationTimerCounter >= getConcentrateFlushPublishInterval() ) + { + CONC_FLUSH_DATA_T data; + + data.concentrateFlushExecState = (U32)getCurrentConcentrateFlushState(); + broadcastData( MSG_ID_FP_CONCENTRATE_FLUSH_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( CONC_FLUSH_DATA_T ) ); + + concentrateFlushDataPublicationTimerCounter = 0; + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testConcentrateFlushDataPublishIntervalOverride function overrides the + * FP Concentrate flush mode data publish interval. + * @details \b Inputs: concentrateFlushDataPublishInterval + * @details \b Outputs: concentrateFlushDataPublishInterval + * @param Override message from Dialin which includes the interval + * (in ms) to override the FP Concentrate flush data publish interval to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testConcentrateFlushDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &concentrateFlushDataPublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testConcentrateFlushTimerOverride function overrides the + * FP Concentrate flush timeout value. + * @details \b Inputs: concentrateFlushTimeout + * @details \b Outputs: concentrateFlushTimeout + * @param Override message from Dialin which includes the interval + * (in ms) to override the FP Concentrate flush timeout to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testConcentrateFlushTimerOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &concentrateFlushTimeout, 0, CONCENTRATE_FLUSH_MAX_TIMEOUT ); + + return result; +} + +/**@}*/