Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r608780a6e5449b5a9710ac07299ec028117c9f4d -r62b202c33e90b032326da24aa4067e2f5032f448 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 608780a6e5449b5a9710ac07299ec028117c9f4d) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 62b202c33e90b032326da24aa4067e2f5032f448) @@ -48,7 +48,7 @@ #define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%). #define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%). -#define HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE 0.6F ///< Heaters minimum duty cycle during heat disinfect. +#define HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE 0.6F // TODO remove ///< Heaters minimum duty cycle during heat disinfect. #define HEATERS_MIN_EST_GAIN 0.2F ///< Heaters minimum estimation gain. #define HEATERS_MAX_EST_GAIN 5.0F ///< Heaters maximum estimation gain. #define HEATERS_NEUTRAL_EST_GAIN 1.0F ///< Heaters neutral estimation gain. @@ -63,7 +63,7 @@ #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 TRIMMER_HEATER_MAX_POWER_W 66.5F ///< Trimmer heater maximum power in Watts. -#define TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. +#define HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Heater control interval count. #define DELTA_TEMPERATURE_TIME_COSNTANT_C 8.6F ///< Delta temperature calculated from time constant. #define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.015F ///< Primary heaters duty cycle per temperature in C. @@ -95,7 +95,7 @@ static HEATER_STATUS_T heatersStatus[ NUM_OF_DG_HEATERS ]; ///< Heaters status. static U32 dataPublicationTimerCounter; ///< Data publication timer counter. -static U32 trimmerHeaterControlCounter; ///< Trimmer heater control counter. +static U32 heaterControlCounter; ///< Heater control counter. static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. // ********** private function prototypes ********** @@ -131,7 +131,7 @@ { DG_HEATERS_T heater; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) { @@ -329,9 +329,9 @@ if ( TRUE == heatersStatus[ heater ].isHeaterOn ) { ALARM_ID_T alarm; - F32 measFlow; - F32 minFlow; - BOOL isFlowLow; + F32 measFlow = 0.0F; + F32 minFlow = 0.0F; + BOOL isFlowLow = FALSE; if ( DG_PRIMARY_HEATER == heater ) { @@ -354,11 +354,11 @@ { if ( DG_PRIMARY_HEATER == heater ) { - checkPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, FALSE, 0.0, 0.0 ); + checkPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, FALSE, 0.0F, 0.0F ); } else { - checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, FALSE, 0.0, 0.0 ); + checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, FALSE, 0.0F, 0.0F ); } } } @@ -498,8 +498,9 @@ // Do nothing the mode that DG is in right now, does not need heaters to be on } - // Update the calculated target temperature + // Update the calculated target temperature and flow heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature = targetTemperature; + heatersStatus[ DG_PRIMARY_HEATER ].targetFlow = targetFlow; setHeaterDutyCycle( heater, dutyCycle ); return state; @@ -541,28 +542,23 @@ HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; F32 heatDisinfectSensorTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); - // Check if the heaters control conditions have changed, if yes, switch back to ramp to target - if ( TRUE == haveHeaterControlConditionsChanged( heater ) ) + if ( ++heaterControlCounter > HEATER_CONTROL_CHECK_INTERVAL_COUNT ) { - state = HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET; - } + F32 tempDutyCycle = 0.0F; + F32 targetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; + F32 targetFlowLPM = heatersStatus[ DG_TRIMMER_HEATER ].targetFlow; + F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, heatDisinfectSensorTemp, targetFlowLPM, FALSE ); + heaterControlCounter = 0; + // Trimmer heater duty cycle function checks the minimum to -100%. So if the duty cycle was calculated to be negative it is set to 0 here + tempDutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); - // If the heat disinfect sensor indicates that the temperature is below target temperature but the target temperature had been reached - // before turn on the heaters with 100% power - if ( ( heatDisinfectSensorTemp <= heatersStatus[ heater ].targetTemp ) && ( TRUE == heatersStatus[ heater ].hasTargetBeenReached ) ) - { - heatersStatus[ heater ].hasTargetBeenReached = FALSE; - setHeaterDutyCycle( heater, HEATERS_MAX_DUTY_CYCLE ); - } + setHeaterDutyCycle( DG_TRIMMER_HEATER, tempDutyCycle ); - // If we have reached to target temperature, turn off the heaters - if ( heatDisinfectSensorTemp > heatersStatus[ heater ].targetTemp ) - { - // Set the flag to true for the next run - heatersStatus[ heater ].hasTargetBeenReached = TRUE; - // The primary heater are not turned off but it is set to a minimum duty cycle so the temperature is kept - // above the target - setHeaterDutyCycle( heater, HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE ); + targetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; + targetFlowLPM = heatersStatus[ DG_PRIMARY_HEATER ].targetFlow; + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, heatDisinfectSensorTemp, targetFlowLPM, FALSE ); + + setHeaterDutyCycle( DG_PRIMARY_HEATER, dutyCycle ); } return state; @@ -580,9 +576,9 @@ { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; DG_HEATERS_T heater = DG_TRIMMER_HEATER; - F32 currentTemperature = 0.0; + F32 currentTemperature = 0.0F; F32 targetFlowLPM = getTargetDialysateFlowLPM(); - F32 dutyCycle = 0.0; + F32 dutyCycle = 0.0F; F32 targetTemperature = heatersStatus[ heater ].targetTemp; DG_OP_MODE_T opMode = getCurrentOperationMode(); @@ -608,7 +604,7 @@ heatersStatus[ heater ].calculatedTemperature = currentTemperature; heatersStatus[ heater ].inactiveRsrvr = getInactiveReservoir(); heatersStatus[ heater ].targetFlow = targetFlowLPM; - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; // Cap the minimum duty cycle. So if it is calculated to negative, set it to 0 dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); @@ -628,23 +624,23 @@ static HEATERS_STATE_T handleHeaterStateTrimmerControlToTarget( void ) { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; - F32 tempDutyCycle = 0.0; + F32 tempDutyCycle = 0.0F; // If the inactive reservoir has changed from the last run transition to ramp state to recalculate the // duty cycle for the next delivery if ( heatersStatus[ DG_TRIMMER_HEATER ].inactiveRsrvr != getInactiveReservoir() ) { state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; } - else if ( ++trimmerHeaterControlCounter > TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ) + else if ( ++heaterControlCounter > HEATER_CONTROL_CHECK_INTERVAL_COUNT ) { // When the trimmer heater is on, its duty cycle is adjusted at the control interval. For this control check, // dialysate inlet temperature sensor is used rather than the theoretical calculations. F32 outletRedundantTemperature = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); F32 targetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; F32 targetFlowLPM = heatersStatus[ DG_TRIMMER_HEATER ].targetFlow; F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, outletRedundantTemperature, targetFlowLPM, TRUE ); - trimmerHeaterControlCounter = 0; + heaterControlCounter = 0; tempDutyCycle = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle + dutyCycle; tempDutyCycle = MIN( tempDutyCycle, HEATERS_MAX_DUTY_CYCLE );