Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r4d7d40a27130dc813d653f044cbb856b1b7d8481 -r87a22cbaa87daab0d7cedabc67452cead83d8630 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 4d7d40a27130dc813d653f044cbb856b1b7d8481) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 87a22cbaa87daab0d7cedabc67452cead83d8630) @@ -16,14 +16,16 @@ ***************************************************************************/ #include // for memcpy() - + +#include "Heaters.h" +#include "LoadCell.h" #include "ModeRecirculate.h" #include "OperationModes.h" +#include "Reservoirs.h" #include "SystemCommMessages.h" -#include "TaskGeneral.h" +#include "TaskGeneral.h" +#include "Timers.h" #include "Valves.h" -#include "Reservoirs.h" -#include "Heaters.h" /** * @addtogroup Reservoirs @@ -32,26 +34,37 @@ // ********** private definitions ********** -#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. -#define MAX_RESERVOIR_VOLUME_ML 2000 ///< Maximum reservoir volume in mL. -#define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. -#define DISINFECT_FILL_VOLUME_ML 2400 ///> Fill volume for disinfection in mL. -#define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///> Maximum fill volume in mL. -#define DEFAULT_DRAIN_VOLUME_ML 100 ///> Default drain volume in mL. -#define MAX_DRAIN_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///> Maximum drain volume in mL. -#define MIN_DRAIN_VOLUME_ML 100 ///> Minimum drain volume in mL. +#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. +#define MAX_RESERVOIR_VOLUME_ML 2000 ///< Maximum reservoir volume in mL. +#define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. +#define DISINFECT_FILL_VOLUME_ML 2400 ///> Fill volume for disinfection in mL. +#define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///> Maximum fill volume in mL. +#define DEFAULT_DRAIN_VOLUME_ML 100 ///> Default drain volume in mL. +#define MAX_DRAIN_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///> Maximum drain volume in mL. +#define MIN_DRAIN_VOLUME_ML 100 ///> Minimum drain volume in mL. -#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. + // ********** private data ********** -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 drainVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir drain 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 LOAD_CELL_ID_T associateLoadCell[ NUM_OF_RESERVOIRS ] = { LOAD_CELL_A1, + LOAD_CELL_B1 }; ///< The reservoirs' associate load cell. +static LOAD_CELL_ID_T redundantLoadCell[ NUM_OF_RESERVOIRS ] = { LOAD_CELL_A2, + LOAD_CELL_B2 }; ///< The reservoirs' associate redundant load cell. + +static F32 reservoirLowestWeight[ NUM_OF_RESERVOIRS ] = { MAX_RESERVOIR_VOLUME_ML, + MAX_RESERVOIR_VOLUME_ML }; ///< The reservoirs' lowest weight during draining. +static U32 reservoirWeightUnchangeStartTime[ NUM_OF_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. -// ********** private function prototypes ********** +// ********** private function prototypes ********** +static U32 getReservoirDrainVolumeTargetMl( void ); /*********************************************************************//** * @brief @@ -194,17 +207,18 @@ * @param drainToVolMl Target volume (in mL) to drain reservoir to * @return TRUE if drain command successful, FALSE if not. *************************************************************************/ -BOOL startDrainCmd( U32 drainToVolMl ) +BOOL startDrainCmd( DRAIN_CMD_T drainCmd ) { BOOL result = FALSE; // drain command only valid in re-circulate mode if ( DG_MODE_CIRC == getCurrentOperationMode() ) { // validate parameters - if ( ( drainToVolMl >= MIN_DRAIN_VOLUME_ML ) && ( drainToVolMl <= MAX_DRAIN_VOLUME_ML ) ) + if ( ( drainCmd.targetVolume >= MIN_DRAIN_VOLUME_ML ) && ( drainCmd.targetVolume <= MAX_DRAIN_VOLUME_ML ) ) { - drainVolumeTargetMl.data = drainToVolMl; + drainVolumeTargetMl.data = drainCmd.targetVolume; + tareLoadCellRequest = drainCmd.tareLoadCell; requestNewOperationMode( DG_MODE_DRAI ); result = TRUE; } @@ -287,6 +301,25 @@ return result; } + +/*********************************************************************//** + * @brief + * The getInactiveReservoir function gets the inactive reservoir. + * @details Inputs: activeReservoir + * @details Outputs: none + * @return the currently inactive reservoir. + *************************************************************************/ +RESERVOIR_ID_T getInactiveReservoir( void ) +{ + RESERVOIR_ID_T inactiveReservoir = RESERVOIR_1; + + if ( RESERVOIR_1 == getActiveReservoir() ) + { + inactiveReservoir = RESERVOIR_2; + } + + return inactiveReservoir; +} /*********************************************************************//** * @brief @@ -305,28 +338,85 @@ } return result; -} - -/*********************************************************************//** - * @brief - * The getReservoirDrainVolumeTargetMl function gets the reservoir drain volume (in mL). - * @details Inputs: drainVolumeTargetMl - * @details Outputs: none - * @return the current target reservoir drain volume (in mL). - *************************************************************************/ -U32 getReservoirDrainVolumeTargetMl( void ) -{ - U32 result = drainVolumeTargetMl.data; - - if ( OVERRIDE_KEY == drainVolumeTargetMl.override ) - { - result = drainVolumeTargetMl.ovData; - } - - return result; -} +} - +/*********************************************************************//** + * @brief + * The resetReservoirLoadCellsOffset function sets the reservoir's load cells + * offset to zero. + * @details Inputs: associateLoadCell[], redundantLoadCell[] + * @details Outputs: reset reservoir's associate load cells auto calibration offset + * @param reservoirId reservoir id + * @return none + *************************************************************************/ +void resetReservoirLoadCellsOffset( RESERVOIR_ID_T reservoirId ) +{ + resetLoadCellOffset( associateLoadCell[ reservoirId ] ); + resetLoadCellOffset( redundantLoadCell[ reservoirId ] ); +} + +/*********************************************************************//** + * @brief + * The hasTargetDrainVolumeReached function checks if the target drain volume + * for specific reservoir has been reached or exceed time limit. + * @details Inputs: drainVolumeTargetMl + * @details Outputs: none + * @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 hasTargetDrainVolumeReached( RESERVOIR_ID_T reservoirId, U32 timeout ) +{ + BOOL result = FALSE; + F32 const loadcellWeight = getLoadCellFilteredWeight( associateLoadCell[ reservoirId ] ); + F32 const redundantLoadcellWeight = getLoadCellFilteredWeight( redundantLoadCell[ reservoirId ] ); + U32 const targetDrainVolume = getReservoirDrainVolumeTargetMl(); + + if ( ( loadcellWeight < reservoirLowestWeight[ reservoirId ] ) || ( redundantLoadcellWeight < reservoirLowestWeight[ reservoirId ] ) ) + { + reservoirLowestWeight[ reservoirId ] = loadcellWeight < redundantLoadcellWeight ? loadcellWeight : redundantLoadcellWeight; + reservoirWeightUnchangeStartTime[ reservoirId ] = getMSTimerCount(); + } + + BOOL const hasTimeOut = didTimeout( reservoirWeightUnchangeStartTime[ reservoirId ], timeout ); + BOOL const hasTargetReached = ( targetDrainVolume >= loadcellWeight ) || ( targetDrainVolume >= redundantLoadcellWeight ); + + if ( hasTimeOut || hasTargetReached ) + { + result = TRUE; + reservoirLowestWeight[ reservoirId ] = MAX_RESERVOIR_VOLUME_ML; + + if ( tareLoadCellRequest ) + { + tareLoadCellRequest = FALSE; + tareLoadCell( associateLoadCell[ reservoirId ] ); + tareLoadCell( redundantLoadCell[ reservoirId ] ); + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getReservoirDrainVolumeTargetMl function gets the reservoir drain volume (in mL). + * @details Inputs: drainVolumeTargetMl + * @details Outputs: none + * @return the current target reservoir drain volume (in mL). + *************************************************************************/ +static U32 getReservoirDrainVolumeTargetMl( void ) +{ + U32 result = drainVolumeTargetMl.data; + + if ( OVERRIDE_KEY == drainVolumeTargetMl.override ) + { + result = drainVolumeTargetMl.ovData; + } + + return result; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/