Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r20535cdea80fac7a48eb84d47c9ec4a1968051c5 -r5e8f96e11c797bddeddfc009c87f20df3b7a8664 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 20535cdea80fac7a48eb84d47c9ec4a1968051c5) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 5e8f96e11c797bddeddfc009c87f20df3b7a8664) @@ -7,8 +7,8 @@ * * @file ModeFill.c * -* @author (last) Dara Navaei -* @date (last) 12-Aug-2022 +* @author (last) Michael Garthwaite +* @date (last) 21-Nov-2022 * * @author (original) Leonardo Baloa * @date (original) 19-Nov-2019 @@ -38,6 +38,7 @@ #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" +#include "Utilities.h" #include "UVReactors.h" #include "Valves.h" @@ -71,6 +72,8 @@ #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. +#define DELAY_FMP_CHECK_START_BY_MS ( 10 * MS_PER_SECOND ) ///< Delay start of FMP check during dialysate deliver state by this amount of time (in ms). + // 2m long tubing to cap = 19.5 mL (acid line) + 7.92 mL/m * 2 m (tubing to cap) + 20.82 mL (straw) = 56.15 mL // Prime time in seconds = ( 56.15 mL / 48 mL/min ) x 60 second/min + 25 seconds margin time = 95 seconds. #define PRIME_CONCENTRATE_LINES_TIME_OUT_MS ( 95 * MS_PER_SECOND ) ///< Time required to prime the concentrate lines. @@ -113,7 +116,7 @@ static U32 flushBubblesStartTime; ///< Starting time for flush bubbles. static U32 concentratePumpPrimeCount; ///< Interval count for concentrate pump prime. -static F32 integratedVolumeML; ///< Total RO flow rate over period of time. +static BOOL didFMPCheckStart; ///< Flag indicates whether FMP flow vs. LC volume check has begun. static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. static F32 bicarbConductivityTotal; ///< Total of bicarb conductivity during fill. static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. @@ -134,6 +137,7 @@ 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, FILL_MODE_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish fill mode data to CAN bus. +static OVERRIDE_F32_T integratedVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< Total RO flow rate over period of time. // ********** private function prototypes ********** @@ -169,7 +173,8 @@ dialysateFillStartTime = 0; dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; reservoirBaseWeight = 0.0F; - integratedVolumeML = 0.0F; + integratedVolumeML.data = 0.0F; + didFMPCheckStart = FALSE; concentrateTestStartTime = 0; acidConductivityTotal = 0.0F; bicarbConductivityTotal = 0.0F; @@ -228,6 +233,7 @@ { checkRORejectionRatio(); checkDialysateTemperatureSensors(); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); fillState = ( TRUE == areInletWaterConditionsAlarmsActive() ? DG_FILL_MODE_STATE_PAUSED : fillState ); @@ -322,6 +328,20 @@ /*********************************************************************//** * @brief + * The getIntegratedVolumeML function returns the integrated volume in mL + * @details Inputs: integratedVolumeML + * @details Outputs: integrated volume + * @return integrated volume + *************************************************************************/ +F32 getIntegratedVolumeML( void ) +{ + + F32 integratedVolume = getF32OverrideValue(&integratedVolumeML); + return integratedVolume; +} + +/*********************************************************************//** + * @brief * The resetFillStatusParameters function resets the fill status parameters. * @details Inputs: none * @details Outputs: fillStatus @@ -707,8 +727,8 @@ { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - reservoirBaseWeight = getReservoirWeight( getInactiveReservoir() ); dialysateFillStartTime = getMSTimerCount(); + fillStatus.isThisFirstFill = FALSE; result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; } @@ -727,14 +747,22 @@ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { DG_ACID_CONCENTRATES_RECORD_T acid; - F32 acidMix; DG_BICARB_CONCENTRATES_RECORD_T bicarb; - F32 bicarbMix; - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; - DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 acidMix = 0.0F; + F32 bicarbMix = 0.0F; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + DG_RESERVOIR_ID_T inactiveRsrvr = getInactiveReservoir(); + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); // TODO the systems team will let us know when we can use TD2 in DVT. Until then it is disabled + F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); //getTemperatureValue( (U32)TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); +#ifndef _RELEASE_ + if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) + { + inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + } +#endif + getAcidConcentrateCalRecord( &acid ); getBicarbConcentrateCalRecord( &bicarb ); @@ -744,7 +772,18 @@ // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); - integratedVolumeML += getMeasuredROFlowRateWithConcPumpsLPM() * ML_PER_LITER * FLOW_INTEGRATOR; + // Delay start of FMP check, then begin integrating flow to a volume + if ( TRUE == didTimeout( dialysateFillStartTime, DELAY_FMP_CHECK_START_BY_MS ) ) + { + if ( FALSE == didFMPCheckStart ) + { // When FMP check starts, set baseline weight of reservoir we are filling + didFMPCheckStart = TRUE; + reservoirBaseWeight = getReservoirWeight( getInactiveReservoir() ); + } + + integratedVolumeML.data += getMeasuredROFlowRateWithConcPumpsLPM() * ML_PER_LITER * FLOW_INTEGRATOR; + } + usedAcidVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; usedBicarbVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; acidConductivityTotal += acidConductivity; @@ -754,7 +793,7 @@ // DG is delivering dialysate keep collecting the sample counter and the measured flow fillStatus.fillSampleCounter += 1; fillStatus.fillFlowRateRunningSum += getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); - fillStatus.fillTemperatureRunningSum += getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + fillStatus.fillTemperatureRunningSum += inletTemperature; // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir @@ -764,10 +803,10 @@ } // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode // SRSDG 398 - if ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) + if ( TRUE == hasTargetFillVolumeBeenReached( inactiveRsrvr ) ) { - F32 filledVolumeML = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; - F32 integratedVolumeToLoadCellReadingPercent = fabs( 1.0F - ( filledVolumeML / integratedVolumeML ) ); + F32 filledVolumeML = getReservoirWeight( inactiveRsrvr ) - reservoirBaseWeight; + F32 integratedVolumeToLoadCellReadingPercent = fabs( 1.0F - ( filledVolumeML / getIntegratedVolumeML() ) ); F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; F32 avgBicarbConductivity = bicarbConductivityTotal / conductivitySampleCount; F32 acidNormalConductivity = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConductivityUSPerCM; @@ -779,7 +818,7 @@ { if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) // SRSDG 240 { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolumeML, integratedVolumeML ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolumeML, getIntegratedVolumeML() ); } } @@ -815,7 +854,7 @@ fillStatus.fillFlowRateRunningSum = 0.0F; fillStatus.fillTemperatureRunningSum = 0.0F; fillStatus.fillSampleCounter = 0; - fillStatus.fillLastTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + fillStatus.fillLastTemperature = inletTemperature; calculateHeaterEstimationGain( DG_PRIMARY_HEATER ); requestNewOperationMode( DG_MODE_GENE ); @@ -982,8 +1021,8 @@ * @brief * The publishFillModeData function publishes fill mode data * at the set interval. - * @details Inputs: fillModeDataPublicationTimerCounter - * @details Outputs: fillModeDataPublicationTimerCounter + * @details Inputs: fillModeDataPublicationTimerCounter, fillModeDataPublishInterval + * @details Outputs: fillModeData * @return none *************************************************************************/ static void publishFillModeData( void ) @@ -1000,7 +1039,7 @@ fillModeData.pctDiffInConductivity = pctDiffInConductivity; fillModeData.usedAcidVolumeML = getChemicalUsedVolumeML( ACID ); fillModeData.usedBicarbVolumeML = getChemicalUsedVolumeML( BICARB ); - fillModeData.integratedVolumeML = integratedVolumeML; + fillModeData.integratedVolumeML = getIntegratedVolumeML(); broadcastData( MSG_ID_DG_FILL_MODE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&fillModeData, sizeof( DG_FILL_MODE_DATA_T ) ); @@ -1156,4 +1195,49 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetIntegratedVolumeOverride function overrides the + * integrated volume. + * @details Inputs: value + * @details Outputs: integratedVolumeML + * @param: value integrated volume in mL + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetIntegratedVolumeOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + integratedVolumeML.ovData = value; + integratedVolumeML.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetIntegratedVolumeOverride function resets the + * override of integrated volume. + * @details Inputs: none + * @details Outputs: integratedVolumeML + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetIntegratedVolumeOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + integratedVolumeML.override = OVERRIDE_RESET; + integratedVolumeML.ovData = integratedVolumeML.ovInitData; + result = TRUE; + } + + return result; +} + /**@}*/