Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r3e5c16b70fb34da7d58f5cf6efff896fdb3d00c3 -rdcca963aa54aeae4f1f5a3995ce63066156eb517 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 3e5c16b70fb34da7d58f5cf6efff896fdb3d00c3) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision dcca963aa54aeae4f1f5a3995ce63066156eb517) @@ -55,6 +55,14 @@ #define DATA_PUBLISH_COUNTER_START_COUNT 5 ///< Data publish counter start count. #define NUM_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK 1 ///< Number of acid and bicarb non-volatile data to check. +// The gain and offset are for the equation to account for the loss of temperature during the transition from DG to HD and back +/* + * Qd = 100 mL/min Tloss = 1.5C + * Qd = 500 mL/min Tloss = 0.5C + */ +#define TRIMMER_HEATER_TARGET_TEMP_GAIN -0.002F ///< Trimmer heater target temperature gain. +#define TRIMMER_HEATER_TARGET_TEMP_OFFSET 1.7F ///< Trimmer heater target temperature offset. + // ********** private data ********** /// Heaters temperature calculation data structure @@ -94,8 +102,7 @@ static U32 dataPublishCounter; ///< 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 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). /// The reservoirs' associate load cell. @@ -566,7 +573,8 @@ *************************************************************************/ F32 getTrimmerHeaterTargetTemperature( void ) { - return heatersTempCalc.tempTargetTrimmer; + return heatersTempCalc.tempTargetTrimmer + ( getTargetDialysateFlowLPM() * TRIMMER_HEATER_TARGET_TEMP_GAIN * ML_PER_LITER ) + + TRIMMER_HEATER_TARGET_TEMP_OFFSET; } /*********************************************************************//** @@ -617,6 +625,21 @@ /*********************************************************************//** * @brief + * The getTargetDrainVolumeML function returns the target drain volume + * in milliliters. + * @details Inputs: drainVolumeTargetMl + * @details Outputs: none + * @return target drain volume in milliliters + *************************************************************************/ +U32 getTargetDrainVolumeML( void ) +{ + U32 targetDrainVolML = getU32OverrideValue( &drainVolumeTargetMl ); + + return targetDrainVolML; +} + +/*********************************************************************//** + * @brief * The setDialysateHeatingParameters function sets the dialysate heating * parameters. * @details Inputs: none @@ -650,7 +673,7 @@ *************************************************************************/ F32 getPrimaryHeaterTargetTemperature( void ) { - F32 tempTargetC = heatersTempCalc.tempTargetTrimmer; + F32 tempTargetC = getTrimmerHeaterTargetTemperature(); F32 priTargetTempC = 0.0F; F32 targetFillVolML = getTargetFillVolumeML(); F32 UFTimeConstant = 0.0F; @@ -681,7 +704,7 @@ * 8. T_primary_target = T_mix_target * (Q_total / Q_RO) - (Q_acid / Q_RO) * T_acid - (Q_bicarb / Q_RO) * T_bicarb */ - tempReservoirUse = heatersTempCalc.tempTargetTrimmer; + tempReservoirUse = getTrimmerHeaterTargetTemperature(); heatersTempCalc.tempReservoirEndFill = tempReservoirUse - ( heatersTempCalc.timeReservoirFill2SwitchMS * RsrvrTauCPerMS ); heatersTempCalc.tempReservoir0 = heatersTempCalc.tempReservoirEndFill - ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * RsrvrTauCPerMS ); @@ -695,7 +718,7 @@ } else { - tempTargetC = heatersTempCalc.tempTargetTrimmer + RESERVOIR_EXTRA_TEMPERATURE; + tempTargetC = getTrimmerHeaterTargetTemperature() + RESERVOIR_EXTRA_TEMPERATURE; } } @@ -834,8 +857,16 @@ F32 loadcellWeight1 = getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); F32 loadcellWeight2 = getLoadCellSmallFilteredWeight( redundantLoadCell[ reservoirId ] ); U32 targetFillVolume = getU32OverrideValue( &fillVolumeTargetMl ); - BOOL hasTargetReached = ( ( loadcellWeight1 >= targetFillVolume || loadcellWeight2 > ( targetFillVolume + MAX_REDUNDANT_LOAD_CELL_DIFF ) ) ? TRUE : FALSE ); + BOOL hasTargetReached = FALSE; + if ( DG_HANDLE_BAD_FILL_STATE_FLUSH_FILL == getCurrentGenIdleBadFillState() ) + { + // In bad fill flush fill we fill to 1000 mL + targetFillVolume = BAD_FLUSH_FILL_TARGET_VOLUME_ML; + } + + hasTargetReached = ( ( loadcellWeight1 >= targetFillVolume || loadcellWeight2 > ( targetFillVolume + MAX_REDUNDANT_LOAD_CELL_DIFF ) ) ? TRUE : FALSE ); + // if redundant load cells too far apart at end of fill, alarm if ( loadcellWeight1 < targetFillVolume ) { @@ -847,16 +878,15 @@ /*********************************************************************//** * @brief - * The hasTargetDrainVolumeReached function checks if the target drain volume - * for specific reservoir has been reached or exceed time limit. - * @details Inputs: reservoirWeightUnchangeStartTime, reservoirWeightUnchangeStartTime - * @details Outputs: reservoirWeightUnchangeStartTime, tareLoadCellRequest, - * reservoirWeightUnchangeStartTime + * The hasTargetDrainToZeroBeenReached function checks if the specific + * reservoir has been drained to zero or it has exceeded the time limit. + * @details Inputs: reservoirWeightUnchangeStartTime, associatedLoadCell + * @details Outputs: reservoirWeightUnchangeStartTime, tareLoadCellRequest * @param reservoirId reservoir id * @param timeout timeout period when weight remains the same * @return TRUE if target drain volume has been reached or exceeds time limit, FALSE if not. *************************************************************************/ -BOOL hasTargetDrainVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId, U32 timeout ) +BOOL hasTargetDrainToZeroBeenReached( DG_RESERVOIR_ID_T reservoirId, U32 timeout ) { BOOL result = FALSE; F32 loadcellWeightML = getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); @@ -908,6 +938,36 @@ /*********************************************************************//** * @brief + * The hasTargetDrainVolumeReached function checks if the target drain volume + * for specific reservoir has been reached or exceeded time limit. + * @details Inputs: reservoirWeightUnchangeStartTime, associatedLoadCell + * @details Outputs: reservoirWeightUnchangeStartTime + * @param reservoirId reservoir id + * @param targetVolumeML target volume to be drained to in milliliters + * @param timeoutMS timeout period when weight remains the same in milliseconds + * @return TRUE if target drain volume has been reached or exceeds time + * limit, FALSE if not. + *************************************************************************/ +BOOL hasTargetDrainToVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId, U32 targetVolumeML, U32 timeoutMS ) +{ + // NOTE: this function is used for testing only. No timeout is implemented right now. + BOOL result = FALSE; + F32 loadcellWeightML = getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); + U32 drainPumpFeedbackRPM = getDrainPumpMeasuredRPM( DRAIN_PUMP_HALL_SNSR_FB ); + + if ( drainPumpFeedbackRPM > 0 ) + { + if ( loadcellWeightML < (F32)targetVolumeML ) + { + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief * The tareLoadCellsAtEmpty function tares the load cells for the given * reservoir when empty and tare request is pending. * @details Inputs: tareLoadCellRequest @@ -917,7 +977,7 @@ *************************************************************************/ void tareLoadCellsAtEmpty( DG_RESERVOIR_ID_T reservoirId ) { - U32 const targetDrainVolume = getU32OverrideValue( &drainVolumeTargetMl ); + U32 targetDrainVolume = getU32OverrideValue( &drainVolumeTargetMl ); if ( TRUE == tareLoadCellRequest ) {