Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -rdb7a07277014e802f582716c4215044ff905266b -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision db7a07277014e802f582716c4215044ff905266b) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -52,14 +52,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 @@ -217,6 +217,9 @@ // finish the balancing chamber fill 50 ms prior completing the regular cycle time. balChamberSwitchingPeriod -= 1; + //Update heater control on dialysate flow change + signalHeaterControlOnQDUpdate( lastTdDialysateFlowrate ); + //Update last td dialysate flow rate lastTdDialysateFlowrate = tdDialysateFlowrate; @@ -226,9 +229,6 @@ //Reset the BC switching flag for new Qd. isFirstCycleBCSwitchingCompleted = FALSE; - //Update heater control on dialysate flow change - signalHeaterControlOnQDUpdate(); - //Testing balChamberValveClosePeriod = balChamberSwitchingPeriod; balChamberValveClosePeriod -= 1; // Close valves prior 50 msecond for testing Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -rf3746f881341ba8bc8302cbba7d0e22e7b930d90 -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f3746f881341ba8bc8302cbba7d0e22e7b930d90) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -58,12 +58,15 @@ #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_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.05F ///< P Term for trimmer heater control for higher dialysate flow rate. +#define D45_HEAT_HIGHER_QD_I_COEFFICIENT 0.015F ///< 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. @@ -95,8 +98,8 @@ #define RINSE_PUMP_EST_FLOWRATE 110 ///< Estimated rinse pump flow rate #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. -#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. @@ -280,6 +283,10 @@ 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, 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++ ) { @@ -402,8 +409,11 @@ * @param heater: heater ID to update the heater control. * @return none *************************************************************************/ -void signalHeaterControlOnQDUpdate( void ) +void signalHeaterControlOnQDUpdate( F32 prevDialFlowrate ) { + F32 flowrate = getTDDialysateFlowrate(); + F32 dutyCycle = 0.0F; + // check heater state if ( HEATER_EXEC_STATE_CONTROL_TO_TARGET == heatersStatus[ D5_HEAT ].state ) { @@ -414,7 +424,24 @@ 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; + //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 ) + { + dutyCycle = prevDuty / ( prevDialFlowrate / flowrate ); + } + + 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 ); + } } } @@ -475,9 +502,16 @@ F32 ctrl = 0.0F; F32 measuredTempAtDialyzer = 0.0F; F32 targetTempfromTD = 0.0F; + F32 diffTempC = 0.0F; if ( ++primaryTargetTempAdjCounter >= d5OuterLoopControlInterval ) { +#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 ); @@ -486,17 +520,18 @@ { measuredTempAtDialyzer = getFilteredConductivitySensorTemperature( D27_COND ); } - +#endif calcTargetTemp = getHeaterTargetTemperature( D5_HEAT ); + diffTempC = fabs( calcTargetTemp - measuredTempAtDialyzer ); deltaTempC = targetTempfromTD - measuredTempAtDialyzer; - if ( FALSE == isTargetTempAdjusted ) + if ( ( FALSE == isTargetTempAdjusted ) && ( diffTempC <= HEATER_TEMP_CONTROL_TRANSFER ) ) { 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; @@ -753,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 @@ -822,8 +866,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 >= 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. @@ -859,14 +903,30 @@ 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 ); - //Update the calculated feed forward value - setPIControllerFeedForward( PI_CONTROLLER_ID_D45_HEAT, dutyCycle ); - if ( absDeltaTempC > D45_HEATER_DEADBAND_CONTROL ) + if ( flowrate >= D45_HEAT_HIGH_DIAL_FLOW_RATE ) { - ctrl = runPIController( PI_CONTROLLER_ID_D45_HEAT, targetTemperature, measuredTemperature ); - control[ heater ].data = ctrl; + //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 -r542755e62be20cbdd396053c5568ef8a13efad05 -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 542755e62be20cbdd396053c5568ef8a13efad05) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -75,7 +75,7 @@ BOOL setHeaterTargetTemperature( DD_HEATERS_T heater, F32 targetTemperature ); void startHeater( DD_HEATERS_T heater ); F32 getHeaterTargetTemperature( DD_HEATERS_T heater ); -void signalHeaterControlOnQDUpdate( void ); +void signalHeaterControlOnQDUpdate( F32 prevDialFlowrate ); void setD28TempFeedbackControl( BOOL enable ); BOOL isHeaterOn( DD_HEATERS_T heater ); void calculateTargetDialysateTemp( void ); Index: firmware/App/DDCommon.h =================================================================== diff -u -rf3746f881341ba8bc8302cbba7d0e22e7b930d90 -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/DDCommon.h (.../DDCommon.h) (revision f3746f881341ba8bc8302cbba7d0e22e7b930d90) +++ firmware/App/DDCommon.h (.../DDCommon.h) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -51,6 +51,9 @@ //Uncomment below to disable heaters debug message #define __HEATERS_DEBUG__ 1 +//Uncomment below if D1 placement is used for Temp control at dialyzer +#define __USE_D1_TEMP_ 1 + #include #include #endif Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -rf3746f881341ba8bc8302cbba7d0e22e7b930d90 -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision f3746f881341ba8bc8302cbba7d0e22e7b930d90) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -998,8 +998,8 @@ updateBalChamberSwitchingPeriod(); // Get the target temperature from TD - targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); - //calculateTargetDialysateTemp(); + //targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); + calculateTargetDialysateTemp(); // Update the target temperature for heater control setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); Index: firmware/App/Monitors/Temperature.c =================================================================== diff -u -r94789b2f2324d5901685b6ff7b6224d4af3a0276 -rba7e088fc3308f844ea30376a78e1da6d32621c1 --- firmware/App/Monitors/Temperature.c (.../Temperature.c) (revision 94789b2f2324d5901685b6ff7b6224d4af3a0276) +++ firmware/App/Monitors/Temperature.c (.../Temperature.c) (revision ba7e088fc3308f844ea30376a78e1da6d32621c1) @@ -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 );