Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -rbfd1ad206360b585a01b75ce2310bfba3ffd9e1f -r1eb7496d07548ac5fb33e1051542f42cd5ff529c --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision bfd1ad206360b585a01b75ce2310bfba3ffd9e1f) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 1eb7496d07548ac5fb33e1051542f42cd5ff529c) @@ -59,7 +59,7 @@ #define D5_HEAT_TX_I_COEFFICIENT 0.001F ///< I Term for AC primary heater control during treatment mode. #define D45_HEAT_P_COEFFICIENT 0.05F //0.01F ///< P Term for trimmer heater control. -#define D45_HEAT_I_COEFFICIENT 0.0025F ///< I Term for trimmer heater control. +#define D45_HEAT_I_COEFFICIENT 0.0010F ///< I Term for trimmer heater control. #define D45_HEAT_TX_INIT_FEED_FORWARD 0.0F ///< Initial Feed forward term for heater control #define D45_HEAT_HIGHER_QD_P_COEFFICIENT 0.2F ///< P Term for trimmer heater control for higher dialysate flow rate. #define D45_HEAT_HIGHER_QD_I_COEFFICIENT 0.05F ///< I Term for trimmer heater control for higher dialysate flow rate. @@ -103,8 +103,12 @@ #define D5_HEAT_OUT_TX_I_COEFFICIENT 0.4F ///< I Term for AC primary heater outer loop control during treatment mode. #else #define D5_HEAT_OUT_TX_P_COEFFICIENT 0.75F //2.00F //0.5F ///< P Term for AC primary heater outer loop control during treatment mode. -#define D5_HEAT_OUT_TX_I_COEFFICIENT 0.1F //0.04F //0.08F //0.4F ///< I Term for AC primary heater outer loop control during treatment mode. +#define D5_HEAT_OUT_TX_I_COEFFICIENT 0.15F //0.04F //0.08F //0.4F ///< I Term for AC primary heater outer loop control during treatment mode. #endif +#define D5_HEAT_OUT_LOWQD_TX_P_COEFFICIENT 0.3F ///< P Term for AC primary heater outer loop - low Qd(<200) control during treatment mode. +#define D5_HEAT_OUT_LOWQD_TX_I_COEFFICIENT 0.1F ///< I Term for AC primary heater outer loop - low Qd(<200) control during treatment mode. +#define D5_HEAT_HIGH_DIAL_FLOW_RATE 200.0F ///< Decide Primary heater outer loop - PI control based on the dialysate flow rate + #define D5_HEAT_OUT_MIN_DELTA_TEMP 0.0F ///< Minimum Delta temperature that can be adjusted for D5 control #define D5_HEAT_OUT_MAX_DELTA_TEMP 50.0 ///< Maximum Delta temperature that can be adjusted for D5 control #define D5_HEAT_OUT_DEADBAND_CONTROL 0.1F ///< Heater outer loop dead band range for control. @@ -137,6 +141,9 @@ #define BETA2_0_B3_HEAT_DIS_FOURTH_COEFF 0.0092543272727F ///< Fourth coefficient for Heat loss dissipation calculation from D28 to Dialyzer. #define BETA2_0_B3_HEAT_DIS_FIFTH_COEFF 1.079412363636F ///< Fifth coefficient for Heat loss dissipation calculation from D28 to Dialyzer. +#define BETA2_0_B_HEAT_DIS_FIRST_COEFF 0.38F ///< First coefficient for Heat loss dissipation calculation from D4 to D113 (natural logarthmic equation). +#define BETA2_0_B_HEAT_DIS_SEC_COEFF 2.72F ///< Second coefficient for Heat loss dissipation calculation from D4 to D113. + //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 data structure @@ -197,6 +204,7 @@ static F32 calculateBeta2HeatDissipationB3( void ); static F32 calculateHeatDissipationB1andB2( void ); static F32 calculateHeatDissipationB3( void ); +static F32 calculateHeatDissipationB( void ); static F32 calculateInitialTemp( F32 targetTemp, F32 heatDissipation ); static F32 calculateDutyCycle( F32 flowrate, F32 deltaTemp, F32 power, F32 efficiency, F32 min, F32 max ); @@ -281,9 +289,14 @@ 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 ); - initializePIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_TX_P_COEFFICIENT, D5_HEAT_OUT_TX_I_COEFFICIENT, + // Outerloop control for high Qd (>200) + initializePIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_HIGHER_QD, D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_TX_P_COEFFICIENT, D5_HEAT_OUT_TX_I_COEFFICIENT, D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_MAX_DELTA_TEMP, FALSE, D5_HEAT_TX_INIT_FEED_FORWARD ); + // Outerloop control for Low Qd ( <200) + initializePIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_LOWQD_TX_P_COEFFICIENT, D5_HEAT_OUT_LOWQD_TX_I_COEFFICIENT, + D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_MAX_DELTA_TEMP, FALSE, D5_HEAT_TX_INIT_FEED_FORWARD ); + // 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, DC_HEATER_MAX_DUTY_CYCLE, FALSE, D45_HEAT_TX_INIT_FEED_FORWARD ); @@ -424,12 +437,13 @@ { // Reset the adjusted temperature target isTargetTempAdjusted = FALSE; + // start outer loop control immediately upon changing Qd + flowrate = getTDDialysateFlowrate(); + primaryTargetTempAdjCounter = ( flowrate >= D5_HEAT_HIGH_DIAL_FLOW_RATE ? D5_TARGET_TEMP_ADJUST_HIGH_QD_INTERVAL : D5_TARGET_TEMP_ADJUST_LOW_QD_INTERVAL ); } if ( HEATER_EXEC_STATE_CONTROL_TO_TARGET == heatersStatus[ D45_HEAT ].state ) { - //Change back to ramp state to reset the controller - //heatersStatus[ D45_HEAT ].state = HEATER_EXEC_STATE_RAMP_TO_TARGET; F32 prevDuty = getHeaterControl( D45_HEAT ); // When Qd change happens, use previous PWM to calculate the new PWM @@ -467,7 +481,7 @@ F32 targetTemp = getTDTargetDialysateTemperature(); F32 targetTempAtD28 = 0.0F; F32 targetTempAtD4 = 0.0F; - +#ifndef __USE_D1_TEMP_ // Heat loss model predicts the heat loss ( B1,B2 and B3) in the DD flow path and // finds the delta temperature to be added with the target temperature // to maintain the target temperature at dialyzer. @@ -488,6 +502,14 @@ targetTempAtD28 = calculateInitialTemp( targetTemp, heatDissipation_b3 ); // calculation of target temp at D4 to get the target temp at D28 level targetTempAtD4 = calculateInitialTemp( targetTempAtD28, heatDissipation_b1b2 ); +#else + // heat loss model based on the temp sensor (D113) closely located to dialyzer. + // Find the difference in temperature between dialyzer temperature(D113) and + // D4 temperature and that is considered as heat loss factor(B). + heatDissipation_b1b2 = calculateHeatDissipationB(); + // calculation of target temp at D4 to get the target temp at D113 level + targetTempAtD4 = calculateInitialTemp( targetTemp, heatDissipation_b1b2 ); +#endif //Update target temperature setTargetHydChamberTemp( targetTempAtD4 ); } @@ -506,8 +528,8 @@ F32 deltaTempC = 0.0F; F32 ctrl = 0.0F; F32 measuredTempAtDialyzer = 0.0F; - F32 targetTempfromTD = 0.0F; - F32 diffTempC = 0.0F; + F32 flowrate = getTDDialysateFlowrate(); + F32 targetTempfromTD = getTDTargetDialysateTemperature(); if ( ++primaryTargetTempAdjCounter >= d5OuterLoopControlInterval ) { @@ -527,18 +549,32 @@ } #endif calcTargetTemp = getHeaterTargetTemperature( D5_HEAT ); - diffTempC = fabs( calcTargetTemp - measuredTempAtDialyzer ); - deltaTempC = targetTempfromTD - measuredTempAtDialyzer; + deltaTempC = fabs( targetTempfromTD - measuredTempAtDialyzer ); - if ( ( FALSE == isTargetTempAdjusted ) && ( diffTempC <= HEATER_TEMP_CONTROL_TRANSFER ) ) + if ( ( FALSE == isTargetTempAdjusted ) && ( deltaTempC <= HEATER_TEMP_CONTROL_TRANSFER ) ) { isTargetTempAdjusted = TRUE; adjustedPrimaryTargetTemp = calcTargetTemp; - resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, calcTargetTemp, HEATERS_MIN_DUTY_CYCLE ); + + if ( flowrate >= D5_HEAT_HIGH_DIAL_FLOW_RATE ) + { + resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_HIGHER_QD, calcTargetTemp, HEATERS_MIN_DUTY_CYCLE ); + } + else + { + resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, calcTargetTemp, HEATERS_MIN_DUTY_CYCLE ); + } } - else if ( ( fabs(deltaTempC) >= D5_HEAT_OUT_DEADBAND_CONTROL ) && ( TRUE == isTargetTempAdjusted ) ) + else if ( ( deltaTempC >= D5_HEAT_OUT_DEADBAND_CONTROL ) && ( TRUE == isTargetTempAdjusted ) ) { - ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, getTDTargetDialysateTemperature(), measuredTempAtDialyzer ); + if ( flowrate >= D5_HEAT_HIGH_DIAL_FLOW_RATE ) + { + ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_HIGHER_QD, getTDTargetDialysateTemperature(), measuredTempAtDialyzer ); + } + else + { + ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, getTDTargetDialysateTemperature(), measuredTempAtDialyzer ); + } adjustedPrimaryTargetTemp = ctrl; } @@ -769,6 +805,7 @@ // Reset PI Controllers resetPIController( PI_CONTROLLER_ID_D5_HEAT, HEATERS_MIN_DUTY_CYCLE, feedforward ); resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, targetTemperature, HEATERS_MIN_DUTY_CYCLE ); + resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_HIGHER_QD, targetTemperature, HEATERS_MIN_DUTY_CYCLE ); // Transfer Control to target when delta temp is minimal. state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; @@ -870,8 +907,8 @@ setPIControllerFeedForward( PI_CONTROLLER_ID_D5_HEAT, d5FeedForward ); // decide outer loop control interval based on the Qd - //flowrate = getTDDialysateFlowrate(); - //d5OuterLoopControlInterval = ( flowrate >= HIGH_DIAL_FLOW_RATE ? D5_TARGET_TEMP_ADJUST_HIGH_QD_INTERVAL : D5_TARGET_TEMP_ADJUST_LOW_QD_INTERVAL ); + flowrate = getTDDialysateFlowrate(); + d5OuterLoopControlInterval = ( flowrate >= D5_HEAT_HIGH_DIAL_FLOW_RATE ? D5_TARGET_TEMP_ADJUST_HIGH_QD_INTERVAL : D5_TARGET_TEMP_ADJUST_LOW_QD_INTERVAL ); // If D28 feedback control is enabled and adjusted temp calculation is done // then update the target temperature. @@ -1022,7 +1059,7 @@ * @brief * The calculateBeta2HeatDissipationB1andB2 function calculates the heat dissipation * constants called B1 and B2 that describes the heat loss between D4 to D28 in - * the PID flow path for Beta2.0 hardware. + * the P&ID flow path for Beta2.0 hardware. * @details \b Inputs: Qd. * @details \b Outputs: none * @return the calculated heat dissipation constants. @@ -1047,7 +1084,7 @@ * @brief * The calculateBeta2HeatDissipationB3 function calculates the heat dissipation * constants called B3 that describes the heat loss between D28 to dialyzer in - * the PID flow path for Beta2.0 hardware. + * the P&ID flow path for Beta2.0 hardware. * @details \b Inputs: Qd. * @details \b Outputs: none * @return the calculated heat dissipation constant. @@ -1072,7 +1109,7 @@ * @brief * The calculateHeatDissipationB1andB2 function calculates the heat dissipation * constants called B1 and B2 that describes the heat loss between D4 to D28 in - * the PID flow path. + * the P&ID flow path. * @details \b Inputs: Qd. * @details \b Outputs: none * @return the calculated heat dissipation constants. @@ -1096,7 +1133,7 @@ * @brief * The calculateHeatDissipationB3 function calculates the heat dissipation * constants called B3 that describes the heat loss between D28 to dialyzer in - * the PID flow path. + * the P&ID flow path. * @details \b Inputs: Qd. * @details \b Outputs: none * @return the calculated heat dissipation constant. @@ -1118,6 +1155,29 @@ /*********************************************************************//** * @brief + * The calculateHeatDissipationB function calculates the heat dissipation + * constants called B that describes the heat loss between D4 to (D113)dialyzer in + * the P&ID flow path. + * @details \b Inputs: Qd. + * @details \b Outputs: none + * @return the calculated heat dissipation constant. + *************************************************************************/ +static F32 calculateHeatDissipationB( void ) +{ + // Get the dialysate flow rate from TD + F32 b = 0.0F; + F32 qd = getTDDialysateFlowrate(); + F32 logQd = logf(qd); // natural logarthemic + F32 firstPart = BETA2_0_B_HEAT_DIS_FIRST_COEFF * logQd; + + // B = 0.38*LN(qd)-2.72 + b = firstPart - BETA2_0_B_HEAT_DIS_SEC_COEFF; + + return b; +} + +/*********************************************************************//** + * @brief * The calculateInitialTemp function calculates the initial temperature * required to get the target temperature considering heat loss. * @details \b Inputs: ambient temperature