Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r9826fc85bd1497ec617ae0e825f78b91972de2b3 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 9826fc85bd1497ec617ae0e825f78b91972de2b3) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file ConductivitySensors.c * -* @author (last) Dara Navaei -* @date (last) 03-Aug-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Quang Nguyen * @date (original) 13-Jul-2020 @@ -40,9 +40,9 @@ #define COND_CPI_SENSOR_PROBE_TYPE 100 ///< 1 K cell constant conductivity probe. #define COND_CPO_SENSOR_PROBE_TYPE 10 ///< 0.1 K cell constant conductivity probe. -#define COND_SENSOR_DECIMAL_CONVERSION 100 ///< Conductivity value from FPGA has two decimal place. +#define COND_SENSOR_DECIMAL_CONVERSION 100.0F ///< Conductivity value from FPGA has two decimal place. #define COND_SENSOR_TEMPERATURE_COEF 0.02F ///< Linear temperature coefficient of variation at 25 Celcius for fresh water. -#define COND_SENSOR_REFERENCE_TEMPERATURE 25 ///< Reference temperature for conductivity sensor. +#define COND_SENSOR_REFERENCE_TEMPERATURE 25.0F ///< Reference temperature for conductivity sensor. #define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. #define MAX_COND_SENSOR_CPI_WARNING_HIGH 2000.0F ///< Maximum allowed high conductivity value. @@ -57,7 +57,7 @@ #define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0F ///< Out of range value for RO rejection ratio when CPi conductivity is zero. #define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. -#define MAX_CPO_CONDUCTIVITY_ALLOW 30.0 ///< Maximum CPo sensor conductivity value. +#define MAX_CPO_CONDUCTIVITY_ALLOW 30.0F ///< Maximum CPo sensor conductivity value. #define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. #define RO_REJECTION_RATIO_PERSISTENCE_PERIOD ( 10 * MS_PER_SECOND ) ///< Persistence period for RO rejection ratio. @@ -327,15 +327,15 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - BOOL isRORectionOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ? TRUE : FALSE ); - BOOL isCPoOutOfRange = ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ? TRUE : FALSE ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + BOOL isRORejectionOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ? TRUE : FALSE ); + BOOL isCPoOutOfRange = ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ? TRUE : FALSE ); // Fault alarm per PRS 483 checkPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, isCPoOutOfRange, cpo, MAX_CPO_CONDUCTIVITY_ALLOW ); // Fault alarm per PRS 483 - checkPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORectionOutOfRange, roRejectionRatio, MAX_RO_REJECTION_RATIO_ALLOW ); + checkPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORejectionOutOfRange, roRejectionRatio, MAX_RO_REJECTION_RATIO_ALLOW ); } } @@ -405,6 +405,7 @@ { roRejectionRatio = cpo / cpi; } + } /*********************************************************************//** Index: firmware/App/Controllers/DialysateFlow.c =================================================================== diff -u -r04f1fe65f5a31f8521d914a0a5ec89a048f4a30e -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/DialysateFlow.c (.../DialysateFlow.c) (revision 04f1fe65f5a31f8521d914a0a5ec89a048f4a30e) +++ firmware/App/Controllers/DialysateFlow.c (.../DialysateFlow.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -8,7 +8,7 @@ * @file DialysateFlow.c * * @author (last) Bill Bracken -* @date (last) 24-Aug-2022 +* @date (last) 25-Aug-2022 * * @author (original) Hung Nguyen * @date (original) 20-Oct-2021 @@ -121,7 +121,7 @@ if ( TRUE == isNewCalibrationRecordAvailable() ) { getNVRecord2Driver( GET_CAL_FLOW_SENSORS, (U08*)&flowSensorsCalRecord, sizeof( DG_FLOW_SENSORS_CAL_RECORD_T ), - NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_DIALYSATE_FLOW_SENSOR_INVALID_CAL_RECORD ); + NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_RO_FLOW_SENSOR_INVALID_CAL_RECORD ); } // Read flow at the control set Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -ra4669c80291e85fa5ce17d77ebcfd0c882831202 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision a4669c80291e85fa5ce17d77ebcfd0c882831202) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file DrainPump.c * -* @author (last) Dara Navaei -* @date (last) 11-Jul-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Sean * @date (original) 08-Apr-2020 @@ -58,7 +58,7 @@ FLOAT_TO_INT_ROUNDUP_OFFSET ) ///< RPM to DAC conversion equation. #define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.000005F ///< Toggle period to resolution in seconds. -#define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4 ///< Rotational to toggle period conversion coefficient. +#define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4.0F ///< Rotational to toggle period conversion coefficient. #define DRAIN_PUMP_P_COEFFICIENT 0.5F ///< P term for drain pump delta pressure control. #define DRAIN_PUMP_I_COEFFICIENT 1.0F ///< I term for drain pump delta pressure control. @@ -123,7 +123,7 @@ static DG_DRAIN_PUMP_CAL_RECORD_T drainPumpCalRecord; ///< Drain pump calibration record. /// ADC to RPM conversion coefficient or RPM to ADC conversion. -static const F32 CONVERSION_COEFF = SEC_PER_MIN / ( 2 * TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); +static const F32 CONVERSION_COEFF = (F32) SEC_PER_MIN / ( 2.0F * TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); // ********** private function prototypes ********** Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r788c0f92052a7d8f0d67dd4ab607b48520013589 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 788c0f92052a7d8f0d67dd4ab607b48520013589) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file Heaters.c * -* @author (last) Dara Navaei -* @date (last) 04-Aug-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Dara Navaei * @date (original) 23-Apr-2020 @@ -68,6 +68,7 @@ #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. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. +#define MIN_RO_HEATER_FLOWRATE_LPM 0.2F ///< Minimum target RO heater flow rate in L/min. static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. static const F32 PRIMARY_HEATERS_MAXIMUM_POWER_WATTS = 475 + 237.5F; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r04f1fe65f5a31f8521d914a0a5ec89a048f4a30e -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 04f1fe65f5a31f8521d914a0a5ec89a048f4a30e) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -8,7 +8,7 @@ * @file ROPump.c * * @author (last) Bill Bracken -* @date (last) 24-Aug-2022 +* @date (last) 25-Aug-2022 * * @author (original) Sean * @date (original) 04-Apr-2020 Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r599bf09c73fca5e18a55e750133ac2eb93dd2c51 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 599bf09c73fca5e18a55e750133ac2eb93dd2c51) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file ROPump.h * -* @author (last) Dara Navaei -* @date (last) 31-May-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Sean * @date (original) 04-Apr-2020 @@ -32,7 +32,7 @@ // ********** public definitions ********** #define MAX_RO_FLOWRATE_LPM 1.8F ///< Maximum target RO flow rate in L/min. -#define MIN_RO_FLOWRATE_LPM 0.2F ///< Minimum target RO flow rate in L/min. +#define MIN_RO_FLOWRATE_LPM 0.0F ///< Minimum target RO flow rate in L/min. /// RO pump data struct. typedef struct Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -rd182ea22d168c4a6522993f8a0a362586e87e591 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision d182ea22d168c4a6522993f8a0a362586e87e591) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file UVReactors.c * -* @author (last) Dara Navaei -* @date (last) 02-May-2022 +* @author (last) Bill Bracken +* @date (last) 18-Aug-2022 * * @author (original) Dara Navaei * @date (original) 24-Nov-2020 @@ -43,7 +43,8 @@ #define SELF_TEST_DELAY_TIME 1000 ///< Self test wait time after enabling the reactors and before checking for their health in ms. #define MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD MS_PER_SECOND ///< UV reactors unhealthy state period. #define DATA_PUBLISH_COUNTER_START_COUNT 90 ///< Data publish counter start count. -#define UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< UV reactors on with no flow time out in milliseconds. +#define UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< UV reactors on with no flow time out in milliseconds. +#define MIN_RO_UV_FLOWRATE_LPM 0.2F ///< Minimum target RO UV flow rate in L/min. /// UV reactors self test states typedef enum self_tests @@ -374,7 +375,7 @@ if ( TURN_ON == reactorsStatus[ reactor ].switchState ) { // Check if the flow is below minimum - reactorsStatus[ reactor ].isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); + reactorsStatus[ reactor ].isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_UV_FLOWRATE_LPM ? TRUE : FALSE ); // If the flow is no longer below minimum and the reactor is requested to be on, turn it back on if ( FALSE == reactorsStatus[ reactor ].isFlowBelowMin ) @@ -418,7 +419,7 @@ } // Check if the flow is below minimum - BOOL isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); + BOOL isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_UV_FLOWRATE_LPM ? TRUE : FALSE ); if ( TRUE == isFlowBelowMin ) { Index: firmware/App/DGCommon.h =================================================================== diff -u -r04f1fe65f5a31f8521d914a0a5ec89a048f4a30e -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 04f1fe65f5a31f8521d914a0a5ec89a048f4a30e) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -25,7 +25,7 @@ #define DG_VERSION_MAJOR 0 #define DG_VERSION_MINOR 6 #define DG_VERSION_MICRO 0 -#define DG_VERSION_BUILD 29 +#define DG_VERSION_BUILD 30 // ********** build switches ********** Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -r98a1a2a624373a1d140daed0136522ab6e635237 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 98a1a2a624373a1d140daed0136522ab6e635237) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file ModeChemicalDisinfect.c * -* @author (last) Dara Navaei -* @date (last) 13-Jun-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Sean * @date (original) 04-Apr-2020 @@ -146,11 +146,11 @@ static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during chemical disinfect. static U32 dataPublishCounter = 0; ///< Chemical Disinfect data publish counter. static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. -static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. +static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect. static U32 primeAcidSteadyStateCounter = 0; ///< Prime acid steady state counter. -static BOOL haveDrainParamsBeenInit; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. // ********** private function prototypes ********** @@ -202,24 +202,25 @@ *************************************************************************/ void initChemicalDisinfectMode( void ) { - chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - areTempSensorsInRange = FALSE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - R1ChemDisinfectVol = 0.0; - R2ChemDisinfectVol = 0.0; - overallChemDisinfectTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; - numberOfPostDisinfectRinses = 0; - primeAcidSteadyStateCounter = 0; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; - haveDrainParamsBeenInit = FALSE; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + stateTimer = 0; + isThisLastDrain = FALSE; + stateTrialCounter = 0; + areTempSensorsInRange = FALSE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + R1ChemDisinfectVol = 0.0; + R2ChemDisinfectVol = 0.0; + overallChemDisinfectTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillStableTimeCounter = 0; + isPartialDisinfectInProgress = FALSE; + numberOfPostDisinfectRinses = 0; + primeAcidSteadyStateCounter = 0; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; } /*********************************************************************//** @@ -857,7 +858,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -1551,7 +1552,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -1643,7 +1644,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -1936,28 +1937,28 @@ DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; // If the drain parameters of the reservoir is not initialized, initialize them - if ( FALSE == haveDrainParamsBeenInit ) + if ( FALSE == haveDrainParamsBeenInit[ r ] ) { initDrainParameters( r ); - haveDrainParamsBeenInit = TRUE; + haveDrainParamsBeenInit[ r ] = TRUE; } BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); - haveDrainParamsBeenInit = FALSE; - status = DG_RESERVOIR_REACHED_TARGET; + stateTimer = getMSTimerCount(); + haveDrainParamsBeenInit[ r ] = FALSE; + status = DG_RESERVOIR_REACHED_TARGET; } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to drain on time. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectState = chemDisinfectState; - haveDrainParamsBeenInit = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevChemDisinfectState = chemDisinfectState; + haveDrainParamsBeenInit[ r ] = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -ra4669c80291e85fa5ce17d77ebcfd0c882831202 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision a4669c80291e85fa5ce17d77ebcfd0c882831202) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file ModeFlush.c * -* @author (last) Dara Navaei -* @date (last) 13-Jun-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Leonardo Baloa * @date (original) 20-Dec-2019 @@ -50,14 +50,15 @@ #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 ( 2 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo it was 2 minutes +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. // Flush dialysate state defines -#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. +#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. // Flush concentrate straws state defines -#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. todo was 3 minutes +#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. todo was 3 minutes #define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid pump speed in mL/min. + // The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during flush #define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb pump speed in mL/min. @@ -95,7 +96,7 @@ static U32 dataPublishCounter; ///< Flush data publish counter. static BOOL hasWaterCancellationBeenSet; ///< Water cancellation set/not set boolean flag. static F32 flushLinesVolumeL; ///< Volume of water pumped by RO pump during flush lines state. -static BOOL haveDrainParamsBeenInit; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. // ********** private function prototypes ********** @@ -133,19 +134,20 @@ void initFlushMode( void ) { // Initialize the variables - flushState = DG_FLUSH_STATE_START; - prevFlushState = DG_FLUSH_STATE_START; - flushUIState = FLUSH_UI_STATE_NOT_RUNNING; - rsrvrFillStableTimeCounter = 0; - overallFlushElapsedTimeStart = 0; - isThisInitialDrain = TRUE; - dataPublishCounter = 0; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - hasWaterCancellationBeenSet = FALSE; - flushLinesVolumeL = 0.0; - haveDrainParamsBeenInit = FALSE; - stateTimerStart = 0; + flushState = DG_FLUSH_STATE_START; + prevFlushState = DG_FLUSH_STATE_START; + flushUIState = FLUSH_UI_STATE_NOT_RUNNING; + rsrvrFillStableTimeCounter = 0; + overallFlushElapsedTimeStart = 0; + isThisInitialDrain = TRUE; + dataPublishCounter = 0; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + hasWaterCancellationBeenSet = FALSE; + flushLinesVolumeL = 0.0; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + stateTimerStart = 0; } /*********************************************************************//** @@ -309,15 +311,19 @@ // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); + // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; + flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; stateTimerStart = getMSTimerCount(); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R1; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R1; return state; } @@ -353,10 +359,12 @@ // Set the actuators to drain R2 // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); stateTimerStart = getMSTimerCount(); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R2; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -397,6 +405,7 @@ setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); state = DG_FLUSH_STATE_FLUSH_DRAIN; } @@ -516,7 +525,7 @@ rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; flushUIState = FLUSH_UI_STATE_FLUSH_RESERVOIRS; - state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; } return state; @@ -575,7 +584,7 @@ // Set both reservoirs' status rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { @@ -639,7 +648,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevFlushState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -664,11 +673,17 @@ turnOffUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); + // Close VPi and VPd to drain + setValveState(VPI, VALVE_STATE_CLOSED); + setValveState(VPD, VALVE_STATE_DRAIN_C_TO_NO); + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + stateTimerStart = getMSTimerCount(); isThisInitialDrain = FALSE; rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; flushUIState = FLUSH_UI_STATE_DRAIN_RESERVOIRS; - state = DG_FLUSH_STATE_DRAIN_R1; + state = DG_FLUSH_STATE_DRAIN_R1; } // Check if reservoir 1 fill timed out else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) @@ -948,7 +963,17 @@ status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check - stateTimerStart = getMSTimerCount(); + if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_2 == r) ) + { + if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + stateTimerStart = getMSTimerCount(); + } + } + else + { + stateTimerStart = getMSTimerCount(); + } } } else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) @@ -982,28 +1007,38 @@ DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; // If the drain parameters of the reservoir is not initialized, initialize them - if ( FALSE == haveDrainParamsBeenInit ) + if ( FALSE == haveDrainParamsBeenInit [ r ] ) { initDrainParameters( r ); - haveDrainParamsBeenInit = TRUE; + haveDrainParamsBeenInit[ r ] = TRUE; } BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { - // Set the state timer in case it needs to be used for another timeout check - stateTimerStart = getMSTimerCount(); - haveDrainParamsBeenInit = FALSE; + if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_1 == r) ) + { + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status) && ( 0 == getDrainPumpTargetRPM() ) ) + { + stateTimerStart = getMSTimerCount(); + } + } + else + { + stateTimerStart = getMSTimerCount(); + } + + haveDrainParamsBeenInit[ r ] = FALSE; status = DG_RESERVOIR_REACHED_TARGET; } else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) { // Failed to drain on time - prevFlushState = flushState; - haveDrainParamsBeenInit = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevFlushState = flushState; + haveDrainParamsBeenInit [ r ] = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -rd182ea22d168c4a6522993f8a0a362586e87e591 -r971fc9950b919f8b54ff88a627f6cb1e8a0906ee --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision d182ea22d168c4a6522993f8a0a362586e87e591) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 971fc9950b919f8b54ff88a627f6cb1e8a0906ee) @@ -7,8 +7,8 @@ * * @file ModeHeatDisinfect.c * -* @author (last) Dara Navaei -* @date (last) 13-Jun-2022 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * * @author (original) Sean * @date (original) 20-Apr-2020 @@ -162,14 +162,14 @@ 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 U32 rsrvrFillStableTimeCounter; ///< 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 U32 ROFCirculationTimer = 0; ///< RO filter circulation timer. static U32 ROFCoolingTimer = 0; ///< RO filter cooling timer. static BOOL hasROFCirculationBeenStarted = FALSE; ///< Flag to indicate the water in RO filter has been recirculated. static U32 targetDisinfectTime = 0; ///< Target disinfect time. -static BOOL haveDrainParamsBeenInit; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. static U32 tempGradOutOfRangeTimer; ///< Temperature gradient out of range start timer. // ********** private function prototypes ********** @@ -222,29 +222,30 @@ *************************************************************************/ void initHeatDisinfectMode( void ) { - heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; - prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - areTempSensorsInRange = FALSE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - R1HeatDisinfectVol = 0.0; - R2HeatDisinfectVol = 0.0; - overallHeatDisinfectTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; - isDrainPumpInMixDrainOn = FALSE; - ROFCirculationTimer = 0; - ROFCoolingTimer = 0; - hasROFCirculationBeenStarted = FALSE; - concentratePumpsPrimeTimer = 0; - targetDisinfectTime = 0; - haveDrainParamsBeenInit = FALSE; - tempGradOutOfRangeTimer = 0; + heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; + stateTimer = 0; + isThisLastDrain = FALSE; + stateTrialCounter = 0; + areTempSensorsInRange = FALSE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + R1HeatDisinfectVol = 0.0; + R2HeatDisinfectVol = 0.0; + overallHeatDisinfectTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillStableTimeCounter = 0; + isPartialDisinfectInProgress = FALSE; + isDrainPumpInMixDrainOn = FALSE; + ROFCirculationTimer = 0; + ROFCoolingTimer = 0; + hasROFCirculationBeenStarted = FALSE; + concentratePumpsPrimeTimer = 0; + targetDisinfectTime = 0; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + tempGradOutOfRangeTimer = 0; } /*********************************************************************//** @@ -450,9 +451,9 @@ // Set all the actuators to reset and de-energized state deenergizeActuators(); - // If the inlet pressure is less than the threshold and TDi and TRo difference is greater than 3 C, the cycle + // If the inlet pressure is less than or equal to the threshold or TDi and TRo difference is greater than 3 C, the cycle // should be canceled - if ( ( ppiPressure < MIN_INLET_PRESSURE_PSI ) && ( fabs( TDiTemp - TRoTemp ) > MAX_START_STATE_TEMP_SENSORS_DIFF_C ) ) + if ( ( ppiPressure <= MIN_INLET_PRESSURE_PSI ) || ( fabs( TDiTemp - TRoTemp ) > MAX_START_STATE_TEMP_SENSORS_DIFF_C ) ) { prevHeatDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_INLET_PRES_AND_TEMP_SNSRS_OUT; @@ -465,6 +466,7 @@ // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); @@ -508,7 +510,6 @@ setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -537,6 +538,8 @@ state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; } + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + // Start the timer stateTimer = getMSTimerCount(); } @@ -591,6 +594,7 @@ stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; } + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { @@ -866,7 +870,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevHeatDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -1564,7 +1568,7 @@ // until reservoir 1 is filled up and the tubing might expand or leak. // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { prevHeatDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; @@ -1584,7 +1588,7 @@ // De-energize all the valves and set the VDr to drain R2 setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD2, VALVE_STATE_OPEN ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); @@ -1849,18 +1853,18 @@ { if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) { - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); } } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to fill ontime. Update the previous heat disinfect state and transition to basic cancellation - prevHeatDisinfectState = heatDisinfectState; + prevHeatDisinfectState = heatDisinfectState; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -1885,28 +1889,28 @@ DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; // If the drain parameters of the reservoir is not initialized, initialize them - if ( FALSE == haveDrainParamsBeenInit ) + if ( FALSE == haveDrainParamsBeenInit[ r ] ) { initDrainParameters( r ); - haveDrainParamsBeenInit = TRUE; + haveDrainParamsBeenInit[ r ] = TRUE; } BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); - haveDrainParamsBeenInit = FALSE; - status = DG_RESERVOIR_REACHED_TARGET; + stateTimer = getMSTimerCount(); + haveDrainParamsBeenInit[ r ] = FALSE; + status = DG_RESERVOIR_REACHED_TARGET; } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to drain on time. Update the previous heat disinfect state and transition to basic cancellation - prevHeatDisinfectState = heatDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - haveDrainParamsBeenInit = FALSE; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevHeatDisinfectState = heatDisinfectState; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + haveDrainParamsBeenInit[ r ] = FALSE; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status;