Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r577532788d2042e5299fd22aff6bae46c292002d -rf0ab8f06e0c8af10bd8db099927669dbd94326b8 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 577532788d2042e5299fd22aff6bae46c292002d) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f0ab8f06e0c8af10bd8db099927669dbd94326b8) @@ -40,29 +40,39 @@ // ********** private definitions ********** #ifndef __ALPHA_AO_VER__ -#define HEATERS_MAX_DUTY_CYCLE 100.00F ///< Heaters max duty cycle (100%) or ON state -#define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%) or OFF state -#define D5_HEAT_ON 50.00F ///< Primary heater ON control -#define HEATERS_DISINFECT_DUTY_CYCLE 80.0F ///< Heaters disinfect cycle. -#define HEATERS_DISINFECT_TRANSFER_DUTY_CYCLE 60.0F ///< Heaters disinfect transfer duty cycle. +#define AC_HEATER_TX_MAX_DUTY_CYCLE 0.50F ///< AC Heater Treatement mode max duty cycle (50% of 1400W : 700W ) or ON state +#define AC_HEATER_HEAT_MAX_DUTY_CYCLE 0.70F ///< AC Heater heat disinfect mode max duty cycle (70% of 1400W : 980W ) or ON state +#define AC_HEATER_MAX_DUTY_CYCLE 1.0F ///< AC Heater max duty cycle (100.0%) or ON state +#define DC_HEATER_MAX_DUTY_CYCLE 1.0F ///< DC Heater max duty cycle (100%) or ON state +#define HEATERS_MIN_DUTY_CYCLE 0.0F ///< Heaters minimum duty cycle (0.00%) or OFF state #else -#define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%) or ON state -#define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%) or OFF state -#define D5_HEAT_ON 1.00F ///< Primary heater ON control +#define HEATERS_MAX_DUTY_CYCLE 1.0F ///< Heaters max duty cycle (100%) or ON state +#define HEATERS_MIN_DUTY_CYCLE 0.0F ///< Heaters minimum duty cycle (0.00%) or OFF state +#define D5_HEAT_ON 1.0F ///< Primary heater ON control #define HEATERS_DISINFECT_DUTY_CYCLE 0.80F ///< Heaters disinfect cycle. #define HEATERS_DISINFECT_TRANSFER_DUTY_CYCLE 0.60F ///< Heaters disinfect transfer duty cycle. #endif #define HEATERS_DISINFECT_TEMPERATURE_DRIFT_C 3.0F ///< Heaters disinfect temperature drift in C. #define HEATERS_ZERO_DELTA_TEMP_C 0.0F ///< Heaters zero delta temperature in C. #define HEATERS_DUTY_CYCLE_CONVERSION_FACTOR 100.0F ///< Heaters duty cycle 0: OFF, 100: 100% duty cycle. #define D45_HEAT_GAIN 10.0F ///< Trimmer heater gain for testing. +//Testing : Without Feedfrward gain +//#define D5_HEAT_TX_P_COEFFICIENT 0.20F ///< P Term for AC primary heater control during treatment mode. +//#define D5_HEAT_TX_I_COEFFICIENT 0.002F ///< I Term for AC primary heater control during treatment mode. -#define D5_HEAT_P_COEFFICIENT 21.0F ///< P Term for primary heater control. -#define D5_HEAT_I_COEFFICIENT 6.00F ///< I Term for primary heater control. -#define D45_HEAT_P_COEFFICIENT 35.0F ///< P Term for trimmer heater control. -#define D45_HEAT_I_COEFFICIENT 5.00F ///< I Term for trimmer heater control. +#if 1 +#define D5_HEAT_TX_P_COEFFICIENT 0.04F ///< P Term for AC primary heater control during treatment mode. +#define D5_HEAT_TX_I_COEFFICIENT 0.0007F ///< I Term for AC primary heater control during treatment mode. +#define D5_HEAT_TX_INIT_FEED_FORWARD 0.0F ///< Initial Feed forward term for heater control +#endif +#define D45_HEAT_P_COEFFICIENT 0.35F ///< P Term for trimmer heater control. +#define D45_HEAT_I_COEFFICIENT 0.05F ///< I Term for trimmer heater control. +#define D45_HEAT_TX_INIT_FEED_FORWARD 0.0F ///< Initial Feed forward term for heater control + #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. +//Testing +//#define HEATERS_DATA_PUBLISH_INTERVAL ( 250 / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. #define HEATER_TEMP_CONTROL_TOLERANCE 2.0F ///< Primary Heater temp tolerance for ON/Off control #define HEATER_TARGET_TEMPERATURE_MIN 10.0F ///< Minimum allowed target temperature for the heaters. @@ -73,14 +83,20 @@ #define HEATERS_MAX_OPERATING_VOLTAGE_V 24.0F ///< Heaters max operating voltage in volts. #define HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heaters voltage out of range time out in milliseconds. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heaters max voltage out of range tolerance. -#define D45_HEAT_INITIAL_CONTROL_INTERVAL_COUNT ( ( 5 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater initial control interval count. -#define D45_HEAT_CONTROL_INTERVAL_COUNT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. -#define D5_HEAT_CONTROL_INTERVAL_COUNT ( ( 1 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Primary heater control interval count. -#define TX_PRIMARY_HEATER_MAX_PWR_WATTS 700 ///< Estimated power to be supplied to the primary heater during treatement mode -#define HEAT_PRIMARY_HEATER_MAX_PWR_WATTS 1000 ///< Estimated power to be supplied to the primary heater during heat disinfect mode -#define MAX_INLET_FLOW_LPM ( 800 / 1000 ) ///< Maximum inlet flow to hydraulics chamber from FP ( 800 ml/min => 0.8LPM) -#define TRIMMER_HEATER_MAX_PWR_WATTS 120 ///< Maximum power supplied to trimmer heater -#define AC_HEATER_PWM_PERIOD 1667 ///< PWM period for 60Hz AC ( in 10us resoultion), 1/60Hz = 16666us/10us = 1667. +//Testing +//#define D5_HEAT_CONTROL_INTERVAL_COUNT ( ( 1 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Primary heater control interval count. +#define D5_HEAT_CONTROL_INTERVAL_MS 500 /// Primary heater control interval in milli seconds +#define D5_HEAT_CONTROL_INTERVAL_COUNT ( D5_HEAT_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) ///< Primary heater control interval count. +#define D5_HEAT_CONTROL_SAMPLE_PERIOD ( (F32)D5_HEAT_CONTROL_INTERVAL_MS / (F32)MS_PER_SECOND ) ///< Primary heater control sample period. +#define D45_HEAT_CONTROL_INTERVAL_MS ( 1 * MS_PER_SECOND ) ///< Trimmer heater control interval in milli seconds +#define D45_HEAT_CONTROL_INTERVAL_COUNT ( D45_HEAT_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. +#define D45_HEAT_CONTROL_SAMPLE_PERIOD ( (F32)D45_HEAT_CONTROL_INTERVAL_MS / (F32)MS_PER_SECOND ) ///< Trimmer heater control sample period. +#define TX_PRIMARY_HEATER_MAX_PWR_WATTS 700.0F ///< Estimated power to be supplied to the primary heater during treatement mode +#define HEAT_PRIMARY_HEATER_MAX_PWR_WATTS 980.0F ///< Estimated power to be supplied to the primary heater during heat disinfect mode +#define MAX_INLET_FLOW_LPM ( 600.0F / 1000.0F ) ///< Maximum inlet flow to hydraulics chamber from FP +#define TRIMMER_HEATER_MAX_PWR_WATTS 120.0F ///< Maximum power supplied to trimmer heater +#define AC_HEATER_PWM_PERIOD 10000 ///< PWM period for 60Hz AC ( in 10us resoultion), 1/10Hz = 1000000us/10us = 10000. +#define AC_HEATER_EFFICIENCY 0.90F ///< Approximated AC heater efficiency to be used in energy calcualtions. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. @@ -112,10 +128,12 @@ static OVERRIDE_F32_T targetTempC[ NUM_OF_DD_HEATERS ]; ///< Heater target temperature. static OVERRIDE_F32_T control[ NUM_OF_DD_HEATERS ]; ///< Heater control ( Primary : On/Off, Trimmer : Dutycycle). static OVERRIDE_F32_T pwmPeriod[ NUM_OF_DD_HEATERS ]; ///< Total PWM period ( ON state + Off State of PWM) +static U32 controlInterval[ NUM_OF_DD_HEATERS ]; ///< Heater control interval time. static U32 dataPublicationTimerCounter; ///< Data publication timer counter. -static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. +static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184.0F / (F32)SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. static F32 convertDC; ///< AC Heater converted duty cycle +static F32 heaterEfficiency[ NUM_OF_DD_HEATERS ]; ///< AC Heater efficiency to be used in energy calculations. //For testing #ifdef __HEATERS_DEBUG__ @@ -124,7 +142,7 @@ // ********** private function prototypes ********** static HEATERS_STATE_T handleHeaterStateOff( DD_HEATERS_T heater ); -static HEATERS_STATE_T handleHeaterStateRampToTarget( DD_HEATERS_T heater ); +static HEATERS_STATE_T handleHeaterStateInitialControlSetup( DD_HEATERS_T heater ); static HEATERS_STATE_T handleHeaterStateControlToTarget( DD_HEATERS_T heater ); static HEATERS_STATE_T handleHeaterStateControlToDisinfectTarget( DD_HEATERS_T heater ); @@ -169,6 +187,11 @@ //Initialize Converted Duty cycle convertDC = 0.0F; + controlInterval[ D5_HEAT ] = D5_HEAT_CONTROL_INTERVAL_COUNT; + controlInterval[ D45_HEAT ] = D45_HEAT_CONTROL_INTERVAL_COUNT; + + heaterEfficiency[ D5_HEAT ] = AC_HEATER_EFFICIENCY; + #endif for ( heater = DD_HEATERS_FIRST; heater < NUM_OF_DD_HEATERS; heater++ ) @@ -193,13 +216,13 @@ setHeaterControl( heater ); } - // Initialize the primary controller PI controller - initializePIController( PI_CONTROLLER_ID_D5_HEAT, HEATERS_MIN_DUTY_CYCLE, D5_HEAT_P_COEFFICIENT, D5_HEAT_I_COEFFICIENT, - HEATERS_MIN_DUTY_CYCLE, HEATERS_MAX_DUTY_CYCLE ); + // Initialize the primary heater PI controller + initializePIController( PI_CONTROLLER_ID_D5_HEAT, HEATERS_MIN_DUTY_CYCLE, D5_HEAT_TX_P_COEFFICIENT, D5_HEAT_TX_I_COEFFICIENT, + HEATERS_MIN_DUTY_CYCLE, AC_HEATER_TX_MAX_DUTY_CYCLE, TRUE, D5_HEAT_TX_INIT_FEED_FORWARD, D5_HEAT_CONTROL_SAMPLE_PERIOD ); // Initialize the trimmer heater PI controller initializePIController( PI_CONTROLLER_ID_D45_HEAT, HEATERS_MIN_DUTY_CYCLE, D45_HEAT_P_COEFFICIENT, D45_HEAT_I_COEFFICIENT, - HEATERS_MIN_DUTY_CYCLE, HEATERS_MAX_DUTY_CYCLE ); + HEATERS_MIN_DUTY_CYCLE, DC_HEATER_MAX_DUTY_CYCLE, FALSE, D45_HEAT_TX_INIT_FEED_FORWARD, D45_HEAT_CONTROL_SAMPLE_PERIOD ); #ifdef __HEATERS_DEBUG__ for ( i = 0; i < NUM_OF_CONTROLLER_SIGNAL; i++ ) @@ -372,8 +395,8 @@ heatersStatus[ heater ].state = handleHeaterStateOff( heater ); break; - case HEATER_EXEC_STATE_RAMP_TO_TARGET: - heatersStatus[ heater ].state = handleHeaterStateRampToTarget( heater ); + case HEATER_EXEC_STATE_INITIAL_SETUP: + heatersStatus[ heater ].state = handleHeaterStateInitialControlSetup( heater ); break; case HEATER_EXEC_STATE_CONTROL_TO_TARGET: @@ -473,25 +496,25 @@ heatersStatus[ heater ].heaterOnState = TRUE; heatersStatus[ heater ].startHeaterSignal = FALSE; - // proceed to ramp state - state = HEATER_EXEC_STATE_RAMP_TO_TARGET; + // proceed to setup state + state = HEATER_EXEC_STATE_INITIAL_SETUP; } return state; } /*********************************************************************//** * @brief - * The handleHeaterStateRampToTarget function handles the given heaters' + * The handleHeaterStateInitialControlSetup function handles the given heaters' * control while they are ramping to target temperature. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus - * @param heater: The heater Id to handle the ramping up to target temp. + * @param heater: The heater Id to handle the initial setup control for heater. * @return next state of the state machine *************************************************************************/ -static HEATERS_STATE_T handleHeaterStateRampToTarget( DD_HEATERS_T heater ) +static HEATERS_STATE_T handleHeaterStateInitialControlSetup( DD_HEATERS_T heater ) { - HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; + HEATERS_STATE_T state = HEATER_EXEC_STATE_INITIAL_SETUP; F32 ctrl = 0.0F; DD_OP_MODE_T opMode = getCurrentOperationMode(); F32 measuredTemperature = 0.0F; @@ -506,13 +529,21 @@ #ifndef __ALPHA_AO_VER__ F32 deltaTempC = targetTemperature - measuredTemperature; F32 capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); - F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * MAX_INLET_FLOW_LPM ) / TX_PRIMARY_HEATER_MAX_PWR_WATTS ); - dutyCycle *= HEATERS_DUTY_CYCLE_CONVERSION_FACTOR; - dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); +// F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * MAX_INLET_FLOW_LPM ) / TX_PRIMARY_HEATER_MAX_PWR_WATTS ); +// dutyCycle = MIN( dutyCycle, AC_HEATER_TX_MAX_DUTY_CYCLE ); +// dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); +// +// control[ heater ].data = dutyCycle; + // Testing - Uncomment below line + //resetPIController( PI_CONTROLLER_ID_D5_HEAT, dutyCycle ); - control[ heater ].data = dutyCycle; - resetPIController( PI_CONTROLLER_ID_D5_HEAT, dutyCycle ); + F32 feedforward = ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * MAX_INLET_FLOW_LPM ) / TX_PRIMARY_HEATER_MAX_PWR_WATTS; + feedforward = ( feedforward * AC_HEATER_TX_MAX_DUTY_CYCLE ) / heaterEfficiency[ D5_HEAT ]; + feedforward = MIN( feedforward, AC_HEATER_TX_MAX_DUTY_CYCLE ); + feedforward = MAX( feedforward, HEATERS_MIN_DUTY_CYCLE ); + + control[ heater ].data = feedforward; + resetPIController( PI_CONTROLLER_ID_D5_HEAT, HEATERS_MIN_DUTY_CYCLE, feedforward ); #else // Assign initial value control[ heater ].data = D5_HEAT_ON; @@ -536,12 +567,11 @@ F32 capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * MAX_INLET_FLOW_LPM ) / TRIMMER_HEATER_MAX_PWR_WATTS ); //F32 dutyCycle = ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * MAX_INLET_FLOW_LPM ) / TRIMMER_HEATER_MAX_PWR_WATTS ; - dutyCycle *= HEATERS_DUTY_CYCLE_CONVERSION_FACTOR; - dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); + dutyCycle = MIN( dutyCycle, DC_HEATER_MAX_DUTY_CYCLE ); dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); control[ heater ].data = dutyCycle; - resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle ); + resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); #else // Assign initial value ctrl = ( ( targetTemperature / HEATER_TARGET_TEMPERATURE_MAX ) * HEATERS_DUTY_CYCLE_CONVERSION_FACTOR ) + FLOAT_TO_INT_ROUNDUP_OFFSET; @@ -580,7 +610,7 @@ F32 measuredTemperature = 0.0F; F32 ctrl = 0.0F; - if( ++heatersStatus[ heater ].controlIntervalCounter > D5_HEAT_CONTROL_INTERVAL_COUNT ) + if( ++heatersStatus[ heater ].controlIntervalCounter > controlInterval[ heater ] ) { if ( D5_HEAT == heater ) { @@ -609,7 +639,6 @@ pIControlSignal[ i ] = getPIControllerSignals( PI_CONTROLLER_ID_D5_HEAT, (PI_CONTROLLER_SIGNALS_ID)i ); } #endif - } else { @@ -630,6 +659,14 @@ control[ heater ].data = ( ctrl * HEATERS_DUTY_CYCLE_CONVERSION_FACTOR ) + FLOAT_TO_INT_ROUNDUP_OFFSET; #endif +#ifdef __HEATERS_DEBUG__ + U32 i; + + for ( i = 0; i < NUM_OF_CONTROLLER_SIGNAL; i++ ) + { + pIControlSignal[ i ] = getPIControllerSignals( PI_CONTROLLER_ID_D45_HEAT, (PI_CONTROLLER_SIGNALS_ID)i ); + } +#endif } heatersStatus[ heater ].hasTargetTempChanged = FALSE; @@ -683,8 +720,9 @@ if ( D5_HEAT == heater ) { #ifndef __ALPHA_AO_VER__ - //Convert duty cycle into LowState and multiply by period for now - convertDC = ( HEATERS_DUTY_CYCLE_CONVERSION_FACTOR - control ) * period; + //Convert duty cycle into LowState and multiply by period + F32 duty = AC_HEATER_MAX_DUTY_CYCLE - control; + convertDC = duty * period; setFPGAD5HeaterPWMPeriod( (U16)period ); setFPGAD5HeaterPWMLowState( (U16)convertDC ); @@ -797,6 +835,7 @@ data.dbg6 = pIControlSignal[ 5 ]; data.dbg7 = pIControlSignal[ 6 ]; data.dbg8 = pIControlSignal[ 7 ]; + data.dbg9 = pIControlSignal[ 8 ]; #endif dataPublicationTimerCounter = 0;