Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -rf0ab8f06e0c8af10bd8db099927669dbd94326b8 -r9ee16bedc8686e674f2cdee571a7c4f93df178ea --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f0ab8f06e0c8af10bd8db099927669dbd94326b8) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 9ee16bedc8686e674f2cdee571a7c4f93df178ea) @@ -29,6 +29,7 @@ #include "SafetyShutdown.h" #include "TaskGeneral.h" #include "TaskPriority.h" +#include "TDInterface.h" #include "TemperatureSensors.h" #include "Timers.h" #include "Utilities.h" @@ -56,16 +57,19 @@ #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 +//Testing : PI Controller Gain without FF //#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. -#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. +//Testing : PI Controller gain with FF +//#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 +// PI controller gain with initial Open loop and FF later +#define D5_HEAT_TX_P_COEFFICIENT 0.015F ///< P Term for AC primary heater control during treatment mode. +#define D5_HEAT_TX_I_COEFFICIENT 0.00007F ///< I Term for AC primary heater control during treatment mode. + #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 @@ -74,7 +78,7 @@ //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_TEMP_CONTROL_TRANSFER 1.0F ///< Primary Heater temperature difference to switch to control function #define HEATER_TARGET_TEMPERATURE_MIN 10.0F ///< Minimum allowed target temperature for the heaters. #define HEATER_TARGET_TEMPERATURE_MAX 90.0F ///< Maximum allowed target temperature for the heaters. @@ -83,17 +87,18 @@ #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. -//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_MS 30000 /// 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 PRIMARY_HEATER_MAX_PWR_WATTS 1400.0F ///< AC Primary Heater Max Power consumeption in Watts #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 LITER_IN_ML 1000.0F ///< Liter in milliliter units #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. @@ -134,6 +139,7 @@ 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. +static BOOL startupHeaterControl; ///< First time control with the energy equation. //For testing #ifdef __HEATERS_DEBUG__ @@ -190,7 +196,12 @@ controlInterval[ D5_HEAT ] = D5_HEAT_CONTROL_INTERVAL_COUNT; controlInterval[ D45_HEAT ] = D45_HEAT_CONTROL_INTERVAL_COUNT; + // Assign counter close to the target period + heatersStatus[ D5_HEAT ].controlIntervalCounter = 590; + heatersStatus[ D45_HEAT ].controlIntervalCounter = 0; + heaterEfficiency[ D5_HEAT ] = AC_HEATER_EFFICIENCY; + startupHeaterControl = TRUE; #endif @@ -210,7 +221,6 @@ heatersStatus[ heater ].targetFlowLPM = 0.0F; heatersStatus[ heater ].nomTargetFlowLPM = 0.0F; heatersStatus[ heater ].hasTargetTempChanged = FALSE; - heatersStatus[ heater ].controlIntervalCounter = 0; heatersStatus[ heater ].isThisFirstControl = TRUE; heatersStatus[ heater ].prevDiaTargetFlowLPM = 0.0F; setHeaterControl( heater ); @@ -324,6 +334,28 @@ /*********************************************************************//** * @brief + * The signalHeaterControl function updates heater control based on + * the latest treatment paratmeter change + * @details \b Inputs: heatersStatus + * @details \b Outputs: none + * @param heater: heater ID to update the heater control. + * @return none + *************************************************************************/ +void signalHeaterControl( DD_HEATERS_T heater ) +{ + if ( D5_HEAT == heater ) + { + // check heater state + if ( HEATER_EXEC_STATE_CONTROL_TO_TARGET == heatersStatus[ heater ].state ) + { + // Set flag to recalculate the feedforward signals + startupHeaterControl = TRUE; + } + } +} + +/*********************************************************************//** + * @brief * The startHeater function starts the given heater by setting the flag. * @details \b Inputs: heatersStatus * @details \b Outputs: startHeaterSignal @@ -529,26 +561,22 @@ #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 = 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 ); - 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 ); + if ( capDeltaTempC <= HEATER_TEMP_CONTROL_TRANSFER ) + { + // Transfer Control to target when delta temp is minimal. + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; + } + else + { + // Start Open loop control with max power + control[ heater ].data = AC_HEATER_TX_MAX_DUTY_CYCLE; + } #else // Assign initial value control[ heater ].data = D5_HEAT_ON; -#endif state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; +#endif } else { @@ -565,8 +593,8 @@ #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 ; + F32 flowrate = getTDDialysateFlowrate() / LITER_IN_ML ; + F32 dutyCycle = ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * flowrate ) / TRIMMER_HEATER_MAX_PWR_WATTS; dutyCycle = MIN( dutyCycle, DC_HEATER_MAX_DUTY_CYCLE ); dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); @@ -607,6 +635,7 @@ { HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; F32 targetTemperature = getHeaterTargetTemperature( heater ); + F32 inletTemperature = 0.0F; F32 measuredTemperature = 0.0F; F32 ctrl = 0.0F; @@ -615,10 +644,31 @@ if ( D5_HEAT == heater ) { measuredTemperature = getTemperatureValue( D4_TEMP ); + // Inlet temperature post heat exchanger + inletTemperature = getTemperatureValue( X6_TEMP ); #ifndef __ALPHA_AO_VER__ - ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT, targetTemperature, measuredTemperature ); - control[ heater ].data = ctrl; + if ( TRUE == startupHeaterControl ) + { + startupHeaterControl = FALSE; + //TODO : testing + //F32 deltaTempC = targetTemperature - inletTemperature; + F32 deltaTempC = 10.0F; // Hard code for testing, later remove it. + F32 capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); + F32 flowrate = getTDDialysateFlowrate() / LITER_IN_ML ; + F32 feedforward = ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * capDeltaTempC * flowrate ) / PRIMARY_HEATER_MAX_PWR_WATTS; + feedforward = feedforward / 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 + { + ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT, targetTemperature, measuredTemperature ); + control[ heater ].data = ctrl; + } #else if ( measuredTemperature >= targetTemperature ) { @@ -733,7 +783,8 @@ } else { - setFPGAD45HeaterPWMControl( (U08)control ); + U08 ctrl = ( control * HEATERS_DUTY_CYCLE_CONVERSION_FACTOR ) + FLOAT_TO_INT_ROUNDUP_OFFSET; + setFPGAD45HeaterPWMControl( ctrl ); } } else @@ -816,7 +867,9 @@ data.d5_HeaterDC = getHeaterControl( D5_HEAT ); data.d45_HeaterDC = getHeaterControl( D45_HEAT ); data.d5_HeaterTargetTemp = getHeaterTargetTemperature( D5_HEAT ); - data.d45_HeaterTargetTemp = getHeaterTargetTemperature( D45_HEAT ); + //TODO : Testing + //data.d45_HeaterTargetTemp = getHeaterTargetTemperature( D45_HEAT ); + data.d45_HeaterTargetTemp = getTemperatureValue( D4_TEMP ); data.d5_HeaterState = heatersStatus[ D5_HEAT ].state; data.d45_HeaterState = heatersStatus[ D45_HEAT ].state; #ifndef __HEATERS_DEBUG__ Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -rf0ab8f06e0c8af10bd8db099927669dbd94326b8 -r9ee16bedc8686e674f2cdee571a7c4f93df178ea --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision f0ab8f06e0c8af10bd8db099927669dbd94326b8) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 9ee16bedc8686e674f2cdee571a7c4f93df178ea) @@ -73,6 +73,7 @@ BOOL setHeaterTargetTemperature( DD_HEATERS_T heater, F32 targetTemperature ); void startHeater( DD_HEATERS_T heater ); F32 getHeaterTargetTemperature( DD_HEATERS_T heater ); +void signalHeaterControl( DD_HEATERS_T heater ); BOOL isHeaterOn( DD_HEATERS_T heater ); void stopHeater( DD_HEATERS_T heater ); void execHeatersControl( void ); Index: firmware/App/Drivers/TemperatureSensors.c =================================================================== diff -u -rf0ab8f06e0c8af10bd8db099927669dbd94326b8 -r9ee16bedc8686e674f2cdee571a7c4f93df178ea --- firmware/App/Drivers/TemperatureSensors.c (.../TemperatureSensors.c) (revision f0ab8f06e0c8af10bd8db099927669dbd94326b8) +++ firmware/App/Drivers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 9ee16bedc8686e674f2cdee571a7c4f93df178ea) @@ -36,8 +36,8 @@ #define PRIMARY_HEATER_TEMP_SENSORS_GAIN 8U ///< Primary heater temperature sensors gain. //TODO : Fix the final resistor value based on the upcoming board versions design -//#define PRIMARY_HEATER_TEMP_SENSORS_REF_RESISTANCE 20000 ///< Primary heater temperature sensors reference resistance. -#define PRIMARY_HEATER_TEMP_SENSORS_REF_RESISTANCE 19600 ///< Primary heater temperature sensors reference resistance. +#define PRIMARY_HEATER_TEMP_SENSORS_REF_RESISTANCE 20000 ///< Primary heater temperature sensors reference resistance. +//#define PRIMARY_HEATER_TEMP_SENSORS_REF_RESISTANCE 19600 ///< Primary heater temperature sensors reference resistance. #define PRIMARY_HEATER_TEMP_SENSORS_0_DEGREE_RESISTANCE 1000U ///< Primary heater temperature sensors zero degree resistance. #ifdef USE_PT_100