Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -r47205a5002f27add91d8548f31c8a6fa18993fea --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 47205a5002f27add91d8548f31c8a6fa18993fea) @@ -15,7 +15,7 @@ * ***************************************************************************/ -#include +#include // TODO remove if not needed // TI PWM driver #include "etpwm.h" @@ -40,26 +40,20 @@ // ********** private definitions ********** -#ifndef V_2_SYSTEM #define MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE 1.00 ///< Main primary heater (heater A) max duty cycle (100%). #define SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE 1.00 ///< Small Primary heater (heater B) max duty cycle (100%). #define TRIMMER_HEATER_MAX_DUTY_CYCLE 1.00 ///< Trimmer heater max duty cycle (100%). -#else -#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%). -#endif #define HEATERS_MIN_DUTY_CYCLE 0.00 ///< Primary and trimmer heaters minimum duty cycle (0.00%). #define PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ( MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE + \ SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ) ///< Primary heaters cumulative duty cycle. #define PRIMARY_HEATER_INITIAL_DUTY_CYCLE_ESTIMATE_DIVISOR 2.0 ///< Primary heaters initial duty cycle estimation divisor. #define MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR 2.0 ///< Main and small primary heater duty cycle divisor -#define PRIMARY_HEATERS_P_COEFFICIENT 0.15 ///< Primary heaters proportional coefficient. -#define PRIMARY_HEATERS_I_COEFFICIENT 0.001 ///< Primary heaters integral coefficient. +#define PRIMARY_HEATERS_P_COEFFICIENT 0.15 // TODO remove ///< Primary heaters proportional coefficient. +#define PRIMARY_HEATERS_I_COEFFICIENT 0.001 // TODO remove ///< 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 TRIMMER_HEATER_P_COEFFICIENT 0.02 // TODO remove ///< Trimmer heater proportional coefficient. +#define TRIMMER_HEATER_I_COEFFICIENT 0.001 // TODO remove ///< 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. @@ -78,23 +72,82 @@ #define HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters voltage monitor timer interval. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2 ///< Heaters max voltage out of range tolerance. -/// Primary heaters exec states +#define PRIMARY_HEATERS_POWER_TO_VOLTAGE_SLOPE 31.644 ///< Primary heaters power to voltage slope. +#define PRIMARY_HEATERS_POWER_TO_VOLTAGE_INTERCEPT 2.0996 ///< Primary heaters power to voltage intercept. + +/**************************************************** New defines ***********************/ +typedef enum Heaters_Exec_States +{ + HEATER_EXEC_STATE_NOT_RUNNING = 0, ///< Heater exec state not running + HEATER_EXEC_STATE_RAMP_UP_TO_TARGET, ///< Heater exec state ramp up to target + HEATER_EXEC_STATE_CONTROL_TO_TARGET, ///< Heater exec state control to target + NUM_OF_HEATERS_STATE, ///< Number of heaters state +} HEATERS_STATE_T; + +typedef struct +{ + F32 targetTemperature; ///< Heater Target temperature + F32 previousTemperature; ///< Heater Previous temperature TODO do we need this anymore? + HEATERS_STATE_T state; ///< Heater state + TEMPERATURE_SENSORS_T feedbackSensor; ///< Heater feedback sensor for controlling + U32 controlTimerCounter; ///< Heater control timer counter + BOOL startHeaterSignal; ///< Heater start indication flag + BOOL isHeaterOn; ///< Heater on/off status flag + // TODO remove once the mechanical thermal cutoff was implemented + U32 tempOutOfRangeTimer; ///< Heater temperature out of range timer + BOOL isHeaterTempOutOfRange; ///< Heater temperature out of range flag indicator + // TODO remove once the mechanical thermal cutoff was implemented + F32 dutycycle; ///< Heater duty cycle + F32 maxAllowedDutyCycle; ///< Heater maximum allowed duty cycle + F32 targetROFlow; ///< Heater target flow +} HEATER_STATUS_T; + +static HEATER_STATUS_T heaterStatus[ NUM_OF_DG_HEATERS ]; ///< Heaters status. +static U32 dataPublicationTimerCounter; ///< Data publication timer counter. +static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, + HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. +static U32 heatersOnWithNoFlowTimer; ///< Heaters are on but there is no sufficient flow. + +static BOOL isFlowBelowMin = FALSE; ///< Boolean flag to indicate if the flow is below the minimum. +static U32 voltageMonitorTimeCounter = 0; ///< Heaters voltage monitor counter. + +// ********** private function prototypes ********** + +static HEATERS_STATE_T handleHeaterStateNotRunning( DG_HEATERS_T heater ); +static HEATERS_STATE_T handleHeaterStateRampUpToTarget( DG_HEATERS_T heater ); +static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ); + +static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ); +static F32 calculateHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature ); + +static void setMainPrimaryHeaterPWM( F32 pwm ); +static void setSmallPrimaryHeaterPWM( F32 pwm ); +static void setTrimmerHeaterPWM( F32 pwm ); +static U32 getPublishHeatersDataInterval( void ); +static void publishHeatersData( void ); +static void checkPrimaryHeaterTempSensors( void ); +static void checkTrimmerHeaterTempSensors( void ); +static void monitorHeatersVoltage( void ); + +/**************************************************** New defines ***********************/ + +/// Primary heaters exec states TODO remove 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 +/// Trimmer heater exec states TODO remove 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 +/// Name of the heaters states TODO remove typedef enum name_of_heaters { PRIMARY_HEATER = 0, ///< Primary heater @@ -104,185 +157,192 @@ // ********** private data ********** -static PRIMARY_HEATERS_EXEC_STATES_T primaryHeatersExecState; ///< Primary heaters exec state. -static TRIMMER_HEATER_EXEC_STATES_T trimmerHeaterExecState; ///< Trimmer heater exec state. +static PRIMARY_HEATERS_EXEC_STATES_T primaryHeatersExecState; ///< Primary heaters exec state. TODO remove +static TRIMMER_HEATER_EXEC_STATES_T trimmerHeaterExecState; ///< Trimmer heater exec state. TODO remove -static F32 primaryHeaterTargetTemperature; ///< Primary heaters target temperature. -static F32 trimmerHeaterTargetTemperature; ///< Trimmer heater target temperature. +static F32 primaryHeaterTargetTemperature; ///< Primary heaters target temperature. TODO remove +static F32 trimmerHeaterTargetTemperature; ///< Trimmer heater target temperature. TODO remove -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 F32 mainPrimaryHeaterDutyCycle; ///< Main primary heater duty cycle. TODO remove +static F32 smallPrimaryHeaterDutyCycle; ///< Small primary heater duty cycle. TODO remove +static F32 trimmerHeaterDutyCycle; ///< Trimmer heater duty cycle. TODO remove +static U32 primaryHeaterTimerCounter; ///< Primary heater timer counter. TODO remove +static U32 trimmerHeaterTimerCounter; ///< Trimmer heater timer counter. TODO remove -static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, - HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. -static BOOL hasStartPrimaryHeaterRequested; ///< Start primary heater request flag. -static BOOL hasStartTrimmerHeaterRequested; ///< Start trimmer heater request flag. -static U32 heatersOnWithNoFlowTimer; ///< Heaters are on but there is no sufficient flow. -static TEMPERATURE_SENSORS_T primaryHeatersFeedbackTempSensor = TEMPSENSORS_OUTLET_PRIMARY_HEATER; ///< Primary heaters feedback temperature sensors. -static TEMPERATURE_SENSORS_T trimmerHeaterFeedbackTempSensor = TEMPSENSORS_INLET_DIALYSATE; ///< Trimmer heater feedback temperature sensors. -static U32 primaryHeaterTempOutTimer = 0; ///< Primary heaters temperature out of range start timer. -static U32 trimmerHeaterTempOutTimer = 0; ///< Trimmer heater internal temperature out of range timer. -static BOOL isPrimaryHeaterTempOutOfRange = FALSE; ///< Boolean flag to indicate if the primary heaters internal temperature out of range. -static BOOL isTrimmerHeaterTempOutOfRange = FALSE; ///< Boolean flag to indicate if the trimmer heater internal temperature out of range. -static BOOL isFlowBelowMin = FALSE; ///< Boolean flag to indicate if the flow is below the minimum. -static U32 heatersVoltageMonitorTimeCounter = 0; ///< Heaters voltage monitor counter. +static BOOL isPrimaryHeaterOn; ///< Flag to show if the primary heater is on. TODO remove +static BOOL isTrimmerHeaterOn; ///< Flag to show if the trimmer heater is on. TODO remove +static BOOL hasStartPrimaryHeaterRequested; ///< Start primary heater request flag. TODO remove +static BOOL hasStartTrimmerHeaterRequested; ///< Start trimmer heater request flag. TODO remove + +static TEMPERATURE_SENSORS_T primaryHeatersFeedbackTempSensor = TEMPSENSORS_OUTLET_PRIMARY_HEATER; ///< Primary heaters feedback temperature sensors. TODO remove +static TEMPERATURE_SENSORS_T trimmerHeaterFeedbackTempSensor = TEMPSENSORS_INLET_DIALYSATE; ///< Trimmer heater feedback temperature sensors. TODO remove + +static U32 primaryHeaterTempOutTimer = 0; ///< Primary heaters temperature out of range start timer. TODO remove +static U32 trimmerHeaterTempOutTimer = 0; ///< Trimmer heater internal temperature out of range timer. TODO remove +static BOOL isPrimaryHeaterTempOutOfRange = FALSE; ///< Boolean flag to indicate if the primary heaters internal temperature out of range. TODO remove +static BOOL isTrimmerHeaterTempOutOfRange = FALSE; ///< Boolean flag to indicate if the trimmer heater internal temperature out of range. TODO remove + // ********** private function prototypes ********** -static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateOff( void ); -static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateControlToTarget( void ); +static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateOff( void ); // TODO remove +static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateControlToTarget( void ); // TODO remove -static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterStateOff( void ); -static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterControlToTarget( void ); +static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterStateOff( void ); // TODO remove +static TRIMMER_HEATER_EXEC_STATES_T handleTrimmerHeaterControlToTarget( void ); // TODO remove -static void setMainPrimaryHeaterPWM( F32 pwm ); -static void setSmallPrimaryHeaterPWM( F32 pwm ); -static void setTrimmerHeaterPWM( F32 pwm ); -static void resetHeaterState( NAME_OF_HEATER_T heater ); -static U32 getPublishHeatersDataInterval( void ); -static void publishHeatersData( void ); -static void checkPrimaryHeaterTempSensors( void ); -static void checkTrimmerHeaterTempSensors( void ); -static void monitorHeatersVoltage( void ); +static void resetHeaterState( NAME_OF_HEATER_T heater ); // TODO remove /*********************************************************************//** * @brief - * The initHeaters function initializes the variables and the PI controllers - * for the primary and trimmer heaters. + * The initHeaters initializes the heaters driver. * @details Inputs: none - * @details Outputs: Heaters module initialized + * @details Outputs: isFlowBelowMin, voltageMonitorTimeCounter, heaterStatus * @return none *************************************************************************/ void initHeaters( void ) { - 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; - primaryHeatersFeedbackTempSensor = TEMPSENSORS_OUTLET_PRIMARY_HEATER; - trimmerHeaterFeedbackTempSensor = TEMPSENSORS_INLET_DIALYSATE; - primaryHeaterTempOutTimer = 0; - trimmerHeaterTempOutTimer = 0; - isPrimaryHeaterTempOutOfRange = FALSE; - isTrimmerHeaterTempOutOfRange = FALSE; - isFlowBelowMin = FALSE; - heatersVoltageMonitorTimeCounter = 0; + DG_HEATERS_T heater; + isFlowBelowMin = FALSE; + voltageMonitorTimeCounter = 0; + + for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) + { + heaterStatus[ heater ].controlTimerCounter = 0; + // The default feedback sensor of the primary heater is TPo but it changes to THd in heat disinfect + // The default feedback sensor of the trimmer heater is TDi all the time + heaterStatus[ heater ].feedbackSensor = ( DG_PRIMARY_HEATER == heater ? TEMPSENSORS_OUTLET_PRIMARY_HEATER : TEMPSENSORS_OUTLET_REDUNDANT ); + heaterStatus[ heater ].startHeaterSignal = FALSE; + heaterStatus[ heater ].tempOutOfRangeTimer = 0; + heaterStatus[ heater ].isHeaterTempOutOfRange = FALSE; + heaterStatus[ heater ].previousTemperature = 0.0; + heaterStatus[ heater ].state = HEATER_EXEC_STATE_NOT_RUNNING; + heaterStatus[ heater ].targetTemperature = 0.0; + heaterStatus[ heater ].dutycycle = 0.0; + heaterStatus[ heater ].maxAllowedDutyCycle = ( DG_PRIMARY_HEATER == heater ? PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE : TRIMMER_HEATER_MAX_DUTY_CYCLE ); + heaterStatus[ heater ].targetROFlow = 0.0; + } + + // TODO remove // 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, PRIMARY_HEATERS_CUMULATIVE_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 ); + // TODO remove } -/*********************************************************************//** - * @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. + * The setHeaterTargetTemperature function sets the target temperature of a heater. * @details Inputs: none - * @details Outputs: trimmerHeaterTargetTemperature - * @param targetTemp target temperature for the trimmer heater + * @details Outputs: heaterStatus + * @param heater: heater ID that its target temperature is set + * @param targetTemperature: target temperature of that the heater has to + * heat the fluid * @return none *************************************************************************/ -void setTrimmerHeaterTargetTemperature( F32 targetTemp ) +void setHeaterTargetTemperature( DG_HEATERS_T heater, F32 targetTemperature ) { - 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 ) ) + if( heater < NUM_OF_DG_HEATERS ) { - hasStartPrimaryHeaterRequested = TRUE; - status = TRUE; + if ( ( targetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( targetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) + { + heaterStatus[ heater ].targetTemperature = targetTemperature; + // TODO alarm if temperature if out of range or just reject? + } } - - return status; + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_HEATER_ID_SELECTED, heater ) + } } /*********************************************************************//** * @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 + * The startHeater function starts the specified heater. + * @details Inputs: none + * @details Outputs: heaterStatus + * @param heater: heater ID that is requested to turn on + * @return TRUE if the start was accepted otherwise, FALSE *************************************************************************/ -BOOL startTrimmerHeater( void ) +BOOL startHeater( DG_HEATERS_T heater ) { BOOL status = FALSE; - if ( ( trimmerHeaterTargetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( trimmerHeaterTargetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) + if( heater < NUM_OF_DG_HEATERS ) { - hasStartTrimmerHeaterRequested = TRUE; - status = TRUE; + F32 targetTemp = heaterStatus[ heater ].targetTemperature; + + if ( ( targetTemp >= MINIMUM_TARGET_TEMPERATURE ) && ( targetTemp <= MAXIMUM_TARGET_TEMPERATURE ) ) + { + status = TRUE; + heaterStatus[ heater ].startHeaterSignal = TRUE; + } } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_HEATER_ID_SELECTED, heater ) + } return status; } /*********************************************************************//** * @brief - * The stopPrimaryHeater function stops the primary heater. + * The stopHeater stops the specified heater. * @details Inputs: none - * @details Outputs: Primary heater stops - * @return none + * @details Outputs: heaterStatus + * @param heater: heater ID that is requested to turn on + * @return TRUE if the start was accepted otherwise, FALSE *************************************************************************/ -void stopPrimaryHeater( void ) +void stopHeater( DG_HEATERS_T heater ) { - setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); - setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); - isPrimaryHeaterOn = FALSE; + heaterStatus[ heater ].isHeaterOn = FALSE; } /*********************************************************************//** * @brief - * The stopTrimmerHeater function stops the trimmer heater. - * @details Inputs: none - * @details Outputs: Trimmer heater stops + * The execHeaters function executes the heaters state machine. + * @details Inputs: heaterStatus + * @details Outputs: heaterStatus * @return none *************************************************************************/ -void stopTrimmerHeater( void ) +void execHeaters( void ) { - setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); - isTrimmerHeaterOn = FALSE; + DG_HEATERS_T heater; + HEATERS_STATE_T state; + + for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) + { + state = heaterStatus[ heater ].state; + + switch( state ) + { + case HEATER_EXEC_STATE_NOT_RUNNING: + heaterStatus[ heater ].state = handleHeaterStateNotRunning( heater ); + break; + + case HEATER_EXEC_STATE_RAMP_UP_TO_TARGET: + heaterStatus[ heater ].state = handleHeaterStateRampUpToTarget( heater ); + break; + + case HEATER_EXEC_STATE_CONTROL_TO_TARGET: + heaterStatus[ heater ].state = handleHeaterStateControlToTarget( heater ); + break; + + default: + // The heater is in an unknown state. Turn it off and switch to not running state + stopHeater( heater ); + heaterStatus[ heater ].state = HEATER_EXEC_STATE_NOT_RUNNING; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_EXEC_STATE, heater ); + break; + } + } } /*********************************************************************//** @@ -396,6 +456,264 @@ /*********************************************************************//** * @brief + * The handleHeaterStateNotRunning function handles the heater not running state. + * @details Inputs: heaterStatus + * @details Outputs: heaterStatus + * @param heater: The heater Id that its not running state is handled + * @return next state of the state machine + *************************************************************************/ +static HEATERS_STATE_T handleHeaterStateNotRunning( DG_HEATERS_T heater ) +{ + HEATERS_STATE_T state = HEATER_EXEC_STATE_NOT_RUNNING; + + if ( TRUE == heaterStatus[ heater ].startHeaterSignal ) + { + heaterStatus[ heater ].isHeaterOn = TRUE; + heaterStatus[ heater ].startHeaterSignal = FALSE; + + // If the operation mode is heater disinfect and the heater is primary heater, change the feedback sensor to THd + if ( ( DG_MODE_HEAT == getCurrentOperationMode() ) && ( DG_PRIMARY_HEATER == heater ) ) + { +#ifdef THD_USING_TRO_CONNECTOR + // Set the feedback temperature sensor and THd uses TRo in V3 + heaterStatus[ heater ].feedbackSensor = TEMPSENSORS_OUTLET_REDUNDANT; +#else + heaterStatus[ heater ].feedbackSensor = TEMPSENSORS_HEAT_DISINFECT; +#endif + } + + // Set the heater duty cycle to maximum + setHeaterDutyCycle( heater, heaterStatus[ heater ].maxAllowedDutyCycle ); + + // Turn on the heater + state = HEATER_EXEC_STATE_RAMP_UP_TO_TARGET; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleHeaterStateRampUpToTarget function handles the heaters' control + * while they are ramped up to target temperature. + * @details Inputs: heaterStatus + * @details Outputs: heaterStatus + * @param heater: The heater Id that its on state is handled + * @return next state of the state machine + *************************************************************************/ +static HEATERS_STATE_T handleHeaterStateRampUpToTarget( DG_HEATERS_T heater ) +{ + HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_UP_TO_TARGET; + + TEMPERATURE_SENSORS_T sensor = heaterStatus[ heater ].feedbackSensor; + F32 temperature = getTemperatureValue( (U32)sensor ); + + // TODO remove + setHeaterDutyCycle( heater, 0.44 ); + + if ( FALSE == heaterStatus[ heater ].isHeaterOn ) + { + setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); + state = HEATER_EXEC_STATE_NOT_RUNNING; + } + // TODO remove + + /*if ( ++heaterStatus[ heater ].controlTimerCounter > CONTROLLER_CHECK_INTERVAL_COUNT ) + { + // If the heaters are not longer on, set the duty cycle to 0 + if ( FALSE == heaterStatus[ heater ].isHeaterOn ) + { + setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); + } + else + { + F32 targetTemperature = heaterStatus[ heater ].targetTemperature; + F32 prevTemperature = heaterStatus[ heater ].previousTemperature; + F32 temperatureSlope = ( temperature - prevTemperature ) / CONTROLLER_CHECK_INTERVAL_COUNT; + + if ( temperatureSlope > 0.0 ) + { + // TODO make a #define for delta temperature from target + // TODO create the cases for the temperature being above the target + if ( ( targetTemperature - temperature > 0.5 ) && ( temperature < targetTemperature ) ) + { + setHeaterDutyCycle( heater, heaterStatus[ heater ].maxAllowedDutyCycle ); + } + if ( ( targetTemperature - temperature < 0.5 ) && ( temperature < targetTemperature ) ) + { + // We are in range + // Start the P controller + } + } + else if ( ( temperatureSlope < 0.0 ) && ( targetTemperature - temperature < 0.5 ) && ( temperature < targetTemperature ) ) + { + setHeaterDutyCycle( heater, heaterStatus[ heater ].maxAllowedDutyCycle ); + } + } + + heaterStatus[ heater ].controlTimerCounter = 0; + }*/ + + return state; +} + +static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ) +{ + HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; + + F32 flow = getMeasuredROFlowRate(); + + F32 power = sqrt( ( targetTemperature - currentTemperature ) * flow ); + + F32 dutyCycle = ( ( power * PRIMARY_HEATERS_POWER_TO_VOLTAGE_SLOPE ) - PRIMARY_HEATERS_POWER_TO_VOLTAGE_INTERCEPT ) / HEATERS_MAX_OPERATING_VOLTAGE_V; + + + return state; +} + + + +/*********************************************************************//** + * @brief + * The setHeaterDutyCycle function sets the duty cycle of a heater. + * @details Inputs: none + * @details Outputs: none + * @param heater: The heater Id that its duty cycle is set + * @param pwm: The PWM that is set + * @return none + *************************************************************************/ +static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ) +{ + if ( DG_PRIMARY_HEATER == heater ) + { + F32 main = pwm / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + F32 small = pwm / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + + setMainPrimaryHeaterPWM( main ); + setSmallPrimaryHeaterPWM( small ); + + heaterStatus[ DG_PRIMARY_HEATER ].dutycycle = main; + } + else if ( DG_TRIMMER_HEATER == heater ) + { + setTrimmerHeaterPWM( pwm ); + + heaterStatus[ DG_TRIMMER_HEATER ].dutycycle = pwm; + } +} + +static F32 calculateHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature ) +{ + F32 flow = getMeasuredROFlowRate(); + + F32 power = sqrt( ( targetTemperature - currentTemperature ) * flow ); + + F32 dutyCycle = ( ( power * PRIMARY_HEATERS_POWER_TO_VOLTAGE_SLOPE ) - PRIMARY_HEATERS_POWER_TO_VOLTAGE_INTERCEPT ) / HEATERS_MAX_OPERATING_VOLTAGE_V; + + return dutyCycle; +} + +/*********************************************************************//** + * @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 ) ) + { + hasStartPrimaryHeaterRequested = TRUE; + 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 ) ) + { + hasStartTrimmerHeaterRequested = TRUE; + 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 ) +{ + setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); + setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); + isPrimaryHeaterOn = FALSE; +} + +/*********************************************************************//** + * @brief + * The stopTrimmerHeater function stops the trimmer heater. + * @details Inputs: none + * @details Outputs: Trimmer heater stops + * @return none + *************************************************************************/ +void stopTrimmerHeater( void ) +{ + setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); + isTrimmerHeaterOn = FALSE; +} + + + +/*********************************************************************//** + * @brief * The execPrimaryHeaters function executes the primary heaters' state machine. * @details Inputs: primaryHeatersExecState * @details Outputs: primaryHeatersExecState @@ -414,7 +732,7 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_PRIMARY_HEATER_EXEC_INVALID_STATE, primaryHeatersExecState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_EXEC_STATE, primaryHeatersExecState ); primaryHeatersExecState = PRIMARY_HEATERS_EXEC_STATE_CONTROL_TO_TARGET; break; } @@ -440,7 +758,7 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_TRIMMER_HEATER_EXEC_INVALID_STATE, trimmerHeaterExecState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_EXEC_STATE, trimmerHeaterExecState ); trimmerHeaterExecState = TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET; break; } @@ -732,11 +1050,13 @@ { HEATERS_DATA_T data; - data.mainPrimayHeaterDC = mainPrimaryHeaterDutyCycle * 100.0; - data.smallPrimaryHeaterDC = smallPrimaryHeaterDutyCycle * 100.0; - data.trimmerHeaterDC = trimmerHeaterDutyCycle * 100.0; - data.primaryTargetTemp = primaryHeaterTargetTemperature; - data.trimmerTargetTemp = trimmerHeaterTargetTemperature; + data.mainPrimayHeaterDC = heaterStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; + // The duty cycle of the primary heater is divided into 2 parts and is applied to main + // and small primary heaters. So they are always the same. + data.smallPrimaryHeaterDC = heaterStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; + data.trimmerHeaterDC = heaterStatus[ DG_TRIMMER_HEATER ].dutycycle * 100.0; + data.primaryTargetTemp = heaterStatus[ DG_PRIMARY_HEATER ].targetTemperature; + data.trimmerTargetTemp = heaterStatus[ DG_TRIMMER_HEATER ].targetTemperature; broadcastHeatersData( &data ); @@ -837,7 +1157,7 @@ *************************************************************************/ static void monitorHeatersVoltage( void ) { - if ( ++heatersVoltageMonitorTimeCounter >= HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ) + if ( ++voltageMonitorTimeCounter >= HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ) { F32 mainPriVoltage = getIntADCVoltageConverted( INT_ADC_PRIMARY_HEATER_24_VOLTS ); // TODO it is assumed that the main and small primary heaters have equal voltage since the PWMs are divided into 2 @@ -868,7 +1188,7 @@ SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, trimmerVoltage ); } - heatersVoltageMonitorTimeCounter = 0; + voltageMonitorTimeCounter = 0; } }