Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r6e49f490cdfd0450c1477eeb903221937e0d567e -re0f0e562f964f53ac9b9bd62ff2092c0b12e202b --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 6e49f490cdfd0450c1477eeb903221937e0d567e) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision e0f0e562f964f53ac9b9bd62ff2092c0b12e202b) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeFill.c * * @author (last) Dara Navaei -* @date (last) 18-Aug-2023 +* @date (last) 28-Oct-2024 * * @author (original) Leonardo Baloa * @date (original) 19-Nov-2019 @@ -54,20 +54,22 @@ #define RO_PUMP_800_ML_PER_MIN 800.0F ///< RO pump speed of 800.0 mL/minute. #define TARGET_RO_FLOW_RATE_IN_PAUSE_L 0.8F ///< Target flow rate for RO pump during pause in liters. #define MILLILITERS_PER_LITER 1000.0F ///< One liter is 1000 milliliters -#define ACID_PUMP_20_ML_PER_MIN 20.0F ///< Acid pump speed of 20.0 mL/minute. +#define ACID_PUMP_23_ML_PER_MIN 23.0F ///< Acid pump speed of 23.0 mL/minute. #define BICARB_PUMP_40_ML_PER_MIN 40.0F ///< Bicarb pump speed of 40.0 mL/minute. #define CONCENTRATE_PUMP_40_ML_PER_MIN 40.0F ///< Concentrate pump speed of 40.0 mL/minute. #define FILL_MODE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the fill mode data is published on the CAN bus. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. -#define CONC_PUMPS_PRIME_AT_MAX_SPEED_TIME_OUT_MS ( 7 * MS_PER_SECOND ) ///< Concentrate pumps prime at maximum speed timeout in milliseconds. -#define CONC_PUMPS_PRIME_CHECK_COND_SNSRS_TIME_OUT_MS ( 10 * MS_PER_SECOND ) ///< Concentrate pumps prime check conductivity sensors timeout in milliseconds. -#define CONC_PUMPS_PRIME_MAX_ALLOWED_PRIME_TIME_OUT_MS ( 60 * MS_PER_SECOND ) ///< Concentrate pumps prime maximum allowed timeout in prime in milliseconds. +#define CONC_PUMPS_PRIME_AT_MAX_SPEED_TIME_OUT_MS ( 10 * MS_PER_SECOND ) ///< Concentrate pumps prime at maximum speed timeout in milliseconds. +#define CONC_PUMPS_PRIME_CHECK_COND_SNSRS_TIME_OUT_MS ( 13 * MS_PER_SECOND ) ///< Concentrate pumps prime check conductivity sensors timeout in milliseconds. +#define CONC_PUMPS_PRIME_MAX_ALLOWED_PRIME_TIME_OUT_MS ( 45 * MS_PER_SECOND ) ///< Concentrate pumps prime maximum allowed timeout in prime in milliseconds. #define HUNDRED_PERCENT_FACTOR 1.00F ///< Hundred percent of expected conductivity when first time reaches it. #define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1F ///< Flow integrated volume has 10% tolerance compare to load cell reading. #define FIVE_PERCENT_FACTOR 0.05F ///< 5.0 / 100.0 used to calculate conductivity within range of -/+ 5%. +#define BICARB_CHECK_TOL_FACTOR 0.2F ///< Bicarb check tolerance factor. +#define ACID_CHECK_TOL_FACTOR 0.1F ///< Acid check tolerance factor. #define RO_PUMP_LOOKUP_TABLE_SIZE 4 ///< Size of array used as RO pump speed lookup table. #define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0F ///< Concentrate pump additional speed during priming in mL/min. #define CONCENTRATE_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. @@ -95,6 +97,16 @@ // ********** private data ********** +/// Fill for calibration check enumeration from dialin +typedef enum dialin_fill_for_cal +{ + DIALIN_FILL_FOR_CAL_PRIME = 0, ///< Dialin fill for calibration prime. + DIALIN_FILL_FOR_CAL_BICARB_CHECK, ///< Dialin fill for calibration bicarb check. + DIALIN_FILL_FOR_CAL_ACID_CHECK, ///< Dialin fill for calibration acid check. + DIALIN_FILL_FOR_CAL_NONE, ///< Dialin fill for calibration none. + NUM_OF_DIALIN_FILL_FOR_CAL ///< Number of dialin fill for calibration. +} DIALIN_FILL_FOR_CAL_CHECK_T; + /// Fill conditions status typedef struct { @@ -116,10 +128,13 @@ static U32 dataPublishCounter; ///< Used to schedule dialysate fill data publication to CAN bus. static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. -static U32 dialysateFillStartTimeMS; ///< Current time when starting to fill dialysate in milliseconds. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. static FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. +static BOOL didFillRecoverFromPause; ///< Flag to indicate whether the previous state was pause or not. +static U32 dialysateFillStartTimeMS; ///< Current time when starting to fill dialysate in milliseconds. +static U32 dialysatePauseStartTimeMS; ///< Current time when starting a pause during fill dialysate in milliseconds. +static U32 dialysatePauseElapsedTimeMS; ///< Elapsed time in pause during fill dialysate in milliseconds. static U32 concentrateTestStartTime; ///< Starting time for concentrate test. static U32 concentratePrimingStartTime; ///< Starting time for concentrate priming. static U32 flushBubblesStartTime; ///< Starting time for flush bubbles. @@ -145,8 +160,6 @@ static U32 fillCPoConductivitySampleCnt; ///< Number of samples in sum of CPo and Rej. Ratio conductivity readings for fill. static U32 pumpSpeedIndex; ///< Index used to access the desired pump speed in roPumpFlushBubblesSpeed table. -static BOOL havePauseActuatorsBeenSet; ///< Flag to indicate the actuators have been set to pause for the first time. -static BOOL didFillRecoverFromPause; ///< Flag to indicate whether the previous state was pause or not. static FILL_ACID_BICARB_TYPES_T chemicalsTypes; ///< Chemicals Types (acid and bicarb). static DG_CHEMICALS_FILL_COND_CAL_RECORD_T chemicalsCond; ///< Chemicals fill conductivity records. static F32 acidMixRatio; ///< Acid conductivity mix ratio. @@ -155,6 +168,9 @@ // NOTE: This variable should be initialized here because the init function is called every time and then this variable is set to FALSE even if the settings from the // UI wants the RO only mode. static BOOL hasROOnlyModeBeenEnabled = FALSE; ///< Flag to indicate the RO only mode has been set or not. +// NOTE: This variable should be initialized here because the init function is called every time and then it cannot be initialized there. This variable is +// set via Dialin for calibration check purposes only +static DIALIN_FILL_FOR_CAL_CHECK_T dialinFillForCalCheck = DIALIN_FILL_FOR_CAL_NONE; ///< Dialin fill for calibration check. static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. static OVERRIDE_F32_T usedBicarbVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in mL. static OVERRIDE_U32_T fillModeDataPublishInterval = { FILL_MODE_DATA_PUB_INTERVAL, @@ -178,6 +194,7 @@ static void handleDialysateMixing( F32 measuredROFlowRate_mL_min, F32 acidMixingRatio, F32 bicarbMixingRatio ); static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ); static void publishFillModeData( void ); +static void updateChemicalsUsage( void ); /*********************************************************************//** * @brief @@ -194,32 +211,35 @@ getAcidConcentrateCalRecord( &acid ); getBicarbConcentrateCalRecord( &bicarb ); + acidConductivitySampleCount = 0; + acidConductivityTotal = 0.0F; acidMixRatio = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; + averageAcidConductivity = 0.0F; + averageBicarbConductivity = 0.0F; + bicarbConductivitySampleCount = 0; + bicarbConductivityTotal = 0.0F; bicarbMixRatio = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; - fillState = DG_FILL_MODE_STATE_TEST_INLET_WATER; - dialysateFillStartTimeMS = 0; - dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; - reservoirBaseWeight = 0.0F; - integratedVolumeML.data = 0.0F; - didFMPCheckStart = FALSE; concentrateTestStartTime = 0; - acidConductivityTotal = 0.0F; - bicarbConductivityTotal = 0.0F; - conductivitySampleCount = 0; concPumpPrimeStartTimeMS = getMSTimerCount(); - pumpSpeedIndex = 0; - averageBicarbConductivity = 0.0F; - averageAcidConductivity = 0.0F; + conductivitySampleCount = 0; + dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + // This timer is set to 0 to be checked whether we were in pause but this is still 0 so so we the start time regardless + // If we were filling and then went to pause we do not reset this anymore + dialysateFillStartTimeMS = 0; + dialysatePauseElapsedTimeMS = 0; + dialysatePauseStartTimeMS = 0; + didFillRecoverFromPause = FALSE; + didFMPCheckStart = FALSE; + fillCPoConductivitySampleCnt = 0; + fillState = DG_FILL_MODE_STATE_TEST_INLET_WATER; + integratedVolumeML.data = 0.0F; pctDiffInConductivity = 0.0F; - bicarbConductivitySampleCount = 0; - acidConductivitySampleCount = 0; - totalBicarbConductivity = 0.0F; - totalAcidConductivity = 0.0F; - havePauseActuatorsBeenSet = FALSE; + pumpSpeedIndex = 0; + reservoirBaseWeight = 0.0F; sumFillCPoConductivity = 0.0F; sumFillRejRatio = 0.0F; - fillCPoConductivitySampleCnt = 0; - didFillRecoverFromPause = FALSE; + totalAcidConductivity = 0.0F; + totalBicarbConductivity = 0.0F; } /*********************************************************************//** @@ -233,17 +253,22 @@ { F32 targetFlowLPM = getTargetFillFlowRateLPM(); - if ( ( getTestConfigStatus( TEST_CONFIG_RECOVER_TREATMENT ) != TRUE ) || ( getPreviousOperationMode() != DG_MODE_FAUL ) ) - { - initFillMode(); - setCurrentSubState( NO_SUB_STATE ); + initFillMode(); + setCurrentSubState( NO_SUB_STATE ); + // Set initial actuator states + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - // Set initial actuator states - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - } - else - { +#if !defined(DEBUG_ENABLED) && !defined (_RELEASE_) && !defined (_VECTORCAST_) + // Compile this part of code only if it is not debug, release, or VectorCAST. This is to make sure this part of code is not compiled + // and instrumented in VectorCAST + // Reset the state machine + // Note: the substate timers, and operation flags need to be reset on recovery, consider + // reinitializing the state variables, the resetting the state, by calling setModeFillStateTransition() + if ( ( TRUE == getTestConfigStatus( TEST_CONFIG_RECOVER_TREATMENT ) ) && ( DG_MODE_FAUL == getPreviousOperationMode() ) ) + { // Restore the prior fillstate to a valid, running fill state, with timer state reset. + fillState = restoreFillState; + setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); @@ -290,20 +315,19 @@ requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - dialysateFillStartTimeMS = getMSTimerCount(); fillStatus.isThisFirstFill = FALSE; break; case DG_FILL_MODE_STATE_PAUSED: targetFlowLPM = TARGET_RO_FLOW_RATE_IN_PAUSE_L; - havePauseActuatorsBeenSet = FALSE; + dialysatePauseStartTimeMS = getMSTimerCount(); break; } } +#endif getFillChemicalCondRecord( &chemicalsCond ); - turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); @@ -329,10 +353,15 @@ { checkDialysateTemperatureSensors(); setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); + updateChemicalsUsage(); - if ( ( TRUE == areInletWaterConditionsAlarmsActive() ) || ( TRUE == areConductivityAlarmsActive() ) ) + if ( fillState != DG_FILL_MODE_STATE_PAUSED ) { - fillState = DG_FILL_MODE_STATE_PAUSED; + if ( ( TRUE == areInletWaterConditionsAlarmsActive() ) || ( TRUE == areConductivityAlarmsActive() ) ) + { + setModeFillStateTransition( DG_FILL_MODE_STATE_PAUSED ); + fillState = DG_FILL_MODE_STATE_PAUSED; + } } // Execute current Fill state @@ -375,7 +404,6 @@ fillState = DG_FILL_MODE_STATE_TEST_INLET_WATER; break; } - publishFillModeData(); return fillState; @@ -430,6 +458,7 @@ F32 getIntegratedVolumeML( void ) { F32 integratedVolume = getF32OverrideValue( &integratedVolumeML ); + return integratedVolume; } @@ -529,7 +558,7 @@ * @param flag to TRUE if prime is needed otherwise FALSE * @return none *************************************************************************/ -void setThisFisrtFillFlag( BOOL flag ) +void setThisFirstFillFlag( BOOL flag ) { fillStatus.isThisFirstFill = flag; } @@ -590,19 +619,43 @@ { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_TEST_INLET_WATER; - // If this is the first fill of a treatment, prime acid and bicarb lines, otherwise transition - // to dialysate production directly - if ( TRUE == isThisTheFirstFill() ) + if ( ( isConcPumpParkInProgress( CONCENTRATEPUMPS_CP1_ACID ) != TRUE ) && ( isConcPumpParkInProgress( CONCENTRATEPUMPS_CP2_BICARB ) ) != TRUE ) { - result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; - } - else - { - result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; - } + // If this is the first fill of a treatment, prime acid and bicarb lines, otherwise transition + // to dialysate production directly + if ( TRUE == isThisTheFirstFill() ) + { + result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; + } + else + { + result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + } - setModeFillStateTransition( result ); + if ( TRUE == isTestingActivated() ) + { + switch ( dialinFillForCalCheck ) + { + case DIALIN_FILL_FOR_CAL_PRIME: + result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; + break; + case DIALIN_FILL_FOR_CAL_BICARB_CHECK: + result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; + break; + + case DIALIN_FILL_FOR_CAL_ACID_CHECK: + result = DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY; + break; + + default: + // Do nothing. This means there is not a request for the fill calibration check so proceed with the normal operations. + break; + } + } + setModeFillStateTransition( result ); + } + return result; } @@ -686,7 +739,9 @@ averageBicarbConductivity = totalBicarbConductivity / bicarbConductivitySampleCount; - if ( TRUE == isValueWithinPercentRange( averageBicarbConductivity, bicarbCondUSPerCM, FIVE_PERCENT_FACTOR ) ) + SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_BICARB_CHECK_RESULT, averageBicarbConductivity, bicarbCondUSPerCM ) + + if ( TRUE == isValueWithinPercentRange( averageBicarbConductivity, bicarbCondUSPerCM, BICARB_CHECK_TOL_FACTOR ) ) { isConductivityInRange = TRUE; } @@ -699,7 +754,7 @@ else { // Bicarb test failed, go to fault - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_BICARB_CONDUCTIVITY_OUT_OF_RANGE, averageBicarbConductivity ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_BICARB_CONDUCTIVITY_OUT_OF_RANGE, averageBicarbConductivity, bicarbCondUSPerCM ) } } @@ -733,36 +788,30 @@ if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - F32 acidCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_ACID_TEST ].acidConduSPerCM; + F32 acidCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_ACID_TEST ].bicarbConduSPerCM; BOOL hasAcidTestPassed = FALSE; - BOOL hasCD1CD2TestPassed = FALSE; averageBicarbConductivity = totalBicarbConductivity / bicarbConductivitySampleCount; averageAcidConductivity = totalAcidConductivity / acidConductivitySampleCount; pctDiffInConductivity = fabs( 2.0F * ( averageAcidConductivity - averageBicarbConductivity ) / ( averageAcidConductivity + averageBicarbConductivity ) ); + // NOTE: CD2 or bicarb conductivity sensor is used for acid check since it is a more accurate sensor. + // CD2 is the downstream of the acid concentrate pump so the acid sensed there. + SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_ACID_CHECK_RESULT, averageBicarbConductivity, acidCondUSPerCM ) + SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_COND1_VS_COND2_DIFF_RESULT, pctDiffInConductivity, 0.0F ) - if ( ( TRUE == isValueWithinPercentRange( averageAcidConductivity, acidCondUSPerCM, FIVE_PERCENT_FACTOR ) ) || + if ( ( TRUE == isValueWithinPercentRange( averageBicarbConductivity, acidCondUSPerCM, ACID_CHECK_TOL_FACTOR ) ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) { hasAcidTestPassed = TRUE; } else { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_ACID_CONDUCTIVITY_OUT_OF_RANGE, averageAcidConductivity ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_ACID_CONDUCTIVITY_OUT_OF_RANGE, averageBicarbConductivity, acidCondUSPerCM ) } - if ( ( pctDiffInConductivity < FIVE_PERCENT_FACTOR ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) + if ( TRUE == hasAcidTestPassed ) { - hasCD1CD2TestPassed = TRUE; - } - else - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_CD1_CD2_CHECK_FAULT, pctDiffInConductivity ) - } - - if ( ( TRUE == hasAcidTestPassed ) && ( TRUE == hasCD1CD2TestPassed ) ) - { result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; setModeFillStateTransition( result ); } @@ -791,18 +840,16 @@ if ( TRUE == didTimeout( concPumpPrimeStartTimeMS, CONC_PUMPS_PRIME_CHECK_COND_SNSRS_TIME_OUT_MS ) ) { /* Once the time for priming the concentrate lines has elapsed, check the mixing conductivity of the sensors - * If the acid and bicarb conductivity values are at about 100% of the target concentrate during fill, transition to the next state - * If the acid and bicarb conductivity values are not at 100% but the maximum prime time has elapsed, transition to the next state + * If the bicarb conductivity values are at about 100% of the target concentrate during fill, transition to the next state + * If the bicarb conductivity values are not at 100% but the maximum prime time has elapsed, transition to the next state */ - F32 acidConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); F32 bicarbConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 acidFillConduSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].acidConduSPerCM; F32 bicarbFillConduSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].bicarbConduSPerCM; /* we are insisting conductivity reach 100% of expected level since signal is very noisy and peak noise will reach 100% when average is about 93%. * if sensor noise is reduced, this level should also be reduced accordingly. */ - if ( ( acidConduSPerCM >= ( acidFillConduSPerCM * HUNDRED_PERCENT_FACTOR ) ) && ( bicarbConduSPerCM >= ( bicarbFillConduSPerCM * HUNDRED_PERCENT_FACTOR ) ) ) + if ( bicarbConduSPerCM >= ( bicarbFillConduSPerCM * HUNDRED_PERCENT_FACTOR ) ) { result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; setModeFillStateTransition( result ); @@ -872,12 +919,9 @@ didFMPCheckStart = TRUE; reservoirBaseWeight = getReservoirWeight( getInactiveReservoir() ); } - integratedVolumeML.data += getMeasuredROFlowRateWithConcPumpsLPM() * ML_PER_LITER * FLOW_INTEGRATOR; } - usedAcidVolumeML.data += getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; - usedBicarbVolumeML.data += getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; acidConductivityTotal += acidConduSPerCM; bicarbConductivityTotal += bicarbConduSPerCM; conductivitySampleCount++; @@ -888,8 +932,10 @@ fillStatus.fillTemperatureRunningSum += inletTemperature; // TODO: Check for open straw door status and alarm if closed - // Check if run out of time to fill the reservoir - if ( TRUE == didTimeout( dialysateFillStartTimeMS, DIALYSATE_FILL_TIME_OUT ) ) + // Check if run out of time to fill the reservoir, disregarding time paused, + // because pause time isn't the reservoir's, or loadcell's fault + // the 5 minutes DIALYSATE_FILL_TIME_OUT is a mystery number. + if ( TRUE == didTimeout( dialysateFillStartTimeMS, DIALYSATE_FILL_TIME_OUT + dialysatePauseElapsedTimeMS ) ) { activateAlarmNoData( ALARM_ID_DG_DIALYSATE_FILL_OUT_OF_TIME ); } @@ -942,7 +988,7 @@ ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) { setBadAvgConductivityDetectedFlag( TRUE ); // signal idle bad avg conductivity detected - setThisFisrtFillFlag( TRUE ); + setThisFirstFillFlag( TRUE ); resetChemicalUsedVolumeML( BICARB ); resetChemicalUsedVolumeML( ACID ); SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FILL_CONDUCTIVITY_OUT_OF_RANGE, avgBicarbConduSPerCM, bicarbNormalConduSPerCM ); // trigger replace bottles alarm #1 @@ -971,21 +1017,19 @@ * @brief * The handlePausedState function executes the paused state of the fill * mode state machine. - * @details Inputs: havePauseActuatorsBeenSet - * @details Outputs: havePauseActuatorsBeenSet, didFillRecoverFromPause + * @details Inputs: Inlet water conditions and conductivity + * @details Outputs: didFillRecoverFromPause * @return the next state *************************************************************************/ static DG_FILL_MODE_STATE_T handlePausedState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PAUSED; - setModeFillStateTransition( result ); - if ( ( FALSE == areInletWaterConditionsAlarmsActive() ) && ( FALSE == areConductivityAlarmsActive() ) ) { didFillRecoverFromPause = TRUE; - havePauseActuatorsBeenSet = FALSE; result = DG_FILL_MODE_STATE_TEST_INLET_WATER; + setModeFillStateTransition( result ); } return result; @@ -995,17 +1039,28 @@ * @brief * The setModeFillStateTransition function sets the actuators and variables * for the state transition in mode fill. - * @details Inputs: pumpSpeedIndex, havePauseActuatorsBeenSet, + * @details Inputs: pumpSpeedIndex, dialysatePauseStartTimeMS * didFillRecoverFromPause * @details Outputs: concPumpPrimeStartTimeMS, fillStatus, pumpSpeedIndex, * concentratePrimingStartTime, totalBicarbConductivity, averageBicarbConductivity, * bicarbConductivitySampleCount, concentrateTestStartTime, fillStatus, - * havePauseActuatorsBeenSet, flushBubblesStartTime, didFillRecoverFromPause + * flushBubblesStartTime, didFillRecoverFromPause + * dialysatePauseElapsedTimeMS, dialysatePauseStartTimeMS * @param state mode fill state enum * @return none *************************************************************************/ static void setModeFillStateTransition( DG_FILL_MODE_STATE_T state ) { + // Execute cleanup on exiting pause + if ( state != fillState ) + { + if ( DG_FILL_MODE_STATE_PAUSED == fillState ) + { // accumulate pause + dialysatePauseElapsedTimeMS += calcTimeSince( dialysatePauseStartTimeMS ); + } + } + + // Execute on running state switch( state ) { case DG_FILL_MODE_STATE_TEST_INLET_WATER: @@ -1030,6 +1085,13 @@ pumpSpeedIndex = 0; setROPumpTargetFlowRateLPM( RO_PUMP_FLUSH_BUBBLES_FLOWS[ pumpSpeedIndex ] / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); flushBubblesStartTime = getMSTimerCount(); + if ( ( DIALIN_FILL_FOR_CAL_PRIME == dialinFillForCalCheck ) && ( TRUE == isTestingActivated() ) ) + { + // After prime, the state transitions to flush bubbles. If the cal for check prime was set, transition to Gen Idle and + // set the fill for cal check to none. This is done upon the transition of the next state so then we can transition to Gen Idle. + dialinFillForCalCheck = DIALIN_FILL_FOR_CAL_NONE; + requestNewOperationMode( DG_MODE_GENE ); + } break; case DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY: @@ -1051,7 +1113,7 @@ requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // Set pumps flow rate to prepare for acid conductivity testing setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_20_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_23_ML_PER_MIN ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); // Set back the conductivity of CD2 calibration table to the normal calibration table @@ -1061,6 +1123,15 @@ bicarbConductivitySampleCount = 0; acidConductivitySampleCount = 0; concentrateTestStartTime = getMSTimerCount(); + if ( ( DIALIN_FILL_FOR_CAL_BICARB_CHECK == dialinFillForCalCheck ) && ( TRUE == isTestingActivated() ) ) + { + // After bicarb test, the state transitions to acid test. If the cal for check prime was set, transition to Gen Idle and + // set the fill for cal check to none. This is done upon the transition of the next state so then we can transition to Gen Idle. + // NOTE: If the bicarb test fails, it transitions to fault mode so it automatically exits mode fill so this is only for the situation + // that bicarb test was successful + dialinFillForCalCheck = DIALIN_FILL_FOR_CAL_NONE; + requestNewOperationMode( DG_MODE_GENE ); + } break; case DG_FILL_MODE_STATE_PRODUCE_DIALYSATE: @@ -1070,11 +1141,20 @@ requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); concPumpPrimeStartTimeMS = getMSTimerCount(); fillStatus.isThisFirstFill = FALSE; + if ( ( DIALIN_FILL_FOR_CAL_ACID_CHECK == dialinFillForCalCheck ) && ( TRUE == isTestingActivated() ) ) + { + // After acid test, the state transitions to acid test. If the cal for check prime was set, transition to Gen Idle and + // set the fill for cal check to none. This is done upon the transition of the next state so then we can transition to Gen Idle. + // NOTE: If the acid test fails, it transitions to fault mode so it automatically exits mode fill so this is only for the situation + // that bicarb test was successful + dialinFillForCalCheck = DIALIN_FILL_FOR_CAL_NONE; + requestNewOperationMode( DG_MODE_GENE ); + } break; case DG_FILL_MODE_STATE_DELIVER_DIALYSATE: setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - if ( didFillRecoverFromPause != TRUE ) + if ( ( didFillRecoverFromPause != TRUE ) || ( 0 == dialysateFillStartTimeMS ) ) { dialysateFillStartTimeMS = getMSTimerCount(); } @@ -1083,14 +1163,11 @@ break; case DG_FILL_MODE_STATE_PAUSED: - if ( FALSE == havePauseActuatorsBeenSet ) - { - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_IN_PAUSE_L, TARGET_RO_PRESSURE_PSI ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - havePauseActuatorsBeenSet = TRUE; - } + dialysatePauseStartTimeMS = getMSTimerCount(); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_IN_PAUSE_L, TARGET_RO_PRESSURE_PSI ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); break; default: @@ -1159,7 +1236,9 @@ * percentFactor. * @details Inputs: None * @details Outputs: None - * @param: testValue, baseValue, percentFactor + * @param testValue value to check range for + * @param baseValue value associated with 100% + * @param percentFactor percentage range (100% +/- this value) * @return TRUE if testValue is within range. Otherwise, return FALSE *************************************************************************/ static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ) @@ -1238,7 +1317,20 @@ } } +/*********************************************************************//** + * @brief + * The updateChemicalsUsage function updates the used acid and bicarb volumes. + * @details Inputs: usedAcidVolumeML, usedBicarbVolumeML + * @details Outputs: none + * @return none + *************************************************************************/ +static void updateChemicalsUsage( void ) +{ + usedAcidVolumeML.data += getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; + usedBicarbVolumeML.data += getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -1250,7 +1342,7 @@ * acid volume. * @details Inputs: used acid volume * @details Outputs: used acid volume - * @param: value : override used acid volume in mL + * @param value override used acid volume in mL * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetUsedAcidVolumeMLOverride( F32 value ) @@ -1298,7 +1390,7 @@ * bicarb volume. * @details Inputs: used bicarb volume * @details Outputs: used bicarb volume - * @param: value : override used bicarb volume in mL + * @param value override used bicarb volume in mL * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetUsedBicarbVolumeMLOverride( F32 value ) @@ -1346,7 +1438,7 @@ * fill mode data publish interval. * @details Inputs: FillModeDataPublishInterval * @details Outputs: FillModeDataPublishInterval - * @param: value override fill mode data publish interval with (in ms) + * @param value override fill mode data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetFillModeDataPublishIntervalOverride( U32 value ) @@ -1392,7 +1484,7 @@ * integrated volume. * @details Inputs: value * @details Outputs: integratedVolumeML - * @param: value integrated volume in mL + * @param value integrated volume in mL * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetIntegratedVolumeOverride( F32 value ) @@ -1431,4 +1523,28 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetModeFillForCal function sets the variable to run mode fill only + * for calibration check + * @details Inputs: none + * @details Outputs: fillForCalCheck + * @param calForCheck the mode that is requested (0 = prime, 1 = bicarb check, + * 2 = acid check) + * @return TRUE if the request is in the range otherwise, FALSE + *************************************************************************/ +BOOL testSetModeFillForCal( U32 calForCheck ) +{ + BOOL result = FALSE; + + if ( ( calForCheck < NUM_OF_DIALIN_FILL_FOR_CAL ) && ( TRUE == isTestingActivated() ) ) + { + dialinFillForCalCheck = (DIALIN_FILL_FOR_CAL_CHECK_T)calForCheck; + result = TRUE; + requestNewOperationMode( DG_MODE_FILL ); + } + + return result; +} + /**@}*/