/************************************************************************** * * Copyright (c) 2019-2020 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 Heaters.c * * @author (last) Quang Nguyen * @date (last) 14-Sep-2020 * * @author (original) Dara Navaei * @date (original) 23-Apr-2020 * ***************************************************************************/ #include #include "etpwm.h" #include "AlarmMgmt.h" #include "Heaters.h" #include "ROPump.h" #include "PIControllers.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" #ifdef ENABLE_DIP_SWITCHES #include "mibspi.h" #include "FPGA.h" #endif /** * @addtogroup Heaters * @{ */ // ********** private definitions ********** #define MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE 0.89 ///< Main primary heater (heater A) max duty cycle (89%). #define SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE 0.50 ///< Small Primary heater (heater B) max duty cycle (50%). #define TRIMMER_HEATER_MAX_DUTY_CYCLE 0.50 ///< Trimmer heater max duty cycle (50%). #define HEATERS_MIN_DUTY_CYCLE 0.00 ///< Primary and trimmer heaters minimum duty cycle (0.00%). #define PRIMARY_HEATERS_P_COEFFICIENT 0.02 ///< Primary heaters proportional coefficient. #define PRIMARY_HEATERS_I_COEFFICIENT 0.001 ///< Primary heaters integral coefficient. #define TRIMMER_HEATER_P_COEFFICIENT 0.02 ///< Trimmer heater proportional coefficient. #define TRIMMER_HEATER_I_COEFFICIENT 0.001 ///< Trimmer heater integral coefficient. #define CONTROLLER_CHECK_INTERVAL_COUNT 10U ///< Time interval count to check the PI controller. #define TEMP_SENSORS_INTERVAL_COUNT 10U ///< Temperature sensors interval count. #define HEATERS_DATA_PUBLISH_INTERVAL (500 / TASK_GENERAL_INTERVAL ) ///< Heaters data publish interval. #define SMALL_PRIMARY_AND_TRIMMER_HEATERS_POST_TARGET_TEMPERATURE 40U ///< Small primary and trimmer heaters target temperature during POST. #define MAIN_PRIMARY_HEATER_POST_TARGET_TEMPERATURE 35U ///< Main primary heater target temperature during POST. #define HEATERS_POST_HEAT_UP_TIME_SECONDS 50U ///< The time that the heaters are heated up to reach to the target temperature during POST. #define HEATERS_POST_TEMPERATURE_TOLERANCE 1U ///< Tolerance of the sensors to the target temperature during POST. #define MINIMUM_TARGET_TEMPERATURE 10U ///< Minimum allowed target temperature for the heaters. #define MAXIMUM_TARGET_TEMPERATURE 90U ///< Maximum allowed target temperature for the heaters. /// Heaters self-test enums typedef enum heaters_self_test_states { HEATERS_SELF_TEST_START = 0, ///< Heaters self-test start state HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS, ///< Heaters self-test small primary and trimmer heaters state HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER, ///< Heaters self-test start main primary state HEATERS_SELF_TEST_COMPLETE, ///< Heaters self-test complete state NUM_OF_HEATERS_SELF_TEST_STATES ///< Number of heaters self-test states } HEATERS_SELF_TEST_STATES_T ; /// Primary heaters exec states typedef enum primary_heaters_exec_states { PRIMARY_HEATERS_EXEC_STATE_OFF = 0, ///< Primary heaters exec state off PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET, ///< Primary heaters exec state control to target (PI controller state) NUM_OF_PRIMARY_HEATERS_EXEC_STATES ///< Number of primary heaters exec states } PRIMARY_HEATERS_EXEC_STATES_T; /// Trimmer heater exec states typedef enum trimmer_heater_exec_states { TRIMMER_HEATER_EXEC_STATE_OFF = 0, ///< Trimmer heater exec state off TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET, ///< Trimmer heater exec state control to target (PI controller state) NUM_OF_TRIMMER_HEATER_EXEC_STATES ///< Number of trimmer heater exec states } TRIMMER_HEATER_EXEC_STATES_T; /// Name of the heaters states typedef enum name_of_heaters { PRIMARY_HEATER = 0, ///< Primary heater TRIMMER_HEATER, ///< Trimmer heater NUM_OF_HEATERS ///< Number of heaters } NAME_OF_HEATER_T; // ********** private data ********** static SELF_TEST_STATUS_T heatersSelfTestResult; ///< Heaters self-test results. static HEATERS_SELF_TEST_STATES_T heatersSelfTestState; ///< Heaters self-test state. static PRIMARY_HEATERS_EXEC_STATES_T primaryHeatersExecState; ///< Primary heaters exec state. static TRIMMER_HEATER_EXEC_STATES_T trimmerHeaterExecState; ///< Trimmer heater exec state. static F32 primaryHeaterTargetTemperature; ///< Primary heaters target temperature. static F32 trimmerHeaterTargetTemperature; ///< Trimmer heater target temperature. static F32 mainPrimaryHeaterDutyCycle; ///< Main primary heater duty cycle. static F32 smallPrimaryHeaterDutyCycle; ///< Small primary heater duty cycle. static F32 trimmerHeaterDutyCycle; ///< Trimmer heater duty cycle. static U32 primaryHeaterTimerCounter; ///< Primary heater timer counter. static U32 trimmerHeaterTimerCounter; ///< Trimmer heater timer counter. static U32 dataPublicationTimerCounter; ///< Data publication timer counter. static BOOL isPrimaryHeaterOn; ///< Flag to show if the primary heater is on. static BOOL isTrimmerHeaterOn; ///< Flag to show if the trimmer heater is on. static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. static U32 selfTestElapsedTime; ///< Self-test elapsed time variable. static BOOL hasStartPrimaryHeaterRequested; ///< Start primary heater request flag. static BOOL hasStartTrimmerHeaterRequested; ///< Start trimmer heater request flag. // ********** private function prototypes ********** static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestStart( void ); static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters( void ); static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestMainPrimaryHeater( void ); static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateOff( void ); static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateControlToTarget( void ); static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterStateOff( void ); static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterControlToTarget( void ); static void setMainPrimaryHeaterPWM( F32 pwm ); static void setSmallPrimaryHeaterPWM( F32 pwm ); static void setTrimmerHeaterPWM( F32 pwm ); static void resetHeaterState( NAME_OF_HEATER_T heater ); static void publishHeatersData( void ); static U32 getPublishHeatersDataInterval( void ); // TODO: Remove the below code. FOR TESTING ONLY #define PRIMARY_HEATER_MIBSPI1_PORT_MASK 0x00000002 // (CS1 - re-purposed as input GPIO) #define TOGGLEPRIMAYHEATER() ( ( mibspiREG1->PC2 & PRIMARY_HEATER_MIBSPI1_PORT_MASK ) != 0 ) //TODO: Remove the above code. FOR TESTING ONLY /*********************************************************************//** * @brief * The initHeaters function initializes the variables and the PI controllers * for the primary and trimmer heaters. * @details Inputs: none * @details Outputs: Heaters module initialized * @return none *************************************************************************/ void initHeaters( void ) { heatersSelfTestState = HEATERS_SELF_TEST_START; primaryHeatersExecState = PRIMARY_HEATERS_EXEC_STATE_OFF; trimmerHeaterExecState = TRIMMER_HEATER_EXEC_STATE_OFF; primaryHeaterTargetTemperature = 0.0; trimmerHeaterTargetTemperature = 0.0; primaryHeaterTimerCounter = 0; trimmerHeaterTimerCounter = 5; dataPublicationTimerCounter = 0; isPrimaryHeaterOn = FALSE; isTrimmerHeaterOn = FALSE; selfTestElapsedTime = 0; // Initialize the PI controller for the primary heaters initializePIController( PI_CONTROLLER_ID_PRIMARY_HEATER, HEATERS_MIN_DUTY_CYCLE, PRIMARY_HEATERS_P_COEFFICIENT, PRIMARY_HEATERS_I_COEFFICIENT, HEATERS_MIN_DUTY_CYCLE, MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE + SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ); // Initialize the PI controller for the trimmer heater initializePIController( PI_CONTROLLER_ID_TRIMMER_HEATER, HEATERS_MIN_DUTY_CYCLE, TRIMMER_HEATER_P_COEFFICIENT, TRIMMER_HEATER_I_COEFFICIENT, HEATERS_MIN_DUTY_CYCLE, TRIMMER_HEATER_MAX_DUTY_CYCLE ); } /*********************************************************************//** * @brief * The setPrimaryHeaterTargetTemperature function sets the primary heater * target temperature. * @details Inputs: none * @details Outputs: primaryHeaterTargetTemperature * @param targetTemp target temperature for the primary heater * @return none *************************************************************************/ void setPrimaryHeaterTargetTemperature( F32 targetTemp ) { primaryHeaterTargetTemperature = targetTemp; } /*********************************************************************//** * @brief * The setTrimmerHeaterTargetTemperature function sets the trimmer heater * target temperature. * @details Inputs: none * @details Outputs: trimmerHeaterTargetTemperature * @param targetTemp target temperature for the trimmer heater * @return none *************************************************************************/ void setTrimmerHeaterTargetTemperature( F32 targetTemp ) { trimmerHeaterTargetTemperature = targetTemp; } /*********************************************************************//** * @brief * The startPrimaryHeater function starts the primary heaters. It resets * the primary heaters state and sets the main primary heater duty cycle. * @details Inputs: primaryHeaterTargetTemperature * @details Outputs: hasStartPrimaryHeaterRequested * @return status *************************************************************************/ BOOL startPrimaryHeater( void ) { BOOL status = FALSE; if ( ( primaryHeaterTargetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( primaryHeaterTargetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) { #ifndef DISABLE_HEATERS_AND_TEMPS hasStartPrimaryHeaterRequested = TRUE; #endif status = TRUE; } return status; } /*********************************************************************//** * @brief * The startTrimmerHeater function starts the trimmer heater. It resets the * trimmer heater's state and sets the duty cycle of the trimmer heater. * @details Inputs: trimmerHeaterTargetTemperature * @details Outputs: hasStartTrimmerHeaterRequested * @return status *************************************************************************/ BOOL startTrimmerHeater( void ) { BOOL status = FALSE; if ( ( trimmerHeaterTargetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( trimmerHeaterTargetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) { #ifndef DISABLE_HEATERS_AND_TEMPS hasStartTrimmerHeaterRequested = TRUE; #endif status = TRUE; } return status; } /*********************************************************************//** * @brief * The stopPrimaryHeater function stops the primary heater. * @details Inputs: none * @details Outputs: Primary heater stops * @return none *************************************************************************/ void stopPrimaryHeater( void ) { mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); isPrimaryHeaterOn = FALSE; } /*********************************************************************//** * @brief * The stopTrimmerHeater function stops the trimmer heater. * @details Inputs: none * @details Outputs: Trimmer heater stops * @return none *************************************************************************/ void stopTrimmerHeater( void ) { trimmerHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; setTrimmerHeaterPWM( trimmerHeaterDutyCycle ); isTrimmerHeaterOn = FALSE; } /*********************************************************************//** * @brief * The execHeatersMonitor function turns off the heaters when RO pump is not on. * @details Inputs: none * @details Outputs: Turns off the heaters when RO pump is not on * @return none *************************************************************************/ void execHeatersMonitor( void ) { // If the RO pump is not on, turn off the heaters if ( ! isReverseOsmosisPumpOn() ) { #ifndef ENABLE_DIP_SWITCHES #ifndef EMC_TEST_BUILD stopPrimaryHeater(); // TODO - this is so immediate - if other module requests RO pump on and start heater, this monitor may stop the heater request before RO pump has a chance to start stopTrimmerHeater(); #endif #endif } } /*********************************************************************//** * @brief * The execHeatersSelfTest function executes the heaters' self-test state machine. * @details Inputs: heatersSelfTestState * @details Outputs: heatersSelfTestState * @return heatersSelfTestState *************************************************************************/ SELF_TEST_STATUS_T execHeatersSelfTest( void ) { switch ( heatersSelfTestState ) { case HEATERS_SELF_TEST_START: heatersSelfTestState = handleHeatersSelfTestStart(); break; case HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS: heatersSelfTestState = handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters(); break; case HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER: heatersSelfTestState = handleHeatersSelfTestMainPrimaryHeater(); break; case HEATERS_SELF_TEST_COMPLETE: // POST is done. Do nothing break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_SELF_TEST_INVALID_STATE, heatersSelfTestState ); heatersSelfTestState = HEATERS_SELF_TEST_COMPLETE; break; } return heatersSelfTestResult; } /*********************************************************************//** * @brief * The execPrimaryHeaters function executes the primary heaters' state machine. * @details Inputs: primaryHeatersExecState * @details Outputs: primaryHeatersExecState * @return none *************************************************************************/ void execPrimaryHeaters( void ) { switch ( primaryHeatersExecState ) { case PRIMARY_HEATERS_EXEC_STATE_OFF: primaryHeatersExecState = handlePrimaryHeaterStateOff(); break; case PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET: primaryHeatersExecState = handlePrimaryHeaterStateControlToTarget(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_PRIMARY_HEATER_EXEC_INVALID_STATE, primaryHeatersExecState ); primaryHeatersExecState = PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET; break; } } /*********************************************************************//** * @brief * The execTrimmerHeater function executes the trimmer heater's state machine. * @details Inputs: trimmerHeaterExecState * @details Outputs: trimmerHeaterExecState * @return none *************************************************************************/ void execTrimmerHeater( void ) { switch ( trimmerHeaterExecState ) { case TRIMMER_HEATER_EXEC_STATE_OFF: trimmerHeaterExecState = handleTrimmerHeaterStateOff(); break; case TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET: trimmerHeaterExecState = handleTrimmerHeaterControlToTarget(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_TRIMMER_HEATER_EXEC_INVALID_STATE, trimmerHeaterExecState ); trimmerHeaterExecState = TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET; break; } } /*********************************************************************//** * @brief * The handleHeatersSelfTestStart function starts the small primary and * the trimmer heaters for self-test. * @details Inputs: heatersSelfTestResult, selfTestElapsedTime * @details Outputs: heatersSelfTestResult, selfTestElapsedTime * @return state (HEATERS_SELF_TEST_STATES_T) *************************************************************************/ static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestStart( void ) { // Code temporarily disabled since POST is not tested yet // TODO once POST is tested and implemented, remove #ifndef #ifndef _VECTORCAST_ heatersSelfTestResult = SELF_TEST_STATUS_PASSED; return HEATERS_SELF_TEST_COMPLETE; #else heatersSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; setSmallPrimaryHeaterPWM( SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ); setTrimmerHeaterPWM( TRIMMER_HEATER_MAX_DUTY_CYCLE ); selfTestElapsedTime = getMSTimerCount(); return HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS; #endif } /*********************************************************************//** * @brief * The handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters function checks if * the time on the small primary and trimmer heaters has elapsed. If time has * elapsed, it checks the thermocouple temperature shared among the two * heaters. If they are in range, it sets the main primary heater and transitions * to the next state. If it fails, it sets an alarm and fails the test. * @details Inputs: heatersSelfTestResult, selfTestElapsedTime * @details Outputs: heatersSelfTestResult, selfTestElapsedTime * @return state (HEATERS_SELF_TEST_STATES_T) *************************************************************************/ static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters( void ) { HEATERS_SELF_TEST_STATES_T state = HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS; if ( didTimeout( selfTestElapsedTime, HEATERS_POST_HEAT_UP_TIME_SECONDS ) ) { setSmallPrimaryHeaterPWM( 0 ); setTrimmerHeaterPWM( 0 ); F32 convertedTemperature = getTemperatureValue( TEMPSENSORS_TRIMMER_HEATER_INTERNAL ); if ( fabs( convertedTemperature - SMALL_PRIMARY_AND_TRIMMER_HEATERS_POST_TARGET_TEMPERATURE ) > HEATERS_POST_TEMPERATURE_TOLERANCE ) { //TODO alarm // TODO POST failed heatersSelfTestResult = SELF_TEST_STATUS_FAILED; state = HEATERS_SELF_TEST_COMPLETE; } else { setMainPrimaryHeaterPWM( MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ); selfTestElapsedTime = getMSTimerCount(); state = HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER; } } return state; } /*********************************************************************//** * @brief * The handleHeatersSelfTestMainPrimaryHeater function checks if the time * on the main primary heater has elapsed. When the time has elapsed, it * checks to ensure the thermocouple temperature is within the tolerance * of the target temperature. It then transitions to the complete state. * @details Inputs: heatersSelfTestResult * @details Outputs: heatersSelfTestResult * @return state (HEATERS_SELF_TEST_STATES_T) *************************************************************************/ static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestMainPrimaryHeater( void ) { HEATERS_SELF_TEST_STATES_T state = HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER; if ( didTimeout( selfTestElapsedTime, HEATERS_POST_HEAT_UP_TIME_SECONDS ) ) { setMainPrimaryHeaterPWM( 0 ); F32 convertedTemperature = getTemperatureValue( TEMPSENSORS_PRIMARY_HEATER_INTERNAL ); if ( fabs( convertedTemperature - MAIN_PRIMARY_HEATER_POST_TARGET_TEMPERATURE ) > HEATERS_POST_TEMPERATURE_TOLERANCE ) { //TODO alarm // TODO POST failed heatersSelfTestResult = SELF_TEST_STATUS_FAILED; } else { heatersSelfTestResult = SELF_TEST_STATUS_PASSED; } state = HEATERS_SELF_TEST_COMPLETE; } return state; } /*********************************************************************//** * @brief * The handlePrimaryHeaterStateOff function handles the primary heaters at * off state. * @details Inputs: hasStartPrimaryHeaterRequested, isPrimaryHeaterOn * @details Outputs: state (PRIMARY_HEATERS_EXEC_STATES_T), isPrimaryHeaterOn * @return state (PRIMARY_HEATERS_EXEC_STATES_T) *************************************************************************/ static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateOff( void ) { PRIMARY_HEATERS_EXEC_STATES_T state = PRIMARY_HEATERS_EXEC_STATE_OFF; // TODO for testing only. remove #ifdef DEBUG_ENABLED #ifdef ENABLE_DIP_SWITCHES #ifndef EMC_TEST_BUILD if ( TOGGLEPRIMAYHEATER() ) { setPrimaryHeaterTargetTemperature( 37 ); startPrimaryHeater(); F32 pumpPWM = 1; etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( pumpPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); F32 fanPWM = 0.25; etpwmSetCmpA( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); etpwmSetCmpB( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); hasStartPrimaryHeaterRequested = TRUE; } #endif #endif #endif // TODO remove this code for testing if ( hasStartPrimaryHeaterRequested ) { resetHeaterState( PRIMARY_HEATER ); setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); isPrimaryHeaterOn = TRUE; hasStartPrimaryHeaterRequested = FALSE; state = PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET; } publishHeatersData(); return state; } /*********************************************************************//** * @brief * The handlePrimaryHeaterStateControlToTarget function handles the primary * heaters at control state when the heaters are active. * @details Inputs: primaryHeaterTimerCounter, mainPrimaryHeaterDutyCycle, * smallPrimaryHeaterDutyCycle, isPrimaryHeaterOn * @details Outputs: primaryHeaterTimerCounter, mainPrimaryHeaterDutyCycle, * smallPrimaryHeaterDutyCycle * @return state (PRIMARY_HEATERS_EXEC_STATES_T) *************************************************************************/ static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateControlToTarget( void ) { PRIMARY_HEATERS_EXEC_STATES_T state = PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET; if ( ++primaryHeaterTimerCounter >= CONTROLLER_CHECK_INTERVAL_COUNT ) { F32 outletTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); mainPrimaryHeaterDutyCycle = runPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, primaryHeaterTargetTemperature, outletTemp ); if ( mainPrimaryHeaterDutyCycle >= MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ) { // The duty cycle from the PI controller was greater than max duty cycle of the main primary // heater. So subtract the remaining from the max main primary heater duty cycle and set // the rest to the small primary heater smallPrimaryHeaterDutyCycle = mainPrimaryHeaterDutyCycle - MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; mainPrimaryHeaterDutyCycle = MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); } else { setMainPrimaryHeaterPWM( mainPrimaryHeaterDutyCycle ); smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; setSmallPrimaryHeaterPWM( smallPrimaryHeaterDutyCycle ); } primaryHeaterTimerCounter = 0; } publishHeatersData(); // TODO remove this code #ifdef DEBUG_ENABLED #ifdef ENABLE_DIP_SWITCHES #ifndef EMC_TEST_BUILD if ( !TOGGLEPRIMAYHEATER() ) { stopPrimaryHeater(); F32 pumpPWM = 0; etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( pumpPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); F32 fanPWM = 0; etpwmSetCmpA( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); etpwmSetCmpB( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } #endif #endif #endif // TODO Remove this code if ( ! isPrimaryHeaterOn ) { state = PRIMARY_HEATERS_EXEC_STATE_OFF; } return state; } /*********************************************************************//** * @brief * The handleTrimmerHeaterStateOff function handles the trimmer heater at * off state. * @details Inputs: hasStartTrimmerHeaterRequested, isTrimmerHeaterOn * @details Outputs: state (TRIMMER_HEATER_EXEC_STATES_T), isTrimmerHeaterOn * @return state (TRIMMER_HEATER_EXEC_STATES_T) *************************************************************************/ static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterStateOff( void ) { TRIMMER_HEATER_EXEC_STATES_T state = TRIMMER_HEATER_EXEC_STATE_OFF; // TODO for testing only. remove #ifdef DEBUG_ENABLED #ifdef ENABLE_DIP_SWITCHES #ifndef EMC_TEST_BUILD // if ( TOGGLEPRIMAYHEATER() ) // { //setTrimmerHeaterTargetTemperature( 38 ); //startTrimmerHeater(); //F32 pumpPWM = 1; //etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( pumpPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //temporaryStartROPump(); //temporaryStartFan(); //F32 fanPWM = 0.25; //etpwmSetCmpA( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //etpwmSetCmpB( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //temporaryStartROPump(); //temporaryStartFan(); // } #endif #endif #endif // TODO remove this code for testing if ( hasStartTrimmerHeaterRequested ) { resetHeaterState( TRIMMER_HEATER ); isTrimmerHeaterOn = TRUE; hasStartTrimmerHeaterRequested = FALSE; setTrimmerHeaterPWM( trimmerHeaterDutyCycle ); state = TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET; } publishHeatersData(); return state; } /*********************************************************************//** * @brief * The handleTrimmerHeaterControlToTarget function handles the trimmer * heater at control state when the heater is active. * @details Inputs: trimmerHeaterTimerCounter, trimmerHeaterDutyCycle * @details Outputs: trimmerHeaterTimerCounter, trimmerHeaterDutyCycle, isTrimmerHeaterOn * @return state (TRIMMER_HEATER_EXEC_STATES_T) *************************************************************************/ static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterControlToTarget( void ) { TRIMMER_HEATER_EXEC_STATES_T state = TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET; if ( ++trimmerHeaterTimerCounter >= CONTROLLER_CHECK_INTERVAL_COUNT ) { F32 outletTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANCY ); trimmerHeaterDutyCycle = runPIController( PI_CONTROLLER_ID_TRIMMER_HEATER, trimmerHeaterTargetTemperature, outletTemp ); setTrimmerHeaterPWM( trimmerHeaterDutyCycle ); trimmerHeaterTimerCounter = 0; } publishHeatersData(); // TODO remove this code #ifdef DEBUG_ENABLED #ifdef ENABLE_DIP_SWITCHES #ifndef EMC_TEST_BUILD // if ( !TOGGLEPRIMAYHEATER() ) // { //stopTrimmerHeater(); //F32 pumpPWM = 0; //etpwmSetCmpB( etpwmREG2, (U32)( (S32)( ( pumpPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //temporaryStartROPump(); //temporaryStartFan(); //F32 fanPWM = 0; //etpwmSetCmpA( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //etpwmSetCmpB( etpwmREG6, (U32)( (S32)( ( fanPWM * (F32)(etpwmREG6->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); //temporaryStopROPump(); //temporaryStopFan(); // } #endif #endif #endif // TODO Remove this code if ( ! isTrimmerHeaterOn ) { state = TRIMMER_HEATER_EXEC_STATE_OFF; } return state; } /*********************************************************************//** * @brief * The setMainPrimaryHeaterPWM function sets the PWM of the main primary heater. * @details Inputs: none * @details Outputs: Sets the PWM duty cycle for the main primary heater * @param pwm PWM duty cycle to set for 1st primary heater element * @return none *************************************************************************/ static void setMainPrimaryHeaterPWM( F32 pwm ) { etpwmSetCmpA( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } /*********************************************************************//** * @brief * The setSmallPrimaryHeaterPWM function sets the PWM of the small primary heater. * @details Inputs: none * @details Outputs: Sets the PWM duty cycle for the small primary heater * @param pwm PWM duty cycle to set for 2nd primary heater element * @return none *************************************************************************/ static void setSmallPrimaryHeaterPWM( F32 pwm ) { etpwmSetCmpB( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } /*********************************************************************//** * @brief * The setTrimmerHeaterPWM function sets the PWM of the trimmer heater. * @details Inputs: none * @details Outputs: Sets the PWM duty cycle for the trimmer heater * @param pwm PWM duty cycle to set for trimmer heater * @return none *************************************************************************/ static void setTrimmerHeaterPWM( F32 pwm ) { etpwmSetCmpA( etpwmREG3, (U32)( (S32)( ( pwm * (F32)(etpwmREG3->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } /*********************************************************************//** * @brief * The resetHeaterState function resets the PI controller of the selected heater. * @details Inputs: mainPrimaryHeaterDutyCycle, trimmerHeaterDutyCycle * @details Outputs: mainPrimaryHeaterDutyCycle, trimmerHeaterDutyCycle * @param heater enumeration of the heater for which the PI controller will be reset * @return none *************************************************************************/ static void resetHeaterState( NAME_OF_HEATER_T heater ) { if ( heater == PRIMARY_HEATER ) { mainPrimaryHeaterDutyCycle = MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE; resetPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ); } else if ( heater == TRIMMER_HEATER ) { trimmerHeaterDutyCycle = TRIMMER_HEATER_MAX_DUTY_CYCLE; resetPIController( PI_CONTROLLER_ID_TRIMMER_HEATER, TRIMMER_HEATER_MAX_DUTY_CYCLE ); } } /*********************************************************************//** * @brief * The getPublishHeatersDataInterval function gets the publish interval. * @details Inputs: heatersDataPublishInterval * @details Outputs: none * @return result *************************************************************************/ U32 getPublishHeatersDataInterval( void ) { U32 result = heatersDataPublishInterval.data; if ( OVERRIDE_KEY == heatersDataPublishInterval.override ) { result = heatersDataPublishInterval.ovData; } return result; } /*********************************************************************//** * @brief * The publishTemperatureData function publishes the temperature sensors * data into the USB debug port at the defined time interval. * @details Inputs: dataPublicationTimerCounter * @details Outputs: Broadcast temperature sensors' data * @return none *************************************************************************/ static void publishHeatersData( void ) { if ( ++dataPublicationTimerCounter >= getPublishHeatersDataInterval() ) { broadcastHeatersData( (U32)(mainPrimaryHeaterDutyCycle*100), (U32)(smallPrimaryHeaterDutyCycle*100), (U32)(trimmerHeaterDutyCycle*100) ); //NOTE: This section will be removed #ifdef DEBUG_ENABLED #ifdef HEATERS_DEBUG { char debugTempStr[ 256 ]; sprintf( debugTempStr, "TPo: %6.2f, PriCJ: %6.2f, PriTC: %6.2f, TpriInt: %6.2f, TRo: %6.2f, TriCJ: %6.2f, TriTC: %6.2f, TtriInt: %6.2f\r\n", getTemperatureValue ( TEMPSENSORS_OUTLET_PRIMARY_HEATER ), getTemperatureValue ( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ), getTemperatureValue ( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ), getTemperatureValue ( TEMPSENSORS_PRIMARY_HEATER_INTERNAL ), getTemperatureValue ( TEMPSENSORS_OUTLET_REDUNDANCY ), getTemperatureValue ( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ), getTemperatureValue ( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ), getTemperatureValue ( TEMPSENSORS_TRIMMER_HEATER_INTERNAL ) ); sendDebugData ( (U08*)debugTempStr, strlen(debugTempStr) ); } #endif #endif dataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetHeatersPublishIntervalOverride function overrides the heaters * publish data time interval. * @details Inputs: heatersDataPublishInterval * @details Outputs: heatersDataPublishInterval * @return result *************************************************************************/ BOOL testSetHeatersPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( isTestingActivated() ) { U32 interval = value / TASK_GENERAL_INTERVAL; result = TRUE; heatersDataPublishInterval.ovData = interval; heatersDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetHeatersPublishIntervalOverride function resets the heaters * publish time interval to its previous time interval. * @details Inputs: heatersDataPublishInterval * @details Outputs: heatersDataPublishInterval * @return result *************************************************************************/ BOOL testResetHeatersPublishIntervalOverride( void ) { BOOL result = FALSE; if ( isTestingActivated() ) { result = TRUE; heatersDataPublishInterval.override = OVERRIDE_RESET; heatersDataPublishInterval.ovData = heatersDataPublishInterval.ovInitData; } return result; } /**@}*/