Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r5e92cbb2c29854fb60a91dc4abafeb9b08d3272c -r4498cae8c39b40a3756f8f009c124f12772a0b51 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 5e92cbb2c29854fb60a91dc4abafeb9b08d3272c) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 4498cae8c39b40a3756f8f009c124f12772a0b51) @@ -39,21 +39,28 @@ */ // ********** 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. +#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_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. -#define D5_HEAT_P_COEFFICIENT 1.0F ///< P Term for primary heater control. -#define D5_HEAT_I_COEFFICIENT 1.0F ///< I Term for primary heater control. -#define D45_HEAT_P_COEFFICIENT 1.0F ///< P Term for trimmer heater control. -#define D45_HEAT_I_COEFFICIENT 1.0F ///< I Term for trimmer heater control. +#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. #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. @@ -69,6 +76,11 @@ #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. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. @@ -99,7 +111,9 @@ static HEATER_STATUS_T heatersStatus[ NUM_OF_DD_HEATERS ]; ///< Heaters status. 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 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 OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. // ********** private function prototypes ********** @@ -127,6 +141,24 @@ DD_HEATERS_T heater; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; +#ifndef __ALPHA_AO_VER__ + //Enable PWM based heater control + setFPGAD5HeaterPWMEnableControl( TRUE ); + + // Define PWM period for AC heater + pwmPeriod[ D5_HEAT ].data = AC_HEATER_PWM_PERIOD; + pwmPeriod[ D5_HEAT ].ovData = AC_HEATER_PWM_PERIOD; + pwmPeriod[ D5_HEAT ].ovInitData = AC_HEATER_PWM_PERIOD; + pwmPeriod[ D5_HEAT ].override = OVERRIDE_RESET; + + // TODO : Trimmer heater PWM period + pwmPeriod[ D45_HEAT ].data = 0.0F; + pwmPeriod[ D45_HEAT ].ovData = 0.0F; + pwmPeriod[ D45_HEAT ].ovInitData = 0.0F; + pwmPeriod[ D45_HEAT ].override = OVERRIDE_RESET; + +#endif + for ( heater = DD_HEATERS_FIRST; heater < NUM_OF_DD_HEATERS; heater++ ) { targetTempC[ heater ].data = 0.0F; @@ -220,6 +252,22 @@ /*********************************************************************//** * @brief + * The getHeaterPWMPeriod function returns the given heater PWM + * period. + * @details \b Inputs: none + * @details \b Outputs: pwmPeriod + * @param heater: heater ID to get heater PWM period. + * @return the given heater PWM period. + *************************************************************************/ +F32 getHeaterPWMPeriod( DD_HEATERS_T heater ) +{ + F32 pwmPrd = getF32OverrideValue( &pwmPeriod[ heater ] ); + + return pwmPrd; +} + +/*********************************************************************//** + * @brief * The isHeaterOn function returns the given heater status whether * it is on or off * @details \b Inputs: heaterStatus @@ -424,16 +472,34 @@ *************************************************************************/ static HEATERS_STATE_T handleHeaterStateRampToTarget( DD_HEATERS_T heater ) { - HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; - F32 ctrl = 0.0F; - DD_OP_MODE_T opMode = getCurrentOperationMode(); - F32 targetTemperature = getHeaterTargetTemperature( heater ); + HEATERS_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; + F32 ctrl = 0.0F; + DD_OP_MODE_T opMode = getCurrentOperationMode(); + F32 measuredTemperature = 0.0F; + F32 targetTemperature = getHeaterTargetTemperature( heater ); if ( D5_HEAT == heater ) { + measuredTemperature = getTemperatureValue( D4_TEMP ); + if ( DD_MODE_HEAT != opMode ) { +#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 ); + + control[ heater ].data = dutyCycle; + resetPIController( PI_CONTROLLER_ID_D5_HEAT, dutyCycle ); + +#else + // Assign initial value control[ heater ].data = D5_HEAT_ON; +#endif state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } else @@ -444,9 +510,25 @@ } else { + measuredTemperature = getTemperatureValue( D50_TEMP ); + if ( DD_MODE_HEAT != opMode ) { +#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 ) / 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 = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); + + control[ heater ].data = dutyCycle; + resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle ); +#else + // Assign initial value ctrl = ( ( targetTemperature / HEATER_TARGET_TEMPERATURE_MAX ) * HEATERS_DUTY_CYCLE_CONVERSION_FACTOR ) + FLOAT_TO_INT_ROUNDUP_OFFSET; +#endif state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } else @@ -485,7 +567,14 @@ { if ( D5_HEAT == heater ) { - measuredTemperature = getTemperatureValue( (U32)D4_TEMP ); + measuredTemperature = getTemperatureValue( D4_TEMP ); + +#ifndef __ALPHA_AO_VER__ + + ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT, targetTemperature, measuredTemperature ); + control[ heater ].data = ctrl; + +#else if ( measuredTemperature >= targetTemperature ) { // Turn off heater @@ -496,13 +585,18 @@ // Turn On heater control[ heater ].data = D5_HEAT_ON; } - - //control = runPIController( PI_CONTROLLER_ID_D5_HEAT, targetTemperature, measuredTemperature ); +#endif } else { - measuredTemperature = getTemperatureValue( (U32)D50_TEMP ); - //control = runPIController( PI_CONTROLLER_ID_D45_HEAT, targetTemperature, measuredTemperature ); + measuredTemperature = getTemperatureValue( D50_TEMP ); + +#ifndef __ALPHA_AO_VER__ + + ctrl = runPIController( PI_CONTROLLER_ID_D45_HEAT, targetTemperature, measuredTemperature ); + control[ heater ].data = ctrl; + +#else if ( targetTemperature > 0.0F ) { ctrl = HEATERS_MAX_DUTY_CYCLE - ( measuredTemperature / targetTemperature ); @@ -513,6 +607,7 @@ } control[ heater ].data = ( ctrl * HEATERS_DUTY_CYCLE_CONVERSION_FACTOR ) + FLOAT_TO_INT_ROUNDUP_OFFSET; +#endif } heatersStatus[ heater ].hasTargetTempChanged = FALSE; @@ -560,14 +655,21 @@ { if ( heater < NUM_OF_DD_HEATERS ) { - F32 control; + F32 control = getHeaterControl( heater ); + F32 period = getHeaterPWMPeriod ( heater ); - control = getHeaterControl( heater ); - if ( D5_HEAT == heater ) { +#ifndef __ALPHA_AO_VER__ + //Convert duty cycle into LowState and multiply by period for now + F32 convertDC = ( HEATERS_DUTY_CYCLE_CONVERSION_FACTOR - control ) * period; + + setFPGAD5HeaterPWMPeriod( (U16)period ); + setFPGAD5HeaterPWMLowState( (U16)convertDC ); +#else BOOL heaterCntrl = (BOOL)control; setFPGAD5HeaterOnOffControl( heaterCntrl ); +#endif } else { @@ -725,6 +827,23 @@ /*********************************************************************//** * @brief + * The testHeaterPWMPeriodOverride function overrides the specified heater's + * PWM period. + * @details \b Inputs: pwmPeriod + * @details \b Outputs: pwmPeriod + * @param message Override message from Dialin which includes an ID of + * the heater to override and the PWM period of the heater. + * @return TRUE if the override was successful otherwise FALSE + *************************************************************************/ +BOOL testHeaterPWMPeriodOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &pwmPeriod[ 0 ], NUM_OF_DD_HEATERS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief * The testHeaterStartStopOverride function starts/stops a given heater * at mentioned temperature. * @details \b Inputs: tester logged in