Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -68,8 +68,6 @@ #define DELTA_TEMPERATURE_TIME_COSNTANT_C 8.6 ///< Delta temperature calculated from time constant. #define MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C 0.25 ///< Maximum allowed temperature deviation from target temperature in C. #define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.03 ///< Primary heaters duty cycle per temperature in C. -#define RESERVOIR_TEMPERATURE_TIME_CONSTANT_C_PER_MIN 0.512 ///< Reservoir temperature time constant C/min. -#define ULTRAFILTER_TEMPERATURE_TIME_CONSTANT_C_PER_MIN 0.345 ///< Ultrafilter temperature time constant C/min. static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. static const F32 PRIMARY_HEATERS_MAXIMUM_POWER_WATTS = 475 + 237.5; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). @@ -121,7 +119,7 @@ static HEATERS_STATE_T handleHeaterStateTrimmerControlToTarget( void ); static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ); -static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ); +static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ); static BOOL haveHeaterControlConditionsChanged( DG_HEATERS_T heater ); static void setMainPrimaryHeaterPWM( F32 pwm ); Index: firmware/App/Controllers/Heaters.h =================================================================== diff -u -r6bb7cd715299d16c131ab074fac0e62d8022f235 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 6bb7cd715299d16c131ab074fac0e62d8022f235) +++ firmware/App/Controllers/Heaters.h (.../Heaters.h) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -34,6 +34,7 @@ // ********** Public definitions ********** +/// Name of DG heaters typedef enum Heaters { DG_PRIMARY_HEATER = 0, ///< DG primary heater @@ -46,7 +47,8 @@ { F32 targetPrimaryHeaterTemp; ///< Primary heater set temperature target F32 targetTrimmerHeaterTemp; ///< Trimmer heater set temperature target -} TARGET_TEMPS_PAYLOAD_T; + U32 activeReservoirCycleTimeMS; ///< Active reservoir cycle time in milliseconds +} TARGET_TEMPS_AND_TIME_PAYLOAD_T; /// Trimmer heater command data structure. typedef struct Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -211,7 +211,7 @@ * can reach * @return TRUE if new target flow rate is set successfully, FALSE if not *************************************************************************/ -BOOL setROPumpTargetFlowRate( F32 roFlowRate, U32 maxPressure ) +BOOL setROPumpTargetFlowRateLPM( F32 roFlowRate, U32 maxPressure ) { BOOL result = FALSE; @@ -932,7 +932,7 @@ // The flow rate and pressure must be in range if ( ( flow <= MAX_RO_FLOWRATE_LPM ) && ( flow >= MIN_RO_FLOWRATE_LPM ) ) { - result = setROPumpTargetFlowRate( flow, MAX_ALLOWED_PRESSURE_PSI ); + result = setROPumpTargetFlowRateLPM( flow, MAX_ALLOWED_PRESSURE_PSI ); } } Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r94a190522ce398399c7b93c59f788d7666ec0060 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 94a190522ce398399c7b93c59f788d7666ec0060) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -53,7 +53,7 @@ SELF_TEST_STATUS_T execROPumpSelfTest( void ); -BOOL setROPumpTargetFlowRate( F32 roFlowRate, U32 maxPressure ); +BOOL setROPumpTargetFlowRateLPM( F32 roFlowRate, U32 maxPressure ); BOOL setROPumpTargetFlowRateDelayed( F32 roFlowRate, U32 maxPressure, U32 delayMs ); void signalROPumpHardStop( void ); @@ -63,7 +63,7 @@ F32 getTargetROPumpFlowRate( void ); F32 getMeasuredROFlowRate( void ); -F32 getTargetROPumpPressure( void ); +F32 getTargetROPumpPressure( void ); BOOL testSetROPumpDataPublishIntervalOverride( U32 value ); BOOL testResetROPumpDataPublishIntervalOverride( void ); Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -r94a190522ce398399c7b93c59f788d7666ec0060 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 94a190522ce398399c7b93c59f788d7666ec0060) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -501,7 +501,7 @@ // TODO turn on the concentrate pumps // Set the RO pump to run at full pressure - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Done with final draining isThisLastDrain = FALSE; @@ -610,7 +610,7 @@ ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); stateTimer = getMSTimerCount(); stateTrialCounter = 0; state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; @@ -1004,7 +1004,7 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); // Turn on the RO pump - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Start heating the water while we are filling up the reservoirs setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_TARGET_TEMPERATURE_C ); @@ -1087,7 +1087,7 @@ // Set the drain pump to control mode setDrainPumpTargetOutletPressure( CHEM_DISINFECT_TARGET_DRAIN_PRES_PSI ); - setROPumpTargetFlowRate( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, CHEM_DISINFECT_MAX_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, CHEM_DISINFECT_MAX_RO_PRESSURE_PSI ); // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' // volume does not change more than a certain amount during the actual chemical disinfect cycle @@ -1389,7 +1389,7 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r1aeab08c1baf6445514b81fe51fc60a3e536e782 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 1aeab08c1baf6445514b81fe51fc60a3e536e782) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -115,7 +115,7 @@ // 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( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); #endif startHeater( DG_PRIMARY_HEATER ); Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -79,22 +79,22 @@ 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 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 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 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 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. // ********** private function prototypes ********** @@ -167,7 +167,7 @@ // 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( getTargetFillFlowRateLPM(), TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( getTargetFillFlowRateLPM(), TARGET_RO_PRESSURE_PSI ); #endif startHeater( DG_PRIMARY_HEATER ); @@ -322,14 +322,16 @@ 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 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 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; + #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 ); @@ -343,7 +345,7 @@ 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,16 +379,17 @@ *************************************************************************/ 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 + 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 ); @@ -562,16 +565,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 ); @@ -610,12 +614,16 @@ *************************************************************************/ 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 ) ); } /*********************************************************************//** @@ -629,7 +637,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 ); } Index: firmware/App/Modes/ModeFill.h =================================================================== diff -u -r3b5080777e3dac1b5802ee18227f66a0b49deefa -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 3b5080777e3dac1b5802ee18227f66a0b49deefa) +++ firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -37,11 +37,11 @@ U32 transitionToFillMode( void ); // prepares for transition to fill mode U32 execFillMode( void ); // execute the fill mode state machine (call from OperationModes) -F32 getAvgFillFlowRate( void ); +F32 getAvgFillFlowRate( void ); // TODO do we need this? -F32 getAvgFillTemperature( void ); // TODO do we need this? +F32 getAvgFillTemperature( void ); -F32 getLastFillTemperature( void ); +F32 getLastFillTemperature( void ); /**@}*/ Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r94a190522ce398399c7b93c59f788d7666ec0060 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 94a190522ce398399c7b93c59f788d7666ec0060) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -403,7 +403,7 @@ setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setROPumpTargetFlowRate( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Turn on the UV reactors turnOnUVReactor( INLET_UV_REACTOR ); @@ -438,7 +438,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Turn on the UV reactors turnOnUVReactor( INLET_UV_REACTOR ); @@ -708,7 +708,7 @@ setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); stateTimerStart = getMSTimerCount(); Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -r94a190522ce398399c7b93c59f788d7666ec0060 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 94a190522ce398399c7b93c59f788d7666ec0060) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -107,7 +107,7 @@ // 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_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); setHeaterTargetTemperature( DG_PRIMARY_HEATER, 39.0 ); // TODO remove this line. It comes form HD this for testing only startHeater( DG_PRIMARY_HEATER ); #endif @@ -217,7 +217,7 @@ if ( flushLinesVolumeL >= getFlushLineVolume() ) { #ifndef DISABLE_FLOW_CONTROL_TREATMENT - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); #endif result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r1aeab08c1baf6445514b81fe51fc60a3e536e782 -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 1aeab08c1baf6445514b81fe51fc60a3e536e782) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -500,7 +500,7 @@ // TODO turn on the concentrate pumps // Set the RO pump to run at full pressure - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Done with final draining isThisLastDrain = FALSE; @@ -514,10 +514,6 @@ // Assume reservoir 2 is full and drain it rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Request a tare for reservoir 1 - tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - // Done with draining R1, close it setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2. @@ -611,11 +607,12 @@ if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { // If the inlet temperature and conductivity are in range, move onto the next state - if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && - ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) + //if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && + // ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) + if ( TRUE ) // DEBUG_DENALI enable the conductivity check { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); stateTimer = getMSTimerCount(); stateTrialCounter = 0; state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; @@ -962,7 +959,7 @@ setValveState( VRD2, VALVE_STATE_OPEN ); // Turn on the RO pump - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Start heating the water while we are filling up the reservoirs setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); @@ -1030,7 +1027,7 @@ // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter // at inlet temperature > 45 C - setROPumpTargetFlowRate( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); // Start the trimmer heater since we are recirculating water and there is flow in the shunt line setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); @@ -1301,7 +1298,7 @@ // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter // at inlet temperature > 45 C - setROPumpTargetFlowRate( ROF_COOL_DOWN_TARGET_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( ROF_COOL_DOWN_TARGET_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); hasROFCirculationBeenStarted = TRUE; ROFCirculationTimer = getMSTimerCount(); @@ -1406,7 +1403,7 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -20,6 +20,7 @@ #include "LoadCell.h" #include "MessageSupport.h" #include "ModeDrain.h" +#include "ModeFill.h" #include "ModeGenIdle.h" #include "OperationModes.h" #include "Pressures.h" @@ -37,7 +38,7 @@ // ********** private definitions ********** #define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. -#define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. +#define DEFAULT_FILL_VOLUME_ML 1500 ///< Default fill volume for treatment in mL. #define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum fill volume in mL. #define DEFAULT_DRAIN_VOLUME_ML 0 ///< Default drain volume in mL. #define MAX_DRAIN_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum drain volume in mL. @@ -48,10 +49,29 @@ #define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the reservoir data is published on the CAN bus. -#define MAX_REDUNDANT_LOAD_CELL_DIFF 50.0 ///< Maximum difference in redundant load cells when determing if fill completed. +#define MAX_REDUNDANT_LOAD_CELL_DIFF 50.0 ///< Maximum difference in redundant load cells when determing if fill completed. -// ********** private data ********** - + +// TODO add doxygen comments +#define RESERVOIR_TEMPERATURE_TAU_C_PER_MIN -0.512 ///< Reservoir temperature time constant C/min. +#define ULTRAFILTER_TEMPERATURE_TAU_C_PER_MIN -0.512 ///< Ultrafilter temperature time constant C/min. +#define ULTRAFILTER_VOLUME_ML 700 + + +// ********** private data ********** + +// TODO yes we should add all the doxygen comments soon +// TODO add doxygen comments +typedef struct +{ + U32 timeReservoirCycleMS; + F32 timeUFDecayMS; + F32 tempUFFill; + F32 tempRerservoirStartFill; + +} HEATERS_TEMPERATURE_CALC_DATA_T; + +static HEATERS_TEMPERATURE_CALC_DATA_T heatersTempCalc; static U32 reservoirDataPublicationTimerCounter = 0; ///< used to schedule reservoir data publication to CAN bus. static OVERRIDE_U32_T activeReservoir = { 0, 0, 0, 0 }; ///< The active reservoir that the DG is filling/draining/etc. @@ -69,11 +89,16 @@ static U32 reservoirWeightUnchangeStartTime[ NUM_OF_DG_RESERVOIRS ] = { 0, 0 }; ///< The reservoirs' weight start time when weight stop decreasing. static BOOL tareLoadCellRequest; ///< Flag indicates if load cell tare has been requested by HD. static DG_RESERVOIR_VOLUME_RECORD_T reservoirsCalRecord; ///< DG reservoirs non-volatile record. -static F32 targetFillFlowRateLPM; +static F32 targetFillFlowRateLPM; ///< Target fill flow rate in L/min. +static const F32 ULTRAFILTER_TAU_C_PER_MS = ULTRAFILTER_TEMPERATURE_TAU_C_PER_MIN * SEC_PER_MIN * MS_PER_SECOND; +static const F32 RESERVOIR_TAU_C_PER_MS = RESERVOIR_TEMPERATURE_TAU_C_PER_MIN * SEC_PER_MIN * MS_PER_SECOND; + // ********** private function prototypes ********** -static BOOL processCalibrationData( void ); +static BOOL processCalibrationData( void ); +static F32 getPrimaryHeaterTargetTemperature( void ); +static F32 getTrimmerHeaterTargetTemperature( void ); /*********************************************************************//** * @brief @@ -88,7 +113,7 @@ activeReservoir.data = (U32)DG_RESERVOIR_1; fillVolumeTargetMl.data = DEFAULT_FILL_VOLUME_ML; drainVolumeTargetMl.data = DEFAULT_DRAIN_VOLUME_ML; - targetFillFlowRateLPM = 0.0; + targetFillFlowRateLPM = 0.0; } /*********************************************************************//** @@ -270,9 +295,9 @@ if ( fillToVolMl < MAX_FILL_VOLUME_ML ) { fillVolumeTargetMl.data = fillToVolMl; + cmdResponse.rejected = FALSE; requestNewOperationMode( DG_MODE_FILL ); - cmdResponse.rejected = FALSE; } else { @@ -284,6 +309,7 @@ cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; } + // Set the fill flow rate targetFillFlowRateLPM = fillTargetLPM; sendCommandResponseMsg( &cmdResponse ); @@ -451,19 +477,53 @@ /*********************************************************************//** * @brief + * The getTargetFillVolumeML function returns the target fill volume in mL. + * @details Inputs: none + * @details Outputs: none + * @return target fill volume in mL + *************************************************************************/ +U32 getTargetFillVolumeML( void ) +{ + U32 targetFill = fillVolumeTargetMl.data; + + if ( OVERRIDE_KEY == fillVolumeTargetMl.override ) + { + targetFill = fillVolumeTargetMl.ovData; + } + + return targetFill; +} + +/*********************************************************************//** + * @brief * The getTargetFillFlowRateLPM function returns the target fill flow rate * in L/min. * @details Inputs: none * @details Outputs: none * @return target fill flow rate in L/min *************************************************************************/ -F32 getTargetFillFlowRateLPM( void ) +F32 getTargetFillFlowRateLPM( void ) { return targetFillFlowRateLPM; } /*********************************************************************//** * @brief + * The setActiveReservoirCycleTime function sets the active reservoir cycle + * time in milliseconds. + * @details Inputs: none + * @details Outputs: heatersTemperatureCalcData + * @return none + *************************************************************************/ +void setHeatersTargetTemperature( TARGET_TEMPS_AND_TIME_PAYLOAD_T targets ) +{ + heatersTempCalc.timeReservoirCycleMS = targets.activeReservoirCycleTimeMS; + + setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); +} + +/*********************************************************************//** + * @brief * The getReservoirsCalRecord function returns the reservoirs' calibration * record. * @details Inputs: reservoirsCalRecord @@ -617,7 +677,42 @@ return status; } +/*********************************************************************//** + * @brief + * The getPrimaryHeaterTargetTemperature function calculates the primary + * heater target temperature and returns target temperature value. + * @details Inputs: none + * @details Outputs: heatersTempCalc + * @return TRUE if the calibration record is valid, otherwise FALSE + *************************************************************************/ +static F32 getPrimaryHeaterTargetTemperature( void ) +{ + F32 targetTemp = 0.0; + F32 targetFillVolML = getTargetFillVolumeML(); + F32 timeFillMS = ( getTargetFillFlowRateLPM() * ML_PER_LITER ) / targetFillVolML; // TODO target flow can come from RO pump too + heatersTempCalc.timeUFDecayMS = (F32)heatersTempCalc.timeReservoirCycleMS - timeFillMS; + heatersTempCalc.tempUFFill = getLastFillTemperature() + ( heatersTempCalc.timeUFDecayMS * ULTRAFILTER_TAU_C_PER_MS ); + + F32 ultrafilterPart = ( ULTRAFILTER_VOLUME_ML / targetFillVolML ) * heatersTempCalc.tempUFFill; + F32 fillPart = ( ( ( targetFillVolML - ULTRAFILTER_VOLUME_ML ) / targetFillVolML ) * getAvgFillTemperature() ); + + heatersTempCalc.tempRerservoirStartFill = ultrafilterPart + fillPart; + + return targetTemp; +} + +static F32 getTrimmerHeaterTargetTemperature( void ) +{ + F32 targetTemp = 0.0; + F32 targetFillVolML = getTargetFillVolumeML(); + F32 timeHalfFillMS = ( getTargetFillFlowRateLPM() * ML_PER_LITER * 0.5 ) / targetFillVolML; // TODO target flow can come from RO pump + + + return targetTemp; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -681,8 +776,8 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; - fillVolumeTargetMl.ovData = value; + result = TRUE; + fillVolumeTargetMl.ovData = value; fillVolumeTargetMl.override = OVERRIDE_KEY; } @@ -703,9 +798,9 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; + result = TRUE; fillVolumeTargetMl.override = OVERRIDE_RESET; - fillVolumeTargetMl.ovData = fillVolumeTargetMl.ovInitData; + fillVolumeTargetMl.ovData = fillVolumeTargetMl.ovInitData; } return result; Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -20,6 +20,7 @@ #include "DGCommon.h" #include "DGDefs.h" +#include "Heaters.h" // TODO maybe remove this and bring TARGET_TEMPS_AND_TIME_PAYLOAD_T to reservoirs? #include "NVDataMgmt.h" /** @@ -87,9 +88,13 @@ void resetReservoirsLowestWeight( void ); DG_RESERVOIR_ID_T getInactiveReservoir( void ); -F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ); -F32 getTargetFillFlowRateLPM( void ); +F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ); +// Heaters target temperature function prototype +void setHeatersTargetTemperature( TARGET_TEMPS_AND_TIME_PAYLOAD_T targets ); +U32 getTargetFillVolumeML( void ); +F32 getTargetFillFlowRateLPM( void ); + DG_RESERVOIR_VOLUME_RECORD_T getReservoirsCalRecord( void ); BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r7d293e18ea5ac0fce443c68525100e44df80b4fd -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 7d293e18ea5ac0fce443c68525100e44df80b4fd) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) @@ -417,14 +417,16 @@ { BOOL result = FALSE; - if ( message->hdr.payloadLen == sizeof( TARGET_TEMPS_PAYLOAD_T ) ) + if ( message->hdr.payloadLen == sizeof( TARGET_TEMPS_AND_TIME_PAYLOAD_T ) ) { - TARGET_TEMPS_PAYLOAD_T payload; + TARGET_TEMPS_AND_TIME_PAYLOAD_T payload; result = TRUE; - memcpy( &payload, message->payload, sizeof( TARGET_TEMPS_PAYLOAD_T ) ); - setHeaterTargetTemperature( DG_PRIMARY_HEATER, payload.targetPrimaryHeaterTemp ); - setHeaterTargetTemperature( DG_TRIMMER_HEATER, payload.targetTrimmerHeaterTemp ); + memcpy( &payload, message->payload, sizeof( TARGET_TEMPS_AND_TIME_PAYLOAD_T ) ); + // TOD + // + //setHeaterTargetTemperature( DG_TRIMMER_HEATER, payload.targetTrimmerHeaterTemp ); + setHeatersTargetTemperature( payload ); } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } @@ -596,7 +598,6 @@ return result; } - /*********************************************************************//** * @brief * The sendDGSystemRecord function sends out the DG system record.