Index: firmware/App/Controllers/PermeateTank.c =================================================================== diff -u --- firmware/App/Controllers/PermeateTank.c (revision 0) +++ firmware/App/Controllers/PermeateTank.c (revision 6e65344e6675394118806ce98dc428c27920e1cb) @@ -0,0 +1,428 @@ +/************************************************************************** +* +* Copyright (c) 2024-2025 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 PermeateTank.h +* +* @author (last) Michael Garthwaite +* @date (last) 03-Mar-2025 +* +* @author (original) Michael Garthwaite +* @date (original) 03-Mar-2025 +* +***************************************************************************/ + +#include "Level.h" +#include "MessageSupport.h" +#include "Messaging.h" +#include "ModeStandby.h" +#include "OperationModes.h" +#include "TaskGeneral.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup FPGenPermeateMode + * @{ + */ + +// ********** private definitions ********** + +#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. + +// ********** 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. + +// ********** private function prototypes ********** + +static void publishGenPModeData( void ); +static FP_GENP_MODE_STATE_T handleGenPTankFullState( void ); +static FP_GENP_MODE_STATE_T handleGenPTankFillState( void ); +static void setModeGenPTransition( FP_GENP_MODE_STATE_T state ); +static U32 getGenPermeateDataPublishInterval( void ); + +/*********************************************************************//** + * @brief + * The initGenPermeateMode function initializes the water generation mode unit. + * @details \b Inputs: none + * @details \b Outputs: Gen water mode unit initialized + * @return none + *************************************************************************/ +void initGenPermeateMode( void ) +{ + genPermeateState = FP_GENP_TANK_FILL_STATE; + genPermeateDataPublishInterval.data = PRE_GEN_PERMEATE_DATA_PUBLISH_INTERVAL; + genPermeateDataPublishInterval.ovData = PRE_GEN_PERMEATE_DATA_PUBLISH_INTERVAL; + genPermeateDataPublishInterval.ovInitData = 0; + genPermeateDataPublishInterval.override = OVERRIDE_RESET; + genPermeateDataPublicationTimerCounter = 0; + tankFullDelayTime = 0; + tankFullAlarmTimeout = 0; + pendingStartGenRequest = 0; + genPermeateRODutyCycle = 0.0F; + genPermeateBoostDutyCycle = 0.0F; +} + +/*********************************************************************//** + * @brief + * The transitionToGenPermeateMode function prepares for transition to gen + * permeate mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @return initial state + *************************************************************************/ +U32 transitionToGenPermeateMode( void ) +{ + initGenPermeateMode(); + setCurrentSubState( genPermeateState ); + setModeGenPTransition( genPermeateState ); + + // Setting RO pump pwm at the start instead of + // each transition to allow testing of different target control + // while in Gen Permeate + if ( 0.0F == getGenPermeateRODutyCycle() ) // we skipped verify water via dialin + { + setROPumpTargetDutyCycle( GEN_PERMEATE_PWM_DEFAULT ); + } + else + { + setROPumpTargetDutyCycle( getGenPermeateRODutyCycle() ); + } + return genPermeateState; +} + +/*********************************************************************//** + * @brief + * The execGenPermeateMode function executes the Gen Permeate mode state machine. + * @details \b Inputs: none + * @details \b Outputs: Gen Permeate mode state machine executed + * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT when wrong gen Permeate state invoked. + * @return current state. + *************************************************************************/ +U32 execGenPermeateMode( void ) +{ + FP_GENP_MODE_STATE_T prevState = genPermeateState; + + // execute current gen Permeate state + switch ( genPermeateState ) + { + case FP_GENP_TANK_FILL_STATE: + genPermeateState = handleGenPTankFillState(); + break; + + case FP_GENP_TANK_FULL_STATE: + genPermeateState = handleGenPTankFullState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_GENP_STATE, genPermeateState ) + break; + + } + + if ( prevState != genPermeateState ) + { + setModeGenPTransition( genPermeateState ); + SEND_EVENT_WITH_2_U32_DATA( FP_EVENT_GENP_CHANGE, genPermeateState, prevState ) + } + //Publish Gen Permeate mode data + publishGenPModeData(); + + return genPermeateState; +} + +/*********************************************************************//** + * @brief + * The setModeGenPTransition function sets the actuators and variables + * for the state transition in generate permeate mode. + * @details Inputs: Valve states, Pump speed + * @details Outputs: Actuate valves, pumps as desired. + * @param state gen permeate state enum + * @return none + *************************************************************************/ +static void setModeGenPTransition( FP_GENP_MODE_STATE_T state ) +{ + // Execute on running state + switch( state ) + { + case FP_GENP_TANK_FILL_STATE: + setValveState( M4_VALV,VALVE_STATE_OPEN ); + setValveState( P6_VALV,VALVE_STATE_CLOSED ); + setValveState( P11_VALV, VALVE_STATE_OPEN ); + setValveState( P33_VALV, VALVE_STATE_OPEN ); // TODO - Change valves to handle RO rejection config + setValveState( P34_VALV, VALVE_STATE_CLOSED ); // Current set to Medium recovery for alpha HW + setValveState( P37_VALV, VALVE_STATE_CLOSED ); + setValveState( P39_VALV,VALVE_STATE_OPEN ); + if ( TRUE == isBoostPumpInstalled() ) + { + setBoostPumpTargetPressure( GEN_PERMEATE_BOOST_PUMP_TGT_PSI ); + } + break; + + case FP_GENP_TANK_FULL_STATE: + setValveState( M4_VALV,VALVE_STATE_CLOSED ); + setValveState( P6_VALV,VALVE_STATE_CLOSED ); + setValveState( P11_VALV, VALVE_STATE_CLOSED ); + setValveState( P33_VALV, VALVE_STATE_OPEN ); + setValveState( P34_VALV, VALVE_STATE_CLOSED ); + setValveState( P37_VALV, VALVE_STATE_CLOSED ); + setValveState( P39_VALV,VALVE_STATE_OPEN ); + + if ( TRUE == isBoostPumpInstalled() ) + { + signalBoostPumpHardStop(); + } + tankFullDelayTime = getMSTimerCount(); + tankFullAlarmTimeout = getMSTimerCount(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_GENP_STATE, state ) + break; + } +} + +/*********************************************************************//** + * @brief + * The handleGenPTankFillState handles the fill state of gen water. + * @details \b Inputs: none + * @details \b Outputs: none + * @return the next state of gen water mode + *************************************************************************/ +static FP_GENP_MODE_STATE_T handleGenPTankFillState( void ) +{ + FP_GENP_MODE_STATE_T state = FP_GENP_TANK_FILL_STATE; + LEVEL_STATE_T level = getLevelStatus(); + + if ( LEVEL_STATE_HIGH == level ) + { + state = FP_GENP_TANK_FULL_STATE; + // save boost pump + if ( TRUE == isBoostPumpInstalled() ) + { + setGenPermeateBoostDutyCycle( getCurrentBoostPumpDutyCyclePCT() ); + SEND_EVENT_WITH_2_U32_DATA( FP_EVENT_GENP_BOOST_SET_PWM, getCurrentBoostPumpDutyCyclePCT(), getFluidPumpReadPWMDutyCycle( P40_PUMP ) ) + } + } + + else if ( level <= LEVEL_STATE_MEDIUM ) + { + // expected state. No action required. + // If level is low we still want to fill. + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleGenPTankFullState handles the full state of gen permeate. + * @details \b Inputs: stateDelayTime + * @details \b Outputs: none + * @return the next state of gen permeate mode + *************************************************************************/ +static FP_GENP_MODE_STATE_T handleGenPTankFullState( void ) +{ + FP_GENP_MODE_STATE_T state = FP_GENP_TANK_FULL_STATE; + LEVEL_STATE_T level = getLevelStatus(); + + if ( TRUE == didTimeout( tankFullAlarmTimeout, GEN_PERMEATE_TANK_FULL_TIMEOUT_MS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_FP_GEN_PERMEATE_TANK_FULL_TIMEOUT, level ) + } + + if ( ( ( level == LEVEL_STATE_MEDIUM ) && ( TRUE == didTimeout( tankFullDelayTime, GEN_PERMEATE_TANK_FULL_SWITCH_MS ) ) ) || + ( level == LEVEL_STATE_LOW ) ) + { + state = FP_GENP_TANK_FILL_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The getGenPermeateBoostDutyCycle function returns the current Boost pump pwm setting + * in gen permeate mode. + * @details \b Inputs: genPermeateBoostDutyCycle + * @details \b Outputs: genPermeateBoostDutyCycle + * @return the current pwm setting for the RO Pump + *************************************************************************/ +F32 getGenPermeateBoostDutyCycle( void ) +{ + return genPermeateBoostDutyCycle; +} + +/*********************************************************************//** + * @brief + * The setGenPermeateBoostDutyCycle function sets the Boost pump pwm in gen permeate + * mode + * @details \b Inputs: none + * @details \b Outputs: genPermeateBoostDutyCycle + * @return none + *************************************************************************/ +void setGenPermeateBoostDutyCycle( F32 duty) +{ + genPermeateBoostDutyCycle = duty; +} + +/*********************************************************************//** + * @brief + * The getGenPermeateRODutyCycle function returns the current pwm setting + * for the RO pump in gen permeate mode. + * @details \b Inputs: genPermeateRODutyCycle + * @details \b Outputs: genPermeateRODutyCycle + * @return the current pwm setting for the RO Pump + *************************************************************************/ +F32 getGenPermeateRODutyCycle( void ) +{ + return genPermeateRODutyCycle; +} + +/*********************************************************************//** + * @brief + * The setGenPermeateRODutyCycle function sets the RO PWM pump in gen permeate + * mode + * @details \b Inputs: none + * @details \b Outputs: genPermeateRODutyCycle + * @return none + *************************************************************************/ +void setGenPermeateRODutyCycle( F32 duty) +{ + genPermeateRODutyCycle = duty; +} + +/*********************************************************************//** + * @brief + * The getCurrentGenPermeateState function returns the current state of the + * gen permeate mode. + * @details \b Inputs: genPermeateState + * @details \b Outputs: genPermeateState + * @return the current state of gen permeate mode + *************************************************************************/ +FP_GENP_MODE_STATE_T getCurrentGenPermeateState( void ) +{ + return genPermeateState; +} + +/*********************************************************************//** + * @brief + * The getGenPermeateRequest function returns the current state of the + * gen permeate mode. + * @details \b Inputs: pendingStartGenRequest + * @details \b Outputs: none + * @return the current state of gen permeate request + *************************************************************************/ +BOOL getGenPermeateRequest( void ) +{ + return pendingStartGenRequest; +} + +/*********************************************************************//** + * @brief + * The getGenPermeateDataPublishInterval function gets the generate water + * mode data publish interval. + * @details \b Inputs: genPermeateDataPublishInterval + * @details \b Outputs: none + * @return the interval at generate permeate mode data being published. + *************************************************************************/ +static U32 getGenPermeateDataPublishInterval( void ) +{ + U32 result = getU32OverrideValue( &genPermeateDataPublishInterval ); + + return result; +} + +/*********************************************************************//** + * @brief + * The publishGenPModeData function broadcasts the generate water + * mode data at defined interval. + * @details \b Inputs: genPermeateDataPublicationTimerCounter + * @details \b Outputs: FP generate permeate data broadcast message sent + * @details \b Message \Sent: MSG_ID_FP_GEN_WATER_MODE_DATA to publish the + * generate water mode data. + * @return none + *************************************************************************/ +static void publishGenPModeData( void ) +{ + if ( ++genPermeateDataPublicationTimerCounter >= getGenPermeateDataPublishInterval() ) + { + GEN_PERMEATE_MODE_DATA_T data; + + data.genPermeateExecState = (U32)getCurrentGenPermeateState(); + data.setFlowRate = (F32)getDDPermeateFlowRate(); + + broadcastData( MSG_ID_FP_GEN_WATER_MODE_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( GEN_PERMEATE_MODE_DATA_T ) ); + + genPermeateDataPublicationTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The requestGenWaterStart function handles an DD request to start (go to gen permeate mode). + * @details \b Inputs: preGenWState + * @details \b Outputs: pendingStartGenRequest + * @return TRUE if request accepted, FALSE if not. + *************************************************************************/ +BOOL requestGenWaterStart( void ) +{ + BOOL result = TRUE; + pendingStartGenRequest = TRUE; + requestNewOperationMode( FP_MODE_GENP ); + + return result; +} + +/*********************************************************************//** + * @brief + * The requestGenWaterStop function handles an DD request to stop (go to standby mode). + * @details \b Inputs: none + * @details \b Outputs: pendingStartGenRequest + * @return TRUE if request accepted, FALSE if not. + *************************************************************************/ +BOOL requestGenWaterStop( void ) +{ + BOOL result = TRUE; + pendingStartGenRequest = FALSE; + signalROPumpHardStop(); + + if ( TRUE == isBoostPumpInstalled() ) + { + signalBoostPumpHardStop(); + } + requestNewOperationMode( FP_MODE_STAN ); + + return result; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testGenPermeateDataPublishIntervalOverride function overrides the + * DD generate water mode data publish interval. + * @details \b Inputs: genPermeateDataPublishInterval + * @details \b Outputs: genPermeateDataPublishInterval + * @param Override message from Dialin which includes the interval + * (in ms) to override the FP generate permeate data publish interval to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testGenPermeateDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &genPermeateDataPublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + +/**@}*/ Index: firmware/App/Controllers/PermeateTank.h =================================================================== diff -u --- firmware/App/Controllers/PermeateTank.h (revision 0) +++ firmware/App/Controllers/PermeateTank.h (revision 6e65344e6675394118806ce98dc428c27920e1cb) @@ -0,0 +1,60 @@ +/************************************************************************** +* +* Copyright (c) 2024-2025 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 PermeateTank.h +* +* @author (last) Michael Garthwaite +* @date (last) 03-Mar-2025 +* +* @author (original) Michael Garthwaite +* @date (original) 03-Mar-2025 +* +***************************************************************************/ + +#ifndef __PERM_TANK_H__ +#define __PERM_TANK_H__ + +#include "FPCommon.h" +#include "FPDefs.h" + +/** + * @defgroup FPGenPermeateMode FPGenPermeateMode + * @brief Generate Permeate unit. Manages water generation functions via a state machine. + * + * @addtogroup FPGenPermeateMode + * @{ + */ + +// ********** public definitions ********** + +/// Generate Permeate mode data structure +typedef struct +{ + U32 genPermeateExecState; ///< Generate Permeate execution state + F32 setFlowRate; ///< Permeate flow rate requested by the DD. +} GEN_PERMEATE_MODE_DATA_T; + +// ********** public function prototypes ********** + +void initGenPermeateMode( void ); // Initialize this gen permeate mode unit +U32 transitionToGenPermeateMode( void ); // Transition to gen permeate mode +U32 execGenPermeateMode( void ); // Execute the gen permeate mode state machine (call from OperationModes) +BOOL requestGenWaterStart( void ); +BOOL requestGenWaterStop( void ); +F32 getGenPermeateRODutyCycle( void ); +void setGenPermeateRODutyCycle( F32 duty); +F32 getGenPermeateBoostDutyCycle( void ); +void setGenPermeateBoostDutyCycle( F32 duty); + +FP_GENP_MODE_STATE_T getCurrentGenPermeateState( void ); // Get the current state of the gen water mode + +BOOL testGenPermeateDataPublishIntervalOverride( MESSAGE_T *message ); // override broadcast interval for gen permeate + +/**@}*/ + + +#endif