Index: firmware/App/Controllers/PermeateTank.c =================================================================== diff -u -rf79d3737907fd08293d56f60f9f439ac68c81855 -r6dd382e3988fac2f9ee041b4738d67305e17a6a2 --- firmware/App/Controllers/PermeateTank.c (.../PermeateTank.c) (revision f79d3737907fd08293d56f60f9f439ac68c81855) +++ firmware/App/Controllers/PermeateTank.c (.../PermeateTank.c) (revision 6dd382e3988fac2f9ee041b4738d67305e17a6a2) @@ -31,22 +31,367 @@ // ********** private definitions ********** -#define PERMEATE_TANK_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) for permeate tank broadcast +#define PERMEATE_TANK_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) for permeate tank broadcast +#define PERMEATE_TANK_PUBLISH_COUNTER_START_COUNT 9 +#define PERMEATE_TANK_FULL_SWITCH_MS ( 6 * MS_PER_SECOND ) ///< state switch timeout (in ms) +#define PERMEATE_TANK_FULL_TIMEOUT_MS ( 60 * MS_PER_SECOND ) // ********** private data ********** -static PERMEATE_TANK_STATE_T permeateTankControllerState; ///< Current state of permeate controller state machine. -static U32 permeateTankDataPublicationTimerCounter; ///< Used to schedule permeate tank data publication to CAN bus. -static OVERRIDE_U32_T permeateTankPublishInterval; ///< Interval (in ms) at which to publish permeate tank data to CAN bus. +static PERMEATE_TANK_STATE_T permeateTankControllerState; ///< Current state of permeate controller state machine. +static U32 permeateTankDataPublicationTimerCounter; ///< Used to schedule permeate tank data publication to CAN bus. +static OVERRIDE_U32_T permeateTankPublishInterval; ///< Interval (in ms) at which to publish permeate tank data to CAN bus. +static BOOL pendingStartPermeateTankController; ///< Flag indicates an air trap controller start request is pending. +static BOOL pendingStopPermeateTankController; ///< Flag indicates an air trap controller stop request is pending. +static U32 tankFullAlarmTimeout; ///< Time stamp to track alarm timeout. +static U32 tankFullDelayTime; ///< Time stamp to track delay before valve switch. // ********** private function prototypes ********** -static void publishAirTrapData( void ); +static PERMEATE_TANK_STATE_T handlePermeateTankManualControlState( void ); +static PERMEATE_TANK_STATE_T handlePermeateTankFillState( void ); +static PERMEATE_TANK_STATE_T handlePermeateTankFullState( void ); +static void setPermeateTankTransition( PERMEATE_TANK_STATE_T state ); +static void publishPermeateTankData( void ); +/*********************************************************************//** + * @brief + * The initPermeateTank function initializes the permeate tank controller unit. + * @details \b Inputs: none + * @details \b Outputs: permeate tank controller unit initialized + * @return none + *************************************************************************/ +void initPermeateTank( void ) +{ + resetPermeateTank(); + permeateTankDataPublicationTimerCounter = PERMEATE_TANK_PUBLISH_COUNTER_START_COUNT; + permeateTankPublishInterval.data = PERMEATE_TANK_PUMP_DATA_PUB_INTERVAL; + permeateTankPublishInterval.ovData = PERMEATE_TANK_PUMP_DATA_PUB_INTERVAL; + permeateTankPublishInterval.ovInitData = PERMEATE_TANK_PUMP_DATA_PUB_INTERVAL; + permeateTankPublishInterval.override = OVERRIDE_RESET; + tankFullDelayTime = 0; + tankFullAlarmTimeout = 0; + +} + +/*********************************************************************//** + * @brief + * The resetPermeateTank function resets certain parts of the permeate tank module + * between water generation. + * @details \b Inputs: none + * @details \b Outputs: Permeate Tank controller reset. + * @return none + *************************************************************************/ +void resetPermeateTank( void ) +{ + permeateTankControllerState = PERMEATE_TANK_INIT_STATE; + pendingStartPermeateTankController = FALSE; + pendingStopPermeateTankController = FALSE; +} + +/*********************************************************************//** + * @brief + * The startPermeateTankControl function requests a start to permeate tank control. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: pendingStartPermeateTankController + * @return none + *************************************************************************/ +void startPermeateTankControl( void ) +{ + if ( FALSE == isPermeateTankControlling() ) + { + pendingStartPermeateTankController = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The endPermeateTankControl function requests a stop to permeate tank control. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: pendingStopPermeateTankController + * @return none + *************************************************************************/ +void endPermeateTankControl( void ) +{ + if ( TRUE == isPermeateTankControlling() ) + { + pendingStopPermeateTankController = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The isPermeateTankControlling function determines whether the permeate tank is + * currently controlling. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: none + * @return TRUE if air trap is currently controlling, FALSE if not. + *************************************************************************/ +BOOL isPermeateTankControlling( void ) +{ + BOOL result = FALSE; + + if ( permeateTankControllerState > PERMEATE_TANK_MANUAL_CONTROL_STATE ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getPermeateTankState function returns the current state of the + * permeate tank controller. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: none + * @return the current state of permeate tank + *************************************************************************/ +PERMEATE_TANK_STATE_T getPermeateTankState( void ) +{ + return permeateTankControllerState; +} +/*********************************************************************//** + * @brief + * The execPermeateTankController function executes the air trap control state machine. + * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if current permeate tank control + * state is invalid. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if air trap valve closed due to fault. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: permeateTankControllerState + * @return none + *************************************************************************/ +void execPermeateTankController( void ) +{ + PERMEATE_TANK_STATE_T prevState = permeateTankControllerState; + // If we have faulted, close valve and go to manual control + if ( FP_MODE_FAUL == getCurrentOperationMode() ) + { + endPermeateTankControl(); + } + + // Execute air trap state machine + switch( permeateTankControllerState ) + { + case PERMEATE_TANK_INIT_STATE: + permeateTankControllerState = PERMEATE_TANK_MANUAL_CONTROL_STATE; + break; + + case PERMEATE_TANK_MANUAL_CONTROL_STATE: + permeateTankControllerState = handlePermeateTankManualControlState(); + break; + + case PERMEATE_TANK_FILL_STATE: + permeateTankControllerState = handlePermeateTankFillState(); + break; + + case PERMEATE_TANK_FULL_STATE: + permeateTankControllerState = handlePermeateTankFullState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, (U32)SW_FAULT_ID_FP_INVALID_PERMEATE_TANK_STATE, (U32)permeateTankControllerState ) + permeateTankControllerState = PERMEATE_TANK_INIT_STATE; + break; + } + + if ( prevState != permeateTankControllerState ) + { + setPermeateTankTransition( permeateTankControllerState ); + } + + // Publish permeate tank data if due + publishPermeateTankData(); +} + +/*********************************************************************//** + * @brief + * The handlePermeateTankManualControlState function handles the manual control + * state of the permeate tank. + * @details \b Inputs: permeateTankControllerState + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static PERMEATE_TANK_STATE_T handlePermeateTankManualControlState( void ) +{ + PERMEATE_TANK_STATE_T state = PERMEATE_TANK_MANUAL_CONTROL_STATE; + + // Transition to valve control states when requested + if ( TRUE == pendingStartPermeateTankController ) + { + pendingStartPermeateTankController = FALSE; + state = PERMEATE_TANK_FILL_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleAirTrapRaiseLevelState function handles the raise level state + * of the permeate tank. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if raising level completed + * @details \b Inputs: pendingStopAirTrapController + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static PERMEATE_TANK_STATE_T handlePermeateTankFillState( void ) +{ + PERMEATE_TANK_STATE_T state = PERMEATE_TANK_FILL_STATE; + LEVEL_STATE_T level = getLevelStatus(); + + // Transition to manual valve control state when requested + if ( TRUE == pendingStopPermeateTankController ) + { + pendingStopPermeateTankController = FALSE; + state = PERMEATE_TANK_MANUAL_CONTROL_STATE; + } + + else if ( LEVEL_STATE_HIGH == level ) + { + state = PERMEATE_TANK_FULL_STATE; + } + + else if ( level <= LEVEL_STATE_MEDIUM ) + { + // expected state. No action required. + // If level is low we still want to fill. + } + + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePermeateTankFullState function handles the lower level state + * of the permeate tank. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static PERMEATE_TANK_STATE_T handlePermeateTankFullState( void ) +{ + PERMEATE_TANK_STATE_T state = PERMEATE_TANK_FULL_STATE; + LEVEL_STATE_T level = getLevelStatus(); + + if ( TRUE == didTimeout( tankFullAlarmTimeout, PERMEATE_TANK_FULL_TIMEOUT_MS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_FP_GEN_PERMEATE_TANK_FULL_TIMEOUT, level ) + } + + // Transition to manual valve control state when requested + if ( TRUE == pendingStopPermeateTankController ) + { + pendingStopPermeateTankController = FALSE; + state = PERMEATE_TANK_MANUAL_CONTROL_STATE; + } + + else if ( ( ( level == LEVEL_STATE_MEDIUM ) && ( TRUE == didTimeout( tankFullDelayTime, PERMEATE_TANK_FULL_SWITCH_MS ) ) ) || + ( level == LEVEL_STATE_LOW ) ) + { + state = PERMEATE_TANK_FILL_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The setPermeateTankTransition function sets the actuators and variables + * for the state transition in permeate tank controller. + * @details Inputs: Valve states + * @details Outputs: Actuate valves + * @param state permeate tank state enum + * @return none + *************************************************************************/ +static void setPermeateTankTransition( PERMEATE_TANK_STATE_T state ) +{ + // Execute on running state + switch( state ) + { + case PERMEATE_TANK_INIT_STATE: + case PERMEATE_TANK_MANUAL_CONTROL_STATE: + break; + + case PERMEATE_TANK_FILL_STATE: + setValveState( M4_VALV,VALVE_STATE_OPEN ); + setValveState( M7_VALV, VALVE_STATE_CLOSED ); + 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 ); + setValveState( P20_VALV, VALVE_STATE_CLOSED ); + setValveState( P43_VALV, VALVE_STATE_CLOSED ); + break; + + case PERMEATE_TANK_FULL_STATE: + setValveState( M4_VALV, VALVE_STATE_CLOSED ); + setValveState( M7_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 ); + setValveState( P20_VALV, VALVE_STATE_CLOSED ); + setValveState( P43_VALV, VALVE_STATE_CLOSED ); + 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 publishPermeateTankData function publishes permeate tank at the set interval. + * @details \b Message \b Sent: MSG_ID_FP_PERMEATE_TANK_DATA + * @details \b Inputs: permeateTankDataPublicationTimerCounter + * @details \b Outputs: permeateTankDataPublicationTimerCounter + * @return none + *************************************************************************/ +static void publishPermeateTankData( void ) +{ + // publish RO pump data on interval + if ( ++permeateTankDataPublicationTimerCounter >= getU32OverrideValue( &permeateTankPublishInterval ) ) + { + PERMEATE_TANK_DATA_T data; + data.tankState = permeateTankControllerState; + + broadcastData( MSG_ID_FP_PERMEATE_TANK_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( PERMEATE_TANK_DATA_T ) ); + permeateTankDataPublicationTimerCounter = 0; + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ +/*********************************************************************//** + * @brief + * The testPermeateTankDataPublishIntervalOverride function overrides the + * permeate tank data publish interval. + * @details \b Inputs: permeateTankPublishInterval + * @details \b Outputs: permeateTankPublishInterval + * @param message Override message from Dialin which includes the value + * that override permeate tank data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testPermeateTankDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &permeateTankPublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + + /**@}*/