Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r6e3bbb4c27eae91fed11b118cced935a04c6b90a -rf4a444de1b2b78922a911448a65cfcc8677f86cb --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 6e3bbb4c27eae91fed11b118cced935a04c6b90a) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f4a444de1b2b78922a911448a65cfcc8677f86cb) @@ -59,7 +59,7 @@ #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 170.0F ///< Heaters max allowed internal temperature in C. #define HEATERS_MAX_ALLOWED_COLD_JUNCTION_TEMPERATURE_C 80.0F ///< Heaters max allowed cold junction temperature in C. #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters max allowed internal temperature timeout in milliseconds. -#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. +#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. #define HEATERS_MAX_OPERATING_VOLTAGE_V 24.0F ///< Heaters max operating voltage in volts. #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.2F ///< Heaters max voltage out of range tolerance. @@ -89,20 +89,19 @@ /// Heaters data structure typedef struct { - F32 targetTemp; ///< Heater target temperature. + F32 targetTemp; ///< Heater target temperature. HEATERS_STATE_T state; ///< Heater state. BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. - F32 dutycycle; ///< Heater duty cycle. - F32 targetROFlow; ///< Heater target flow. - U32 heaterOnWithNoFlowTimer; // TODO remove ///< Heater on with no flow timer. + F32 dutycycle; ///< Heater duty cycle. + F32 dutyCyleBeforeFlow; + F32 targetROFlow; ///< Heater target flow. + U32 heaterOnWithNoFlowTimer; ///< Heater on with no flow timer. BOOL isFlowBelowMin; ///< Heater flow below minimum flag indicator. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. - F32 heaterEfficiency; ///< Heater efficiency during the run. + F32 heaterEfficiency; ///< Heater efficiency during the run. BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. - U32 tempOutOfRangeTimer; ///< Heater temperature out of range timer TODO remove once the mechanical thermal cutoff was implemented - BOOL isHeaterTempOutOfRange; ///< Heater temperature out of range flag indicator TODO remove once the mechanical thermal cutoff was implemented F32 temporaryInterimTemperature; ///< TODO remove } HEATER_STATUS_T; @@ -149,8 +148,6 @@ for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) { heatersStatus[ heater ].startHeaterSignal = FALSE; - heatersStatus[ heater ].tempOutOfRangeTimer = 0; - heatersStatus[ heater ].isHeaterTempOutOfRange = FALSE; heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; heatersStatus[ heater ].targetTemp = 0.0; heatersStatus[ heater ].dutycycle = 0.0; @@ -367,50 +364,53 @@ *************************************************************************/ void execHeatersMonitor( void ) { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - DG_HEATERS_T heater; + DG_HEATERS_T heater; - for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) + for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) + { + // Check if the heater is on and if it is, check the flow sensor's status + if ( TRUE == heatersStatus[ heater ].isHeaterOn ) { - // Check if a heater is on and whether is duty cycle is not zero - if ( ( TRUE == heatersStatus[ heater ].isHeaterOn ) && ( ( heatersStatus[ heater ].dutycycle - HEATERS_MIN_DUTY_CYCLE ) > NEARLY_ZERO ) ) - { - // TODO add the function that gets the flow of the new flow sensor for DG. For now it is assumed that trimmer heater flow sensor - // is not 0 so the heater can run if needed - F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredROFlowRateLPM() : 50.0 ); - // TODO get the minimum new flow sensor flow sensor - F32 minFlow = ( DG_PRIMARY_HEATER == heater ? MIN_RO_FLOWRATE_LPM : MIN_RO_FLOWRATE_LPM ); - BOOL isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); + // TODO add the function that gets the flow of the new flow sensor for DG. For now it is assumed that trimmer heater flow sensor + // is not 0 so the heater can run if needed + F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredROFlowRateLPM() : 50.0 ); + // TODO get the minimum new flow sensor flow sensor + F32 minFlow = ( DG_PRIMARY_HEATER == heater ? MIN_RO_FLOWRATE_LPM : MIN_RO_FLOWRATE_LPM ); + BOOL isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); - if ( TRUE == isFlowLow ) + if ( TRUE == isFlowLow ) + { + // Check if the flow of the heater is below minimum for the first time + if ( FALSE == heatersStatus[ heater ].isFlowBelowMin ) { - // Check if the flow of the heater is below minimum for the first time - if ( FALSE == heatersStatus[ heater ].isFlowBelowMin ) - { - heatersStatus[ heater ].isFlowBelowMin = TRUE; - heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); - } - else if ( TRUE == didTimeout( heatersStatus[ heater ].heaterOnWithNoFlowTimer, HEATERS_ON_NO_FLOW_TIMEOUT_MS ) ) - { - // Heater has been on with no flow time out - stopHeater( heater ); - - ALARM_ID_T alarm = ( DG_PRIMARY_HEATER == heater ? ALARM_ID_DG_PRIMARY_HEATER_ON_WITH_NO_FLOW_TIMEOUT : - ALARM_ID_DG_TRIMMER_HEATER_ON_WITH_NO_FLOW_TIMEOUT ); - activateAlarmNoData( alarm ); - } + // Set the variables for the flow below minimum situation. + // Remember the current duty cycle of the heater + heatersStatus[ heater ].isFlowBelowMin = TRUE; + heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); + heatersStatus[ heater ].dutyCyleBeforeFlow = heatersStatus[ heater ].dutycycle; } - else + else if ( TRUE == didTimeout( heatersStatus[ heater ].heaterOnWithNoFlowTimer, HEATERS_ON_NO_FLOW_TIMEOUT_MS ) ) { - heatersStatus[ heater ].isFlowBelowMin = FALSE; - heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); + // The flow is below minimum for a certain period of time so set the heater's duty cycle to 0. The heaters is not + // set to off and its duty cycle is set to 0 + setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); } } + else + { + heatersStatus[ heater ].isFlowBelowMin = FALSE; + heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); + + // Flow is back on, set the heater to the duty cycle that was saved before zeroing the heater + setHeaterDutyCycle( heater, heatersStatus[ heater ].dutyCyleBeforeFlow ); + } } + } +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { monitorHeatersVoltage(); } @@ -643,17 +643,37 @@ *************************************************************************/ static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ) { - if ( DG_PRIMARY_HEATER == heater ) + // Only if there is a minimum flow, or if 0 duty cycle has been requested, the duty cycle can be changed + // This is to make sure while heaters are temporarily turned off due to a flow drop are not set to another + // duty cycle that might cause an over heat since there is no water flowing through + if ( ( FALSE == heatersStatus[ heater ].isFlowBelowMin ) || ( pwm < NEARLY_ZERO ) ) { - setMainPrimaryHeaterPWM( pwm ); - setSmallPrimaryHeaterPWM( pwm ); + // Check if the requested duty cycle is different from what the heater's duty cycle is. + // If the same duty cycle is requested, then it is not needed to send it again. This is to make sure + // the same duty cycle is not sent to the hardware all the time. + if ( fabs( heatersStatus[ heater ].dutycycle - pwm ) > NEARLY_ZERO ) + { + if ( DG_PRIMARY_HEATER == heater ) + { + setMainPrimaryHeaterPWM( pwm ); + setSmallPrimaryHeaterPWM( pwm ); + } + else if ( DG_TRIMMER_HEATER == heater ) + { + setTrimmerHeaterPWM( pwm ); + } + + // Updated the heater's information + heatersStatus[ heater ].dutycycle = pwm; + } } - else if ( DG_TRIMMER_HEATER == heater ) + else { - setTrimmerHeaterPWM( pwm ); + // The flow is below minimum and the heater is temporarily powered down + // Update the other duty cycle with the requested duty cycle so as soon as the + // flow is back on, the new duty cycle is set + heatersStatus[ heater ].dutyCyleBeforeFlow = pwm; } - - heatersStatus[ heater ].dutycycle = pwm; } /*********************************************************************//** @@ -861,6 +881,7 @@ { if ( ++voltageMonitorTimeCounter >= HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ) { + // TODO the voltages are disabled for now until they are implemented into the persistent alarms. 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 // before applying the PWMs to the heaters. Right now, there is no ADC channel available for the small primary @@ -877,17 +898,17 @@ // The corresponding voltage of the current PWM must be close to the sensed voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * mainPri ) - mainPriVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * mainPriVoltage ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, mainPriVoltage ); + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, mainPriVoltage ); } // Check small primary heater's voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * smallPri ) - smallPriVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * smallPriVoltage ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, smallPriVoltage ); + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, smallPriVoltage ); } // Check trimmer heater's voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * trimmer ) - trimmerVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * trimmerVoltage ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, trimmerVoltage ); + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, trimmerVoltage ); } voltageMonitorTimeCounter = 0; @@ -916,7 +937,7 @@ { U32 interval = value / TASK_PRIORITY_INTERVAL; - result = TRUE; + result = TRUE; heatersDataPublishInterval.ovData = interval; heatersDataPublishInterval.override = OVERRIDE_KEY; } @@ -938,7 +959,7 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; + result = TRUE; heatersDataPublishInterval.override = OVERRIDE_RESET; heatersDataPublishInterval.ovData = heatersDataPublishInterval.ovInitData; }