Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r68aefeff8890cdfa956c7bfdf0d4505b4ac25cb7 -r37a9fd8f15e413db5337371a7d1a1cb65567af7c --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 68aefeff8890cdfa956c7bfdf0d4505b4ac25cb7) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 37a9fd8f15e413db5337371a7d1a1cb65567af7c) @@ -1,20 +1,21 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-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) Sean Nash -* @date (last) 12-Nov-2021 +* @author (last) Darren Cox +* @date (last) 10-Mar-2022 * * @author (original) Dara Navaei * @date (original) 04-Aug-2021 * ***************************************************************************/ +#include // For fabs #include "etpwm.h" #include "Fans.h" @@ -53,31 +54,32 @@ #define FANS_MIN_ALLOWED_RPM 150 ///< Fans max allowed RPM value. #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 DATA_PUBLISH_COUNTER_START_COUNT 15 ///< Data publish counter start count. /// 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 - F32 targetRPM; ///< Fan's target RPM - OVERRIDE_F32_T rpm[ NUM_OF_FANS_NAMES ]; ///< Fan's current tachometers reading in RPM + OVERRIDE_F32_T dutyCycle; ///< Fan's target duty cycle that was fed to the fans. + F32 targetRPM; ///< Fan's 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 BOOL isPOSTComplete = FALSE; ///< Flag that indicates whether POST is complete or not. -static BOOL hasAlarmBeenRaised = FALSE; ///< Flag that indicates whether RPM out of range alarm has been raised once. +static FANS_EXEC_STATES_T fansExecState; ///< Fans exec state. +static U32 fansControlCounter; ///< Fans control interval counter. +static U32 fansPublishCounter; ///< Fans data publish interval counter. +static BOOL isPOSTComplete; ///< Flag that indicates whether POST is complete or not. +static BOOL hasAlarmBeenRaised; ///< Flag that indicates whether RPM out of range alarm has been raised once. static OVERRIDE_U32_T rpmAlarmStartTimeOffset = { 0, 0, 0, 0}; ///< RPM out of range alarm start time offset. -static U32 rpmAlarmStartTime = 0; ///< RPM alarm start time. +static U32 rpmAlarmStartTime; ///< RPM alarm start time. /// 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 ); @@ -115,20 +117,23 @@ // Initialize the variables fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; fansControlCounter = 0; - fansPublishCounter = 0; + fansPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; isPOSTComplete = FALSE; hasAlarmBeenRaised = FALSE; rpmAlarmStartTime = 0; rpmAlarmStartTimeOffset.data = 0; rpmAlarmStartTimeOffset.ovData = 0; rpmAlarmStartTimeOffset.ovInitData = 0; rpmAlarmStartTimeOffset.override = 0; + fansStatus.dutyCycle.data = 0.0; + fansStatus.dutyCycle.ovInitData = 0.0; + fansStatus.dutyCycle.ovData = 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.targetDutyCycle = 0.0; - fansStatus.targetRPM = 0.0; fansStatus.rpm[ fan ].data = 0.0; fansStatus.rpm[ fan ].ovData = 0.0; fansStatus.rpm[ fan ].ovInitData = 0.0; @@ -245,11 +250,6 @@ state = FANS_EXEC_STATE_RUN_STATE; } -#ifndef _VECTORCAST_ // To skip the wait for POST and start running. - // TODO REMOVE - state = FANS_EXEC_STATE_RUN_STATE; - // TODO REMOVE -#endif return state; } @@ -266,7 +266,7 @@ 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 ) + 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(); @@ -286,43 +286,48 @@ // 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 from the duty cycle. - fansStatus.targetRPM = fansStatus.targetDutyCycle * FANS_MAX_ALLOWED_RPM; + fansStatus.targetRPM = fansStatus.dutyCycle.data * FANS_MAX_ALLOWED_RPM; // Set the PWM to inlet and outlet fans - setInletFansDutyCycle( fansStatus.targetDutyCycle ); + setInletFansDutyCycle( fansStatus.dutyCycle.data ); // Reset the counter fansControlCounter = 0; } + else if ( OVERRIDE_KEY == fansStatus.dutyCycle.override ) + { + // The fans are in override mode set the override duty cycle + setInletFansDutyCycle( fansStatus.dutyCycle.ovData ); + } return state; } @@ -418,7 +423,8 @@ // 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 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 ); @@ -429,7 +435,10 @@ isFanRPMOutOfRange |= ( ( rpm < fansMinAllowedRPM ) || ( rpm > fansMaxAllowedRPM ) ? TRUE : FALSE ); } - if ( FALSE == hasAlarmBeenRaised ) + // Check if the alarm has not been raise yet, raise it then + // Before checking for the alarm, the POST must be completed. The fans POST is after the temperatures POST that should get their + // calibration to be able to apply them and calculate the temperatures that are used to alarm the fans. + if ( ( FALSE == hasAlarmBeenRaised ) && ( TRUE == isPOSTComplete ) ) { isAlarmTriggered = isPersistentAlarmTriggered( ALARM_ID_HD_FAN_RPM_OUT_OF_RANGE, isFanRPMOutOfRange ); @@ -438,20 +447,32 @@ SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_FAN_RPM_OUT_OF_RANGE, rpm ) // Set the alarm flag to TRUE hasAlarmBeenRaised = TRUE; + + // 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(); + } } - // If the alarm has been raised but the start time of the alarm has not been set, set the alarm start timer - if ( ( TRUE == hasAlarmBeenRaised ) && ( 0 == rpmAlarmStartTime ) ) - { - rpmAlarmStartTime = getMSTimerCount(); - } } // 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 if ( ( TRUE == hasAlarmBeenRaised ) && ( ( calcTimeSince( rpmAlarmStartTime ) + getRPMAlarmStartTimeOffset() ) >= SECONDS_IN_A_DAY * MS_PER_SECOND ) ) + else { - hasAlarmBeenRaised = FALSE; - rpmAlarmStartTime = 0; + // Get the offset time since the last alarm. If the offset time has been overridden, then do not include the time that the alarm was raised first. + // Overrides are used to verify the code so what is sent to the firmware from override is intended to be the actual time so check whether the alarm is + // raised properly or not. Adding the start time of the alarm might cause inaccuracy in the verification process. + // For instance, if 86390 seconds is overridden to make sure the alarm is not raise before 24 hours or 86400, if the rpmAlarmStartTime is added to it + // it might make the time to be greater than 86400 seconds and therefore the alarm is raised again while it is not expected. + U32 offsetTime = getRPMAlarmStartTimeOffset(); + U32 elapsedTime = ( OVERRIDE_KEY == rpmAlarmStartTimeOffset.override ? offsetTime : calcTimeSince( rpmAlarmStartTime ) + offsetTime ); + + if ( elapsedTime >= SECONDS_IN_A_DAY * MS_PER_SECOND ) + { + hasAlarmBeenRaised = FALSE; + rpmAlarmStartTime = 0; + } } } @@ -507,7 +528,7 @@ { FANS_DATA_T data; - data.fansDutyCycle = fansStatus.targetDutyCycle * FRACTION_TO_PERCENT_FACTOR; + data.fansDutyCycle = ( OVERRIDE_RESET == fansStatus.dutyCycle.override ? fansStatus.dutyCycle.data : fansStatus.dutyCycle.ovData ) * FRACTION_TO_PERCENT_FACTOR; data.fansTargetRPM = fansStatus.targetRPM; data.fanInlet1RPM = getMeasuredFanRPM( FAN_INLET_1 ); data.rpmAlarmTimeOffset = getRPMAlarmStartTimeOffset(); @@ -628,17 +649,16 @@ * start time offset. * @details Inputs: none * @details Outputs: rpmAlarmStartTimeOffset - * @param hours hours to override - * @param minutes minutes to override + * @param seconds seconds to override * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetFanRPMAlarmStartTimeOffsetOverride( U32 hours, U32 minutes ) +BOOL testSetFanRPMAlarmStartTimeOffsetOverride( U32 seconds ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { - rpmAlarmStartTimeOffset.ovData = rpmAlarmStartTimeOffset.ovData + ( ( hours * MIN_PER_HOUR * SEC_PER_MIN ) + ( minutes * SEC_PER_MIN ) ) * MS_PER_SECOND; + rpmAlarmStartTimeOffset.ovData = seconds * MS_PER_SECOND; rpmAlarmStartTimeOffset.override = OVERRIDE_KEY; result = TRUE; @@ -671,5 +691,54 @@ 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; +} + /**@}*/