Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r033c0a8a34377fdc9a4d681877f7be1e103857f0 -r1a6783245f983c48523e11abe4a2074677720f18 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 033c0a8a34377fdc9a4d681877f7be1e103857f0) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 1a6783245f983c48523e11abe4a2074677720f18) @@ -54,9 +54,10 @@ #define MINIMUM_TARGET_TEMPERATURE 10.0 ///< Minimum allowed target temperature for the heaters. #define MAXIMUM_TARGET_TEMPERATURE 90.0 ///< Maximum allowed target temperature for the heaters. +#define MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE 58.0 ///< Maximum allowed target temperature for the idle and drain modes. #define HEATERS_RAMP_STATE_CHECK_INTERVAL_COUNT 20U ///< Heaters ramp check interval count. -#define HEATERS_CONTROL_STATE_CHECK_INTERVAL_COUNT ( 10 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Temperature sensors interval count. +#define HEATERS_CONTROL_STATE_CHECK_INTERVAL_COUNT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Temperature sensors interval count. #define HEATERS_ON_WITH_NO_FLOW_TIMEOUT_COUNT ( ( 3 * MS_PER_SECOND ) / TASK_PRIORITY_INTERVAL ) ///< Heaters are on but there is no sufficient flow timeout in counts. #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 170.0 ///< Heaters max allowed internal temperature in C. #define HEATERS_MAX_ALLOWED_COLD_JUNCTION_TEMPERATURE_C 80.0 ///< Heaters max allowed cold junction temperature in C. @@ -73,7 +74,6 @@ #define DELTA_DUTY_CYCLE_GAIN 0.1 ///< Delta duty cycle gain. #define DELTA_TEMPERATURE_GAIN 1.27 ///< Delta temperature gain. -#define DRAIN_AND_IDLE_MODE_TARGET_TEMPERATURE_OFFSET 3.0 ///< Drain and Idle modes temperature offset from dialysate. #define HEATERS_CONTROL_TO_TARGET_DUTY_CYCLE_CAP 0.09 ///< Heaters control to target duty cycle cap. typedef enum Heaters_Exec_States @@ -97,6 +97,7 @@ BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. F32 dutycycle; ///< Heater duty cycle. + F32 fillDutyCycle; ///< Heater fill duty cycle. F32 targetROFlow; ///< Heater target flow. U32 rampStateStartTime; ///< Heater ramp state start time. U32 heaterOnWithNoFlowTimer; ///< Heater on with no flow timer. @@ -160,8 +161,9 @@ heatersStatus[ heater ].isHeaterTempOutOfRange = FALSE; heatersStatus[ heater ].state = HEATER_EXEC_STATE_NOT_RUNNING; heatersStatus[ heater ].targetTemp = 0.0; - heatersStatus[ heater ].originalTargetTemp = 0.0; + heatersStatus[ heater ].originalTargetTemp = 0.0; heatersStatus[ heater ].dutycycle = 0.0; + heatersStatus[ heater ].fillDutyCycle = 0.0; heatersStatus[ heater ].targetROFlow = 0.0; heatersStatus[ heater ].previousTempsIndex = 0; heatersStatus[ heater ].controllerID = ( DG_PRIMARY_HEATER == heater ? 4 : PI_CONTROLLER_ID_TRIMMER_HEATER ); // TODO remove or refactor? @@ -429,9 +431,17 @@ heatersStatus[ heater ].isHeaterOn = TRUE; heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].targetROFlow = getTargetROPumpFlowRate(); - // Heaters control work with target temperature internally. Original target temperature is set by the user using the APIs - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; + if ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) + { + heatersStatus[ heater ].targetTemp = MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE; + } + else + { + // Heaters control work with target temperature internally. Original target temperature is set by the user using the APIs + heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; + } + // If the operation mode is heat disinfect and the heater is primary heater, change the feedback sensor to THd if ( ( DG_MODE_HEAT == getCurrentOperationMode() ) && ( DG_PRIMARY_HEATER == heater ) ) { @@ -474,39 +484,56 @@ TEMPERATURE_SENSORS_T sensor = heatersStatus[ heater ].feedbackSensor; F32 feedbackTemperature = getTemperatureValue( (U32)sensor ); // Continuously get the target temperature in case it was changed dynamically - F32 targetTemperature = heatersStatus[ heater ].targetTemp; + F32 targetTemperature = heatersStatus[ heater ].originalTargetTemp; U32 currentIndex = heatersStatus[ heater ].previousTempsIndex; F32 targetFlow = getTargetROPumpFlowRate(); BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetROFlow ) > NEARLY_ZERO ? TRUE : FALSE ); + // Set the hand off flag to false + BOOL isItHandOffTime = FALSE; + F32 measuredFlow = getTargetROPumpFlowRate(); // TODO change this to measured flow?? This is target for testing for now - haveHeaterControlConditionsChanged( heater ); + //haveHeaterControlConditionsChanged( heater ); - if ( ++heatersStatus[ heater ].controlTimerCounter > HEATERS_RAMP_STATE_CHECK_INTERVAL_COUNT ) + if ( ( DG_MODE_FILL == getCurrentOperationMode() ) && ( heatersStatus[ heater ].fillDutyCycle - 0.0 > NEARLY_ZERO ) ) { - U32 i; - F32 slope; - F32 deltaTemperature; - F32 deltaDutyCycle; - F32 revDeltaDutyCycle; - F32 inletTemperature; - F32 measuredFlow; + dutyCycle = heatersStatus[ heater ].fillDutyCycle; + heatersStatus[ heater ].targetTemp = targetTemperature; + isItHandOffTime = TRUE; + } + else if ( ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) && ( heatersStatus[ heater ].fillDutyCycle - 0.0 > NEARLY_ZERO ) ) + { + F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); + F32 highTempDutyCycle = calculateHeaterDutyCycle( MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE, inletTemperature, measuredFlow ); - // Set the hand off flag to false - BOOL isItHandOffTime = FALSE; - - // TODO for testing only potentially remove - if ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) + if ( heatersStatus[ heater ].fillDutyCycle - 0.0 < NEARLY_ZERO ) { - F32 inlet = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); - measuredFlow = getTargetROPumpFlowRate(); - F32 highTempDuty = calculateHeaterDutyCycle( 58.0, inlet, measuredFlow ); - dutyCycle = calculateHeaterDutyCycle( 39.0, inlet, 0.8 ); - dutyCycle = ( dutyCycle < highTempDuty ? dutyCycle : highTempDuty ); - isItHandOffTime = TRUE; + dutyCycle = calculateHeaterDutyCycle( targetTemperature, inletTemperature, 0.8 ); // TODO add the fill flow rate } - // TODO for testing only remove else { + dutyCycle = heatersStatus[ heater ].fillDutyCycle; + } + + dutyCycle = ( dutyCycle < highTempDutyCycle ? dutyCycle : highTempDutyCycle ); + + targetTemperature = ( pow( ( dutyCycle + PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_INTERCEPT ) / PRIMARY_HEATERS_THERMAL_POWER_TO_VOLTAGE_SLOPE, 2 ) / measuredFlow ) + feedbackTemperature; + + targetTemperature = ( targetTemperature > MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE ? MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE : targetTemperature ); + heatersStatus[ heater ].targetTemp = targetTemperature; + + isItHandOffTime = TRUE; + } + else if ( heatersStatus[ heater ].fillDutyCycle - 0.0 < NEARLY_ZERO ) + { + if ( ++heatersStatus[ heater ].controlTimerCounter > HEATERS_RAMP_STATE_CHECK_INTERVAL_COUNT ) + { + U32 i; + F32 slope; + F32 deltaTemperature; + F32 deltaDutyCycle; + F32 revDeltaDutyCycle; + F32 inletTemperature; + // Update the temperature data array as well as the next index heatersStatus[ heater ].previousTemps[ currentIndex ] = feedbackTemperature; heatersStatus[ heater ].previousTempsIndex = INC_WRAP( currentIndex, 0, TEMPERATURES_MOVING_AVG_SIZE - 1 ); @@ -515,7 +542,7 @@ // change is addressed automatically if ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) { - heatersStatus[ heater ].hasTargetTempChanged = FALSE; + heatersStatus[ heater ].hasTargetTempChanged = FALSE; // TODO do we need this? } // Calculate the running sum of the temperatures @@ -535,13 +562,18 @@ } // TODO add comments + if ( ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) ) + { + targetTemperature = MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE; + } + slope = slope / (F32)TEMPERATURES_MOVING_AVG_SIZE; //measuredFlow = getMeasuredROFlowRate(); TODO uncomment for testing only - measuredFlow = getTargetROPumpFlowRate(); + measuredFlow = getTargetROPumpFlowRate(); // TODO is this right? dutyCycle = calculateHeaterDutyCycle( targetTemperature, inletTemperature, measuredFlow ); deltaDutyCycle = ( feedbackTemperature <= targetTemperature ? HEATERS_MAX_DUTY_CYCLE - dutyCycle : dutyCycle ); - revDeltaDutyCycle = ( deltaDutyCycle - 0.0 < NEARLY_ZERO ? 0 : 1.0 / deltaDutyCycle ); + revDeltaDutyCycle = ( deltaDutyCycle - 0.0 < NEARLY_ZERO ? 0.0 : 1.0 / deltaDutyCycle ); revDeltaDutyCycle = ( revDeltaDutyCycle * DELTA_DUTY_CYCLE_GAIN < HEATERS_MAX_DUTY_CYCLE ? revDeltaDutyCycle * DELTA_DUTY_CYCLE_GAIN : HEATERS_MAX_DUTY_CYCLE ); deltaTemperature = ( ( atanf( slope ) * DELTA_TEMPERATURE_GAIN ) / measuredFlow ) + revDeltaDutyCycle; @@ -557,20 +589,24 @@ { isItHandOffTime = TRUE; } - } - // TODO potentially remove the else + if ( ( TRUE == isItHandOffTime ) && ( DG_MODE_FILL == getCurrentOperationMode() ) ) + { + heatersStatus[ heater ].fillDutyCycle = dutyCycle; + heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; + } - if ( TRUE == isItHandOffTime ) - { - setHeaterDutyCycle( heater, dutyCycle ); + heatersStatus[ heater ].controlTimerCounter = 0; + } + } - heatersStatus[ heater ].initialDutyCycle = dutyCycle; + if ( TRUE == isItHandOffTime ) + { + setHeaterDutyCycle( heater, dutyCycle ); - state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; - } + heatersStatus[ heater ].initialDutyCycle = dutyCycle; - heatersStatus[ heater ].controlTimerCounter = 0; + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } // Check if the heater is requested to be off @@ -728,7 +764,7 @@ setHeaterDutyCycle( heater, dutyCycle ); } - if ( DG_PRIMARY_HEATER == heater ) + /*if ( DG_PRIMARY_HEATER == heater ) { // Check if the mode is drain or the mode is gen idle if ( ( DG_MODE_DRAI == getCurrentOperationMode() ) || ( DG_MODE_GENE == getCurrentOperationMode() ) ) @@ -738,7 +774,7 @@ { // Add an offset to the dialysate temperature operationMode = getCurrentOperationMode(); - heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp + DRAIN_AND_IDLE_MODE_TARGET_TEMPERATURE_OFFSET; + //heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp + DRAIN_AND_IDLE_MODE_TARGET_TEMPERATURE_OFFSET; } } else if ( ( DG_MODE_FILL == getCurrentOperationMode() ) && ( operationMode != getCurrentOperationMode() ) ) @@ -748,14 +784,14 @@ heatersStatus[ heater ].targetTemp = heatersStatus[ heater ].originalTargetTemp; } - /*if ( ( getCurrentOperationMode() != DG_MODE_DRAI ) || ( getCurrentOperationMode() != DG_MODE_GENE ) ) + if ( ( getCurrentOperationMode() != DG_MODE_DRAI ) || ( getCurrentOperationMode() != DG_MODE_GENE ) ) { if ( TRUE == ( fabs( heatersStatus[ heater ].targetTemp - heatersStatus[ heater ].originalTargetTemp ) > NEARLY_ZERO ) { } - }*/ - } + } + }*/ return status; }