Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -re86977b0f96c69973e9f5f90041aa466a89266af -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision e86977b0f96c69973e9f5f90041aa466a89266af) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2023 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) 11-Nov-2022 +* @date (last) 21-Dec-2022 * * @author (original) Leonardo Baloa * @date (original) 19-Nov-2019 @@ -74,13 +74,14 @@ #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). +#define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. +#define MAX_CPO_CONDUCTIVITY_ALLOW 100.0F ///< Maximum CPo sensor conductivity value. + // 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. #define FLUSH_BUBBLES_PUMP_TIME_OUT_MS ( 2 * MS_PER_SECOND ) ///< RO pump on during flush bubble interval in ms. #define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0F ///< Dialysate temperature tolerance in degree C. -#define DIALYSATE_TEMPERATURE_SENSORS_MAX_DEVIATION_C 1.0F ///< Dialysate temperature sensors maximum allowed deviation in C. -#define DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 63 ///< Data publish counter start count. /// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. @@ -131,6 +132,10 @@ static F32 totalBicarbConductivity; ///< Total bicarb conductivity over 30 seconds. static F32 totalAcidConductivity; ///< Total acid conductivity over 30 seconds. +static F32 sumFillCPoConductivity; ///< Sum of CPo conductivity readings over course of a fill to calculate an average at end of fill. +static F32 sumFillRejRatio; ///< Sum of Rejection Ratio values over course of a fill to calculate an average at end of fill. +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 OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. @@ -151,7 +156,6 @@ static DG_FILL_MODE_STATE_T handlePausedState( void ); static BOOL areInletWaterConditionsAlarmsActive( void ); -static void checkDialysateTemperatureSensors( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min, F32 acidMixingRatio, F32 bicarbMixingRatio ); static void setFillInfoToRTCRAM( void ); static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ); @@ -189,8 +193,9 @@ totalBicarbConductivity = 0.0F; totalAcidConductivity = 0.0F; havePauseActuatorsBeenSet = FALSE; - - initPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, 0, DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ); + sumFillCPoConductivity = 0.0F; + sumFillRejRatio = 0.0F; + fillCPoConductivitySampleCnt = 0; } /*********************************************************************//** @@ -231,7 +236,6 @@ *************************************************************************/ U32 execFillMode( void ) { - checkRORejectionRatio(); checkDialysateTemperatureSensors(); setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); @@ -329,7 +333,7 @@ /*********************************************************************//** * @brief * The getIntegratedVolumeML function returns the integrated volume in mL - * @details Inputs: none + * @details Inputs: integratedVolumeML * @details Outputs: integrated volume * @return integrated volume *************************************************************************/ @@ -402,8 +406,6 @@ return volume; } - - /*********************************************************************//** * @brief * The resetChemicalUsedVolumeML function resets the used volume of a chemical @@ -507,8 +509,8 @@ if ( TRUE == didTimeout( concentratePrimingStartTime, PRIME_CONCENTRATE_LINES_TIME_OUT_MS ) ) { - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // Set the RO pump flow rate in according to the roPumpFlushBubblesSpeed table to flush bubbles pumpSpeedIndex = 0; @@ -601,7 +603,7 @@ if ( TRUE == isConductivityInRange ) { // Initialization - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); totalBicarbConductivity = 0.0F; totalAcidConductivity = 0.0F; bicarbConductivitySampleCount = 0; @@ -729,10 +731,10 @@ { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - dialysateFillStartTime = getMSTimerCount(); + dialysateFillStartTime = getMSTimerCount(); - fillStatus.isThisFirstFill = FALSE; - result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + fillStatus.isThisFirstFill = FALSE; + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; } return result; @@ -755,11 +757,15 @@ 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 ); + F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); + F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 rejRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; // default 1:1 before calculation in case can't divide by zero. #ifndef _RELEASE_ - if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) + if ( ( HW_CONFIG_BETA == getHardwareConfigStatus() ) || + ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_USING_TPO_FOR_PRIMARY_HEATER_CONTROL ) ) ) { inletTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); } @@ -774,6 +780,15 @@ // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); + // Sum conductivity readings for CPo and RR checks + if ( fabs(cpi) >= NEARLY_ZERO ) + { + rejRatio = cpo / cpi; + } + sumFillCPoConductivity += cpo; + sumFillRejRatio += rejRatio; + fillCPoConductivitySampleCnt++; + // Delay start of FMP check, then begin integrating flow to a volume if ( TRUE == didTimeout( dialysateFillStartTime, DELAY_FMP_CHECK_START_BY_MS ) ) { @@ -814,7 +829,28 @@ F32 acidNormalConductivity = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConductivityUSPerCM; F32 bicarbNormalConductivity = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConductivityUSPerCM; + // Check RO filter #ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + F32 avgCPo = sumFillCPoConductivity / (F32)fillCPoConductivitySampleCnt; // sample count incremented above w/o condition so no need for divide by zero checks + F32 avgRR = sumFillRejRatio / (F32)fillCPoConductivitySampleCnt; + + if ( avgCPo > MAX_CPO_CONDUCTIVITY_ALLOW ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, avgCPo, MAX_CPO_CONDUCTIVITY_ALLOW ); + } + if ( avgRR > MAX_RO_REJECTION_RATIO_ALLOW ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, avgRR, MAX_RO_REJECTION_RATIO_ALLOW ); + } + } + + // Check FMP vs. LC +#ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_FLOW_VS_LOAD_CELL_CHECK_IN_FILL ) != SW_CONFIG_ENABLE_VALUE ) #endif { @@ -824,6 +860,7 @@ } } + // Check mixing via avg. conductivities #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MIXING_IN_FILL ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -881,8 +918,8 @@ { setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_IN_PAUSE_L, TARGET_RO_PRESSURE_PSI ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); havePauseActuatorsBeenSet = TRUE; } @@ -913,10 +950,12 @@ checkInletWaterPressure(); // Check if any of the alarms are active - if ( ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) || - ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) || + if ( ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE ) ) || + ( TRUE == isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ) ) || ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_PRESSURE_IN_LOW_RANGE ) ) ) { status = TRUE; @@ -927,30 +966,6 @@ /*********************************************************************//** * @brief - * The checkDialysateTemperatureSensors function checks whether the - * dialysate temperature sensors have drifted. If they are drifted, it raises - * an alarm. - * @details Inputs: none - * @details Outputs: None - * @return none - *************************************************************************/ -static void checkDialysateTemperatureSensors( void ) -{ - F32 TDi = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - F32 TRo = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); - BOOL isDriftOut = ( fabs( TDi - TRo ) >= DIALYSATE_TEMPERATURE_SENSORS_MAX_DEVIATION_C ? TRUE : FALSE ); - -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - checkPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, isDriftOut, fabs( TDi - TRo ), - DIALYSATE_TEMPERATURE_SENSORS_MAX_DEVIATION_C ); - } -} - -/*********************************************************************//** - * @brief * The isValueWithinPercentRange function validates if the test value * is within the percentage range specified by the baseValue and * percentFactor. @@ -1023,8 +1038,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 ) @@ -1073,7 +1088,7 @@ usedAcidVolumeML.ovInitData = usedAcidVolumeML.data; usedAcidVolumeML.ovData = value; usedAcidVolumeML.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -1095,9 +1110,9 @@ { usedAcidVolumeML.data = usedAcidVolumeML.ovInitData; usedAcidVolumeML.override = OVERRIDE_RESET; - usedAcidVolumeML.ovInitData = 0.0; - usedAcidVolumeML.ovData = 0.0; - result = TRUE; + usedAcidVolumeML.ovInitData = 0.0F; + usedAcidVolumeML.ovData = 0.0F; + result = TRUE; } return result; @@ -1121,7 +1136,7 @@ usedBicarbVolumeML.ovInitData = usedBicarbVolumeML.data; usedBicarbVolumeML.ovData = value; usedBicarbVolumeML.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -1143,9 +1158,9 @@ { usedBicarbVolumeML.data = usedBicarbVolumeML.ovInitData; usedBicarbVolumeML.override = OVERRIDE_RESET; - usedBicarbVolumeML.ovInitData = 0.0; - usedBicarbVolumeML.ovData = 0.0; - result = TRUE; + usedBicarbVolumeML.ovInitData = 0.0F; + usedBicarbVolumeML.ovData = 0.0F; + result = TRUE; } return result; @@ -1166,10 +1181,10 @@ if ( TRUE == isTestingActivated() ) { - U32 intvl = value / TASK_GENERAL_INTERVAL; + U32 intvl = value / TASK_GENERAL_INTERVAL; fillModeDataPublishInterval.ovData = intvl; fillModeDataPublishInterval.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; @@ -1191,19 +1206,19 @@ { fillModeDataPublishInterval.override = OVERRIDE_RESET; fillModeDataPublishInterval.ovData = fillModeDataPublishInterval.ovInitData; - result = TRUE; + result = TRUE; } return result; } /*********************************************************************//** * @brief - * The testSetFillModeDataPublishIntervalOverride function overrides the - * fill mode data publish interval. - * @details Inputs: FillModeDataPublishInterval - * @details Outputs: FillModeDataPublishInterval - * @param: value override fill mode data publish interval with (in ms) + * 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 ) @@ -1214,18 +1229,18 @@ { integratedVolumeML.ovData = value; integratedVolumeML.override = OVERRIDE_KEY; - result = TRUE; + result = TRUE; } return result; } /*********************************************************************//** * @brief - * The testResetFillModeDataPublishIntervalOverride function resets the - * override of the fill mode data publish interval. - * @details Inputs: FillModeDataPublishInterval - * @details Outputs: FillModeDataPublishInterval + * 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 ) @@ -1236,7 +1251,7 @@ { integratedVolumeML.override = OVERRIDE_RESET; integratedVolumeML.ovData = integratedVolumeML.ovInitData; - result = TRUE; + result = TRUE; } return result;