Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r1aeab08c1baf6445514b81fe51fc60a3e536e782 -reeb4e9c7c8ca2bc41168353c3d30f311080972b2 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 1aeab08c1baf6445514b81fe51fc60a3e536e782) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision eeb4e9c7c8ca2bc41168353c3d30f311080972b2) @@ -15,6 +15,8 @@ * ***************************************************************************/ +#include // For fabs + #include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "FPGA.h" @@ -43,7 +45,6 @@ // ********** private definitions ********** #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. -#define TARGET_RO_FLOW_RATE_L 0.8 ///< Target flow rate for RO pump. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. #define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. @@ -58,6 +59,8 @@ #define WATER_QUALITY_CHECK_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality check time out period in ms. #define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. +#define DIALYSATE_TEMPERATURE_SENSORS_MAX_DRIFT_C 2.0 ///< Dialysate temperature sensors maximum allowed drift in C. +#define DIALYSATE_TEMPERATURE_SENSORS_DRIFT_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. #define ACID_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of acid concentration in ml. #define BICARB_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of bicarb concentration in ml. @@ -71,30 +74,31 @@ /// Fill conditions status typedef struct { - F32 fillFlowRateRunningSum; ///< Fill flow running sum. - U32 fillSampleCounter; ///< Fill flow sample counter. - F32 fillTemperatureRunningSum; ///< Fill temperature running sum. - F32 fillTemperatureAverage; ///< Fill temperature average value. - F32 fillFlowRateAverage; ///< Fill flow average value. - F32 fillLastTemperature; ///< Fill last temperature value. + F32 fillFlowRateRunningSum; ///< Fill flow running sum. + U32 fillSampleCounter; ///< Fill flow sample counter. + F32 fillTemperatureRunningSum; ///< Fill temperature running sum. + F32 fillTemperatureAverage; ///< Fill temperature average value. + F32 fillFlowRateAverage; ///< Fill flow average value. + F32 fillLastTemperature; ///< Fill last temperature value. + BOOL isThisFirstFill; ///< Fill flag to indicate whether it is the first fill or not. } FILL_CONDITION_STATUS_T; -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 FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. +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 FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. -static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. -static U32 concentrateTestStartTime; ///< Starting time for concentrate test. -static U32 concentratePumpPrimeCount; ///< Interval count for concentrate pump prime. +static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. +static U32 concentrateTestStartTime; ///< Starting time for concentrate test. +static U32 concentratePumpPrimeCount; ///< Interval count for concentrate pump prime. -static F32 totalROFlowRate_mL_min; ///< Total RO flow rate over period of time. -static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. -static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. -static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. +static F32 totalROFlowRateMLPM; ///< Total RO flow rate over period of time. +static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. +static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. +static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. -static OVERRIDE_F32_T usedAcidVolume_mL = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in ml. -static OVERRIDE_F32_T usedBicarbVolume_mL = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in ml. +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. // ********** private function prototypes ********** @@ -106,6 +110,7 @@ static DG_FILL_MODE_STATE_T handlePausedState( void ); static BOOL isWaterQualityGood( void ); +static void checkDialysateTemperatureSensorsDrift( void ); static BOOL checkDialysateTemperature( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); static void setFillInfoToRTCRAM( void ); @@ -114,31 +119,27 @@ * @brief * The initFillMode function initializes the fill mode module. * @details Inputs: none - * @details Outputs: Fill mode module initialized + * @details Outputs: fillState, dialysateFillStartTime, reservoirBaseWeight, + * totalROFlowRateMLPM, concentrateTestStartTime, acidConductivityTotal, + * dialysateConductivityTotal, conductivitySampleCount, + * concentratePumpPrimeCount * @return none *************************************************************************/ void initFillMode( void ) { - fillState = DG_FILL_MODE_STATE_START; - dialysateFillStartTime = 0; - reservoirBaseWeight = 0.0; - totalROFlowRate_mL_min = 0.0; - concentrateTestStartTime = 0; - acidConductivityTotal = 0.0; - dialysateConductivityTotal = 0.0; - conductivitySampleCount = 0; - concentratePumpPrimeCount = 0; - // Get the heaters info form the NV data management - DG_HEATERS_RECORD_T heaterInfo = getHeatersInfoReocrd(); - // If the data in the NV data management was not initialized properly, set it to 0 otherwise, set the average flow rate - fillStatus.fillFlowRateAverage = ( heaterInfo.averageFillFlow < NEARLY_ZERO ? 0.0 : heaterInfo.averageFillFlow ); - fillStatus.fillFlowRateRunningSum = 0.0; - fillStatus.fillSampleCounter = 0; - fillStatus.fillTemperatureRunningSum = 0.0; - fillStatus.fillTemperatureAverage = 0.0; + fillState = DG_FILL_MODE_STATE_START; + dialysateFillStartTime = 0; + reservoirBaseWeight = 0.0; + totalROFlowRateMLPM = 0.0; + concentrateTestStartTime = 0; + acidConductivityTotal = 0.0; + dialysateConductivityTotal = 0.0; + conductivitySampleCount = 0; + concentratePumpPrimeCount = 0; initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); initPersistentAlarm( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); + initPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_DRFIT_TIMEOUT, 0, DIALYSATE_TEMPERATURE_SENSORS_DRIFT_TIMEOUT_MS ); } /*********************************************************************//** @@ -153,7 +154,7 @@ DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); initFillMode(); - reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); + reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); dialysateFillStartTime = getMSTimerCount(); // Set initial actuator states @@ -167,8 +168,9 @@ // 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 - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( getTargetFillFlowRateLPM(), TARGET_RO_PRESSURE_PSI ); #endif + setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); startHeater( DG_PRIMARY_HEATER ); return fillState; @@ -188,6 +190,7 @@ checkInletWaterTemperature(); checkInletPressure(); checkRORejectionRatio(); + checkDialysateTemperatureSensorsDrift(); // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir @@ -279,6 +282,46 @@ /*********************************************************************//** * @brief + * The resetFillStatusParameters function resets the fill status parameters. + * @details Inputs: none + * @details Outputs: fillStatus + * @return none + *************************************************************************/ +void resetFillStatusParameters( void ) +{ + DG_HEATERS_RECORD_T heaterInfo; + // There is no number of NV data to check for the heaters info so it is passed as 0 + U08 numOfNVData2Check = 0; + // Get the heaters info from the NV data management. Do not alarm on the status of the data since it has already been checked in NV POST + getNVRecord2Driver( GET_INF_HEATERS_RECORD, (U08*)&heaterInfo, sizeof( DG_HEATERS_RECORD_T ), numOfNVData2Check, ALARM_ID_NO_ALARM ); + + // If the data in the NV data management was not initialized properly, set it to 0 otherwise, set the average flow rate + fillStatus.fillFlowRateAverage = ( heaterInfo.averageFillFlow < NEARLY_ZERO ? 0.0 : heaterInfo.averageFillFlow ); + fillStatus.fillFlowRateRunningSum = 0.0; + fillStatus.fillSampleCounter = 0; + fillStatus.fillTemperatureRunningSum = 0.0; + // At the beginning the last and average temperatures are considered as the trimmer heater target temperature which + // is the dialysate temperature + fillStatus.fillTemperatureAverage = getHeaterTargetTemperature( DG_TRIMMER_HEATER ); + fillStatus.fillLastTemperature = getHeaterTargetTemperature( DG_TRIMMER_HEATER ) + RESERVOIR_EXTRA_TEMPERATURE; + fillStatus.isThisFirstFill = TRUE; +} + +/*********************************************************************//** + * @brief + * The isThisTheFirstFill function returns the boolean flag that indicates + * whether this is the first fill of a treatment or not. + * @details Inputs: none + * @details Outputs: none + * @return fillStatus.isThisFirstFill + *************************************************************************/ +BOOL isThisTheFirstFill( void ) +{ + return fillStatus.isThisFirstFill; +} + +/*********************************************************************//** + * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -293,13 +336,24 @@ if ( TRUE == isWaterQualityGood() ) #endif { - concentrateTestStartTime = getMSTimerCount(); -#ifndef DISABLE_MIXING - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); -#endif - result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + // If this is the first fill of a treatment, prime and acid and bicarb lines, otherwise transition + // to dialysate production directly + if ( TRUE == isThisTheFirstFill() ) + { + concentrateTestStartTime = getMSTimerCount(); + #ifndef DISABLE_MIXING + + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + #endif + result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + } + else + { + result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + } + } if ( TRUE == didTimeout( waterQualityCheckStartTime, WATER_QUALITY_CHECK_TIME_OUT_MS ) ) @@ -322,28 +376,30 @@ static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); - F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 bicarbPumpFlowRate_mL_min = measuredROFlowRate_mL_min * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio + - CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; + F32 bicarbPumpFlowRateMLPM = measuredROFlowRateMLPM * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio + + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + #ifndef DISABLE_DIALYSATE_CHECK - F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); #else - F32 const bicarbConductivity = MAX_BICARB_CONCENTRATE_CONDUCTIVITY; + F32 bicarbConductivity = MAX_BICARB_CONCENTRATE_CONDUCTIVITY; #endif - bicarbPumpFlowRate_mL_min = MIN( bicarbPumpFlowRate_mL_min, CONCENTRATE_PUMP_MAX_SPEED ); + bicarbPumpFlowRateMLPM = MIN( bicarbPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); - if ( MIN_BICARB_CONCENTRATE_CONDUCTIVITY <= bicarbConductivity ) + if ( bicarbConductivity >= MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) { // Reduce acid pump speed after reaching minimum conductivity // This prevents conductivity value to go out of sensor's range - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbPumpFlowRate_mL_min ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbPumpFlowRateMLPM ); if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) { concentratePumpPrimeCount = 0; - concentrateTestStartTime = getMSTimerCount(); + concentrateTestStartTime = getMSTimerCount(); #ifndef DISABLE_MIXING setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); @@ -377,29 +433,31 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); - F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + + F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; + F32 acidPumpFlowRateMLPM = measuredROFlowRateMLPM * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; #ifndef DISABLE_DIALYSATE_CHECK - F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); #else - F32 const acidConductivity = MAX_ACID_CONCENTRATE_CONDUCTIVITY; + F32 acidConductivity = MAX_ACID_CONCENTRATE_CONDUCTIVITY; #endif - acidPumpFlowRate_mL_min = MIN( acidPumpFlowRate_mL_min, CONCENTRATE_PUMP_MAX_SPEED ); + acidPumpFlowRateMLPM = MIN( acidPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); - if ( MIN_ACID_CONCENTRATE_CONDUCTIVITY <= acidConductivity ) + if ( acidConductivity >= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) { // Reduce acid pump speed after reaching minimum conductivity // This prevents conductivity value to go out of sensor's range - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidPumpFlowRate_mL_min ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidPumpFlowRateMLPM ); if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) { - concentratePumpPrimeCount = 0; + concentratePumpPrimeCount = 0; + fillStatus.isThisFirstFill = FALSE; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; @@ -429,8 +487,8 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; - F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; #ifndef DISABLE_DIALYSATE_CHECK if ( ( TRUE == isWaterQualityGood() ) && ( TRUE == checkDialysateTemperature() ) ) @@ -439,7 +497,7 @@ #endif { // Prime mixing before deliver result to reservoir - handleDialysateMixing( measuredROFlowRate_mL_min ); + handleDialysateMixing( measuredROFlowRateMLPM ); #ifndef DISABLE_MIXING requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); @@ -471,31 +529,34 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { - F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - F32 const dialysateConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL const isAcidConductivityOutOfRange = ( acidConductivity <= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) || ( acidConductivity >= MAX_ACID_CONCENTRATE_CONDUCTIVITY ); - BOOL const isDialysateConductivityOutOfRange = ( dialysateConductivity <= MIN_DIALYSATE_CONDUCTIVITY ) || ( dialysateConductivity >= MAX_DIALYSATE_CONDUCTIVITY ); + F32 integratedVolumeML; - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 dialysateConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + BOOL isAcidConductivityOutOfRange = ( acidConductivity <= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) || + ( acidConductivity >= MAX_ACID_CONCENTRATE_CONDUCTIVITY ) ? TRUE : FALSE; + BOOL isDialysateConductivityOutOfRange = ( dialysateConductivity <= MIN_DIALYSATE_CONDUCTIVITY ) || + ( dialysateConductivity >= MAX_DIALYSATE_CONDUCTIVITY ) ? TRUE : FALSE; + + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - F32 integratedVolume_mL; // Set concentrate pumps speed based off RO pump flow rate - handleDialysateMixing( measuredROFlowRate_mL_min ); + handleDialysateMixing( measuredROFlowRateMLPM ); - totalROFlowRate_mL_min += measuredROFlowRate_mL_min; - integratedVolume_mL = totalROFlowRate_mL_min * FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER; - usedAcidVolume_mL.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; - usedBicarbVolume_mL.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; + totalROFlowRateMLPM += measuredROFlowRateMLPM; + integratedVolumeML = totalROFlowRateMLPM * FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER; + usedAcidVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; + usedBicarbVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; acidConductivityTotal += acidConductivity; dialysateConductivityTotal += dialysateConductivity; conductivitySampleCount++; // DG is delivering dialysate keep collecting the sample counter and the measured flow fillStatus.fillSampleCounter += 1; - fillStatus.fillFlowRateRunningSum += getMeasuredROFlowRate(); + fillStatus.fillFlowRateRunningSum += getMeasuredROFlowRateLPM(); fillStatus.fillTemperatureRunningSum += getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); #ifndef DISABLE_DIALYSATE_CHECK @@ -509,7 +570,7 @@ if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, isAcidConductivityOutOfRange ) ) { - usedAcidVolume_mL.data = 0.0; + usedAcidVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); @@ -518,36 +579,36 @@ if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, isDialysateConductivityOutOfRange ) ) { - usedBicarbVolume_mL.data = 0.0; + usedBicarbVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); result = DG_FILL_MODE_STATE_PAUSED; } #endif #ifndef DISABLE_MIXING - if ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolume_mL ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) + if ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) { activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); } - if ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolume_mL ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) + if ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) { activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); } #endif // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode if ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) { - F32 const filledVolume_mL = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; - F32 const integratedVolumeToLoadCellReadingPercent = fabs( 1 - ( filledVolume_mL / integratedVolume_mL ) ); - F32 const avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; // TODO - should we be checking this below? - F32 const avgDialysateConductivity = dialysateConductivityTotal / conductivitySampleCount; + F32 filledVolumeML = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; + F32 integratedVolumeToLoadCellReadingPercent = fabs( 1 - ( filledVolumeML / integratedVolumeML ) ); + F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; // TODO - should we be checking this below? + F32 avgDialysateConductivity = dialysateConductivityTotal / conductivitySampleCount; if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) { #ifndef DISABLE_FLOW_CHECK_IN_FILL - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolume_mL, integratedVolume_mL ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolumeML, integratedVolumeML ); #endif } @@ -559,16 +620,17 @@ #endif // Done with this fill. Calculate the average fill flow rate and average temperature - fillStatus.fillFlowRateAverage = fillStatus.fillFlowRateRunningSum / (F32)fillStatus.fillSampleCounter; - fillStatus.fillTemperatureAverage = fillStatus.fillTemperatureRunningSum / (F32)fillStatus.fillSampleCounter; // Reset the variables for the next fill + // Get the last fill temperature before leaving to Generation Idle + fillStatus.fillFlowRateAverage = fillStatus.fillFlowRateRunningSum / (F32)fillStatus.fillSampleCounter; + fillStatus.fillTemperatureAverage = fillStatus.fillTemperatureRunningSum / (F32)fillStatus.fillSampleCounter; fillStatus.fillFlowRateRunningSum = 0.0; fillStatus.fillTemperatureRunningSum = 0.0; fillStatus.fillSampleCounter = 1; - // Get the last fill temperature before leaving to Generation Idle fillStatus.fillLastTemperature = getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); // Write the latest fill data into the RTC RAM for heaters control + // TODO test this and make sure it is writing it correctly setFillInfoToRTCRAM(); requestNewOperationMode( DG_MODE_GENE ); @@ -607,16 +669,43 @@ *************************************************************************/ static BOOL isWaterQualityGood( void ) { - BOOL const isInletPressureGood = !isAlarmActive( ALARM_ID_INLET_WATER_LOW_PRESSURE ); - 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 ) && - !isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ); + BOOL isInletPressureGood = ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_PRESSURE ) ? FALSE : TRUE ); - return ( ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ) ? TRUE : FALSE ); + BOOL isWaterTemperatureGood = ( ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE ) && + FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ) ) ? FALSE : TRUE ); + + BOOL isWaterConductivityGood = ( ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY ) && + FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY ) && + FALSE == isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ) ) ? FALSE : TRUE ); + + return ( ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ) ); } /*********************************************************************//** * @brief + * The checkDialysateTemperatureSensorsDrift 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 checkDialysateTemperatureSensorsDrift( void ) +{ +#ifndef THD_USING_TRO_CONNECTOR // Do not use until TRo is back in line + F32 TDi = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); + F32 TRo = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); + BOOL isDriftOut = ( fabs( TDi - TRo ) >= DIALYSATE_TEMPERATURE_SENSORS_MAX_DRIFT_C ? TRUE : FALSE ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_DRFIT_TIMEOUT, isDriftOut ) ) + { + activateAlarmNoData( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_DRFIT_TIMEOUT ); + } +#endif +} + +/*********************************************************************//** + * @brief * The checkDialysateTemperature function checks dialysate temperature after * it gets heated up by primary heater. * @details Inputs: TPo temperature value @@ -626,7 +715,7 @@ static BOOL checkDialysateTemperature( void ) { F32 dialysateTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 targetTemp = getHeaterTargetTemperature( DG_PRIMARY_HEATER ); + F32 targetTemp = getHeaterTargetTemperature( DG_PRIMARY_HEATER ); return ( ( fabs( dialysateTemp - targetTemp ) <= DIALYSATE_TEMPERATURE_TOLERANCE_C ) ? TRUE : FALSE ); } @@ -648,9 +737,13 @@ DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); // Set concentrate pumps speed based off RO pump flow rate - F32 const acidCP1PumpFlowRate = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio * measuredROFlowRate_mL_min; - F32 const bicarbCP2PumpFlowRate = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio * measuredROFlowRate_mL_min; + F32 acidCP1PumpFlowRate = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio * measuredROFlowRate_mL_min; + F32 bicarbCP2PumpFlowRate = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio * measuredROFlowRate_mL_min; + // Cap to the maximum allowed concentrate pumps rate + acidCP1PumpFlowRate = MIN( acidCP1PumpFlowRate, CONCENTRATE_PUMP_MAX_SPEED ); + bicarbCP2PumpFlowRate = MIN( bicarbCP2PumpFlowRate, CONCENTRATE_PUMP_MAX_SPEED ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidCP1PumpFlowRate ); setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbCP2PumpFlowRate ); #endif @@ -673,11 +766,4 @@ setHeatersInfoRecord( (U08*)&record ); } - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ - - - /**@}*/