Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -r0c1f66a170a3a0a4324fa1a3c3bfb4c7f77139b5 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 0c1f66a170a3a0a4324fa1a3c3bfb4c7f77139b5) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -115,13 +115,13 @@ concentratePumpMonitorTimerCounter = 0; - concentratePumps[ CONCENTRATEPUMPS_CP1 ].control = &setFPGACP1Control; - concentratePumps[ CONCENTRATEPUMPS_CP1 ].setStepSpeed = &setFPGACP1SetStepSpeed; + concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].control = &setFPGACP1Control; + concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].setStepSpeed = &setFPGACP1SetStepSpeed; - concentratePumps[ CONCENTRATEPUMPS_CP2 ].control = &setFPGACP2Control; - concentratePumps[ CONCENTRATEPUMPS_CP2 ].setStepSpeed = &setFPGACP2SetStepSpeed; + concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].control = &setFPGACP2Control; + concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].setStepSpeed = &setFPGACP2SetStepSpeed; - for ( pumpId = CONCENTRATEPUMPS_CP1; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) + for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { concentratePumps[ pumpId ].controlTimerCounter = 0; concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; @@ -149,16 +149,16 @@ { CONCENTRATE_PUMP_DATA_T data; - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1, getFPGACP1HallSensePulseWidth() ); - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2, getFPGACP2HallSensePulseWidth() ); + calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); + calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2_BICARB, getFPGACP2HallSensePulseWidth() ); - data.cp1CurrentSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1 ].currentPumpSpeed; - data.cp1MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1 ); - data.cp2CurrentSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2 ].currentPumpSpeed; - data.cp2MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2 ); + data.cp1CurrentSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; + data.cp1MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + data.cp2CurrentSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; + data.cp2MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1 ) - concentratePumps[ CONCENTRATEPUMPS_CP1 ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1 ].currentPumpSpeed; - F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2 ) - concentratePumps[ CONCENTRATEPUMPS_CP2 ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2 ].currentPumpSpeed; + F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; + F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; #ifndef DISABLE_DIALYSATE_CHECK checkPersistentAlarm( ALARM_ID_CP1_SPEED_CONTROL_ERROR, cp1Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp1Error, CONCENTRATE_PUMP_ERROR_TOLERANCE ); @@ -181,7 +181,7 @@ { CONCENTRATE_PUMPS_T pumpId; - for ( pumpId = CONCENTRATEPUMPS_CP1; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) + for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { switch ( concentratePumps[ pumpId ].execState ) { Index: firmware/App/Controllers/ConcentratePumps.h =================================================================== diff -u -r2fea76e972a450a97c74b2a9f627095032a3b586 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision 2fea76e972a450a97c74b2a9f627095032a3b586) +++ firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -33,8 +33,8 @@ /// Enumeration of concentrate pumps. typedef enum ConcentratePumps { - CONCENTRATEPUMPS_CP1 = 0, ///< Acid concentrate pump - CONCENTRATEPUMPS_CP2, ///< Bicarbonate concentrate pump + CONCENTRATEPUMPS_CP1_ACID = 0, ///< Acid concentrate pump + CONCENTRATEPUMPS_CP2_BICARB, ///< Bicarbonate concentrate pump NUM_OF_CONCENTRATE_PUMPS ///< Number of concentrate pumps } CONCENTRATE_PUMPS_T; Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r2fea76e972a450a97c74b2a9f627095032a3b586 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 2fea76e972a450a97c74b2a9f627095032a3b586) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -35,33 +35,37 @@ #define COND_CPI_SENSOR_PROBE_TYPE 100 ///< 1 K cell constant conductivity probe. #define COND_CPO_SENSOR_PROBE_TYPE 10 ///< 0.1 K cell constant conductivity probe. + #define COND_SENSOR_DECIMAL_CONVERSION 100 ///< Conductivity value from FPGA has two decimal place. #define COND_SENSOR_TEMPERATURE_COEF 0.02 ///< Linear temperature coefficient of variation at 25 Celcius for fresh water. #define COND_SENSOR_REFERENCE_TEMPERATURE 25 ///< Reference temperature for conductivity sensor. #define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. -#define COND_SENSOR_CPI_CPO_MAX_VALUE 2000 ///< Maximum inlet water conductivity. -#define COND_SENSOR_CPI_CPO_MIN_VALUE 100 ///< Minimum inlet water conductivity. -#define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. +#define COND_SENSOR_CPI_MAX_VALUE 2000 ///< Maximum inlet water conductivity. +#define COND_SENSOR_CPI_MIN_VALUE 100 ///< Minimum inlet water conductivity. +#define MIN_ACID_CONCENTRATE_CONDUCTIVITY 11000 ///< Minimum conductivity for acid concentrate. +#define MAX_ACID_CONCENTRATE_CONDUCTIVITY 11850 ///< Maximum conductivity for acid concentrate. + +#define MIN_BICARB_CONCENTRATE_CONDUCTIVITY 2000 ///< Minimum conductivity for bicarbonate concentrate. +#define MAX_BICARB_CONCENTRATE_CONDUCTIVITY 3000 ///< Maximum conductivity for bicarbonate concentrate. + +///< Minimum conductivity value for dialysate solution. +#define MIN_DIALYSATE_CONDUCTIVITY ( MIN_ACID_CONCENTRATE_CONDUCTIVITY + MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) +///< Maximum conductivity value for dialysate solution. +#define MAX_DIALYSATE_CONDUCTIVITY ( MAX_ACID_CONCENTRATE_CONDUCTIVITY + MAX_BICARB_CONCENTRATE_CONDUCTIVITY ) + #define MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< New reading every 800 ms, expect to get valid new reading in 1s. #define MAX_CONDUCTIVITY_SENSOR_FAILURES 5 ///< maximum number of conductivity sensor errors within window period before alarm. #define MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ( 60 * MS_PER_SECOND ) ///< Conductivity sensor error window. #define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0 ///< Out of range value for RO rejection ratio when CPi conductivity is zero. #define MAX_RO_REJECTION_RATIO_ALLOW 0.1 ///< Maximum RO rejection ratio. #define MAX_CPO_CONDUCTIVITY_ALLOW 15.0 ///< Maximum CPo sensor conductivity value. + +#define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. #define RO_REJECTION_RATIO_PERSISTENCE_PERIOD ( 10 * MS_PER_SECOND ) ///< Persistence period for RO rejection ratio. -#define CONCENTRATE_POST_ACID_MIN_CONDUCTIVITY 11.0 ///< Minimum conductivity after adding acid. -#define CONCENTRATE_POST_ACID_MAX_CONDUCTIVITY 12.0 ///< Maximum conductivity after adding acid. - -#define CONCENTRATE_POST_BICARB_MIN_CONDUCTIVITY 13.0 ///< Minimum conductivity after adding bicarbonate. -#define CONCENTRATE_POST_BICARB_MAX_CONDUCTIVITY 14.0 ///< Maximum conductivity after adding bicarbonate. - -#define POST_ACID_CONDUCTIVITY_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for post-acid concentrate conductivity out of range. -#define POST_BICARB_CONDUCTIVITY_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for post-bicarb concentrate conductivity out of range. - #define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Measurement offset for emstat pico measurement data. #define EMSTAT_PICO_GOOD_STATUS 0x10 ///< Measurement good status. #define EMSTAT_PICO_FIFO_EMPTY_MASK 0x8000 ///< Emstat Pico buffer empty indication bit. @@ -144,8 +148,6 @@ initPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, RO_REJECTION_RATIO_PERSISTENCE_PERIOD, RO_REJECTION_RATIO_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_POST_ACID_CONDUCTIVITY_OUT_OF_RANGE, POST_ACID_CONDUCTIVITY_PERSISTENCE_PERIOD, POST_ACID_CONDUCTIVITY_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_POST_BICARB_CONDUCTIVITY_OUT_OF_RANGE, POST_ACID_CONDUCTIVITY_PERSISTENCE_PERIOD, POST_ACID_CONDUCTIVITY_PERSISTENCE_PERIOD ); } /*********************************************************************//** @@ -191,11 +193,11 @@ void checkInletWaterConductivity( void ) { F32 const conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - BOOL const isCondTooHigh = ( conductivity > COND_SENSOR_CPI_CPO_MAX_VALUE ); - BOOL const isCondTooLow = ( conductivity < COND_SENSOR_CPI_CPO_MIN_VALUE ); + BOOL const isCondTooHigh = ( conductivity > COND_SENSOR_CPI_MAX_VALUE ); + BOOL const isCondTooLow = ( conductivity < COND_SENSOR_CPI_MIN_VALUE ); - checkPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, isCondTooHigh, conductivity, COND_SENSOR_CPI_CPO_MAX_VALUE ); - checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, isCondTooLow, conductivity, COND_SENSOR_CPI_CPO_MIN_VALUE ); + checkPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, isCondTooHigh, conductivity, COND_SENSOR_CPI_MAX_VALUE ); + checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, isCondTooLow, conductivity, COND_SENSOR_CPI_MIN_VALUE ); } /*********************************************************************//** @@ -209,7 +211,7 @@ *************************************************************************/ void checkRORejectionRatio( void ) { -#ifndef DISABLE_DIALYSATE_CHECK +#ifndef DISABLE_RO_RATIO_CHECK F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); BOOL const isRORejectionRatioOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ) || ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ); @@ -219,28 +221,54 @@ /*********************************************************************//** * @brief - * The checkConcentrateConductivity function checks concentrate conductivity - * after adding acid and bicarbonate and triggers an alarm when conductivity - * is out of allowed range. - * @details Inputs: CD1 and CD2 sensor conductivity - * @details Outputs: Trigger alarms when conductivity is out of allowed range - * @return none + * The isAcidConductivityInRange function checks if acid conductivity value + * is in range. + * @details Inputs: CD1 sensor conductivity + * @details Outputs: none + * @return TRUE if acid conductivity is in range, otherwise FALSE *************************************************************************/ -void checkConcentrateConductivity( void ) +BOOL isAcidConductivityInRange( void ) { - F32 const postAcidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - F32 const postBicarbonateConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL const isPostAcidConductivityOutOfRange = ( postAcidConductivity <= CONCENTRATE_POST_ACID_MIN_CONDUCTIVITY ) || ( postAcidConductivity >= CONCENTRATE_POST_ACID_MAX_CONDUCTIVITY ); - BOOL const isPostBicarbConductivityOutOfRange = ( postBicarbonateConductivity <= CONCENTRATE_POST_BICARB_MIN_CONDUCTIVITY ) || ( postBicarbonateConductivity >= CONCENTRATE_POST_BICARB_MAX_CONDUCTIVITY ); + F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + BOOL const isConductivityInRange = ( MIN_ACID_CONCENTRATE_CONDUCTIVITY <= acidConductivity ) && ( acidConductivity <= MAX_ACID_CONCENTRATE_CONDUCTIVITY ); -#ifndef DISABLE_DIALYSATE_CHECK - checkPersistentAlarm( ALARM_ID_POST_ACID_CONDUCTIVITY_OUT_OF_RANGE, isPostAcidConductivityOutOfRange, postAcidConductivity, CONCENTRATE_POST_ACID_MIN_CONDUCTIVITY ); - checkPersistentAlarm( ALARM_ID_POST_BICARB_CONDUCTIVITY_OUT_OF_RANGE, isPostBicarbConductivityOutOfRange, postBicarbonateConductivity, CONCENTRATE_POST_BICARB_MIN_CONDUCTIVITY ); -#endif + return isConductivityInRange; } /*********************************************************************//** * @brief + * The isBicarbConductivityInRange function checks if bicarbonate conductivity + * value is in range. + * @details Inputs: CD2 sensor conductivity + * @details Outputs: none + * @return TRUE if bicarb conductivity is in range, otherwise FALSE + *************************************************************************/ +BOOL isBicarbConductivityInRange( void ) +{ + F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + BOOL const isConductivityInRange = ( MIN_BICARB_CONCENTRATE_CONDUCTIVITY <= bicarbConductivity ) && ( bicarbConductivity <= MAX_BICARB_CONCENTRATE_CONDUCTIVITY ); + + return isConductivityInRange; +} + +/*********************************************************************//** + * @brief + * The isDialysateConductivityInRange function checks if dialysate conductivity + * value is in range. + * @details Inputs: CD2 sensor conductivity + * @details Outputs: none + * @return TRUE if dialysate conductivity is in range, otherwise FALSE + *************************************************************************/ +BOOL isDialysateConductivityInRange( void ) +{ + F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + BOOL const isConductivityInRange = isAcidConductivityInRange() && ( MIN_DIALYSATE_CONDUCTIVITY <= bicarbConductivity ) && ( bicarbConductivity <= MAX_DIALYSATE_CONDUCTIVITY ); + + return isConductivityInRange; +} + +/*********************************************************************//** + * @brief * The getConductivityValue function gets the compensated conductivity * value for a given conductivity sensor id. * @details Inputs: compensatedConductivityValues[] Index: firmware/App/Controllers/ConductivitySensors.h =================================================================== diff -u -r62ee40b55ed96eb0de1c0f05455eb986f76c1842 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision 62ee40b55ed96eb0de1c0f05455eb986f76c1842) +++ firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -59,8 +59,11 @@ void checkInletWaterConductivity( void ); void checkRORejectionRatio( void ); -void checkConcentrateConductivity( void ); +BOOL isAcidConductivityInRange( void ); +BOOL isBicarbConductivityInRange( void ); +BOOL isDialysateConductivityInRange( void ); + F32 getConductivityValue( U32 sensorId ); BOOL testSetConductivityOverride( U32 sensorId, F32 value ); Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -rccf1219089b835ab2f9d401c0be0d2000be9010a -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision ccf1219089b835ab2f9d401c0be0d2000be9010a) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -53,7 +53,7 @@ #define SHIFT_BITS_BY_2_FOR_AVERAGING 2U ///< Shift the ADCs of the temperature sensors by 2 to average them. #define INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for temperature sensors out of range error period. -#define MIN_WATER_INPUT_TEMPERATURE 10U ///< Minimum water input temperature. +#define MIN_WATER_INPUT_TEMPERATURE 22U ///< Minimum water input temperature. #define MAX_WATER_INPUT_TEMPERATURE 35U ///< Maximum water input temperature. #define HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL 20U ///< Time interval that is used to calculate the heaters internal temperature. Index: firmware/App/DGCommon.h =================================================================== diff -u -r55425a4c5370a6fa1faad61dc24fcd76b854d3ed -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 55425a4c5370a6fa1faad61dc24fcd76b854d3ed) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -44,6 +44,7 @@ // #define HEATERS_DEBUG 1 // #define PRESSURES_DEBUG 1 #define DISABLE_DIALYSATE_CHECK 1 + #define DISABLE_RO_RATIO_CHECK 1 #include #include #endif Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -18,6 +18,7 @@ #include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "FPGA.h" +#include "Heaters.h" #include "LoadCell.h" #include "ModeFill.h" #include "OperationModes.h" @@ -28,6 +29,7 @@ #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" +#include "UVReactors.h" #include "Valves.h" /** @@ -37,11 +39,8 @@ // ********** private definitions ********** -#define FILL_MIN_RO_FLOW_RATE 0.6 ///< Minimum RO flow rate in fill mode. -#define FILL_MAX_RO_FLOW_RATE 1.0 ///< Maximum RO flow rate in fill mode. #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 RO_FLOW_RATE_OUT_OF_RANGE_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for RO flow rate out of range. #define DIALYSATE_ACID_CONCENTRATE_RATIO ( 2.35618 / FRACTION_TO_PERCENT_FACTOR ) ///< Ratio between RO water and acid concentrate. #define DIALYSATE_BICARB_CONCENTRATE_RATIO ( 4.06812 / FRACTION_TO_PERCENT_FACTOR ) ///< Ratio between RO water and bicarbonate concentrate. @@ -51,6 +50,10 @@ #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_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. + +#define CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity error. + /// Multiplier to conver flow (mL/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 ) ); @@ -60,10 +63,15 @@ static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. static F32 totalROFlowRate; ///< Total RO flow rate over period of time. +static U32 concentrateTestStartTime; ///< Starting time for concentrate test. // ********** private function prototypes ********** +static BOOL isWaterQualityGood( void ); +static BOOL checkDialysateConductivity( 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 ); static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ); static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ); @@ -79,6 +87,13 @@ void initFillMode( void ) { fillState = DG_FILL_MODE_STATE_START; + dialysateFillStartTime = 0; + reservoirBaseWeight = 0.0; + totalROFlowRate = 0.0; + concentrateTestStartTime = 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 ); } /*********************************************************************//** @@ -90,14 +105,19 @@ *************************************************************************/ void transitionToFillMode( void ) { - fillState = DG_FILL_MODE_STATE_START; + initFillMode(); + dialysateFillStartTime = getMSTimerCount(); - reservoirBaseWeight = 0.0; - totalROFlowRate = 0.0; // set initial actuator states setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + + startPrimaryHeater(); + setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); } /*********************************************************************//** @@ -132,6 +152,14 @@ fillState = handleCheckInletWaterState(); break; + case DG_FILL_MODE_STATE_BICARB_PUMP_CHECK: + fillState = handleBicarbPumpCheckState(); + break; + + case DG_FILL_MODE_STATE_ACID_PUMP_CHECK: + fillState = handleAcidPumpCheckState(); + break; + case DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION: fillState = handleDialysateProductionState(); break; @@ -151,6 +179,57 @@ /*********************************************************************//** * @brief + * The isWaterQualityGood function checks for inlet water quality. + * @details Inputs: Temperature and conductivity alarms + * @details Outputs: none + * @return TRUE if water quality is good, otherwise FALSE + *************************************************************************/ +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 ); + + return ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ); +} + +/*********************************************************************//** + * @brief + * The checkDialysateConductivity function checks dialysate conductivity + * after adding acid and bicarbonate and triggers an alarm when conductivity + * is out of range. + * @details Inputs: CD1 and CD2 sensor conductivity + * @details Outputs: Trigger alarms when dialysate conductivity is out of allowed range + * @return TRUE if dialysate conductivity is good, otherwise FALSE + *************************************************************************/ +static BOOL checkDialysateConductivity( void ) +{ + BOOL const isDialysateConductivityGood = isDialysateConductivityInRange(); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, !isDialysateConductivityGood ) ) + { + if ( FALSE == isAcidConductivityInRange() ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ) ); + } + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ) ); + } + } + + if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, !isDialysateConductivityGood ) ) + { + clearAlarmCondition( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE ); + clearAlarmCondition( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE ); + } + + return ( isDialysateConductivityGood && isWaterQualityGood() ); +} + +/*********************************************************************//** + * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -162,29 +241,80 @@ DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - 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 isInletWaterReady = isWaterQualityGood(); - BOOL isInletWaterReady = isWaterTemperatureGood && isWaterConductivityGood; - -#ifdef DISABLE_DIALYSATE_CHECK - isInletWaterReady = TRUE; -#endif - +#ifndef DISABLE_DIALYSATE_CHECK if ( isInletWaterReady ) +#endif { reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); + concentrateTestStartTime = getMSTimerCount(); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); + result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + } - // Concentrate pumps on request and set RO pump to flow rate 800 mL/min - requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1 ); - requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2 ); + return result; +} - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); +/*********************************************************************//** + * @brief + * The handleBicarbPumpCheckState function checks conductivity value for + * bicarbonate concentrate. + * @details Inputs: Bicarbonate conductivity sensor value + * @details Outputs: Verified bicarbonate conductivity value + * @return the next state + *************************************************************************/ +static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ) +{ + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + handleDialysateMixing(); + + if ( TRUE == isBicarbConductivityInRange() ) + { + concentrateTestStartTime = getMSTimerCount(); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + } + + if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ) ); + requestNewOperationMode( DG_MODE_CIRC ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleAcidPumpCheckState function checks conductivity value for + * acid concentrate. + * @details Inputs: Acid conductivity sensor value + * @details Outputs: Verified acid conductivity value + * @return the next state + *************************************************************************/ +static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) +{ + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + + handleDialysateMixing(); + + if ( TRUE == isAcidConductivityInRange() ) + { + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; } + if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ) ); + requestNewOperationMode( DG_MODE_CIRC ); + } + return result; } @@ -201,16 +331,11 @@ DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; handleDialysateMixing(); - checkConcentrateConductivity(); - BOOL isDialysateProductionGood = ( !isAlarmActive( ALARM_ID_POST_ACID_CONDUCTIVITY_OUT_OF_RANGE ) && !isAlarmActive( ALARM_ID_POST_BICARB_CONDUCTIVITY_OUT_OF_RANGE ) ); - -#ifdef DISABLE_DIALYSATE_CHECK - isDialysateProductionGood = TRUE; -#endif - // TODO - transition when temperature and mix is in range - if ( isDialysateProductionGood ) +#ifndef DISABLE_DIALYSATE_CHECK + if ( TRUE == checkDialysateConductivity() ) +#endif { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; @@ -231,23 +356,17 @@ { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); + totalROFlowRate += getMeasuredROFlowRate(); handleDialysateMixing(); - checkConcentrateConductivity(); - totalROFlowRate += getMeasuredROFlowRate(); - - BOOL isDialysateConductivityBad = ( isAlarmActive( ALARM_ID_POST_ACID_CONDUCTIVITY_OUT_OF_RANGE ) || isAlarmActive( ALARM_ID_POST_BICARB_CONDUCTIVITY_OUT_OF_RANGE ) ); - -#ifdef DISABLE_DIALYSATE_CHECK - isDialysateConductivityBad = FALSE; -#endif - // TODO - transition back when temperature or mix out of range - if ( isDialysateConductivityBad ) + if ( FALSE == checkDialysateConductivity() ) { +#ifndef DISABLE_DIALYSATE_CHECK setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; +#endif } // if we've reached our target fill to volume (by weight), we're done filling - go back to re-circ mode @@ -262,8 +381,6 @@ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledWeight, integratedVolume ); } - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); requestNewOperationMode( DG_MODE_CIRC ); } @@ -285,8 +402,8 @@ F32 const acidCP1PumpFlowRate = DIALYSATE_ACID_CONCENTRATE_RATIO * measuredROFlowRate * ML_PER_LITER; F32 const bicarbCP2PumpFlowRate = DIALYSATE_BICARB_CONCENTRATE_RATIO * measuredROFlowRate * ML_PER_LITER; - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1, acidCP1PumpFlowRate ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2, bicarbCP2PumpFlowRate ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidCP1PumpFlowRate ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbCP2PumpFlowRate ); } /**@}*/ Index: firmware/App/Modes/ModeFill.h =================================================================== diff -u -r80028d3b1eef322950c1a5b74c282df2ba989ff5 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 80028d3b1eef322950c1a5b74c282df2ba989ff5) +++ firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -35,7 +35,6 @@ void initFillMode( void ); // initialize this module void transitionToFillMode( void ); // prepares for transition to fill mode -void exitFillMode( void ); // prepares to exit fill mode U32 execFillMode( void ); // execute the fill mode state machine (call from OperationModes) /**@}*/ Index: firmware/App/Modes/ModeRecirculate.c =================================================================== diff -u -r55425a4c5370a6fa1faad61dc24fcd76b854d3ed -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision 55425a4c5370a6fa1faad61dc24fcd76b854d3ed) +++ firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -30,6 +30,7 @@ #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" +#include "UVReactors.h" #include "Valves.h" /** @@ -90,9 +91,12 @@ setROPumpTargetFlowRate( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); signalDrainPumpHardStop(); startPrimaryHeater(); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + // UV on + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); #ifndef _VECTORCAST_ { // TODO - test code to start the fan since we're turning the heater on Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rafdf53e4c6c89d257f9b595f08b21077dadc9328 -rb1dc3df084a8517ca1575bdbf741fecd96d56a12 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision afdf53e4c6c89d257f9b595f08b21077dadc9328) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision b1dc3df084a8517ca1575bdbf741fecd96d56a12) @@ -104,8 +104,8 @@ signalDrainPumpHardStop(); stopPrimaryHeater(); stopTrimmerHeater(); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1 ); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2 ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); // UV off resetReservoirLoadCellsOffset( DG_RESERVOIR_1 );