Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -ra1452dc7f16d37db53930c3d73992098709d7915 -r622eebf6fb7f1c6c232ffd82bc072dd30a7b3f94 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision a1452dc7f16d37db53930c3d73992098709d7915) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 622eebf6fb7f1c6c232ffd82bc072dd30a7b3f94) @@ -21,6 +21,8 @@ #include "Heaters.h" #include "LoadCell.h" #include "ModeFill.h" +#include "NVDataMgmtDGRecords.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Pressures.h" @@ -40,41 +42,53 @@ // ********** 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 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. -///< Persistent time interval for concentrate pumps prime. -#define CONCENTRATE_PUMP_PRIME_INTERVAL ( 3 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) +#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. -#define ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER 1.06 ///< Acid and bicarbonate concentrates make up around 6% to total volume. -#define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1 ///< Flow integrated volume has 10% tolerance compare to load cell reading. +#define CONCENTRATE_PUMP_PRIME_INTERVAL ( 3 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Persistent time interval for concentrate pumps prime. -#define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0 ///< Concentrate pump additional speed during priming in mL/min. -#define CONCENTRATE_TEST_TIME_OUT_MS ( 45 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. -#define WATER_QUALITY_CHECK_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality check time out period in ms. +#define ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER 1.06 ///< Acid and bicarbonate concentrates make up around 6% to total volume. +#define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1 ///< Flow integrated volume has 10% tolerance compare to load cell reading. -#define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. +#define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0 ///< Concentrate pump additional speed during priming in mL/min. +#define CONCENTRATE_TEST_TIME_OUT_MS ( 45 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. +#define WATER_QUALITY_CHECK_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality check time out period in ms. -#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. -#define CONCENTRATION_BOTTLE_LOW_VOLUME_ML 100.0 ///< Concentration bottle low volume in ml. +#define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. +#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. +#define CONCENTRATION_BOTTLE_LOW_VOLUME_ML 100.0 ///< Concentration bottle low volume in ml. + /// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. static const F32 FLOW_INTEGRATOR = ( (F32)TASK_GENERAL_INTERVAL / (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); // ********** private data ********** +/// 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. +} 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 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 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. @@ -94,6 +108,7 @@ static BOOL isWaterQualityGood( void ); static BOOL checkDialysateTemperature( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); +static void setFillInfoToRTCRAM( void ); /*********************************************************************//** * @brief @@ -104,15 +119,23 @@ *************************************************************************/ 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; + 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; 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 ); @@ -125,7 +148,7 @@ * @details Outputs: Re-initialized fill mode * @return none *************************************************************************/ -void transitionToFillMode( void ) +U32 transitionToFillMode( void ) { DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); @@ -143,8 +166,12 @@ // NOTE: The target flow rate should be set prior to setting the start primary heater // 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 ); - startPrimaryHeater(); +#endif + startHeater( DG_PRIMARY_HEATER ); + + return fillState; } /*********************************************************************//** @@ -213,6 +240,45 @@ /*********************************************************************//** * @brief + * The getAvgFillFlowRate function returns the average fill flow rate in + * each fill. + * @details Inputs: none + * @details Outputs: fillFlowRateAverage + * @return average of the fill flow rate + *************************************************************************/ +F32 getAvgFillFlowRate( void ) +{ + return fillStatus.fillFlowRateAverage; +} + +/*********************************************************************//** + * @brief + * The getAverageFillTemperature function returns the average fill temperature + * in each fill. + * @details Inputs: none + * @details Outputs: fillTemperatureAverage + * @return average fill temperature + *************************************************************************/ +F32 getAvgFillTemperature( void ) +{ + return fillStatus.fillTemperatureAverage; +} + +/*********************************************************************//** + * @brief + * The getLastFillTemperature function returns the last fill temperature + * in each fill. + * @details Inputs: none + * @details Outputs: fillLastTemperature + * @return last fill temperature + *************************************************************************/ +F32 getLastFillTemperature( void ) +{ + return fillStatus.fillLastTemperature; +} + +/*********************************************************************//** + * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -310,11 +376,11 @@ *************************************************************************/ 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 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 const acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + - CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + F32 acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * 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 ); @@ -360,8 +426,8 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; - F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + F32 measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; #ifndef DISABLE_DIALYSATE_CHECK if ( ( TRUE == isWaterQualityGood() ) && ( TRUE == checkDialysateTemperature() ) ) @@ -413,15 +479,20 @@ // Set concentrate pumps speed based off RO pump flow rate handleDialysateMixing( measuredROFlowRate_mL_min ); - 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; + 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; - acidConductivityTotal += acidConductivity; + 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.fillTemperatureRunningSum += getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + #ifndef DISABLE_DIALYSATE_CHECK if ( ( isWaterQualityGood() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) { @@ -482,6 +553,19 @@ } #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 + 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 + setFillInfoToRTCRAM(); + requestNewOperationMode( DG_MODE_GENE ); } @@ -536,8 +620,8 @@ *************************************************************************/ static BOOL checkDialysateTemperature( void ) { - F32 const dialysateTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 const targetTemp = getPrimaryHeaterTargetTemperature(); + F32 dialysateTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + F32 targetTemp = getHeaterTargetTemperature( DG_PRIMARY_HEATER ); return ( ( fabs( dialysateTemp - targetTemp ) <= DIALYSATE_TEMPERATURE_TOLERANCE_C ) ? TRUE : FALSE ); } @@ -567,7 +651,24 @@ #endif } +/*********************************************************************//** + * @brief + * The setFillInfoToRTCRAM function writes the fill information to the RTC + * RAM at the end of each fill. This information is used for dialysate temperature + * control. + * @details Inputs: fillStatus.fillFlowRateAverage + * @details Outputs: none + * @return none + *************************************************************************/ +static void setFillInfoToRTCRAM( void ) +{ + DG_HEATERS_RECORD_T record; + record.averageFillFlow = fillStatus.fillFlowRateAverage; + setHeatersInfoRecord( (U08*)&record ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/