Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r2d295ca85f19e95da42476a57ca6b4496baf980a -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 2d295ca85f19e95da42476a57ca6b4496baf980a) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -53,14 +53,14 @@ #define SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG 2.0F ///< Above this absolute spent pressure, only one rise hit is required. #define SPENT_FILL_SLOPE_SPENT_PRESSURE_LOW_PSIG 0.5F ///< Below this absolute spent pressure, use Qd-based required rise hit count. #define SPENT_FILL_SLOPE_MAX_RISE_HITS 2 ///< Rise hits required when Qd <= 150 in the low spent-pressure band. -#define SPENT_FILL_DETECT_COUNT_TOL_PCT 0.20F ///< Allowed detection timing tolerance as a fraction of expected BC switching count. +#define SPENT_FILL_DETECT_COUNT_TOL_PCT 1.0F ///< Allowed detection timing tolerance as a fraction of expected BC switching count. #define QD_THRESHOLD_HIGH_MLPM 400.0F ///< Qd threshold (mL/min) below which mid pressure limit applies. #define SPENT_DIFF_COUNT_ZERO 0 ///< Zero count difference for spent side fill comparing target count #define D48_SPEED_ADJUST_FACTOR 0.5F ///< D48 speed adjustment factor ( 50% of speed adjustment = 0.5) #define D48_SPEED_RANGE_LIMIT 0.25F ///< D48 speed adjustment range check limit ( D48 speed can vary +/-25% of initial calculated speed) #define BICARB_CHAMBER_PERIODIC_FILL_TIME ( 1 * SEC_PER_MIN * \ ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ) ///< Periodic bicarb chamber fill request 60 sec x 20 = 1200 -#define BAL_CHAMBER_FILL_TIMEOUT_FACTOR 1.5 ///< Balancing Chamber fill timeout factor (150% of observed fill count) +#define BAL_CHAMBER_FILL_TIMEOUT_FACTOR 2.5 ///< Balancing Chamber fill timeout factor (150% of observed fill count) /// Payload record structure for balancing chamber switch only request typedef struct @@ -701,7 +701,7 @@ // Check both spent and fresh side fill is complete isBothFillsComplete = ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ); - isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ); + isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ) && ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ); if ( FALSE == getBalChamberSwitchingOnlyStatus() ) { @@ -949,7 +949,7 @@ // Check switching cycle time or pressure check for valve closure isBothFillsComplete = ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ); - isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ); + isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ) && ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ); if ( FALSE == getBalChamberSwitchingOnlyStatus() ) { Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r2d295ca85f19e95da42476a57ca6b4496baf980a -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 2d295ca85f19e95da42476a57ca6b4496baf980a) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -54,18 +54,19 @@ #define HEATERS_DUTY_CYCLE_CONVERSION_FACTOR 100.0F ///< Heaters duty cycle 0: OFF, 100: 100% duty cycle. #define HEATERS_ZERO_EFFICIENCY 0.0F ///< Zero heater efficiency #define HEATER_CNTL_TRANSFER_DELTA_TEMP_C 0.50F ///< AC heater delta temperature to transfer control from open to close loop -#define ADJ_DELTA_TEMP_STEP 2.0F ///< Adjust target temperature based on D28 feedback per cycle. -#define MAX_ADJ_DELTA_TEMP_C 7.0F ///< Maximum adjusted delta temperature to add/remove from calculated target temperature #define D5_HEAT_TX_INIT_FEED_FORWARD 0.0F ///< Initial Feed forward term for heater control -#define D5_HEAT_TX_P_COEFFICIENT 0.05F ///< P Term for AC primary heater control during treatment mode. +#define D5_HEAT_TX_P_COEFFICIENT 0.034F ///< P Term for AC primary heater control during treatment mode. #define D5_HEAT_TX_I_COEFFICIENT 0.001F ///< I Term for AC primary heater control during treatment mode. -#define D45_HEAT_P_COEFFICIENT 0.01F ///< P Term for trimmer heater control. -#define D45_HEAT_I_COEFFICIENT 0.005F ///< I Term for trimmer heater control. +#define D45_HEAT_P_COEFFICIENT 0.03F //0.01F ///< P Term for trimmer heater control. +#define D45_HEAT_I_COEFFICIENT 0.0005F ///< 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. +#define D45_HEAT_HIGH_DIAL_FLOW_RATE 200.0F ///< Decide Trimmer heater - high gain PI control based on the dialysate flow rate #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. -#define HEATER_TEMP_CONTROL_TRANSFER 1.0F ///< Primary Heater temperature difference to switch to control function +#define HEATER_TEMP_CONTROL_TRANSFER 2.0F ///< Primary Heater temperature difference to switch to D28 outer loop 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. #define DELTA_TEMP_ADJ_FLOW_RATE 150.0F ///< Fo Qd <= 150, the bottom range of second level temperature correction to be applied. @@ -76,13 +77,12 @@ #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 D5_HEATER_DEADBAND_CONTROL 0.1F ///< Heater dead band range for control. -#define D5_HEATER_PWM_ADJ_SLOPE_FACTOR 0.00005F ///< AC heater close loop PWM adjustment slope factor -#define D5_HEATER_PWM_INTERCEPT_FACTOR 0.0055F ///< AC heater close loop PWM adjustment intercept factor #define D5_HEAT_CONTROL_INTERVAL_MS 3000 /// 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 D45_HEAT_CONTROL_INTERVAL_MS ( 3 * 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_HEATER_DEADBAND_CONTROL 0.1F ///< Trimmer heater dead band range for control. #define D5_TARGET_TEMP_ADJUST_LOW_QD_INTERVAL ( 3 * SEC_PER_MIN * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Adjust primary target temperature - outer loop control interval for low Qd. #define D5_TARGET_TEMP_ADJUST_HIGH_QD_INTERVAL ( 1 * SEC_PER_MIN * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Adjust primary target temperature - outer loop control interval for high Qd. #define PRIMARY_HEATER_MAX_PWR_WATTS 1400.0F ///< AC Primary Heater Max Power consumption in Watts @@ -97,15 +97,9 @@ #define D5_HEAT_CONTROL_INTERVAL_START_COUNT ( D5_HEAT_CONTROL_INTERVAL_COUNT - 10 ) ///< AC heater control interval start count to jump feedforward control from open loop. #define RINSE_PUMP_EST_FLOWRATE 110 ///< Estimated rinse pump flow rate #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. -#define AC_HEAT_EFFICIENCY_LOW 0.1F ///< Lower allowable range for heater efficiency adjustment -#define AC_HEAT_EFFICIENCY_HIGH 10.0F ///< higher allowable range for heater efficiency adjustment -#define AC_HEAT_PWM_ADJUST_PERCENT 0.5F ///< AC heater PWM gain adjustment percentage for close loop control -#define AC_HEAT_PWM_ADJ_MIN -0.10F ///< Minimum PWM value that can adjust the calculated Feed forward value -#define AC_HEAT_PWM_ADJ_MAX 0.10F ///< Maximum PWM value that can adjust the calculated Feed forward value -#define AC_HEAT_PWM_MIN_MAX_FACTOR 2.0F ///< factor used to calculate range values for PWM adjustment -#define D5_HEAT_OUT_TX_P_COEFFICIENT 0.5F ///< P Term for AC primary heater outer loop control during treatment mode. -#define D5_HEAT_OUT_TX_I_COEFFICIENT 0.40F ///< I Term for AC primary heater outer loop control during treatment mode. +#define D5_HEAT_OUT_TX_P_COEFFICIENT 2.00F //0.5F ///< P Term for AC primary heater outer loop control during treatment mode. +#define D5_HEAT_OUT_TX_I_COEFFICIENT 0.04F //0.08F //0.4F ///< I Term for AC primary heater outer loop control during treatment mode. #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. @@ -178,8 +172,6 @@ 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 d5Efficiency; ///< AC heater efficiency factor. -static F32 adjustD5PWM; ///< AC heater close loop PWM adjustment -static F32 capAdjustD5PWM; ///< AC heater PWM adjustment after range check static F32 lastDialTargetTemperatureSet[ NUM_OF_DD_HEATERS ]; ///< last dialysate target temperature set for heater control static F32 d5FeedForward; ///< AC heater feed forward calculated value static U32 d5OuterLoopControlInterval; ///< AC heater outer loop control valve @@ -255,8 +247,6 @@ primaryTargetTempAdjCounter = 0; adjustedPrimaryTargetTemp = 0.0F; d5Efficiency = AC_HEATER_EFFICIENCY; - adjustD5PWM = 0.0F; - capAdjustD5PWM = 0.0F; d5FeedForward = 0.0F; isTargetTempAdjusted = FALSE; isDialyzerTempFeedbackEnabled = TRUE; @@ -287,12 +277,16 @@ 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, - D5_HEAT_OUT_MIN_DELTA_TEMP, D5_HEAT_OUT_MAX_DELTA_TEMP, TRUE, D5_HEAT_TX_INIT_FEED_FORWARD ); + 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 ); + HEATERS_MIN_DUTY_CYCLE, DC_HEATER_MAX_DUTY_CYCLE, TRUE, D45_HEAT_TX_INIT_FEED_FORWARD ); + // Initialize the trimmer heater PI controller for Higher dialysate flow rate + initializePIController( PI_CONTROLLER_ID_D45_HEAT_HIGHER_QD, HEATERS_MIN_DUTY_CYCLE, D45_HEAT_HIGHER_QD_P_COEFFICIENT, D45_HEAT_HIGHER_QD_I_COEFFICIENT, + HEATERS_MIN_DUTY_CYCLE, DC_HEATER_MAX_DUTY_CYCLE, TRUE, D45_HEAT_TX_INIT_FEED_FORWARD ); + #ifdef __HEATERS_DEBUG__ for ( i = 0; i < NUM_OF_CONTROLLER_SIGNAL; i++ ) { @@ -415,38 +409,44 @@ * @param heater: heater ID to update the heater control. * @return none *************************************************************************/ -void signalHeaterControlOnQDUpdate( DD_HEATERS_T heater ) +void signalHeaterControlOnQDUpdate( F32 prevDialFlowrate ) { - if ( D5_HEAT == heater ) + F32 flowrate = getTDDialysateFlowrate(); + F32 dutyCycle = 0.0F; + + // check heater state + if ( HEATER_EXEC_STATE_CONTROL_TO_TARGET == heatersStatus[ D5_HEAT ].state ) { - // check heater state - if ( HEATER_EXEC_STATE_CONTROL_TO_TARGET == heatersStatus[ heater ].state ) + // Reset the adjusted temperature target + isTargetTempAdjusted = FALSE; + } + + 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 + // as starting point. + if ( prevDuty > 0.0F ) { - // Reset the adjusted temperature target - isTargetTempAdjusted = FALSE; + dutyCycle = prevDuty / ( prevDialFlowrate / flowrate ); + } - // Reset the AC heater PWM adjustment - adjustD5PWM = HEATERS_MIN_DUTY_CYCLE; + if ( flowrate >= D45_HEAT_HIGH_DIAL_FLOW_RATE ) + { + resetPIController( PI_CONTROLLER_ID_D45_HEAT_HIGHER_QD, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); } + else + { + resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); + } } } /*********************************************************************//** * @brief - * The signaltoResetPrimaryHeaterAdjustedTargetTemp function resets the flag to - * update/adjust the primary heater target dialysate temperature - * @details \b Inputs: none - * @details \b Outputs: isTargetTempAdjusted - * @param heater: heater ID to update the heater control. - * @return none - *************************************************************************/ -void signaltoResetPrimaryHeaterAdjustedTargetTemp( void ) -{ - isTargetTempAdjusted = FALSE; -} - -/*********************************************************************//** - * @brief * The calculateTargetDialysateTemp function calculate the delta temperature * required for dialysate temperature to meet the set temperature at dialyzer. * @details \b Inputs: Qd and target temperature. @@ -457,30 +457,12 @@ { // Get the dialysate flow rate from TD F32 dialFlowrate = getTDDialysateFlowrate(); - F32 deltaTemp = 0.0F; F32 heatDissipation_b1b2 = 0.0F; F32 heatDissipation_b3 = 0.0F; F32 targetTemp = getTDTargetDialysateTemperature(); F32 targetTempAtD28 = 0.0F; F32 targetTempAtD4 = 0.0F; -#ifndef __REVISED_HEATER_MODEL__ - if ( dialFlowrate >= LOW_DIAL_FLOW_RATE ) - { - // linear relationship seen against high dialysate flowrate Vs DeltaTemp - // deltaTemp = (-0.0029 * Qd) + 3.47 - deltaTemp = ( LINEAR_SLOPE_FACTOR * dialFlowrate ) + LINEAR_INTERCEPT_FACTOR; - } - else - { - // deltaTemp = (0.0006 * Qd * Qd)-(0.1743*Qd) + 17.3 - deltaTemp = ( QUAD_FIRST_COEFFICIENT * dialFlowrate * dialFlowrate ) + - ( QUAD_SECOND_COEFFICIENT * dialFlowrate ) + QUAD_THIRD_COEFFICIENT; - } - // Adjust the D4 target temperature - targetTempAtD4 = getTDTargetDialysateTemperature() + deltaTemp; - setTargetHydChamberTemp( targetTempAtD4 ); -#else // 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. @@ -503,7 +485,6 @@ targetTempAtD4 = calculateInitialTemp( targetTempAtD28, heatDissipation_b1b2 ); //Update target temperature setTargetHydChamberTemp( targetTempAtD4 ); -#endif } /*********************************************************************//** @@ -516,73 +497,47 @@ *************************************************************************/ static void updatePrimaryHeaterTargetTemp( void ) { + F32 calcTargetTemp = 0.0F; + F32 deltaTempC = 0.0F; + F32 ctrl = 0.0F; + F32 measuredTempAtDialyzer = 0.0F; + F32 targetTempfromTD = 0.0F; + F32 diffTempC = 0.0F; + if ( ++primaryTargetTempAdjCounter >= d5OuterLoopControlInterval ) { - F32 targetTempfromTD = getTDTargetDialysateTemperature(); - F32 measuredTempAtDialyzer = 0.0F; +#ifdef __USE_D1_TEMP_ + // Use new RTD sensor placed closed to dialyzer, connected to D1 port + measuredTempAtDialyzer = getFilteredTemperatureValue( D1_TEMP ); + +#else if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) != TRUE ) { - measuredTempAtDialyzer = getTeensyConductivityTemperatureValue( D27_COND ); + measuredTempAtDialyzer = getTeensyConductivityTemperatureValue( D27_COND ); } else { - measuredTempAtDialyzer = getConductivityTemperature( D27_COND ); + measuredTempAtDialyzer = getFilteredConductivitySensorTemperature( D27_COND ); } +#endif + calcTargetTemp = getHeaterTargetTemperature( D5_HEAT ); + diffTempC = fabs( calcTargetTemp - measuredTempAtDialyzer ); + deltaTempC = targetTempfromTD - measuredTempAtDialyzer; - F32 calcTargetTemp = getHeaterTargetTemperature( D5_HEAT ); - F32 dialysateFlowrate = getTDDialysateFlowrate(); - F32 deltaTempC = targetTempfromTD - measuredTempAtDialyzer; - F32 capDeltaTempC = MIN( fabs(deltaTempC), ADJ_DELTA_TEMP_STEP ); - F32 ctrl = 0.0F; -#if 0 - //Assign the initial calcualted temp for adjsutment - if ( FALSE == isTargetTempAdjusted ) + if ( ( FALSE == isTargetTempAdjusted ) && ( diffTempC <= HEATER_TEMP_CONTROL_TRANSFER ) ) { - adjustedPrimaryTargetTemp = calcTargetTemp; - } - - //Keep adjusting the temperature based on D28 feedback - if ( deltaTempC > HEATERS_ZERO_DELTA_TEMP_C ) - { - adjustedPrimaryTargetTemp = adjustedPrimaryTargetTemp + capDeltaTempC; - } - else - { - adjustedPrimaryTargetTemp = adjustedPrimaryTargetTemp - capDeltaTempC; - } - - //Make sure the adjusted temp not crossing the max and min limits. - adjustedPrimaryTargetTemp = MIN( adjustedPrimaryTargetTemp, ( calcTargetTemp + MAX_ADJ_DELTA_TEMP_C ) ); - - // For Qd <= 150, The bottom range of second level temperature correction not to go below the initial - // Delta temperature adjustment. - if ( dialysateFlowrate > DELTA_TEMP_ADJ_FLOW_RATE ) - { - adjustedPrimaryTargetTemp = MAX( adjustedPrimaryTargetTemp, ( calcTargetTemp - MAX_ADJ_DELTA_TEMP_C ) ); - } - else - { - adjustedPrimaryTargetTemp = MAX( adjustedPrimaryTargetTemp, calcTargetTemp ); - } - - isTargetTempAdjusted = TRUE; - primaryTargetTempAdjCounter = 0; -#else - if ( FALSE == isTargetTempAdjusted ) - { isTargetTempAdjusted = TRUE; adjustedPrimaryTargetTemp = calcTargetTemp; resetPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, calcTargetTemp, HEATERS_MIN_DUTY_CYCLE ); } - else if ( fabs(deltaTempC) >= D5_HEAT_OUT_DEADBAND_CONTROL ) + else if ( ( fabs(deltaTempC) >= D5_HEAT_OUT_DEADBAND_CONTROL ) && ( TRUE == isTargetTempAdjusted ) ) { ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT_OUTER_LOOP, getTDTargetDialysateTemperature(), measuredTempAtDialyzer ); adjustedPrimaryTargetTemp = ctrl; } primaryTargetTempAdjCounter = 0; -#endif } } @@ -806,7 +761,7 @@ if ( capDeltaTempC >= HEATER_CNTL_TRANSFER_DELTA_TEMP_C ) { - // Reset PI Controllers with + // 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 ); @@ -833,13 +788,22 @@ { F32 deltaTempC = targetTemperature - measuredTemperature; F32 capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); - F32 flowrate = getTDDialysateFlowrate() / LITER_IN_ML ; - F32 dutyCycle = calculateDutyCycle( flowrate, capDeltaTempC, TRIMMER_HEATER_MAX_PWR_WATTS, DC_HEATER_EFFICIENCY, + F32 flowrate = getTDDialysateFlowrate(); + F32 flowrateInLtr = flowrate / LITER_IN_ML ; + F32 dutyCycle = calculateDutyCycle( flowrateInLtr, capDeltaTempC, TRIMMER_HEATER_MAX_PWR_WATTS, DC_HEATER_EFFICIENCY, HEATERS_MIN_DUTY_CYCLE, DC_HEATER_MAX_DUTY_CYCLE ); control[ heater ].data = dutyCycle; - resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); + if ( flowrate >= D45_HEAT_HIGH_DIAL_FLOW_RATE ) + { + resetPIController( PI_CONTROLLER_ID_D45_HEAT_HIGHER_QD, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); + } + else + { + resetPIController( PI_CONTROLLER_ID_D45_HEAT, dutyCycle, D45_HEAT_TX_INIT_FEED_FORWARD ); + } + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } else @@ -871,14 +835,15 @@ { 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; -#if 0 - F32 d5_eff = 0.0F; - F32 d5_p_gain = 0.0F; - F32 d5_final_FF = 0.0F; - F32 d5_cap_final_FF = 0.0F; -#endif + F32 deltaTempC = 0.0F; + F32 absDeltaTempC = 0.0F; + F32 capDeltaTempC = 0.0F; + F32 flowrate = 0.0F; + F32 dutyCycle = 0.0F; + // Update primary heater target temperature at defined interval if ( D5_HEAT == heater ) { @@ -890,27 +855,27 @@ if ( D5_HEAT == heater ) { // Inlet temperature post heat exchanger - F32 inletTemperature = getFilteredTemperatureValue( D78_TEMP ); - F32 deltaTempC = targetTemperature - inletTemperature; - F32 capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); - F32 flowrate = ( getTDDialysateFlowrate() + RINSE_PUMP_EST_FLOWRATE ) / LITER_IN_ML ; - d5FeedForward = calculateDutyCycle( flowrate, capDeltaTempC, PRIMARY_HEATER_MAX_PWR_WATTS, d5Efficiency, + inletTemperature = getFilteredTemperatureValue( D78_TEMP ); + deltaTempC = targetTemperature - inletTemperature; + capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); + flowrate = ( getTDDialysateFlowrate() + RINSE_PUMP_EST_FLOWRATE ) / LITER_IN_ML ; + d5FeedForward = calculateDutyCycle( flowrate, capDeltaTempC, PRIMARY_HEATER_MAX_PWR_WATTS, d5Efficiency, HEATERS_MIN_DUTY_CYCLE, AC_HEATER_TX_MAX_DUTY_CYCLE ); //Update the calculated feed forward value 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 >= 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. if ( ( TRUE == isTargetTempAdjusted ) && ( TRUE == isDialyzerTempFeedbackEnabled ) ) { targetTemperature = adjustedPrimaryTargetTemp; } -#if 1 + measuredTemperature = getFilteredTemperatureValue( D4_TEMP ); deltaTempC = fabs( targetTemperature - measuredTemperature ); @@ -919,37 +884,7 @@ ctrl = runPIController( PI_CONTROLLER_ID_D5_HEAT, targetTemperature, measuredTemperature ); control[ heater ].data = ctrl; } -#else - measuredTemperature = getFilteredTemperatureValue( D4_TEMP ); - deltaTempC = targetTemperature - measuredTemperature; - capDeltaTempC = fabs(deltaTempC); - d5_p_gain = ( D5_HEATER_PWM_ADJ_SLOPE_FACTOR * getTDDialysateFlowrate() ) + D5_HEATER_PWM_INTERCEPT_FACTOR; - if ( d5FeedForward > NEARLY_ZERO ) - { - if ( capDeltaTempC >= D5_HEATER_DEADBAND_CONTROL ) - { - F32 minAdjPWM = -(d5_p_gain * AC_HEAT_PWM_MIN_MAX_FACTOR); - F32 maxAdjPWM = d5_p_gain * AC_HEAT_PWM_MIN_MAX_FACTOR; - - // Compute the PWM adjustment with 50% gain adjustment - adjustD5PWM += ( d5_p_gain * AC_HEAT_PWM_ADJUST_PERCENT * deltaTempC ); - adjustD5PWM = RANGE(adjustD5PWM, minAdjPWM, maxAdjPWM ); - } - } - else - { - //When feed forward produces zero PWM, no adjustment is needed - adjustD5PWM = HEATERS_MIN_DUTY_CYCLE; - } - - // Update the feed forward PWM with the close loop adjustment - d5_final_FF = d5FeedForward + adjustD5PWM; - d5_cap_final_FF = RANGE(d5_final_FF,HEATERS_MIN_DUTY_CYCLE,AC_HEATER_TX_MAX_DUTY_CYCLE ); - - // assign the feed forward control - control[ heater ].data = d5_cap_final_FF; -#endif #ifdef __HEATERS_DEBUG__ U32 i; @@ -962,9 +897,36 @@ else { measuredTemperature = getFilteredTemperatureValue( D50_TEMP ); + deltaTempC = targetTemperature - measuredTemperature; + absDeltaTempC = fabs( deltaTempC ); + capDeltaTempC = MAX( deltaTempC, HEATERS_ZERO_DELTA_TEMP_C ); + flowrate = getTDDialysateFlowrate() / LITER_IN_ML ; + dutyCycle = calculateDutyCycle( flowrate, capDeltaTempC, TRIMMER_HEATER_MAX_PWR_WATTS, DC_HEATER_EFFICIENCY, + HEATERS_MIN_DUTY_CYCLE, DC_HEATER_MAX_DUTY_CYCLE ); - ctrl = runPIController( PI_CONTROLLER_ID_D45_HEAT, targetTemperature, measuredTemperature ); - control[ heater ].data = ctrl; + if ( flowrate >= D45_HEAT_HIGH_DIAL_FLOW_RATE ) + { + //Update the calculated feed forward value + setPIControllerFeedForward( PI_CONTROLLER_ID_D45_HEAT_HIGHER_QD, dutyCycle ); + + if ( absDeltaTempC > D45_HEATER_DEADBAND_CONTROL ) + { + ctrl = runPIController( PI_CONTROLLER_ID_D45_HEAT_HIGHER_QD, targetTemperature, measuredTemperature ); + control[ heater ].data = ctrl; + } + } + else + { + //Update the calculated feed forward value + setPIControllerFeedForward( PI_CONTROLLER_ID_D45_HEAT, dutyCycle ); + + if ( absDeltaTempC > D45_HEATER_DEADBAND_CONTROL ) + { + ctrl = runPIController( PI_CONTROLLER_ID_D45_HEAT, targetTemperature, measuredTemperature ); + control[ heater ].data = ctrl; + } + } + //#ifdef __HEATERS_DEBUG__ // U32 i; // Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -r94789b2f2324d5901685b6ff7b6224d4af3a0276 -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 94789b2f2324d5901685b6ff7b6224d4af3a0276) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -75,8 +75,7 @@ BOOL setHeaterTargetTemperature( DD_HEATERS_T heater, F32 targetTemperature ); void startHeater( DD_HEATERS_T heater ); F32 getHeaterTargetTemperature( DD_HEATERS_T heater ); -void signalHeaterControlOnQDUpdate( DD_HEATERS_T heater ); -void signaltoResetPrimaryHeaterAdjustedTargetTemp( void ); +void signalHeaterControlOnQDUpdate( F32 prevDialFlowrate ); void setD28TempFeedbackControl( BOOL enable ); BOOL isHeaterOn( DD_HEATERS_T heater ); void calculateTargetDialysateTemp( void ); Index: firmware/App/Controllers/Ultrafiltration.c =================================================================== diff -u -r94789b2f2324d5901685b6ff7b6224d4af3a0276 -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Controllers/Ultrafiltration.c (.../Ultrafiltration.c) (revision 94789b2f2324d5901685b6ff7b6224d4af3a0276) +++ firmware/App/Controllers/Ultrafiltration.c (.../Ultrafiltration.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -204,8 +204,12 @@ *************************************************************************/ static void updateUFRequest( void ) { + F32 qd = getTDDialysateFlowrate(); + BOOL bypass = getTDDialyzerBypass(); + // update latest UF run/pause request - if ( compUFrate > ZERO_RATE ) + // if qd is zero or dialyzer is bypassed, UF pump should be turn off + if ( ( compUFrate > ZERO_RATE ) && ( qd > ZERO_RATE ) && ( FALSE == bypass ) ) { isUltrafiltrationRequested = TRUE; } Index: firmware/App/DDCommon.h =================================================================== diff -u -rc6c72086128954ac103052f05727a20d5e8e604e -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/DDCommon.h (.../DDCommon.h) (revision c6c72086128954ac103052f05727a20d5e8e604e) +++ firmware/App/DDCommon.h (.../DDCommon.h) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -51,8 +51,8 @@ //Uncomment below to disable heaters debug message #define __HEATERS_DEBUG__ 1 -//Uncomment below to disable revised heater model -#define __REVISED_HEATER_MODEL__ 1 +//Uncomment below if D1 placement is used for Temp control at dialyzer +#define __USE_D1_TEMP_ 1 // comment below to disable bicarb multi level sensor for time based chamber F fill #define CONDUCTIVE_LEVEL_SENSOR_ENABLED 1 Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -rabe1c4a42afb385a660381e48bd007331f60950c -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision abe1c4a42afb385a660381e48bd007331f60950c) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -1001,8 +1001,6 @@ // Get the target temperature from TD //targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); calculateTargetDialysateTemp(); - //Reset flag - signaltoResetPrimaryHeaterAdjustedTargetTemp(); // Update the target temperature for heater control setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); Index: firmware/App/Monitors/Conductivity.c =================================================================== diff -u -rfd897db8177752330ad08d877e0a13620513dbdc -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision fd897db8177752330ad08d877e0a13620513dbdc) +++ firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -293,6 +293,7 @@ filteredConductivityReadings[ sensor ].conductivityReadingsIdx = INC_WRAP( filteredConductivityReadings[ sensor ].conductivityReadingsIdx, 0, SIZE_OF_COND_ROLLING_AVG - 1 ); filteredConductivityReadings[ sensor ].conductivityReadingsCount = INC_CAP( filteredConductivityReadings[ sensor ].conductivityReadingsCount, SIZE_OF_COND_ROLLING_AVG ); filteredcurrentConductivityReadings[ sensor ].data = filteredConductivityReadings[ sensor ].conductivityReadingsTotal / (F32)filteredConductivityReadings[ sensor ].conductivityReadingsCount; + freshData = FALSE; } } } @@ -380,6 +381,7 @@ filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx = INC_WRAP( filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx, 0, SIZE_OF_COND_TEMP_ROLLING_AVG - 1 ); filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount = INC_CAP( filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount, SIZE_OF_COND_TEMP_ROLLING_AVG ); filteredcurrentTemperatureReadings[sensor].data = filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsTotal / (F32)filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount; + freshData = FALSE; } } } Index: firmware/App/Monitors/Temperature.c =================================================================== diff -u -r94789b2f2324d5901685b6ff7b6224d4af3a0276 -rc90f3d61bde2a2b47d1048635be4dadf282e2195 --- firmware/App/Monitors/Temperature.c (.../Temperature.c) (revision 94789b2f2324d5901685b6ff7b6224d4af3a0276) +++ firmware/App/Monitors/Temperature.c (.../Temperature.c) (revision c90f3d61bde2a2b47d1048635be4dadf282e2195) @@ -497,10 +497,25 @@ data.d4AvgTemp = getFilteredTemperatureValue( D4_TEMP ); data.d50AvgTemp = getFilteredTemperatureValue( D50_TEMP ); data.d99AvgTemp = getFilteredTemperatureValue( D99_TEMP ); - data.d28AvgTemp = dialTempMovingAvgData[ DIAL_TEMP_D28 ].dialTempAvgC; + //data.d28AvgTemp = dialTempMovingAvgData[ DIAL_TEMP_D28 ].dialTempAvgC; + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) != TRUE ) + { + data.d28AvgTemp = getTeensyConductivityTemperatureValue( D27_COND ); + } + else + { + data.d28AvgTemp = getFilteredConductivitySensorTemperature( D27_COND ); + } + data.d30AvgTemp = dialTempMovingAvgData[ DIAL_TEMP_D30 ].dialTempAvgC; data.d78AvgTemp = getFilteredTemperatureValue( D78_TEMP ); + +#ifdef __USE_D1_TEMP_ + data.d9PresTemp = getFilteredTemperatureValue( D1_TEMP ); +#else data.d9PresTemp = getFilteredPressureSensorTemperature( D9_PRES ); +#endif + data.d66PresTemp = getFilteredPressureSensorTemperature( D66_PRES ); data.d51PresTemp = getFilteredPressureSensorTemperature( D51_PRES ); data.d18PresTemp = getFilteredPressureSensorTemperature( D18_PRES );