Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -r1aeab08c1baf6445514b81fe51fc60a3e536e782 -rf5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 1aeab08c1baf6445514b81fe51fc60a3e536e782) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision f5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5) @@ -160,7 +160,7 @@ if ( 0 != fpgaConcentratePumpsFault ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, fpgaConcentratePumpsFault ); + //SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, fpgaConcentratePumpsFault ); // TODO why did this error occur once? } calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); @@ -177,9 +177,9 @@ F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); data.cp1CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1SetSpeed * -1.0 : cp1SetSpeed ); - data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); + data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0 : cp2SetSpeed ); - data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); + data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); #ifndef DISABLE_DIALYSATE_CHECK F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -re59287e5915e01c44af22fc54eafc29cb0f6c2c0 -rf5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision e59287e5915e01c44af22fc54eafc29cb0f6c2c0) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5) @@ -666,26 +666,29 @@ // Get the primary heater's efficiency and the last fill temperature from the ModeFill F32 heaterEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency; - /*if ( TRUE == checkEfficiency ) + if ( TRUE == checkEfficiency ) // TODO ignore the efficiency for now until it is fixed { - F32 lastFillTemperature = getLastFillTemperature(); - F32 trimmerTargetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; + /*F32 lastFillTemperature = getLastFillTemperature(); + F32 primaryTargetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; // If the last fill temperature > target temperature, it means the primary heater overshot the duty cycle // so with its efficiency is toned down for the next fill cycle // If the heater under-shoots the duty cycle, the efficiency increases the duty cycle for the next fill cycle - if ( lastFillTemperature - trimmerTargetTemperature > MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C ) + if ( lastFillTemperature - primaryTargetTemperature > MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C ) { - heaterEfficiency -= ( lastFillTemperature - trimmerTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + heaterEfficiency -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; } - else if ( lastFillTemperature - trimmerTargetTemperature <= MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C ) + else if ( lastFillTemperature - primaryTargetTemperature <= MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C ) { - heaterEfficiency += ( lastFillTemperature - trimmerTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + heaterEfficiency += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; } + heaterEfficiency = heaterEfficiency <= 0.0 ? 0.0 : heaterEfficiency; + //heaterEfficiency = heaterEfficiency >= 1.0 ? 1.0 : heaterEfficiency; + // Update the heaters efficiency - heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = heaterEfficiency; - }*/ + heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = heaterEfficiency; */ + } // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 // Multiply the duty cycle to the heater efficiency Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r353d01d31bc69d4d1901ff09097ee610bb1c9dbc -rf5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 353d01d31bc69d4d1901ff09097ee610bb1c9dbc) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision f5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5) @@ -607,9 +607,8 @@ 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 ( TRUE ) // DEBUG_DENALI enable the conductivity check + if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && + ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -re59287e5915e01c44af22fc54eafc29cb0f6c2c0 -rf5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision e59287e5915e01c44af22fc54eafc29cb0f6c2c0) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision f5dc98b3d5fcd39e3ab502fbe81110e188ce0ec5) @@ -37,52 +37,48 @@ // ********** private definitions ********** -#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume 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. +#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume 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. -#define MAX_RESERVOIR_WEIGHT 10000 ///< Maximum reservoir weight in grams. +#define MAX_RESERVOIR_WEIGHT 10000 ///< Maximum reservoir weight in grams. -#define MIN_DRAIN_INLET_PSI_EMPTY -3.0 ///< Minimum drain inlet pressure (in PSI) to indicate reservoir is empty while drain pump on. +#define MIN_DRAIN_INLET_PSI_EMPTY -3.0 ///< Minimum drain inlet pressure (in PSI) to indicate reservoir is empty while drain pump on. -#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 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 determining if fill completed. +#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 ///< Ultrafilter volume in milliliters. +#define RESERVOIR_EXTRA_TEMPERATURE 1.0 ///< Reservoirs extra margin temperature. -// TODO add doxygen comments yes for all of the new variables and align them -#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 -#define RESERVOIR_EXTRA_TEMPERATURE 1.0 - // ********** private data ********** -// TODO yes we should add all the doxygen comments soon -// TODO add doxygen comments typedef struct { - U32 timeReservoirCycleMS; - U32 timeReservoirFill2SwitchMS; - F32 timeUFDecayMS; - F32 timeReservoirFillMS; - F32 tempUFFill; - F32 tempReservoirUseActual; - F32 tempReservoir0; - F32 tempReservoirEndFill; - F32 tempTargetTrimmer; - F32 flowTargetDialysateLPM; + U32 timeReservoirCycleMS; ///< Time reservoir cycle in milliseconds. + U32 timeReservoirFill2SwitchMS; ///< Time reservoir fill to switch in milliseconds. + F32 timeUFDecayMS; ///< Time ultrafilter decay in milliseconds. + F32 timeReservoirFillMS; ///< Time reservoir fill in milliseconds. + F32 tempUFFill; ///< Temperature ultrafilter fill in C. + F32 tempReservoirUseActual; ///< Temperature actual reservoir in C. + F32 tempReservoir0; ///< Temperature reservoir at the beginning of fill in C. + F32 tempReservoirEndFill; ///< Temperature reservoir at the end of the fill in C. + F32 tempTargetTrimmer; ///< Temperature target trimmer heater in C. + F32 flowTargetDialysateLPM; ///< Dialysate target flow rate in L/min. } 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 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. -static OVERRIDE_U32_T fillVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir fill volume (in mL). +static OVERRIDE_U32_T activeReservoir = { 0, 0, 0, 0 }; ///< The active reservoir that the DG is filling/draining/etc. +static OVERRIDE_U32_T fillVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir fill volume (in mL). -static OVERRIDE_U32_T drainVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir drain volume (in mL). +static OVERRIDE_U32_T drainVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir drain volume (in mL). /// The reservoirs' associate load cell. static LOAD_CELL_ID_T associatedLoadCell[ NUM_OF_DG_RESERVOIRS ] = { LOAD_CELL_RESERVOIR_1_PRIMARY, LOAD_CELL_RESERVOIR_2_PRIMARY }; @@ -91,14 +87,16 @@ /// The reservoirs' lowest weight during draining. static F32 reservoirLowestWeight[ NUM_OF_DG_RESERVOIRS ] = { MAX_RESERVOIR_WEIGHT, MAX_RESERVOIR_WEIGHT }; -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; ///< Target fill flow rate in L/min. +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; ///< Target fill flow rate in L/min. static BOOL isThisTheFirstCycle = TRUE; -// TODO add doxygen comments +/// Conversion of ultrafilter tau in C/min to C/ms. static const F32 ULTRAFILTER_TAU_C_PER_MS = ULTRAFILTER_TEMPERATURE_TAU_C_PER_MIN / ( SEC_PER_MIN * MS_PER_SECOND ); + +/// Conversion of reservoir tau in C/min to C/ms. static const F32 RESERVOIR_TAU_C_PER_MS = RESERVOIR_TEMPERATURE_TAU_C_PER_MIN / ( SEC_PER_MIN * MS_PER_SECOND ); // ********** private function prototypes ********** @@ -577,16 +575,24 @@ F32 tempLastFill = getLastFillTemperature(); F32 tempAvgFill = getAvgFillTemperature(); - heatersTempCalc.timeUFDecayMS = (F32)heatersTempCalc.timeReservoirCycleMS - heatersTempCalc.timeReservoirFillMS; - UFTimeConstant = heatersTempCalc.timeUFDecayMS * ULTRAFILTER_TAU_C_PER_MS; - heatersTempCalc.tempUFFill = tempLastFill + UFTimeConstant; + // Only do the calculations if the fill volume is not 0.0 so the final value will not be a nan. + if ( targetFillVolML > NEARLY_ZERO ) + { + heatersTempCalc.timeUFDecayMS = (F32)heatersTempCalc.timeReservoirCycleMS - heatersTempCalc.timeReservoirFillMS; + UFTimeConstant = heatersTempCalc.timeUFDecayMS * ULTRAFILTER_TAU_C_PER_MS; + heatersTempCalc.tempUFFill = tempLastFill + UFTimeConstant; - F32 ultrafilterPart = ( ULTRAFILTER_VOLUME_ML / targetFillVolML ) * heatersTempCalc.tempUFFill; - F32 fillPart = ( ( targetFillVolML - ULTRAFILTER_VOLUME_ML ) / targetFillVolML ) * tempAvgFill; - F32 tempReservoir0Actual = ultrafilterPart + fillPart; + F32 ultrafilterPart = ( ULTRAFILTER_VOLUME_ML / targetFillVolML ) * heatersTempCalc.tempUFFill; + F32 fillPart = ( ( targetFillVolML - ULTRAFILTER_VOLUME_ML ) / targetFillVolML ) * tempAvgFill; + F32 tempReservoir0Actual = ultrafilterPart + fillPart; - F32 tempReservoirEndfillActual = tempReservoir0Actual + ( ( heatersTempCalc.timeReservoirFillMS * 0.5 ) * RESERVOIR_TAU_C_PER_MS ); - heatersTempCalc.tempReservoirUseActual = tempReservoirEndfillActual + ( heatersTempCalc.timeReservoirFill2SwitchMS * RESERVOIR_TAU_C_PER_MS ); + F32 tempReservoirEndfillActual = tempReservoir0Actual + ( ( heatersTempCalc.timeReservoirFillMS * 0.5 ) * RESERVOIR_TAU_C_PER_MS ); + heatersTempCalc.tempReservoirUseActual = tempReservoirEndfillActual + ( heatersTempCalc.timeReservoirFill2SwitchMS * RESERVOIR_TAU_C_PER_MS ); + } + else + { + heatersTempCalc.tempReservoirUseActual = 0.0; + } return heatersTempCalc.tempReservoirUseActual; }