Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r2fea76e972a450a97c74b2a9f627095032a3b586 -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2fea76e972a450a97c74b2a9f627095032a3b586) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) @@ -25,6 +25,7 @@ #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" +#include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" #include "Valves.h" @@ -47,10 +48,18 @@ #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. +#define ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER 1.06 ///< Acid and bicarbonate concentrates make up around 6% to total volume. +#define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1 ///< Flow integrated volume has 10% tolerance compare to load cell reading. + +/// Multiplier to conver flow (mL/min) into volume (mL) for period of general task interval. +static const F32 RO_FLOW_INTEGRATOR = ( ( ML_PER_LITER * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); + // ********** private data ********** -static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. -static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. +static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. +static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. +static F32 reservoirBaseWeight; ///< Fill reservoir base weight. +static F32 totalROFlowRate; ///< Total RO flow rate over period of time. // ********** private function prototypes ********** @@ -83,6 +92,8 @@ { fillState = DG_FILL_MODE_STATE_START; dialysateFillStartTime = getMSTimerCount(); + reservoirBaseWeight = 0.0; + totalROFlowRate = 0.0; // set initial actuator states setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); @@ -149,6 +160,7 @@ static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; + DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); BOOL const isWaterTemperatureGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ); BOOL const isWaterConductivityGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY ) && @@ -162,6 +174,8 @@ if ( isInletWaterReady ) { + reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); + // Concentrate pumps on request and set RO pump to flow rate 800 mL/min requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1 ); requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2 ); @@ -216,11 +230,13 @@ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; - RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); + DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); handleDialysateMixing(); checkConcentrateConductivity(); + totalROFlowRate += getMeasuredROFlowRate(); + BOOL isDialysateConductivityBad = ( isAlarmActive( ALARM_ID_POST_ACID_CONDUCTIVITY_OUT_OF_RANGE ) || isAlarmActive( ALARM_ID_POST_BICARB_CONDUCTIVITY_OUT_OF_RANGE ) ); #ifdef DISABLE_DIALYSATE_CHECK @@ -237,6 +253,15 @@ // if we've reached our target fill to volume (by weight), we're done filling - go back to re-circ mode if ( hasTargetFillVolumeBeenReached( inactiveReservoir ) ) { + F32 const filledWeight = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; + F32 const integratedVolume = totalROFlowRate * RO_FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER; + F32 const integratedVolumeToLoadCellReadingPercent = 1 - ( filledWeight / integratedVolume ); + + if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledWeight, integratedVolume ); + } + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); requestNewOperationMode( DG_MODE_CIRC );