Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -rd0536d759cb33f099357033c3429401ff1637d26 -r798037378b180e53fc60846efac4ee8eea3c77be --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision d0536d759cb33f099357033c3429401ff1637d26) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 798037378b180e53fc60846efac4ee8eea3c77be) @@ -80,7 +80,9 @@ #define RSRVRS_PARTIAL_FILL_UP_TIMEOUT_MS ( 7 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. #define RSRVRS_ALMOST_FULL_FILL_UP_TIMEOUT_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. It is assumed the reservoir is nearly full to begin. #define RESERVOIR_MINIMUM_FULL_VOLUME_ML 1850.0F ///< When filling the reservoir, the volume reading must be at least this value before checking for the volume to level off. -#define RSRVRS_FILL_TO_FULL_STABLE_TASK_INT ( ( 2 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in task intervals. +#define RSRVRS_STEADY_STATE_MAX_VOL_CHANGE_ML 5.0F ///< Reservoirs steady state maximum volume change in milliliters. +#define RSRVRS_FULL_STATUS_CHECK_TIME_INTERVAL_MS ( 1 * MS_PER_SECOND ) ///< Reservoirs full status check time interval in milliseconds. +#define RSRVRS_FILL_TO_FULL_STABLE_TASK_INT 4 ///< Reservoirs 1 & 2 full stable time in task intervals. // Prime acid line state defines #define PRIME_ACID_LINE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Priming acid line timeout in milliseconds. @@ -153,6 +155,14 @@ U32 acidCondSamplesNextIndex; ///< Acid conductivity sample next index number. } ACID_DATA_STATUS_T; +/// Reservoir full data structure +typedef struct +{ + F32 prevRsrvrVolumeML[ NUM_OF_DG_RESERVOIRS ]; ///< Previous reservoir volumes in milliliters. + U32 startTimeStampMS; ///< Start time stamp in milliseconds. + BOOL hasTimeStampBeenSet; ///< Boolean flag to indicate that the timer has been set or not. +} RSRVR_FULL_STATUS_T; + // ********** private data ********** static DG_CHEM_DISINFECT_STATE_T chemDisinfectState; ///< Currently active chemical disinfect state. @@ -185,6 +195,7 @@ static U32 maxTemperatureOutOfRangeStartTimeMS; ///< Maximum temperature out of range start time in milliseconds. static U32 maxCondOutOfRangeStartTimeMS; ///< Maximum conductivity out of range start time in milliseconds. static ACID_DATA_STATUS_T acidDataStatus; ///< Acid data status. +static RSRVR_FULL_STATUS_T rsrvrFullStatus; ///< Reservoir full status. #ifndef _RELEASE_ /* Nelson Labs is in charge of testing the efficacy of the disinfects (heat and chem). The codes that contain the name Nelson are used to @@ -248,6 +259,7 @@ * rsrvrFillToFullStableTimeCounter, R2FullVolume, disinfectantMixRatio, * haveDrainParamsBeenInit[ DG_RESERVOIR_1 ], haveDrainParamsBeenInit[ DG_RESERVOIR_2 ], * maxTemperatureOutOfRangeStartTimeMS, maxCondOutOfRangeStartTimeMS, + * rsrvrFullStatus * @return none *************************************************************************/ void initChemicalDisinfectMode( void ) @@ -295,8 +307,11 @@ acidDataStatus.acidDataColHasTimerBeenSet = getMSTimerCount(); acidDataStatus.acidCondRunningSumUSPCM = 0.0F; acidDataStatus.acidCondSamplesNextIndex = 0; + rsrvrFullStatus.hasTimeStampBeenSet = FALSE; + rsrvrFullStatus.startTimeStampMS = getMSTimerCount(); memset( acidDataStatus.acidCondSamplesUSPCM, 0x0, sizeof( F32 ) * ACID_MOVING_AVG_NUM_OF_SAMPLES ); + memset( rsrvrFullStatus.prevRsrvrVolumeML, 0.0F, sizeof( F32 ) * NUM_OF_DG_RESERVOIRS ); #ifndef _RELEASE_ setNelsonSupportConditions(); @@ -1451,39 +1466,63 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillToFullStatus( DG_RESERVOIR_ID_T r, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; - F32 currentVolume = 0.0F; + F32 currentVolumeML = 0.0F; - if ( DG_RESERVOIR_1 == r ) + switch( r ) { - currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + case DG_RESERVOIR_1: + currentVolumeML = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + break; + + case DG_RESERVOIR_2: + currentVolumeML = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) + break; } - else if ( DG_RESERVOIR_2 == r ) - { - currentVolume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) - } // Check the volume of the reservoir against the long term filtered volume - if ( currentVolume > RESERVOIR_MINIMUM_FULL_VOLUME_ML ) + if ( currentVolumeML > RESERVOIR_MINIMUM_FULL_VOLUME_ML ) { - if ( ++rsrvrFillToFullStableTimeCounter >= RSRVRS_FILL_TO_FULL_STABLE_TASK_INT ) + if ( FALSE == rsrvrFullStatus.hasTimeStampBeenSet ) { - status = DG_RESERVOIR_REACHED_TARGET; - rsrvrFillToFullStableTimeCounter = 0; + rsrvrFullStatus.startTimeStampMS = getMSTimerCount(); + rsrvrFullStatus.hasTimeStampBeenSet = TRUE; + } + else if ( TRUE == didTimeout( rsrvrFullStatus.startTimeStampMS, RSRVRS_FULL_STATUS_CHECK_TIME_INTERVAL_MS ) ) + { + if ( fabs( currentVolumeML - rsrvrFullStatus.prevRsrvrVolumeML[ r ] ) < RSRVRS_STEADY_STATE_MAX_VOL_CHANGE_ML ) + { + rsrvrFillToFullStableTimeCounter++; + } + else + { + rsrvrFillToFullStableTimeCounter = 0; + } + + rsrvrFullStatus.prevRsrvrVolumeML[ r ] = currentVolumeML; + rsrvrFullStatus.hasTimeStampBeenSet = FALSE; + } + + if ( rsrvrFillToFullStableTimeCounter > RSRVRS_FILL_TO_FULL_STABLE_TASK_INT ) + { + status = DG_RESERVOIR_REACHED_TARGET; + rsrvrFillToFullStableTimeCounter = 0; + // Set the state timer in case it needs to be used for another timeout check + stateTimer = getMSTimerCount(); + rsrvrFullStatus.prevRsrvrVolumeML[ r ] = 0.0F; + // Record the full volumes if ( DG_RESERVOIR_1 == r ) { - R1FullVolume = currentVolume; + R1FullVolume = currentVolumeML; } else if ( DG_RESERVOIR_2 == r ) { - R2FullVolume = currentVolume; + R2FullVolume = currentVolumeML; } - // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); } } else if ( TRUE == didTimeout( stateTimer, timeout ) )