Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rcea079b61dbd17b2ddaec99b1124248147d14e72 -r6190a4ad94521b74164f1e1fbd79ed359c7c27fb --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision cea079b61dbd17b2ddaec99b1124248147d14e72) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 6190a4ad94521b74164f1e1fbd79ed359c7c27fb) @@ -55,6 +55,10 @@ #define CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity error. +#define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. + +#define ONE_LITER_WEIGHT_GRAMS ( ML_PER_LITER ) ///< One liter weight in grams. + /// Multiplier to convert flow (L/min) into volume (mL) for period of general task interval. static const F32 RO_FLOW_INTEGRATOR = ( ( ML_PER_LITER * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); @@ -66,11 +70,14 @@ static F32 totalROFlowRate_LPM; ///< Total RO flow rate over period of time. static U32 concentrateTestStartTime; ///< Starting time for concentrate test. static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. +static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. +static U32 dialysateConductivitySampleCount; ///< Sample count of dialysate conductivity during fill. // ********** private function prototypes ********** static BOOL isWaterQualityGood( void ); static BOOL checkDialysateConductivity( void ); +static BOOL checkDialysateTemperature( void ); static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ); static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ); static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ); @@ -93,6 +100,8 @@ reservoirBaseWeight = 0.0; totalROFlowRate_LPM = 0.0; concentrateTestStartTime = 0; + dialysateConductivityTotal = 0.0; + dialysateConductivitySampleCount = 0; initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ); initPersistentAlarm( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ); @@ -241,6 +250,22 @@ /*********************************************************************//** * @brief + * The checkDialysateTemperature function checks dialysate temperature after + * it gets heated up by primary heater. + * @details Inputs: TPo temperature value + * @details Outputs: None + * @return TRUE if dialysate temperature is in range, otherwise FALSE + *************************************************************************/ +static BOOL checkDialysateTemperature( void ) +{ + F32 const dialysateTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + F32 const targetTemp = getPrimaryHeaterTargetTemperature(); + + return ( ( fabs( dialysateTemp - targetTemp ) <= DIALYSATE_TEMPERATURE_TOLERANCE_C ) ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -252,10 +277,8 @@ DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - BOOL isInletWaterReady = isWaterQualityGood(); - #ifndef DISABLE_DIALYSATE_CHECK - if ( isInletWaterReady ) + if ( TRUE == isWaterQualityGood() ) #endif { reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); @@ -353,9 +376,8 @@ handleDialysateMixing(); - // TODO - transition when temperature and mix is in range #ifndef DISABLE_DIALYSATE_CHECK - if ( TRUE == checkDialysateConductivity() ) + if ( ( TRUE == checkDialysateConductivity() ) && ( TRUE == checkDialysateTemperature() ) ) #endif { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); @@ -375,23 +397,39 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { + F32 avgDialysateConductivity; DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); + totalROFlowRate_LPM += getMeasuredROFlowRate(); + dialysateConductivityTotal += getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + dialysateConductivitySampleCount++; handleDialysateMixing(); - // TODO - transition back when temperature or mix out of range - if ( FALSE == checkDialysateConductivity() ) + if ( ( checkDialysateConductivity() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) { #ifndef DISABLE_DIALYSATE_CHECK setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; #endif } + if ( getReservoirWeight( inactiveReservoir ) >= ONE_LITER_WEIGHT_GRAMS ) + { + avgDialysateConductivity = dialysateConductivityTotal / dialysateConductivitySampleCount; + + if ( ( avgDialysateConductivity < MIN_DIALYSATE_CONDUCTIVITY ) || ( avgDialysateConductivity > MAX_DIALYSATE_CONDUCTIVITY ) ) + { +#ifndef DISABLE_DIALYSATE_CHECK + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgDialysateConductivity ); + requestNewOperationMode( DG_MODE_CIRC ); +#endif + } + } + // if we've reached our target fill to volume (by weight), we're done filling - go back to re-circ mode - if ( hasTargetFillVolumeBeenReached( inactiveReservoir ) ) + if ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) { F32 const filledVolume_mL = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; F32 const integratedVolume_mL = totalROFlowRate_LPM * RO_FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER;