Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -rae823785919192402707da5083e9b0ad40bd4938 --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision ae823785919192402707da5083e9b0ad40bd4938) @@ -1,12 +1,33 @@ +/************************************************************************** +* +* Copyright (c) 2020-2022 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 Fans.c +* +* @author (last) Dara Navaei +* @date (last) 20-Apr-2022 +* +* @author (original) Dara Navaei +* @date (original) 25-Nov-2020 +* +***************************************************************************/ #include "etpwm.h" +#include "math.h" #include "Fans.h" #include "FPGA.h" +#include "MessageSupport.h" +#include "NVDataMgmt.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" +#include "TemperatureSensors.h" #include "Thermistors.h" +#include "Timers.h" /** * @addtogroup Fans @@ -15,97 +36,113 @@ // ********** private definitions ********** -#define FANS_MIN_DUTY_CYCLE 0.1 ///< Fans min PWM. -#define FANS_MAX_DUTY_CYCLE 0.95 ///< Fans max PWM. -#define MIN_ALLOWED_AMBIENT_TEMPERATURE 20 ///< Min allowed ambient temperature. -#define MAX_ALLOWED_AMBINET_TEMPERATURE 70 ///< Max allowed ambient temperature. -#define FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE 0.3 ///< Fans max allowed ramp up PWM change. -#define FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE 0.005 ///< Fans min allowed ramp down PWM change. +#define FANS_MIN_DUTY_CYCLE 0.1F ///< Fans min PWM. +#define FANS_MAX_DUTY_CYCLE 0.95F ///< Fans max PWM. +#define MIN_ALLOWED_AMBIENT_TEMPERATURE 20 ///< Min allowed ambient temperature. +#define MAX_ALLOWED_AMBINET_TEMPERATURE 70 ///< Max allowed ambient temperature. +#define FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE 0.3F ///< Fans max allowed ramp up PWM change. +#define FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE 0.005F ///< Fans min allowed ramp down PWM change. -#define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.0000025 ///< FPGA fans toggle period resolution in micro seconds. -#define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4 ///< FPGA rotational to toggle period conversion coefficient. +#define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.0000025F ///< FPGA fans toggle period resolution in micro seconds. +#define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4 ///< FPGA rotational to toggle period conversion coefficient. -#define FANS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans publish data time interval in counts. -#define FANS_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans control time interval in counts. -#define FANS_ZERO_RPM_TOGGLE_PERIOD_VALUE 0xFFFF ///< Fans zero RPM toggle period value. -#define MIN_TARGET_RPM_IN_SELF_TEST 1000 ///< Fans min target RPM that they should be during POST. -#define FANS_SELF_TEST_WAIT_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans self test wait time for the fans to get to RPM. -#define FANS_SELF_TEST_TARGET_PWM 0.5 ///< Fans self test target PWM for testing the fans are running. -#define FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ( 3 * MS_PER_SECOND ) ///< Fans max allowed RPM out of range time interval. -#define FANS_MAX_ALLOWED_RPM 5500 ///< Fans max allowed RPM value. -#define FANS_MIN_ALLOWED_RPM 150 ///< Fans max allowed RPM value. -#define FANS_MONITOR_INTERVAL_COUNT ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans monitor time interval in counts. -#define FANS_MIN_RPM_OUT_OF_RANGE_TOL 0.25 ///< Fans min RPM out of range tolerance. -#define FANS_MAX_RPM_OUT_OF_RANGE_TOL 0.5 ///< Fans max RPM out of range tolerance. +#define FANS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans publish data time interval in counts. +#define FANS_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans control time interval in counts. +#define FANS_ZERO_RPM_TOGGLE_PERIOD_VALUE 0xFFFF ///< Fans zero RPM toggle period value. +#define MIN_TARGET_RPM_IN_SELF_TEST 1000 ///< Fans min target RPM that they should be during POST. +#define FANS_SELF_TEST_WAIT_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans self test wait time for the fans to get to RPM. +#define FANS_SELF_TEST_TARGET_PWM 0.5F ///< Fans self test target PWM for testing the fans are running. +#define FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ( 3 * MS_PER_SECOND ) ///< Fans max allowed RPM out of range time interval. +#define FANS_MAX_ALLOWED_RPM 5500 ///< Fans max allowed RPM value. +#define FANS_MIN_ALLOWED_RPM 150 ///< Fans max allowed RPM value. +#define FANS_MIN_RPM_OUT_OF_RANGE_TOL 0.25F ///< Fans min RPM out of range tolerance. +#define FANS_MAX_RPM_OUT_OF_RANGE_TOL 0.5F ///< Fans max RPM out of range tolerance. +#define DATA_PUBLISH_COUNTER_START_COUNT 12 ///< Data publish counter start count. -/// Fans self test states -typedef enum fans_Self_Test -{ - FANS_SELF_TEST_START_STATE = 0, ///< Fans self test start state - FANS_SELF_TEST_CHECK_RPM_STATE, ///< Fans self test check RPM state - FAN_SELF_TEST_COMPLETE_STATE, ///< Fans self test complete state - NUM_OF_SELF_TEST_STATES, ///< Number of fans self test -} FANS_SELF_TEST_STATES_T; - /// Fans exec states typedef enum fans_Exec_States { - FANS_EXEC_STATE_WAIT_FOR_POST_STATE = 0, ///< Fans exec state start state - FANS_EXEC_STATE_RUN_STATE, ///< Fans exec state run state - NUM_OF_FANS_EXEC_STATES, ///< Number of fans exec states + FANS_EXEC_STATE_WAIT_FOR_POST_STATE = 0, ///< Fans exec state start state. + FANS_EXEC_STATE_RUN_STATE, ///< Fans exec state run state. + NUM_OF_FANS_EXEC_STATES, ///< Number of fans exec states. } FANS_EXEC_STATES_T; /// Fans status struct typedef struct { - F32 targetDutyCycle; ///< Fan's target duty cycle that was fed to the fans - U32 rpm[ NUM_OF_FANS_NAMES ]; ///< Fan's current tachometers reading in RPM + OVERRIDE_F32_T dutyCycle; ///< Fans duty cycle that was fed to the fans. + F32 targetRPM; ///< Fans target RPM. + OVERRIDE_F32_T rpm[ NUM_OF_FANS_NAMES ]; ///< Fan's current tachometers reading in RPM. } FAN_STATUS_T; -static FAN_STATUS_T fansStatus; ///< Fans status. -static FANS_EXEC_STATES_T fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; ///< Fans exec state. -static U32 fansControlCounter = 0; ///< Fans control interval counter. -static U32 fansPublishCounter = 0; ///< Fans data publish interval counter. -static U32 fansMonitorCounter = 0; ///< Fans monitor interval counter. -static BOOL isPOSTComplete = FALSE; ///< Flag that indicates whether POST is complete or not. +// ********** private data ********** +static FAN_STATUS_T fansStatus; ///< Fans status. +static FANS_EXEC_STATES_T fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; ///< Fans exec state. +static U32 fansControlCounter = 0; ///< Fans control interval counter. +static U32 fansPublishCounter; ///< Fans data publish interval counter. +static BOOL isPOSTComplete = FALSE; ///< Flag that indicates whether POST is complete or not. +static BOOL hasAlarmBeenRaised = FALSE; ///< Flag that indicates whether the RPM out of range alarm been raise. +static U32 rpmAlarmStartTimeOffset; ///< RPM out of range alarm start time offset. +static U32 rpmAlarmStartTime = 0; ///< RPM alarm start time. +static DG_FANS_CAL_RECORD_T fansCalReocrd; ///< Fans calibration record. + /// Temperature to duty cycle conversion slope (duty cycle not in percent) static const F32 SLOPE = ( FANS_MAX_DUTY_CYCLE - FANS_MIN_DUTY_CYCLE ) / ( MAX_ALLOWED_AMBINET_TEMPERATURE - MIN_ALLOWED_AMBIENT_TEMPERATURE ); /// FGPA Toggle to RPM conversion coefficient static const F32 TOGGLE_PERIOD_2_RPM_COEFFICIENT = SEC_PER_MIN / ( TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); -static OVERRIDE_U32_T fansPublishInterval = { FANS_DATA_PUBLISH_INTERVAL, FANS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Fans publish time interval override +static OVERRIDE_U32_T fansPublishInterval = { FANS_DATA_PUBLISH_INTERVAL, FANS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Fans publish time interval override. +// ********** private function prototypes ********** + static FANS_EXEC_STATES_T handleExecStateWaitForPOST( void ); static FANS_EXEC_STATES_T handleExecStateRun( void ); static void setInletFansDutyCycle( F32 pwm ); static void setOutletFansDutyCycle( F32 pwm ); -static F32 getMaximumTemperature( void ); +static F32 getMaximumTemperature( void ); static void convertTogglePeriod2RPM( void ); static void monitorFans( void ); -static U32 getPublishFansDataInterval( void ); static void publishFansData( void ); /*********************************************************************//** * @brief * The initFans function initializes the fans module. - * @details Inputs: fansExecState, fansStatus, fansControlCounter, - * fansPublishCounter - * @details Outputs: fansExecState, fansStatus, fansControlCounter, - * fansPublishCounter + * @details Inputs: none + * @details Outputs: fansExecState, fansControlCounter, fansPublishCounter, + * isPOSTComplete, hasAlarmBeenRaised, rpmAlarmStartTime, + * fansStatus, rpmAlarmStartTimeOffset * @return none *************************************************************************/ void initFans( void ) { + FAN_NAMES_T fan; + // Initialize the variables - fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; - fansControlCounter = 0; - fansPublishCounter = 0; - fansMonitorCounter = 0; - isPOSTComplete = FALSE; + fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; + fansControlCounter = 0; + fansPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + isPOSTComplete = FALSE; + hasAlarmBeenRaised = FALSE; + rpmAlarmStartTime = 0; + rpmAlarmStartTimeOffset = 0; + fansStatus.dutyCycle.data = 0.0; + fansStatus.dutyCycle.ovData = 0.0; + fansStatus.dutyCycle.ovInitData = 0.0; + fansStatus.dutyCycle.override = OVERRIDE_RESET; + fansStatus.targetRPM = 0.0; + // Initialize the fans + for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) + { + fansStatus.rpm[ fan ].data = 0.0; + fansStatus.rpm[ fan ].ovData = 0.0; + fansStatus.rpm[ fan ].ovInitData = 0.0; + fansStatus.rpm[ fan ].override = OVERRIDE_RESET; + } + // Initialize a persistent alarm for fans RPM out of range initPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ); } @@ -114,20 +151,28 @@ * @brief * The execFansSelfTest function executes the fans self test. * @details Inputs: none - * @details Outputs: isPOSTComplete + * @details Outputs: isPOSTComplete, fansCalReocrd * @return Status of self test *************************************************************************/ SELF_TEST_STATUS_T execFansSelfTest( void ) { - SELF_TEST_STATUS_T status = SELF_TEST_STATUS_IN_PROGRESS; + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - // TODO implement the calibration processing function. - // It returns a pass for now - + BOOL calStatus = getNVRecord2Driver( GET_CAL_FANS_RECORD, (U08*)&fansCalReocrd, sizeof( DG_FANS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_FANS, ALARM_ID_NO_ALARM ); + // Signal POST is completed isPOSTComplete = TRUE; - status = SELF_TEST_STATUS_PASSED; - return status; + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + + return result; } /*********************************************************************//** @@ -139,9 +184,6 @@ *************************************************************************/ void execFans( void ) { - // Monitor the fans - //monitorFans(); TODO uncomment. this is to investigate why the fans RPM are out of range - switch ( fansExecState ) { case FANS_EXEC_STATE_WAIT_FOR_POST_STATE: @@ -158,6 +200,12 @@ break; } + // Convert the counts to RPM + convertTogglePeriod2RPM(); + + // Monitor the RPM of the fans + monitorFans(); + publishFansData(); } @@ -171,12 +219,18 @@ *************************************************************************/ F32 getMeasuredFanRPM( FAN_NAMES_T fan ) { - F32 rpm = 0.0; + F32 rpm; // Check if the called fan is in range if ( fan < NUM_OF_FANS_NAMES ) { - rpm = fansStatus.rpm[ fan ]; + // Assume there is no override + rpm = fansStatus.rpm[ fan ].data; + + if ( OVERRIDE_KEY == fansStatus.rpm[ fan ].override ) + { + rpm = fansStatus.rpm[ fan ].ovData; + } } else { @@ -227,8 +281,9 @@ { FANS_EXEC_STATES_T state = FANS_EXEC_STATE_RUN_STATE; - // Check if it is time to check for the control - if ( ++fansControlCounter > FANS_CONTROL_INTERVAL ) + // Check if it is time to check for the control and the duty cycle override is in the reset mode so the duty cycle + // is not overridden + if ( ( ++fansControlCounter > FANS_CONTROL_INTERVAL ) && ( OVERRIDE_RESET == fansStatus.dutyCycle.override ) ) { // Get the maximum temperature among all the thermistors and temperature sensors to run fan from the hottest temperature F32 temperature = getMaximumTemperature(); @@ -248,41 +303,50 @@ // If the fans calculated duty cycle is greater than the previous calculated duty cycle, we are ramping up // otherwise, we are ramping down - if ( dutyCycle >= fansStatus.targetDutyCycle ) + if ( dutyCycle >= fansStatus.dutyCycle.data ) { // If the delta duty cycle from the previous duty cycle is greater than the max allowed ramp up duty cycle, // otherwise, only add the delta duty cycle - if ( ( dutyCycle - fansStatus.targetDutyCycle ) >= FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE ) + if ( ( dutyCycle - fansStatus.dutyCycle.data ) >= FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE ) { - fansStatus.targetDutyCycle += FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE; + fansStatus.dutyCycle.data += FANS_MAX_ALLOWED_RAMP_UP_DELTA_DUTY_CYCLE; } else { - fansStatus.targetDutyCycle = dutyCycle; + fansStatus.dutyCycle.data = dutyCycle; } } else { // If the delta duty cycle from the previous duty cycle is greater than the max allowed ramp down duty cycle, // otherwise, only add the delta duty cycle - if ( ( fansStatus.targetDutyCycle - dutyCycle ) >= FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE ) + if ( ( fansStatus.dutyCycle.data - dutyCycle ) >= FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE ) { // If we are ramping down, set the target duty cycle to max allowed ramp down duty cycle - fansStatus.targetDutyCycle -= FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE; + fansStatus.dutyCycle.data -= FANS_MAX_ALLOWED_RAMP_DOWN_DELTA_DUTY_CYCLE; } else { - fansStatus.targetDutyCycle = dutyCycle; + fansStatus.dutyCycle.data = dutyCycle; } } + // Calculate the target RPM for the the duty cycle + fansStatus.targetRPM = fansStatus.dutyCycle.data * FANS_MAX_ALLOWED_RPM; + // Set the PWM to inlet and outlet fans - setInletFansDutyCycle( fansStatus.targetDutyCycle ); - setOutletFansDutyCycle( fansStatus.targetDutyCycle ); + setInletFansDutyCycle( fansStatus.dutyCycle.data ); + setOutletFansDutyCycle( fansStatus.dutyCycle.data ); // Reset the counter fansControlCounter = 0; } + else if ( OVERRIDE_KEY == fansStatus.dutyCycle.override ) + { + // Set the PWM to inlet and outlet fans + setInletFansDutyCycle( fansStatus.dutyCycle.ovData ); + setOutletFansDutyCycle( fansStatus.dutyCycle.ovData ); + } return state; } @@ -325,30 +389,40 @@ { F32 temperature; THERMISTORS_TEMP_SENSORS_T thermistor; - F32 maxTemperature = 0.0; + F32 maxTemperature; // Loop through the sensors and thermistors for ( thermistor = THERMISTOR_ONBOARD_NTC; thermistor < NUM_OF_THERMISTORS; thermistor++ ) { - // Get the value - temperature = getThermistorTemperatureValue( thermistor ); - - // If the latest temperature read is greater than the max temperature, - // set the maximum temperature there - if ( temperature > maxTemperature ) - { - maxTemperature = temperature; - } + temperature = getThermistorTemperatureValue( thermistor ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); } + // The temperature sensors that are on the hardware and are not on the fluid path are used to + // decide the maximum temperature + temperature = getTemperatureValue( TEMPSENSORS_FPGA_BOARD_SENSOR ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); + + temperature = getTemperatureValue( TEMPSENSORS_LOAD_CELL_A1_B1 ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); + + temperature = getTemperatureValue( TEMPSENSORS_LOAD_CELL_A2_B2 ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); + + temperature = getTemperatureValue( TEMPSENSORS_INTERNAL_TRO_RTD ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); + + temperature = getTemperatureValue( TEMPSENSORS_INTERNAL_TDI_RTD ); + maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); + return maxTemperature; } /*********************************************************************//** * @brief * The convertTogglePeriod2RPM function runs through the list of the fans * to get the FPGA pulse from them and converts them to RPM. - * @details Inputs: fansStatus, toggle2RPMCoefficient + * @details Inputs: none * @details Outputs: fansStatus * @return none ************************************************************************/ @@ -370,90 +444,103 @@ // Otherwise, convert the pulse to RPM if ( togglePeriods[ fan ] == FANS_ZERO_RPM_TOGGLE_PERIOD_VALUE ) { - fansStatus.rpm[ fan ] = 0; + fansStatus.rpm[ fan ].data = 0; } else { // Convert toggle period to RPM - fansStatus.rpm[ fan ] = TOGGLE_PERIOD_2_RPM_COEFFICIENT / togglePeriods[ fan ]; + fansStatus.rpm[ fan ].data = TOGGLE_PERIOD_2_RPM_COEFFICIENT / togglePeriods[ fan ]; } } } /*********************************************************************//** * @brief * The monitorFans function monitors the fans for RPM. - * @details Inputs: fansStatus - * @details Outputs: none + * @details Inputs: rpmAlarmStartTimer, hasAlarmBeenRaised + * @details Outputs: rpmAlarmStartTimer, hasAlarmBeenRaised * @return none *************************************************************************/ static void monitorFans( void ) { FAN_NAMES_T fan; + F32 rpm = 0.0; + BOOL isAlarmTriggered = FALSE; + BOOL isFanRPMOutOfRange = FALSE; - if ( ++fansMonitorCounter >= FANS_MONITOR_INTERVAL_COUNT ) + // The RPM is expected to be 5500 @ 100% duty cycle + // The nominal RPM = duty cycle * 5500 / 1.0 + // The RPM tolerance is -25% to +50% of the nominal RPM + F32 dutyCycle = ( OVERRIDE_RESET == fansStatus.dutyCycle.override ? fansStatus.dutyCycle.data : fansStatus.dutyCycle.ovData ); + F32 fansNominalRPM = dutyCycle * FANS_MAX_ALLOWED_RPM; + F32 fansMinAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MIN_RPM_OUT_OF_RANGE_TOL ); + F32 fansMaxAllowedRPM = fansNominalRPM + ( fansNominalRPM * FANS_MAX_RPM_OUT_OF_RANGE_TOL ); + + for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) { - // The RPM is expected to be 5500 @ 100% duty cycle - // The nominal RPM = duty cycle * 5500 / 1.0 - // The RPM tolerance is -25% to +50% of the nominal RPM - F32 fansNominalRPM = fansStatus.targetDutyCycle * FANS_MAX_ALLOWED_RPM; - F32 fansMinAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MIN_RPM_OUT_OF_RANGE_TOL ); - F32 fansMaxAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MAX_RPM_OUT_OF_RANGE_TOL ); + rpm = getMeasuredFanRPM( fan ); + isFanRPMOutOfRange |= ( ( rpm < fansMinAllowedRPM ) || ( ( rpm > fansMaxAllowedRPM ) ) ? TRUE : FALSE ); + } - convertTogglePeriod2RPM(); + // If the fans alarm has been raised already, do not raise again + if ( FALSE == hasAlarmBeenRaised ) + { + isAlarmTriggered = isPersistentAlarmTriggered( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, isFanRPMOutOfRange ); - for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) + if ( TRUE == isAlarmTriggered ) { - BOOL const fanRpmOutOfRange = ( fansStatus.rpm[ fan ] < fansMinAllowedRPM ) || ( fansStatus.rpm[ fan ] > fansMaxAllowedRPM ); - checkPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, fanRpmOutOfRange, fansStatus.rpm[ fan ], FANS_MAX_ALLOWED_RPM ); - } + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, rpm ) + // Set the alarm flag to TRUE + hasAlarmBeenRaised = TRUE; - fansMonitorCounter = 0; + // If the alarm has been raised but the start time of the alarm has not been set, set the alarm start timer + if ( 0 == rpmAlarmStartTime ) + { + rpmAlarmStartTime = getMSTimerCount(); + } + } } -} - -/*********************************************************************//** - * @brief - * The getPublishFansDataInterval function gets the fans data publish interval. - * @details Inputs: fansPublishInterval - * @details Outputs: none - * @return data publish time interval in counts - *************************************************************************/ -static U32 getPublishFansDataInterval( void ) -{ - U32 result = fansPublishInterval.data; - - if ( OVERRIDE_KEY == fansPublishInterval.override ) + // If the alarm has been raised and the alarm has been silent for at least a day, set the flag to FALSE + // This way, if the fans RPM are out of range the alarm will be raised again. This alarm is supposed to be raised + // and remain silent for a defined period of time. + else { - result = fansPublishInterval.ovData; - } + S32 elapsedTime = rpmAlarmStartTime - rpmAlarmStartTimeOffset; - return result; + if ( calcTimeSince( elapsedTime ) >= SECONDS_IN_A_DAY * MS_PER_SECOND ) + { + hasAlarmBeenRaised = FALSE; + rpmAlarmStartTime = 0; + rpmAlarmStartTimeOffset = 0; + } + } } /*********************************************************************//** * @brief * The publishFansData function publishes the fans data at the specified * time interval. - * @details Inputs: dataPublishCounter - * @details Outputs: dataPublishCounter + * @details Inputs: fansPublishCounter, fansPublishInterval + * @details Outputs: fansPublishCounter * @return none *************************************************************************/ static void publishFansData( void ) { - if ( ++fansPublishCounter > getPublishFansDataInterval() ) + if ( ++fansPublishCounter >= getU32OverrideValue( &fansPublishInterval ) ) { FANS_DATA_T fansData; - fansData.fansTargetDutyCycle = fansStatus.targetDutyCycle * FRACTION_TO_PERCENT_FACTOR; - fansData.fanInlet1RPM = fansStatus.rpm[ FAN_INLET_1 ]; - fansData.fanInlet2RPM = fansStatus.rpm[ FAN_INLET_2 ]; - fansData.fanInlet3RPM = fansStatus.rpm[ FAN_INLET_3 ]; - fansData.fanOutlet1RPM = fansStatus.rpm[ FAN_OUTLET_1 ]; - fansData.fanOutlet2RPM = fansStatus.rpm[ FAN_OUTLET_2 ]; - fansData.fanOutlet3RPM = fansStatus.rpm[ FAN_OUTLET_3 ]; + fansData.dutyCycle = ( OVERRIDE_RESET == fansStatus.dutyCycle.override ? fansStatus.dutyCycle.data : fansStatus.dutyCycle.ovData ) * FRACTION_TO_PERCENT_FACTOR; + fansData.targetFansRPM = fansStatus.targetRPM; + fansData.fanInlet1RPM = getMeasuredFanRPM( FAN_INLET_1 ); + fansData.fanInlet2RPM = getMeasuredFanRPM( FAN_INLET_2 ); + fansData.fanInlet3RPM = getMeasuredFanRPM( FAN_INLET_3 ); + fansData.fanOutlet1RPM = getMeasuredFanRPM( FAN_OUTLET_1 ); + fansData.fanOutlet2RPM = getMeasuredFanRPM( FAN_OUTLET_2 ); + fansData.fanOutlet3RPM = getMeasuredFanRPM( FAN_OUTLET_3 ); + fansData.rpmAlarmTimeOffset = calcTimeSince( rpmAlarmStartTime - rpmAlarmStartTimeOffset ); - broadcastFansData( &fansData ); + broadcastData( MSG_ID_DG_FANS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&fansData, sizeof( FANS_DATA_T ) ); fansPublishCounter = 0; } @@ -512,4 +599,126 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetFanRPMOverride function overrides the RPM of a fan. + * @details Inputs: none + * @details Outputs: fansStatus + * @param fanId fan ID + * @param rpm the RPM override value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFanRPMOverride( U32 fanId, F32 rpm ) +{ + BOOL result = FALSE; + + if ( fanId < NUM_OF_FANS_NAMES ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fansStatus.rpm[ fanId ].ovData = rpm; + fansStatus.rpm[ fanId ].override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetFanRPMOverride function resets the override value of a fan. + * @details Inputs: fansStatus + * @details Outputs: fansStatus + * @param fanId fan index + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetFanRPMOverride( U32 fanId ) +{ + BOOL result = FALSE; + + if ( fanId < NUM_OF_FANS_NAMES ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fansStatus.rpm[ fanId ].ovData = fansStatus.rpm[ fanId ].ovInitData; + fansStatus.rpm[ fanId ].override = OVERRIDE_RESET; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetFanRPMAlarmStartTimestamp function set the fan RPM alarm start + * time offset. + * @details Inputs: none + * @details Outputs: rpmAlarmStartTimeOffset + * @param milliSeconds the milliseconds the time to be offset + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFanRPMAlarmStartTimestamp( U32 milliSeconds ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + rpmAlarmStartTimeOffset = milliSeconds; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetFansDutyCycleOverride function overrides fans duty cycle + * @details Inputs: none + * @details Outputs: fansStatus + * @param value the duty cycle value to be overridden + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFansDutyCycleOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if( ( value >= FANS_MIN_DUTY_CYCLE ) && ( value <= FANS_MAX_DUTY_CYCLE ) ) + { + fansStatus.dutyCycle.ovData = value; + fansStatus.dutyCycle.override = OVERRIDE_KEY; + + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetFansDutyCycleOverride function resets the fans duty cycle + * override + * @details Inputs: none + * @details Outputs: fansStatus + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetFansDutyCycleOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + fansStatus.dutyCycle.override = OVERRIDE_RESET; + fansStatus.dutyCycle.ovData = 0.0; + + result = TRUE; + } + + return result; +} + /**@}*/