Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r6ce44043f6a5fb452ca10c9eca4f081967656a7d -r79161e35b192de494ac072a2772d73c4b55fca94 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 6ce44043f6a5fb452ca10c9eca4f081967656a7d) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 79161e35b192de494ac072a2772d73c4b55fca94) @@ -22,6 +22,7 @@ #include "AlarmMgmt.h" #include "DGDefs.h" +#include "FlowSensors.h" #include "Heaters.h" #include "MessageSupport.h" #include "ModeFill.h" @@ -48,8 +49,9 @@ #define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%). #define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%). #define HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE 0.6F ///< Heaters minimum duty cycle during heat disinfect. -#define HEATERS_MAX_EFFICIENCY 0.0F ///< Heaters minimum efficiency. -#define HEATERS_MIN_EFFICIENCY 1.0F ///< Heaters maximum efficiency. +#define HEATERS_MIN_EST_GAIN 0.2F ///< Heaters minimum estimation gain. +#define HEATERS_MAX_EST_GAIN 5.0F ///< Heaters maximum estimation gain. +#define HEATERS_NEUTRAL_EST_GAIN 1.0F ///< Heaters neutral estimation gain. #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. @@ -69,6 +71,7 @@ static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. static const F32 PRIMARY_HEATERS_MAXIMUM_POWER_WATTS = 475 + 237.5F; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). +static const F32 HEATERS_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL; ///< Heaters voltage tolerance in volts. /// Heaters exec states typedef enum Heaters_Exec_States @@ -92,7 +95,7 @@ F32 dutycycle; ///< Heater duty cycle. F32 targetFlow; ///< Heater target flow. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. - F32 heaterEfficiency; ///< Heater efficiency during the run. + F32 heaterEstGain; ///< Heater estimation gain during the run. BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. F32 calculatedTemperature; ///< Heater calculated temperature. DG_RESERVOIR_ID_T inactiveRsrvr; ///< Heater inactive reservoir. @@ -147,7 +150,7 @@ heatersStatus[ heater ].dutycycle = 0.0; heatersStatus[ heater ].targetFlow = 0.0; heatersStatus[ heater ].hasTargetTempChanged = FALSE; - heatersStatus[ heater ].heaterEfficiency = 1.0; // Assuming 100% efficiency during initialization until it is updated + heatersStatus[ heater ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; heatersStatus[ heater ].hasTargetBeenReached = FALSE; } @@ -337,7 +340,7 @@ { // 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 ); + F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) /*getMeasuredROFlowRateLPM()*/ : 50.0 ); F32 minFlow = ( DG_PRIMARY_HEATER == heater ? MIN_RO_FLOWRATE_LPM : MIN_RO_FLOWRATE_LPM ); BOOL isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); @@ -370,8 +373,8 @@ *************************************************************************/ void resetHeatersEfficiency( void ) { - heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = 1.0; - heatersStatus[ DG_TRIMMER_HEATER ].heaterEfficiency = 1.0; + heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; + heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; } /*********************************************************************//** @@ -634,44 +637,47 @@ static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency; + F32 heaterEstGain = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; + // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 + // Multiply the duty cycle to the heater efficiency + F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * fabs( targetTemperature - currentTemperature ) * flow ) / + PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( TRUE == checkEfficiency ) { + F32 heaterDutyCycle = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle; F32 lastFillTemperature = getLastFillTemperature(); F32 primaryTargetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; + BOOL isTempUnderTarget = ( lastFillTemperature < primaryTargetTemperature ? TRUE : FALSE ); - // If the last fill temperature > target temperature, it means the primary heater overshot the duty cycle - // so with its efficiency is toned down for the next fill cycle - // If the heater under-shoots the duty cycle, the efficiency increases the duty cycle for the next fill cycle - if ( lastFillTemperature - primaryTargetTemperature < NEARLY_ZERO ) + if ( TRUE == isTempUnderTarget ) { - heaterEfficiency -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + if ( heaterDutyCycle < HEATERS_MAX_DUTY_CYCLE ) + { + heaterEstGain += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } } else { - heaterEfficiency += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + if ( heaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ) + { + heaterEstGain -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } } - // Check the heater's efficiency to make sure it is in between 0 and 1 (0 to 100%) - heaterEfficiency = MIN( heaterEfficiency, HEATERS_MAX_EFFICIENCY ); - heaterEfficiency = MAX( heaterEfficiency, HEATERS_MIN_EFFICIENCY ); - - // Update the heaters efficiency - heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = heaterEfficiency; + heaterEstGain = MAX( heaterEstGain, HEATERS_MIN_EST_GAIN ); + heaterEstGain = MIN( heaterEstGain, HEATERS_MAX_EST_GAIN ); + heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = heaterEstGain; } } - // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 - // Multiply the duty cycle to the heater efficiency - F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); - dutyCycle = ( heaterEfficiency > NEARLY_ZERO ? dutyCycle * heaterEfficiency : dutyCycle ); - dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); + dutyCycle *= heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; + dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); return dutyCycle; } @@ -692,7 +698,7 @@ static F32 calculateTrimmerHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEfficiency; + F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain; F32 dutyCycle = 0.0; #ifndef _RELEASE_ @@ -804,10 +810,9 @@ data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; data.trimmerHeaterState = heatersStatus[ DG_TRIMMER_HEATER ].state; - data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency * 100; + data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain * 100; data.primaryCalcTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature; data.trimmerCalcCurrentTemp = heatersStatus[ DG_TRIMMER_HEATER ].calculatedTemperature; - broadcastData( MSG_ID_DG_HEATERS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( HEATERS_DATA_T ) ); dataPublicationTimerCounter = 0; @@ -835,21 +840,17 @@ F32 smallPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle; F32 trimmerDC = heatersStatus[ DG_TRIMMER_HEATER ].dutycycle; - F32 mainPriVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * HEATERS_MAX_OPERATING_VOLTAGE_V; - F32 smallPriVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * HEATERS_MAX_OPERATING_VOLTAGE_V; - F32 trimmerVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * HEATERS_MAX_OPERATING_VOLTAGE_V; - F32 mainPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0 - mainPriDC ); F32 smallPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0 - smallPriDC ); F32 trimmerExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0 - trimmerDC ); - BOOL isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > mainPriVoltageTol ? TRUE : FALSE ); - BOOL isSmallPriOut = ( fabs( smallPriExpectedVoltage - smallPriVoltage ) > smallPriVoltageTol ? TRUE : FALSE ); - BOOL isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > trimmerVoltageTol ? TRUE : FALSE ); + BOOL isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + BOOL isSmallPriOut = ( fabs( smallPriExpectedVoltage - smallPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + BOOL isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); - //checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPriDC, mainPriVoltageTol ); - //checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPriDC, smallPriVoltageTol ); - //checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmerDC, trimmerVoltageTol ); + checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); + checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); + checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmerDC, HEATERS_VOLTAGE_TOLERANCE_V ); }