Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r3f7d30b23906496854054949d4491f3bae6ef3c4 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 3f7d30b23906496854054949d4491f3bae6ef3c4) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -66,29 +66,14 @@ #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. -#define SMALL_PRIMARY_AND_TRIMMER_HEATERS_POST_TARGET_TEMPERATURE 40U ///< Small primary and trimmer heaters target temperature during POST. -#define MAIN_PRIMARY_HEATER_POST_TARGET_TEMPERATURE 35U ///< Main primary heater target temperature during POST. -#define HEATERS_POST_HEAT_UP_TIME_SECONDS 50U ///< The time that the heaters are heated up to reach to the target temperature during POST. -#define HEATERS_POST_TEMPERATURE_TOLERANCE 1U ///< Tolerance of the sensors to the target temperature during POST. +#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 MINIMUM_TARGET_TEMPERATURE 10U ///< Minimum allowed target temperature for the heaters. -#define MAXIMUM_TARGET_TEMPERATURE 90U ///< Maximum allowed target temperature for the heaters. - #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 190.0 ///< Heaters max allowed internal temperature in degrees C. TODO figure out the max temperature value #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters max allowed internal temperature timeout in milliseconds. #define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. -/// Heaters self-test enums -typedef enum heaters_self_test_states -{ - HEATERS_SELF_TEST_START = 0, ///< Heaters self-test start state - HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS, ///< Heaters self-test small primary and trimmer heaters state - HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER, ///< Heaters self-test start main primary state - HEATERS_SELF_TEST_COMPLETE, ///< Heaters self-test complete state - NUM_OF_HEATERS_SELF_TEST_STATES ///< Number of heaters self-test states -} HEATERS_SELF_TEST_STATES_T ; - /// Primary heaters exec states typedef enum primary_heaters_exec_states { @@ -115,8 +100,6 @@ // ********** private data ********** -static SELF_TEST_STATUS_T heatersSelfTestResult; ///< Heaters self-test results. -static HEATERS_SELF_TEST_STATES_T heatersSelfTestState; ///< Heaters self-test state. static PRIMARY_HEATERS_EXEC_STATES_T primaryHeatersExecState; ///< Primary heaters exec state. static TRIMMER_HEATER_EXEC_STATES_T trimmerHeaterExecState; ///< Trimmer heater exec state. @@ -134,7 +117,6 @@ static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. -static U32 selfTestElapsedTime; ///< Self-test elapsed time variable. static BOOL hasStartPrimaryHeaterRequested; ///< Start primary heater request flag. static BOOL hasStartTrimmerHeaterRequested; ///< Start trimmer heater request flag. static U32 heatersOnWithNoFlowTimer; ///< Heaters are on but there is no sufficient flow. @@ -148,10 +130,6 @@ // ********** private function prototypes ********** -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestStart( void ); -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters( void ); -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestMainPrimaryHeater( void ); - static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateOff( void ); static PRIMARY_HEATERS_EXEC_STATES_T handlePrimaryHeaterStateControlToTarget( void ); @@ -175,7 +153,6 @@ *************************************************************************/ void initHeaters( void ) { - heatersSelfTestState = HEATERS_SELF_TEST_START; primaryHeatersExecState = PRIMARY_HEATERS_EXEC_STATE_OFF; trimmerHeaterExecState = TRIMMER_HEATER_EXEC_STATE_OFF; primaryHeaterTargetTemperature = 0.0; @@ -185,9 +162,8 @@ dataPublicationTimerCounter = 0; isPrimaryHeaterOn = FALSE; isTrimmerHeaterOn = FALSE; - selfTestElapsedTime = 0; primaryHeatersFeedbackTempSensor = TEMPSENSORS_OUTLET_PRIMARY_HEATER; - trimmerHeaterFeedbackTempSensor = TEMPSENSORS_OUTLET_REDUNDANT; + trimmerHeaterFeedbackTempSensor = TEMPSENSORS_INLET_DIALYSATE; primaryHeatersInternalTempOutTimer = 0; trimmerHeaterInternalTempOutTimer = 0; isPrimaryHeatersTempOutOfRange = FALSE; @@ -266,9 +242,7 @@ if ( ( trimmerHeaterTargetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( trimmerHeaterTargetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) { -#ifndef DISABLE_HEATERS_AND_TEMPS hasStartTrimmerHeaterRequested = TRUE; -#endif status = TRUE; } @@ -405,8 +379,11 @@ * If the flow is below minimum for more than the defined time, stop the heaters and raise the alarm * If the flow is in range, reset the variables * This is to make sure that any of the heaters do not stay on while there is no flow + * In the monitor, trimmer heater is only monitored if heat disinfect mode is active. Trimmer heater is usually + * controlled by HD so checking the DG flow rate to decide whether it should be on or off is not appropriate */ - BOOL isHeaterOn = ( TRUE == isPrimaryHeaterOn ) || ( TRUE == isTrimmerHeaterOn ); + BOOL isModeHeat = ( DG_MODE_HEAT == getCurrentOperationMode() ) && ( TRUE == isTrimmerHeaterOn ); + BOOL isHeaterOn = ( TRUE == isPrimaryHeaterOn ) || ( TRUE == isModeHeat ); BOOL isPWMNonZero = ( mainPrimaryHeaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ) || ( smallPrimaryHeaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ) || ( trimmerHeaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ); @@ -444,42 +421,6 @@ /*********************************************************************//** * @brief - * The execHeatersSelfTest function executes the heaters' self-test state machine. - * @details Inputs: heatersSelfTestState - * @details Outputs: heatersSelfTestState - * @return heatersSelfTestState - *************************************************************************/ -SELF_TEST_STATUS_T execHeatersSelfTest( void ) -{ - switch ( heatersSelfTestState ) - { - case HEATERS_SELF_TEST_START: - heatersSelfTestState = handleHeatersSelfTestStart(); - break; - - case HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS: - heatersSelfTestState = handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters(); - break; - - case HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER: - heatersSelfTestState = handleHeatersSelfTestMainPrimaryHeater(); - break; - - case HEATERS_SELF_TEST_COMPLETE: - // POST is done. Do nothing - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_SELF_TEST_INVALID_STATE, heatersSelfTestState ); - heatersSelfTestState = HEATERS_SELF_TEST_COMPLETE; - break; - } - - return heatersSelfTestResult; -} - -/*********************************************************************//** - * @brief * The execPrimaryHeaters function executes the primary heaters' state machine. * @details Inputs: primaryHeatersExecState * @details Outputs: primaryHeatersExecState @@ -532,108 +473,6 @@ /*********************************************************************//** * @brief - * The handleHeatersSelfTestStart function starts the small primary and - * the trimmer heaters for self-test. - * @details Inputs: heatersSelfTestResult, selfTestElapsedTime - * @details Outputs: heatersSelfTestResult, selfTestElapsedTime - * @return state (HEATERS_SELF_TEST_STATES_T) - *************************************************************************/ -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestStart( void ) -{ - // Code temporarily disabled since POST is not tested yet - // TODO once POST is tested and implemented, remove #ifndef -#ifndef _VECTORCAST_ - heatersSelfTestResult = SELF_TEST_STATUS_PASSED; - return HEATERS_SELF_TEST_COMPLETE; -#else - heatersSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - setSmallPrimaryHeaterPWM( SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ); - setTrimmerHeaterPWM( TRIMMER_HEATER_MAX_DUTY_CYCLE ); - selfTestElapsedTime = getMSTimerCount(); - - return HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS; -#endif -} - -/*********************************************************************//** - * @brief - * The handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters function checks if - * the time on the small primary and trimmer heaters has elapsed. If time has - * elapsed, it checks the thermocouple temperature shared among the two - * heaters. If they are in range, it sets the main primary heater and transitions - * to the next state. If it fails, it sets an alarm and fails the test. - * @details Inputs: heatersSelfTestResult, selfTestElapsedTime - * @details Outputs: heatersSelfTestResult, selfTestElapsedTime - * @return state (HEATERS_SELF_TEST_STATES_T) - *************************************************************************/ -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestSmallPrimaryAndTrimmerHeaters( void ) -{ - HEATERS_SELF_TEST_STATES_T state = HEATERS_SELF_TEST_SMALL_PRIMARY_AND_TRIMMER_HEATERS; - - if ( didTimeout( selfTestElapsedTime, HEATERS_POST_HEAT_UP_TIME_SECONDS ) ) - { - setSmallPrimaryHeaterPWM( 0 ); - setTrimmerHeaterPWM( 0 ); - - F32 convertedTemperature = getTemperatureValue( TEMPSENSORS_TRIMMER_HEATER_INTERNAL ); - - if ( fabs( convertedTemperature - SMALL_PRIMARY_AND_TRIMMER_HEATERS_POST_TARGET_TEMPERATURE ) > HEATERS_POST_TEMPERATURE_TOLERANCE ) - { - //TODO alarm - // TODO POST failed - heatersSelfTestResult = SELF_TEST_STATUS_FAILED; - state = HEATERS_SELF_TEST_COMPLETE; - } - else - { - setMainPrimaryHeaterPWM( MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE ); - selfTestElapsedTime = getMSTimerCount(); - state = HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER; - } - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatersSelfTestMainPrimaryHeater function checks if the time - * on the main primary heater has elapsed. When the time has elapsed, it - * checks to ensure the thermocouple temperature is within the tolerance - * of the target temperature. It then transitions to the complete state. - * @details Inputs: heatersSelfTestResult - * @details Outputs: heatersSelfTestResult - * @return state (HEATERS_SELF_TEST_STATES_T) - *************************************************************************/ -static HEATERS_SELF_TEST_STATES_T handleHeatersSelfTestMainPrimaryHeater( void ) -{ - HEATERS_SELF_TEST_STATES_T state = HEATERS_SELF_TEST_MAIN_PRIMARY_HEATER; - - if ( didTimeout( selfTestElapsedTime, HEATERS_POST_HEAT_UP_TIME_SECONDS ) ) - { - setMainPrimaryHeaterPWM( 0 ); - - F32 convertedTemperature = getTemperatureValue( TEMPSENSORS_PRIMARY_HEATER_INTERNAL ); - - if ( fabs( convertedTemperature - MAIN_PRIMARY_HEATER_POST_TARGET_TEMPERATURE ) > HEATERS_POST_TEMPERATURE_TOLERANCE ) - { - //TODO alarm - // TODO POST failed - heatersSelfTestResult = SELF_TEST_STATUS_FAILED; - } - else - { - heatersSelfTestResult = SELF_TEST_STATUS_PASSED; - } - - state = HEATERS_SELF_TEST_COMPLETE; - } - - return state; -} - -/*********************************************************************//** - * @brief * The handlePrimaryHeaterStateOff function handles the primary heaters at * off state. * @details Inputs: hasStartPrimaryHeaterRequested, isPrimaryHeaterOn @@ -719,7 +558,7 @@ primaryHeaterTimerCounter = 0; } - if ( isPrimaryHeaterOn != TRUE ) + if ( FALSE == isPrimaryHeaterOn ) { // Switch to off state. Set the duty cycles to 0 mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; @@ -742,21 +581,12 @@ { TRIMMER_HEATER_EXEC_STATES_T state = TRIMMER_HEATER_EXEC_STATE_OFF; - if ( hasStartTrimmerHeaterRequested ) + if ( TRUE == hasStartTrimmerHeaterRequested ) { resetHeaterState( TRIMMER_HEATER ); isTrimmerHeaterOn = TRUE; hasStartTrimmerHeaterRequested = FALSE; setTrimmerHeaterPWM( trimmerHeaterDutyCycle ); - - // Check if the operation mode is heat disinfect. If the mode is - // heat disinfect, the feedback sensor will be Thd - if ( DG_MODE_HEAT == getCurrentOperationMode() ) - { - // Set the feedback temperature sensor - trimmerHeaterFeedbackTempSensor = TEMPSENSORS_OUTLET_REDUNDANT; //TODO change this to Thd sensors once it is installed - } - state = TRIMMER_HEATER_EXEC_STATE_CONTROL_TO_TARGET; } @@ -795,7 +625,7 @@ trimmerHeaterTimerCounter = 0; } - if ( ! isTrimmerHeaterOn ) + if ( FALSE == isTrimmerHeaterOn ) { // Set the duty cycle to 0 and switch to off state trimmerHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; @@ -864,7 +694,8 @@ // Is 0 or negative, the duty cycle is 0.0 if ( deltaTemp <= 0.0 ) { - mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; } else { @@ -874,11 +705,12 @@ // If the duty cycle is greater 200% on the primary and small primary heaters, set it to 200%, otherwise set it to the // estimated duty cycles duty = ( duty > PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ? PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE : duty ); - mainPrimaryHeaterDutyCycle = duty / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; + mainPrimaryHeaterDutyCycle = duty / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; smallPrimaryHeaterDutyCycle = duty / MAIN_AND_SMALL_PRIMARY_HEATER_DUTY_CYCLE_DIVISOR; } - resetPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, mainPrimaryHeaterDutyCycle ); + // The PI controller of the primary heater consists of main and small primary heaters duty cycles + resetPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, mainPrimaryHeaterDutyCycle + smallPrimaryHeaterDutyCycle ); } else if ( TRIMMER_HEATER == heater ) { Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -rbbf67569fc5f34815c0e0855dd452de2be5a7976 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision bbf67569fc5f34815c0e0855dd452de2be5a7976) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -79,8 +79,6 @@ void execHeatersMonitor( void ); -SELF_TEST_STATUS_T execHeatersSelfTest( void ); - void execPrimaryHeaters( void ); void execTrimmerHeater( void ); Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r7e632c636be41c139d2d97cc845298ff98ff66ed -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 7e632c636be41c139d2d97cc845298ff98ff66ed) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -55,7 +55,7 @@ F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. - F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. + F64 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. @@ -204,7 +204,7 @@ loadcells[ ii ].smallFilterTotal -= loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ]; loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] = getLoadCellWeight( (LOAD_CELL_ID_T)ii ); loadcells[ ii ].smallFilterTotal += getLoadCellWeight( (LOAD_CELL_ID_T)ii ); - loadcells[ ii ].smallFilteredWeight = loadcells[ ii ].smallFilterTotal / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; + loadcells[ ii ].smallFilteredWeight = (F32)( loadcells[ ii ].smallFilterTotal / (F64)SIZE_OF_SMALL_LOAD_CELL_AVG ); } smallReadingsIdx = INC_WRAP( smallReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r8a4182663ef6b12e3fd6414c0c14158943cd4ce1 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 8a4182663ef6b12e3fd6414c0c14158943cd4ce1) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -96,7 +96,12 @@ //setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); TODO uncomment //setDrainPumpTargetRPM( TARGET_DRAIN_PUMP_RPM ); //TODO comment this for testing + + // NOTE: The target flow rate should be set prior to setting the start primary heater + // because the initial guess in the heaters driver needs the target flow to calculate + // the new PWMs for the main and small primary heaters setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + startPrimaryHeater(); } /*********************************************************************//** Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r8a4182663ef6b12e3fd6414c0c14158943cd4ce1 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 8a4182663ef6b12e3fd6414c0c14158943cd4ce1) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -123,8 +123,11 @@ setPrimaryHeaterTargetTemperature( 39.0 ); // TODO remove - startPrimaryHeater(); + // NOTE: The target flow rate should be set prior to setting the start primary heater + // because the initial guess in the heaters driver needs the target flow to calculate + // the new PWMs for the main and small primary heaters setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + startPrimaryHeater(); } /*********************************************************************//** Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -rb63e03ba8b2568afbbd314e9ba6c59c16db29f42 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision b63e03ba8b2568afbbd314e9ba6c59c16db29f42) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -41,7 +41,7 @@ // General defines #define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. -#define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. +#define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode heat disinfect data publish interval in counts. // Start state defines #define MIN_INLET_PRESSURE_PSI 30.0 ///< Minimum water inlet pressure in psi. @@ -53,7 +53,7 @@ #define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time was 60 seconds +#define FLUSH_DRAIN_WAIT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. #define MIN_INLET_TEMPERATURE_C 15.0 ///< Minimum water inlet temperature in C. TODO original temperature was 25 C #define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0 ///< Maximum water inlet conductivity in us/cm @@ -73,29 +73,33 @@ #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. // Fill and heat water -#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 83.0 ///< Heat disinfect target water temperature in C. TODO original temperature was 85.0 -#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0 ///< Heat disinfect minimum acceptable temperature in C. TODO original temperature was 81.0 +#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 83.0 ///< Heat disinfect target water temperature in C. +#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0 ///< Heat disinfect minimum acceptable temperature in C. // R1 to R2 & R2 to R1 heat disinfect circulation -#define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 1.0 ///< Heat disinfect target RO flow rate in L/min. TODO original value was 0.8 +#define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 1.2 ///< Heat disinfect target RO flow rate in L/min. #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. #define HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI 10.0 ///< Heat disinfect target drain outlet pressure in psi. -#define HEAT_DISINFECT_TIME_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. TODO original time was 10 minutes +#define HEAT_DISINFECT_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. #define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. TODO figure out this timeout #define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. TODO change this to 5 seconds #define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 600.0 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. TODO original value is 100 mL #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. +// Cool down RO filter +#define MIN_NUM_OF_ROF_CIRCULATIONS_FOR_COOLING 2 ///< Number of circulations that are needed to make the RO filter is below 45 C. +#define ROF_COOL_DOWN_TARGET_FLOW_LPM 0.3 ///< RO filter cool down target flow in L/min. +#define ROF_COOL_DOWN_CIRCULATION_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< RO filter cool down circulation timer in milliseconds. + // Mix drain R1 and R2 #define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 20 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. #define DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ( 5 * MS_PER_SECOND ) ///< Time to start the drain pump at mix drain after directing the flow to drain in ms. -#define DRAIN_PUMP_RPM_IN_MIX_DRAIN 1500 ///< The RPM that the drain pump should be run during mix drain. TODO the original value is 600 RPM +#define DRAIN_PUMP_RPM_IN_MIX_DRAIN 600 ///< The RPM that the drain pump should be run during mix drain. #define MIX_DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 15 * MS_PER_SECOND ) ///< Time period of unchanged weight during mix draining before timeout. // Rinse R1 to R2 -#define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 45.0 ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. TODO the actual value is 45.0 +#define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 45.0 ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. -// Cancellation paths #define MIX_DRAIN_TEMPERATURE_THRESHOLD_C 60.0 ///< Temperature threshold for performing mix drain or normal drain. /// Cancellation paths @@ -120,28 +124,31 @@ // ********** private data ********** -static DG_HEAT_DISINFECT_STATE_T heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Current active heat disinfect state. -static DG_HEAT_DISINFECT_STATE_T prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Previous active heat disinfect state before alarm. -static DG_HEAT_DISINFECT_UI_STATE_T heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; ///< Current active heat disinfect UI state. -static U32 overallHeatDisinfectTimer = 0; ///< Heat disinfect cycle total timer. -static U32 stateTimer = 0; ///< Heat disinfect state timer to be used in different states. -static U32 stateTrialCounter = 0; ///< Heat disinfect state trial counter to be used for retries in different states. -static BOOL areTempSensorsInRange = FALSE; ///< Heat disinfect temperature sensors in/out range flag. +static DG_HEAT_DISINFECT_STATE_T heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Current active heat disinfect state. +static DG_HEAT_DISINFECT_STATE_T prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Previous active heat disinfect state before alarm. +static DG_HEAT_DISINFECT_UI_STATE_T heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; ///< Current active heat disinfect UI state. +static U32 overallHeatDisinfectTimer = 0; ///< Heat disinfect cycle total timer. +static U32 stateTimer = 0; ///< Heat disinfect state timer to be used in different states. +static U32 stateTrialCounter = 0; ///< Heat disinfect state trial counter to be used for retries in different states. +static BOOL areTempSensorsInRange = FALSE; ///< Heat disinfect temperature sensors in/out range flag. /// Boolean flag to check whether draining R1 and R2 is at the end of the heat disinfect cycle or in the beginning. So the drain states can be reused. static BOOL isThisLastDrain = FALSE; -static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. -static F32 R1HeatDisinfectVol = 0.0; ///< Reservoir 1 full volume during heat disinfect. -static F32 R2HeatDisinfectVol = 0.0; ///< Reservoir 2 full volume during heat disinfect. -static U32 heatDisinfectTimer = 0; ///< Heat disinfect timer. -static BOOL isPartialDisinfectInProgress = FALSE; ///< Heat disinfect partial complete/in progess flag. -static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. -static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during heat disinfect. -static U32 dataPublishCounter = 0; ///< Heat Disinfect data publish counter. -static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. -static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. -static ALARM_ID_T alarmDetectedPendingTrigger; ///< Heat disinfect alarm to raise. -static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to show the drain pump is on during mix drain. +static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. +static F32 R1HeatDisinfectVol = 0.0; ///< Reservoir 1 full volume during heat disinfect. +static F32 R2HeatDisinfectVol = 0.0; ///< Reservoir 2 full volume during heat disinfect. +static U32 heatDisinfectTimer = 0; ///< Heat disinfect timer. +static BOOL isPartialDisinfectInProgress = FALSE; ///< Heat disinfect partial complete/in progess flag. +static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. +static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during heat disinfect. +static U32 dataPublishCounter = 0; ///< Heat Disinfect data publish counter. +static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. +static ALARM_ID_T alarmDetectedPendingTrigger; ///< Heat disinfect alarm to raise. +static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to indicate the drain pump is on during mix drain. +static BOOL hasROFCirculationBeenStarted = FALSE; ///< Flag to indicate the water in RO filter has been recirculated. +static U32 ROFCirculationTimer = 0; ///< RO filter circulation timer. +static U32 ROFCirculationCoolingCounter = 0; ///< RO filter circulation cooling counter. // ********** private function prototypes ********** @@ -184,7 +191,9 @@ * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState - * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain + * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, + * hasROFCirculationBeenStarted, ROFCirculationTimer, + * ROFCirculationCoolingCounter * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -205,6 +214,9 @@ rsrvrFillStableTimeCounter = 0; isPartialDisinfectInProgress = FALSE; isDrainPumpInMixDrainOn = FALSE; + hasROFCirculationBeenStarted = FALSE; + ROFCirculationTimer = 0; + ROFCirculationCoolingCounter = 0; } /*********************************************************************//** @@ -918,7 +930,7 @@ // Turn on the RO pump setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Start heating the water while we are filling up the rsrvrs + // Start heating the water while we are filling up the reservoirs setPrimaryHeaterTargetTemperature( HEAT_DISINFECT_TARGET_TEMPERATURE_C ); startPrimaryHeater(); @@ -982,13 +994,13 @@ // Set the drain pump to control mode setDrainPumpTargetOutletPressure( HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI ); - // Set the RO flow to maximum pressure of 25psi since it is the maximum pressure on the RO filter + // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter // at inlet temperature > 45 C setROPumpTargetFlowRate( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // Start the trimmer heater since we are recirculating water - //setTrimmerHeaterTargetTemperature( HEAT_DISINFECT_TARGET_TEMPERATURE_C ); - //startTrimmerHeater(); TODO turn the trimmer heater on when THD is implemented + // Start the trimmer heater since we are recirculating water and there is flow in the shunt line + setTrimmerHeaterTargetTemperature( HEAT_DISINFECT_TARGET_TEMPERATURE_C ); + startTrimmerHeater(); // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' // volume does not change more than a certain amount during the actual heat disinfect cycle @@ -1053,17 +1065,12 @@ rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; stateTimer = getMSTimerCount(); - // TODO for testing remove - setROPumpTargetFlowRate( 0.8, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // TODO for testing remove - state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; break; + case HEAT_DISINFECT_IN_PROGRESS: default: // Do nothing, heat disinfect is in progress - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_DEVICE; break; } @@ -1087,6 +1094,9 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; + // Set the heat disinfect UI state + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; + // First reservoir 1 must be partially full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1152,6 +1162,11 @@ stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; break; + + case HEAT_DISINFECT_IN_PROGRESS: + default: + // Do nothing heat disinfect is in progress. + break; } return state; @@ -1170,6 +1185,9 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + // Set the heat disinfect UI state + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + if ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) { // Stop the drain pump and the RO pump to exit the closed loop @@ -1178,6 +1196,8 @@ // De-energize all the valves that are not in the path anymore // and wait for the RO membrane to be cooled down. + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); @@ -1194,8 +1214,10 @@ * The handleHeatDisinfectCoolDownROFilterState function handles the heat * disinfect cool down RO filter state. The state monitors the temperature * at THd and if it is less than 45 C, it transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status - * @details Outputs: stateTimer, rsrvr1Status + * @details Inputs: stateTimer, rsrvr1Status, hasROFCirculationBeenStarted, + * ROFCirculationCoolingCounter + * @details Outputs: stateTimer, rsrvr1Status, hasROFCirculationBeenStarted, + * ROFCirculationCoolingCounter * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( void ) @@ -1210,22 +1232,50 @@ // to run fluid through the RO filter F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - // Check if the coldest spot temperature is less than 45 C so the RO filter - // can safely run fluid through - if ( TPoTemp < ROF_MIN_LOW_PRESSURE_TEMPERATURE_C ) + // Check if the coldest spot temperature is less than 45 C so the RO filter can safely run fluid through + if ( ( FALSE == isReverseOsmosisPumpOn() ) && ( TPoTemp < ROF_MIN_LOW_PRESSURE_TEMPERATURE_C ) ) { - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + // If the minimum number of circulations are done, transition to the next state + if ( ROFCirculationCoolingCounter > MIN_NUM_OF_ROF_CIRCULATIONS_FOR_COOLING ) + { + setValveState( VPI, VALVE_STATE_OPEN ); + // To make sure there is no leak from the reservoirs or drain to RO path during mix draining + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; + } + else + { + // Set the valves to circulation. VBf is opened because the fluid in the RO filter might still be hot + setValveState( VBF, VALVE_STATE_OPEN ); + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + + // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter + // at inlet temperature > 45 C + setROPumpTargetFlowRate( ROF_COOL_DOWN_TARGET_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); + + // Increment the RO filter cooling counter + ROFCirculationCoolingCounter++; + hasROFCirculationBeenStarted = TRUE; + ROFCirculationTimer = getMSTimerCount(); + } } + // If the RO filter water circulation is in progress and the time for it has elapsed, stop the pump + else if ( ( TRUE == hasROFCirculationBeenStarted ) && ( TRUE == didTimeout( ROFCirculationTimer, ROF_COOL_DOWN_CIRCULATION_TIME_MS ) ) ) + { + signalROPumpHardStop(); + // Done with running the RO pump + hasROFCirculationBeenStarted = FALSE; + } return state; } @@ -1774,15 +1824,15 @@ * If the heat disinfect has started or has elapsed, it set the status of * heat disinfect accordingly. * @details Inputs: areRsrvrsLeaking, areRsrvrsLeaking - * @details Outputs: areRsrvrsLeaking, areRsrvrsLeaking + * @details Outputs: areRsrvrsLeaking, areRsrvrsLeaking, heatDisinfectState * @return status of the heat disinfect (i.e in progress, complete) *************************************************************************/ static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ) { HEAT_DISINFECT_STATUS_T status = HEAT_DISINFECT_IN_PROGRESS; F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual TPm sensor later + F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual THd sensor later BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; BOOL isR2OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; @@ -1800,7 +1850,7 @@ else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) { areRsrvrsLeaking = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; } } @@ -1810,18 +1860,19 @@ areRsrvrsLeaking = FALSE; } - // If the coldest spot which is TPm is less than minimum heat disinfect temperature, + // If the coldest spot which is THd is less than minimum heat disinfect temperature, // reset the heat disinfect timers and check whether heating up has timed out if ( ThdTemp < HEAT_DISINFECT_START_TEMPERATURE_C ) { // Keep reseting the disinfect timer so the elapsed time is always 0 until disinfect truly starts heatDisinfectTimer = getMSTimerCount(); isPartialDisinfectInProgress = FALSE; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) { // Heating up to minimum temperature for heat disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TARGET_TEMP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TARGET_TEMP_TIMEOUT; status = HEAT_DISINFECT_HEAT_UP_TIMEOUT; } } @@ -1830,6 +1881,16 @@ // The temperature of the coldest spot is in range to start the disinfect timer heatDisinfectTimer = getMSTimerCount(); isPartialDisinfectInProgress = TRUE; + + // Set the heat disinfect UI state + if ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) + { + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_1; + } + else + { + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + } } // If heat disinfect temperature has been reached, check if this stage of heat disinfect is done @@ -1868,17 +1929,17 @@ if ( ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) || ( DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 == heatDisinfectState ) ) { - uiData.heatDisinfectTargetTime = HEAT_DISINFECT_TIME_MS; - uiData.heatDisinfectElapsedTime = calcTimeSince( heatDisinfectTimer ); - data.R1FillLevel = R1HeatDisinfectVol; - data.R2FillLevel = R2HeatDisinfectVol; + uiData.heatDisinfectTargetTime = HEAT_DISINFECT_TIME_MS; + uiData.heatDisinfectCountdownTime = HEAT_DISINFECT_TIME_MS - calcTimeSince( heatDisinfectTimer ); + data.R1FillLevel = R1HeatDisinfectVol; + data.R2FillLevel = R2HeatDisinfectVol; } else { - uiData.heatDisinfectTargetTime = 0; - uiData.heatDisinfectElapsedTime = 0; - data.R1FillLevel = 0.0; - data.R2FillLevel = 0.0; + uiData.heatDisinfectTargetTime = 0; + uiData.heatDisinfectCountdownTime = 0; + data.R1FillLevel = 0.0; + data.R2FillLevel = 0.0; } broadcastHeatDisinfectData( &data ); Index: firmware/App/Modes/ModeHeatDisinfect.h =================================================================== diff -u -r3f7d30b23906496854054949d4491f3bae6ef3c4 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision 3f7d30b23906496854054949d4491f3bae6ef3c4) +++ firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -43,11 +43,11 @@ U32 heatDisinfectUIState; ///< Heat disinfect UI state. } MODE_HEAT_DISINFECT_DATA_T; -/// Heat disinfect data publish struct +/// Heat disinfect UI data publish struct typedef struct { U32 heatDisinfectTargetTime; ///< Target time to heat disinfect. - U32 heatDisinfectElapsedTime; ///< Elapsed time in just heat disinfecting. + U32 heatDisinfectCountdownTime; ///< Heat disinfect countdown time. } MODE_HEAT_DISINFECT_UI_DATA_T; // ********** public function prototypes ********** Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r72dd42b6a116e62d1b3ad5d60088c29e067d10d4 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 72dd42b6a116e62d1b3ad5d60088c29e067d10d4) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -20,7 +20,6 @@ #include "DrainPump.h" #include "Fans.h" #include "FPGA.h" -#include "Heaters.h" #include "LoadCell.h" #include "ModeInitPOST.h" #include "NVDataMgmt.h" @@ -132,11 +131,6 @@ #endif break; - case DG_POST_STATE_HEATERS: - testStatus = execHeatersSelfTest(); - postState = handlePOSTStatus( testStatus ); - break; - case DG_POST_STATE_ACCELEROMETER: #ifndef DISABLE_ACCELS testStatus = execAccelTest(); Index: firmware/App/Modes/ModeRecirculate.c =================================================================== diff -u -r3f7d30b23906496854054949d4491f3bae6ef3c4 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision 3f7d30b23906496854054949d4491f3bae6ef3c4) +++ firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -93,21 +93,25 @@ setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); signalDrainPumpHardStop(); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); - // UV on + // UV reactors on turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // TODO remove setPrimaryHeaterTargetTemperature( 39.0 ); - startPrimaryHeater(); // TODO remove + // NOTE: The target flow rate should be set prior to setting the start primary heater + // because the initial guess in the heaters driver needs the target flow to calculate + // the new PWMs for the main and small primary heaters + setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + startPrimaryHeater(); + #ifndef _VECTORCAST_ { // TODO - test code to start the fan since we're turning the heater on F32 fanPWM = 0.25; Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r8a4182663ef6b12e3fd6414c0c14158943cd4ce1 -rf656b17f3d8d93b4fca49c9725e096e7eb55acc7 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 8a4182663ef6b12e3fd6414c0c14158943cd4ce1) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision f656b17f3d8d93b4fca49c9725e096e7eb55acc7) @@ -458,7 +458,7 @@ BOOL const hasTimeOut = didTimeout( reservoirWeightUnchangeStartTime[ reservoirId ], timeout ); BOOL const hasTargetReached = ( targetDrainVolume >= loadcellWeight ); - if ( hasTimeOut || hasTargetReached ) + if ( ( TRUE == hasTimeOut ) || ( ( TRUE == hasTargetReached ) && ( FALSE == tareLoadCellRequest ) ) ) { result = TRUE; reservoirLowestWeight[ reservoirId ] = MAX_RESERVOIR_WEIGHT;