Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -r557f409455dde035899c9f89a8b93f57e8eb7f2b --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 557f409455dde035899c9f89a8b93f57e8eb7f2b) @@ -19,6 +19,7 @@ #include "ConductivitySensors.h" #include "DrainPump.h" #include "Heaters.h" +#include "ModeFill.h" #include "ModeDrain.h" #include "OperationModes.h" #include "Pressures.h" @@ -246,6 +247,15 @@ } else { + if ( TRUE == isEmptyAcidBottle() ) + { + activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); // trigger empty acid bottle alarm + } + else if ( TRUE == isEmptyBicarbBottle() ) + { + activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); // trigger empty bicarb bottle alarm + } + requestNewOperationMode( DG_MODE_GENE ); } } Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rd502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92 -r557f409455dde035899c9f89a8b93f57e8eb7f2b --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision d502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 557f409455dde035899c9f89a8b93f57e8eb7f2b) @@ -98,6 +98,9 @@ F32 fillLastTemperature; ///< Fill last temperature value. BOOL isThisFirstFill; ///< Fill flag to indicate whether it is the first fill or not. BOOL fillAvgConductivityOutOfRange; ///< Fill average conductivity out of range. + BOOL fillEmtyAcidBottleDetected; ///< Fill acid bottle empty detected. + BOOL fillEmtyBicarbBottleDetected; ///< Fill bicarb bottle empty detected. + BOOL fillBottlesNeedPrimeFlag; ///< Fill flag to indicate acid and bicarb bottle need priming. } FILL_CONDITION_STATUS_T; /// DG broadcast dialysate fill data structure. @@ -378,6 +381,9 @@ fillStatus.fillLastTemperature = getHeaterTargetTemperature( DG_TRIMMER_HEATER ) + RESERVOIR_EXTRA_TEMPERATURE; fillStatus.isThisFirstFill = TRUE; fillStatus.fillAvgConductivityOutOfRange = FALSE; + fillStatus.fillEmtyAcidBottleDetected = FALSE; + fillStatus.fillEmtyBicarbBottleDetected = FALSE; + fillStatus.fillBottlesNeedPrimeFlag = FALSE; } /*********************************************************************//** @@ -408,6 +414,61 @@ /*********************************************************************//** * @brief + * The isEmptyBottle function returns the boolean flag that indicates + * whether the acid bottle is empty. + * @details Inputs: none + * @details Outputs: none + * @return fillStatus.fillEmtyAcidBottleDetected + *************************************************************************/ +BOOL isEmptyAcidBottle( void ) +{ + return fillStatus.fillEmtyAcidBottleDetected; +} + +/*********************************************************************//** + * @brief + * The isEmptyBottle function returns the boolean flag that indicates + * whether the bicarb bottle is empty. + * @details Inputs: none + * @details Outputs: none + * @return fillStatus.fillEmtyBicarbBottleDetected + *************************************************************************/ +BOOL isEmptyBicarbBottle( void ) +{ + return fillStatus.fillEmtyBicarbBottleDetected; +} + +/*********************************************************************//** + * @brief + * The setBottlesNeedPrimeFlag function sets the boolean flag that indicates + * the acid and bicarb bottle need priming. + * @details Inputs: none + * @details Outputs: none + * @return fillStatus.fillBottlesNeedPrimeFlag + * @param flag to TRUE if prime is needed otherwise FALSE + *************************************************************************/ +BOOL setBottlesNeedPrimeFlag( BOOL flag ) +{ + fillStatus.fillBottlesNeedPrimeFlag = flag; + + return fillStatus.fillBottlesNeedPrimeFlag; +} + +/*********************************************************************//** + * @brief + * The getBottlesNeedPrimeFlag function gets the boolean flag that indicates + * the acid and bicarb bottle need priming. + * @details Inputs: none + * @details Outputs: none + * @return fillStatus.fillBottlesNeedPrimeFlag + *************************************************************************/ +BOOL getBottlesNeedPrimeFlag( void ) +{ + return fillStatus.fillBottlesNeedPrimeFlag; +} + +/*********************************************************************//** + * @brief * The handleTestInletWaterState function tests for inlet water quality * and if this is the first fill of a treatment, prime the acid and bicarb * lines before jumping to dialysate production state. @@ -426,7 +487,7 @@ // If this is the first fill of a treatment, prime acid and bicarb lines, otherwise transition // to dialysate production directly #ifndef DISABLE_MIXING - if ( TRUE == isThisTheFirstFill() ) + if ( TRUE == isThisTheFirstFill() || TRUE == getBottlesNeedPrimeFlag() ) { // Prepare the acid and bicarb pumps to prime the concentrate lines setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); @@ -681,10 +742,6 @@ F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - // Continuous conductivity testing will be implemented in the next phase - //BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); - //BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); - // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( measuredROFlowRateMLPM ); @@ -715,25 +772,27 @@ #ifndef DISABLE_MIXING // Detect empty bottles using integrated volumes // TODO: empty bottles detection using conductivity sensors if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 437 - //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) { usedAcidVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); - result = DG_FILL_MODE_STATE_PAUSED; + //activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); // trigger empty acid bottle alarm at the end of drain mode and set both bottles need prime + fillStatus.isThisFirstFill = TRUE; // empty bottles need replaced, set isThisFirstFill to FALSE so that prime, flush, acid & bicarb test are needed + fillStatus.fillEmtyAcidBottleDetected = TRUE; // set this variable to FALSE when user presses OK on the alarm to confirm bottle has been replaced and resume + //requestNewOperationMode( DG_MODE_GENE ); } if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 438 - //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) { usedBicarbVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); - result = DG_FILL_MODE_STATE_PAUSED; + //activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); // trigger empty bicarb bottle alarm at the end of drain mode and set both bottles need prime + fillStatus.isThisFirstFill = TRUE; + fillStatus.fillEmtyBicarbBottleDetected = TRUE; + //requestNewOperationMode( DG_MODE_GENE ); // Fill -> Generation Idle } #endif @@ -745,7 +804,9 @@ F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; F32 avgBicardConductivity = bicarbConductivityTotal / conductivitySampleCount; + fillStatus.fillAvgConductivityOutOfRange = FALSE; // init to FALSE when fill has reached target + #ifndef DISABLE_FLOW_CHECK_IN_FILL if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) // SRSDG 439 { @@ -756,25 +817,22 @@ #ifndef DISABLE_DIALYSATE_CHECK // SRSDG 400 if ( TRUE == isValueWithinPercentRange( avgBicardConductivity, BICARB_NORMAL_CONDUCTIVITY, FIVE_PERCENT_FACTOR ) ) { - fillStatus.fillAvgConductivityOutOfRange = TRUE; // signal idle mode - requestNewOperationMode( DG_MODE_GENE ); // leave fill mode if bad fill is detected due to avg bicarb is out of range + fillStatus.fillAvgConductivityOutOfRange = TRUE; // signal idle mode to handle bad fill + fillStatus.isThisFirstFill = TRUE; + setBottlesNeedPrimeFlag( TRUE ); SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgBicardConductivity, BICARB_NORMAL_CONDUCTIVITY ); + requestNewOperationMode( DG_MODE_GENE ); // leave fill mode if bad fill is detected due to avg bicarb is out of range } - else - { - fillStatus.fillAvgConductivityOutOfRange = FALSE; - } if ( TRUE == isValueWithinPercentRange( avgAcidConductivity, ACID_NORMAL_CONDUCTIVITY, FIVE_PERCENT_FACTOR ) ) { - fillStatus.fillAvgConductivityOutOfRange = TRUE; // signal idle mode - requestNewOperationMode( DG_MODE_GENE ); // leave fill mode if bad fill is detected due to avg acid out of range + fillStatus.fillAvgConductivityOutOfRange = TRUE; // signal idle mode to handle bad fill + fillStatus.isThisFirstFill = TRUE; + setBottlesNeedPrimeFlag( TRUE ); SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgAcidConductivity, ACID_NORMAL_CONDUCTIVITY ); + requestNewOperationMode( DG_MODE_GENE ); // leave fill mode if bad fill is detected due to avg acid out of range } - else - { - fillStatus.fillAvgConductivityOutOfRange = FALSE; - } + #endif // Done with this fill. Calculate the average fill flow rate and average temperature // Reset the variables for the next fill Index: firmware/App/Modes/ModeFill.h =================================================================== diff -u -rd502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92 -r557f409455dde035899c9f89a8b93f57e8eb7f2b --- firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision d502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92) +++ firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 557f409455dde035899c9f89a8b93f57e8eb7f2b) @@ -45,10 +45,18 @@ F32 getLastFillTemperature( void ); +BOOL setBottlesNeedPrimeFlag( BOOL flag ); + +BOOL getBottlesNeedPrimeFlag( void ); + void resetFillStatusParameters( void ); BOOL isThisTheFirstFill( void ); +BOOL isEmptyAcidBottle( void ); + +BOOL isEmptyBicarbBottle( void ); + BOOL isAvgConductivityOutOfRange( void ); BOOL testSetUsedAcidVolumeMLOverride( F32 value ); Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -rd502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92 -r557f409455dde035899c9f89a8b93f57e8eb7f2b --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision d502fb7b72c8b3aa4f3a7cdbc4b3c4f7b5ae7c92) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 557f409455dde035899c9f89a8b93f57e8eb7f2b) @@ -45,7 +45,7 @@ #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. #define TARGET_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. -#define TARGET_FLUSH_LINES_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. +#define TARGET_FLUSH_WATER_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. TODO: determine the flow rate /// The time of HD lost comm before DG transition back to standby. #define HD_LOST_COMM_TIMEOUT_MS (5 * SEC_PER_MIN * MS_PER_SECOND ) @@ -54,13 +54,12 @@ static DG_GEN_IDLE_MODE_STATE_T genIdleState; ///< Currently active generation idle state. static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T badFillState; ///< Current active bad fill state. -static F32 flushLinesVolumeL = 0.0; ///< Volume of water pumped by RO pump during flush lines state. +static F32 flushWaterVolumeL = 0.0; ///< Volume of water pumped by RO pump during flush water state. static U32 hdLostCommStartTime_ms = 0; ///< Lost communication with HD start time in ms. // ********** private function prototypes ********** static DG_GEN_IDLE_MODE_STATE_T handleIdleStartState( void ); -static DG_GEN_IDLE_MODE_STATE_T handleFlushLinesState( void ); static DG_GEN_IDLE_MODE_STATE_T handleFlushWaterState( void ); static DG_GEN_IDLE_MODE_STATE_T handleBadFillState( void ); // This state has sub-states 1.0 to 1.4 @@ -81,7 +80,7 @@ { genIdleState = DG_GEN_IDLE_MODE_STATE_START; badFillState = DG_HANDLE_BAD_FILL_STATE_FIRST_DRAIN; - flushLinesVolumeL = 0.0; + flushWaterVolumeL = 0.0; hdLostCommStartTime_ms = 0; } @@ -119,7 +118,7 @@ // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters #ifndef DISABLE_FLOW_CONTROL_TREATMENT - setROPumpTargetFlowRateLPM( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( TARGET_FLUSH_WATER_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); startHeater( DG_PRIMARY_HEATER ); #endif @@ -191,10 +190,6 @@ genIdleState = handleIdleStartState(); break; - case DG_GEN_IDLE_MODE_STATE_FLUSH_LINES: - genIdleState = handleFlushLinesState(); - break; - case DG_GEN_IDLE_MODE_STATE_FLUSH_WATER: genIdleState = handleFlushWaterState(); break; @@ -216,49 +211,20 @@ * @brief * The handleIdleStartState function executes the start state of the * generation idle mode state machine. - * @details Inputs: flushLinesVolumeL - * @details Outputs: Integrate volume of water moved through line + * @details Inputs: none + * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleIdleStartState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_START; - if ( TRUE == isAvgConductivityOutOfRange() ) + if ( TRUE == isAvgConductivityOutOfRange() ) // bad fill due to conductivity is out of range and assume bottles need prime { result = DG_GEN_IDLE_MODE_STATE_HANDLE_BAD_FILL ; } else { - result = DG_GEN_IDLE_MODE_STATE_FLUSH_LINES; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleFlushLinesState function executes the flush lines state of the - * generation idle mode state machine. - * @details Inputs: flushLinesVolumeL - * @details Outputs: Integrate volume of water moved through line - * @return the next state - *************************************************************************/ -static DG_GEN_IDLE_MODE_STATE_T handleFlushLinesState( void ) -{ - DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_FLUSH_LINES; - F32 waterFlowRate = getMeasuredROFlowRateLPM(); - F32 waterVolume = ( ( waterFlowRate / SEC_PER_MIN ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - - // Integrate volume of water moved through line - flushLinesVolumeL += waterVolume; - - // When enough water volume has flowed to flush the lines, transition to flush water state - if ( flushLinesVolumeL >= getFlushLineVolume() ) - { -#ifndef DISABLE_FLOW_CONTROL_TREATMENT - setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); -#endif result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; }