Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r4d6c6df8f990037cb66fbd0efdc4cc5a0ec31558 -r89c8709e3b27648926fbb20f25c9a67cbeb99adc --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 4d6c6df8f990037cb66fbd0efdc4cc5a0ec31558) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 89c8709e3b27648926fbb20f25c9a67cbeb99adc) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 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 ValvesDD.c +* @file Valves.c * -* @author (last) Vinayakam Mani -* @date (last) 14-Aug-2024 +* @author (last) “rkallala” +* @date (last) 28-Jan-2026 * * @author (original) Vinayakam Mani -* @date (original) 14-Aug-2024 +* @date (original) 26-Aug-2024 * ***************************************************************************/ @@ -35,6 +35,10 @@ #define ENERGIZED 1 ///< 1 for energized valve. #define ALL_VALVES_DEENERGIZED 0x0000 ///< 0 in U16 bit field for all valves. +#define VALVE_PWM_PERIOD 50 ///< Valve PWM Period in 0.1 us res ( 20kHz ) +#define VALVE_PWM_LOW ( VALVE_PWM_PERIOD * 0.2 ) ///< Valve low PWM percentage +#define VALVE_PWM_PULL_IN 100 ///< Valve 'strike' period at 100% PWM in ms + #define MAX_VALVE_STATE_MISMATCH_TIMER_COUNT (100 / TASK_PRIORITY_INTERVAL ) ///< Maximum time commanded valves state can fail to match read back valve states in a row. #define VALVES_STATE_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval ( ms / task time) at which valves states are published on CAN bus. #define DATA_PUBLISH_COUNTER_START_COUNT 50 ///< Data publish counter start count. @@ -71,6 +75,7 @@ static BOOL checkValveStateName( DD_VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ); static U32 convertValveStateNameToValveState( VALVE_STATE_NAMES_T valveStateName ); static U32 getValveState( U32 valveID ); +static void setFPGAPWMConfigurations( void ); /*********************************************************************//** * @brief @@ -118,16 +123,77 @@ valvesStatesPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; // reset valves states publication timer fpValveStatesPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; // reset valves states publication timer readCommandedValveStates(); + + // TODO set FPGA PWM after finalizing the decision on valve strike and hold behavior + // initially set valve PWM configuration and enable +// setFPGAPWMConfigurations(); + // initially set all valves to de-energized state via FPGA setFPGADDValveStates( commandedValvesStates ); setFPGABCValveStates( commandedBCValveStates ); setFPGASpareValveStates( commandedSpareValveStates ); - setFPGAIOValveStates( commandedIOValveStates ); setFPGAFPValveStates( commandedFPValveStates ); + setFPGAIOValveStates( commandedIOValveStates ); } /*********************************************************************//** * @brief + * The setFPGAPWMConfigurations function sets the FPGA for Valve PWM control. + * @details \b Inputs: none + * @details \b Outputs: Valves PWM timing set and enabled. + * @return none + *************************************************************************/ +static void setFPGAPWMConfigurations( void ) +{ + // Balancing Chamber valves are not PWM configured. + U32 i; + U16 valveDDBits = 0; + U08 valveSPBits = 0; + U08 valveIOBits = 0; + U08 valveFPBits = 0; + + // set timing values + setFPGAValveDDPWMPullIn( VALVE_PWM_PULL_IN ); + setFPGAValveDDPWMLow( VALVE_PWM_LOW ); + setFPGAValveDDPWMPeriod( VALVE_PWM_PERIOD ); + + setFPGAValveSPPWMPullIn( VALVE_PWM_PULL_IN ); + setFPGAValveSPPWMLow( VALVE_PWM_LOW ); + setFPGAValveSPPWMPeriod( VALVE_PWM_PERIOD ); + + setFPGAValveIOFPPWMPullIn( VALVE_PWM_PULL_IN ); + setFPGAValveIOFPPWMLow( VALVE_PWM_LOW ); + setFPGAValveIOFPPWMPeriod( VALVE_PWM_PERIOD ); + + for ( i = FIRST_HYD_VALVE; i <= LAST_HYD_VALVE; i++ ) + { + valveDDBits |= 0x01 << i; + } + + for ( i = FIRST_SP_VALVE; i <= LAST_SP_VALVE; i++ ) + { + valveSPBits |= 0x01 << ( i - FIRST_SP_VALVE ); + } + + for ( i = FIRST_IO_VALVE; i <= LAST_IO_VALVE; i++ ) + { + valveIOBits |= 0x01 << ( i - FIRST_IO_VALVE ); + } + + for ( i = FIRST_FP_VALVE; i <= LAST_FP_VALVE; i++ ) + { + valveFPBits |= 0x01 << ( i - FIRST_FP_VALVE ); + } + + // set enable + setFPGAValveDDPWMEnable( valveDDBits ); + setFPGAValveSPPWMEnable( valveSPBits ); + setFPGAValveIOPWMEnable( valveIOBits ); + setFPGAValveFPPWMEnable( valveFPBits ); +} + +/*********************************************************************//** + * @brief * The execValves function executes the valves driver. * @details \b Inputs: valvesStates, valveStateMismatchCounter * pendingValveStateChangeCountDowns, commandedValvesStates, @@ -141,11 +207,11 @@ void execValves( void ) { U32 i; - U16 readValvesStates = getFPGADDValveStates(); - U08 readValveBCStates = getFPGAValveBCStates(); - U08 readValveSpStates = getFPGAValveSpStates(); - U08 readValveIOStates = getFPGAIOValveStates(); - U08 readValveFPStates = getFPGAFPValveStates(); + U16 readValvesStates = getFPGADDValveStates(); + U08 readValveBCStates = getFPGAValveBCStates(); + U08 readValveSpStates = getFPGAValveSpStates(); + U08 readValveIOStates = getFPGAIOValveStates(); + U08 readValveFPStates = getFPGAFPValveStates(); // Verify read back FPGA valve states match last commanded valve states if ( ( readValvesStates != commandedValvesStates ) || @@ -184,15 +250,135 @@ setFPGADDValveStates( commandedValvesStates ); setFPGABCValveStates( commandedBCValveStates ); setFPGASpareValveStates( commandedSpareValveStates ); - setFPGAIOValveStates( commandedIOValveStates ); setFPGAFPValveStates( commandedFPValveStates ); + setFPGAIOValveStates( commandedIOValveStates ); // Publish valve states on interval publishValvesStates(); } /*********************************************************************//** * @brief + * The setValveState function sets the valve state for given valve. + * @details \b Inputs: none + * @details \b Outputs: valveStates[], pendingValveStateChanges[], pendingValveStateChangeCountDowns[] + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed + * @param valveID ID of valve to set state for + * @param valveStateName name of valve state to set given valve to + * @return TRUE if new valve state is set for given valve ID, FALSE if not. + *************************************************************************/ +BOOL setValveState( DD_VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ) +{ + BOOL result = FALSE; // initialize result flag to FALSE + + if ( valveID < DD_NUM_OF_VALVES ) + { + if ( TRUE == checkValveStateName( valveID, valveStateName ) ) + { + valveStates[ valveID ].data = convertValveStateNameToValveState( valveStateName ); + result = TRUE; + // If a delayed state change is pending for this valve, cancel it + pendingValveStateChanges[ valveID ] = DEENERGIZED; + pendingValveStateChangeCountDowns[ valveID ] = 0; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setValveStateDelayed function sets the valve state for given valve + * after a given delay. + * @details \b Inputs: pendingValveStateChangeCountDowns[] + * @details \b Outputs: pendingValveStateChangeCountDowns[], pendingValveStateChangeCountDowns[] + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed + * @param valveID ID of valve to set state for + * @param valveStateName name of valve state to set given valve to + * @param delayMs delay duration (in ms) before actuation + * @return TRUE if new valve state is set for given valve ID, FALSE if not. + *************************************************************************/ +BOOL setValveStateDelayed( DD_VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName, U32 delayMs ) +{ + BOOL result = FALSE; // initialize result flag to FALSE + + if ( valveID < DD_NUM_OF_VALVES ) + { + if ( TRUE == checkValveStateName( valveID, valveStateName ) ) + { + // If a delayed state change is already pending for this valve, execute it now before setting a new delayed state change + if ( pendingValveStateChangeCountDowns[ valveID ] > 0 ) + { + valveStates[ valveID ].data = pendingValveStateChanges[ valveID ]; + } + // Set delayed valve state change + pendingValveStateChanges[ valveID ] = convertValveStateNameToValveState( valveStateName ); + pendingValveStateChangeCountDowns[ valveID ] = delayMs / TASK_PRIORITY_INTERVAL; + result = TRUE; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getValveStateName function gets the current valve state enum for given valve. + * @details \b Inputs: valveStates[] + * @details \b Outputs: none + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed. + * @param valveID ID of valve to get state for + * @return the current valve state for given valve in enum + *************************************************************************/ +VALVE_STATE_NAMES_T getValveStateName( DD_VALVES_T valveID ) +{ + // Initialized per CppCheck. + VALVE_STATE_NAMES_T name = NUM_OF_VALVE_STATES; + + if ( valveID < DD_NUM_OF_VALVES ) + { + U32 valveState = getU32OverrideValue( &valveSensedStates[ valveID ] ); + + name = ( DEENERGIZED == valveState ? VALVE_STATE_CLOSED : VALVE_STATE_OPEN ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) + } + + return name; +} + + +/*********************************************************************//** + * @brief + * The setHydValvesStatetoClosedState function sets all Hydraulics / DD + * valves to close state except balancing chamber, UF and Inlet water control. + * @details \b Inputs: none + * @details \b Outputs: valve states + * @return none. + *************************************************************************/ +void setHydValvesStatetoClosedState( void ) +{ + DD_VALVES_T valve; + + // Set all Hydraulics valves to closed state + for ( valve = FIRST_HYD_VALVE; valve <= LAST_HYD_VALVE; valve++ ) + { + setValveState( valve, VALVE_STATE_CLOSED ); + } +} + +/*********************************************************************//** + * @brief * The readCommandedValveStates function gets the hydraulics, Balancing chamber * and Ultrafiltration valvesStates that can be passed to FPGA for setting valves. * @details \b Inputs: valveStates[] @@ -266,7 +452,7 @@ ( D19_VALV == valveID ) || ( D25_VALV == valveID ) || ( D21_VALV == valveID ) || ( D24_VALV == valveID ) || ( D20_VALV == valveID ) || ( D26_VALV == valveID ) || ( D22_VALV == valveID ) || ( D80_VALV == valveID ) || ( D81_VALV == valveID ) || ( D79_PMP_VALV == valveID ) || ( P11_VALV == valveID ) || ( P33_VALV == valveID ) || ( P34_VALV == valveID ) || ( P37_VALV == valveID ) || ( P6_VALV == valveID ) || - ( M12_VALV == valveID ) || ( P39_VALV == valveID ) ) + ( M12_VALV == valveID ) || ( P39_VALV == valveID ) || ( D83_VALV == valveID ) || ( D91_VALV == valveID ) || ( D100_VALV == valveID ) || ( D85_VALV == valveID ) ) { result = TRUE; } @@ -314,106 +500,6 @@ /*********************************************************************//** * @brief - * The setValveState function sets the valve state for given valve. - * @details \b Inputs: none - * @details \b Outputs: valveStates[], pendingValveStateChanges[], pendingValveStateChangeCountDowns[] - * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed - * @param valveID ID of valve to set state for - * @param valveStateName name of valve state to set given valve to - * @return TRUE if new valve state is set for given valve ID, FALSE if not. - *************************************************************************/ -BOOL setValveState( DD_VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ) -{ - BOOL result = FALSE; // initialize result flag to FALSE - - if ( valveID < DD_NUM_OF_VALVES ) - { - if ( TRUE == checkValveStateName( valveID, valveStateName ) ) - { - valveStates[ valveID ].data = convertValveStateNameToValveState( valveStateName ); - result = TRUE; - // If a delayed state change is pending for this valve, cancel it - pendingValveStateChanges[ valveID ] = DEENERGIZED; - pendingValveStateChangeCountDowns[ valveID ] = 0; - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) - } - - return result; -} - -/*********************************************************************//** - * @brief - * The setValveStateDelayed function sets the valve state for given valve - * after a given delay. - * @details \b Inputs: pendingValveStateChangeCountDowns[] - * @details \b Outputs: pendingValveStateChangeCountDowns[], pendingValveStateChangeCountDowns[] - * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed - * @param valveID ID of valve to set state for - * @param valveStateName name of valve state to set given valve to - * @param delayMs delay duration (in ms) before actuation - * @return TRUE if new valve state is set for given valve ID, FALSE if not. - *************************************************************************/ -BOOL setValveStateDelayed( DD_VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName, U32 delayMs ) -{ - BOOL result = FALSE; // initialize result flag to FALSE - - if ( valveID < DD_NUM_OF_VALVES ) - { - if ( TRUE == checkValveStateName( valveID, valveStateName ) ) - { - // If a delayed state change is already pending for this valve, execute it now before setting a new delayed state change - if ( pendingValveStateChangeCountDowns[ valveID ] > 0 ) - { - valveStates[ valveID ].data = pendingValveStateChanges[ valveID ]; - } - // Set delayed valve state change - pendingValveStateChanges[ valveID ] = convertValveStateNameToValveState( valveStateName ); - pendingValveStateChangeCountDowns[ valveID ] = delayMs / TASK_PRIORITY_INTERVAL; - result = TRUE; - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) - } - - return result; -} - -/*********************************************************************//** - * @brief - * The getValveStateName function gets the current valve state enum for given valve. - * @details \b Inputs: valveStates[] - * @details \b Outputs: none - * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid valve ID passed. - * @param valveID ID of valve to get state for - * @return the current valve state for given valve in enum - *************************************************************************/ -VALVE_STATE_NAMES_T getValveStateName( DD_VALVES_T valveID ) -{ - // Initialized per CppCheck. - VALVE_STATE_NAMES_T name = NUM_OF_VALVE_STATES; - - if ( valveID < DD_NUM_OF_VALVES ) - { - U32 valveState = getU32OverrideValue( &valveSensedStates[ valveID ] ); - - name = ( DEENERGIZED == valveState ? VALVE_STATE_CLOSED : VALVE_STATE_OPEN ); - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) - } - - return name; -} - -/*********************************************************************//** - * @brief * The getValveState function gets the current valve state for given valve. * @details \b Inputs: valveStates[] * @details \b Outputs: none @@ -439,25 +525,6 @@ /*********************************************************************//** * @brief - * The setHydValvesStatetoClosedState function sets all Hydraulics / DD - * valves to close state except balancing chamber, UF and Inlet water control. - * @details \b Inputs: none - * @details \b Outputs: valve states - * @return none. - *************************************************************************/ -void setHydValvesStatetoClosedState( void ) -{ - DD_VALVES_T valve; - - // Set all Hydraulics valves to closed state - for ( valve = FIRST_HYD_VALVE; valve <= LAST_HYD_VALVE; valve++ ) - { - setValveState( valve, VALVE_STATE_CLOSED ); - } -} - -/*********************************************************************//** - * @brief * The publishValvesStates function publishes DD valves states at the set interval. * @details \b Inputs: valvesStatesPublicationTimerCounter * @details \b Outputs: valvesStatesPublicationTimerCounter