Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r27a68f930508638f2eb6265ebb381c8918cbc37b -r7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 27a68f930508638f2eb6265ebb381c8918cbc37b) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6) @@ -69,11 +69,14 @@ static OVERRIDE_F32_T loadCellWeightInGrams[ NUM_OF_LOAD_CELLS ]; /// Filtered (32 sample) weight of reservoirs. static F32 lgFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; +static F32 lgFilteredReservoirBackupWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; // Load cell filtering data static F32 lgLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Holds load cell samples for large load cell moving average. static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. +static F32 lgLoadCellBackupReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Holds load cell samples for large load cell moving average. +static F32 lgLoadCellBackupReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. // DG Dialysate flow rate static F32 dgDialysateFlowRateMlMin = 0.0; ///< Latest dialysate flow rate reported by the DG. @@ -146,6 +149,8 @@ lgLoadCellReadingsIdx = 0; lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); @@ -329,6 +334,27 @@ /*********************************************************************//** * @brief + * The getReservoirBackupWeightLargeFilter function gets the backup load cell weight + * of the given reservoir after large (32 sample) filter applied. + * @details Inputs: lgFilteredReservoirWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get filtered weight for + * @return the current filtered weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirBackupWeightLargeFilter( DG_RESERVOIR_ID_T resID ) +{ + F32 result = 0.0; + + if ( resID < NUM_OF_DG_RESERVOIRS ) + { + result = lgFilteredReservoirBackupWeightInGrams[ resID ]; + } + + return result; +} + +/*********************************************************************//** + * @brief * The getDialysateTemperature function gets the latest dialysate temperature. * @details Inputs: dgDialysateTemp * @details Outputs: none @@ -492,6 +518,12 @@ lgLoadCellReadings[ res ][ lgLoadCellReadingsIdx ] = wt; lgLoadCellReadingsTotal[ res ] += wt; lgFilteredReservoirWeightInGrams[ res ] = lgLoadCellReadingsTotal[ res ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; + + wt = ( res == DG_RESERVOIR_1 ? res1Primary : res2Primary ); + lgLoadCellBackupReadingsTotal[ res ] -= lgLoadCellBackupReadings[ res ][ lgLoadCellReadingsIdx ]; + lgLoadCellBackupReadings[ res ][ lgLoadCellReadingsIdx ] = wt; + lgLoadCellBackupReadingsTotal[ res ] += wt; + lgFilteredReservoirBackupWeightInGrams[ res ] = lgLoadCellBackupReadingsTotal[ res ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; } lgLoadCellReadingsIdx = INC_WRAP( lgLoadCellReadingsIdx, 0, SIZE_OF_LARGE_LOAD_CELL_AVG - 1 ); Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -ra7675f3c917b632cf16207fc7ccfc1f38eb83f9b -r7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision a7675f3c917b632cf16207fc7ccfc1f38eb83f9b) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6) @@ -34,6 +34,7 @@ #define DEFAULT_TARGET_FILL_FLOW_RATE_LPM 0.8F ///< Default target fill flow rate in L/min. #define DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during treatment. +#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 10.0F ///< Reservoir load cell drift difference allowed /// DG Concentrate ratios data structure. typedef struct @@ -148,6 +149,7 @@ F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ); F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ); F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ); +F32 getReservoirBackupWeightLargeFilter( DG_RESERVOIR_ID_T resID ); F32 getDialysateTemperature( void ); DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ); DG_MIXING_RATIOS_T getDGMixingRatios( void ); Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r49533d4870aa10c1b20406dd5c013567fe854694 -r7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 49533d4870aa10c1b20406dd5c013567fe854694) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 7cf04dc00d1242aba62f3cd4e4bcb19f1e83ebc6) @@ -106,6 +106,7 @@ static void updateUFVolumes( void ); static void publishSalineBolusData( void ); +static void checkLoadCellsStablePrimaryBackupDriftOutOfRange( DG_RESERVOIR_ID_T reservoirID, BOOL reservoirFull ); /*********************************************************************//** * @brief @@ -1135,6 +1136,8 @@ // Set starting baseline volume for next reservoir before we switch to it resStartVolume[ reservoirID ] = resVolume; resFinalVolume[ reservoirID ] = resVolume; + + checkLoadCellsStablePrimaryBackupDriftOutOfRange( reservoirID, false ); } /*********************************************************************//** @@ -1172,6 +1175,8 @@ measUFVolumeFromPriorReservoirs -= ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); resFinalVolume[ inactiveRes ] = resVolume; measUFVolumeFromPriorReservoirs += ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); + + checkLoadCellsStablePrimaryBackupDriftOutOfRange( inactiveRes, true ); } /*********************************************************************//** @@ -1206,4 +1211,109 @@ return ( resFinalVolume[ reservoirID ] - resStartVolume[ reservoirID ] ); } +/*********************************************************************//** + * @brief + * The checkLoadCellsStablePrimaryBackupDriftOutOfRange function checks the + * load cells' primary and backup drift when the reservoir level has been stable + * for greater than large filter time. + * @details Inputs: none + * @details Outputs: none + * @param reservoirID which is the reservoir ID that is range checked + * @param reservoirFull is the reservoir status full or empty + * @return none + *************************************************************************/ +#define LOAD_CELL_ILLEGAL_WEIGHT_VALUE -1000.0F +static void checkLoadCellsStablePrimaryBackupDriftOutOfRange( DG_RESERVOIR_ID_T reservoirID, BOOL reservoirFull ) +{ + static F32 lastEmptyWeight[NUM_OF_LOAD_CELLS] = { LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE }; + static F32 lastFullWeight[NUM_OF_LOAD_CELLS] = { LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE, + LOAD_CELL_ILLEGAL_WEIGHT_VALUE }; + F32 loadCellPrimaryWeight, loadCellBackupWeight; + F32 loadCellPreviousDrift, loadCellCurrentDrift; + F32 driftDiff = 0.0; + + if ( reservoirID == DG_RESERVOIR_1 ) + { + // Reservoir 1 + loadCellPrimaryWeight = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + loadCellBackupWeight = getReservoirBackupWeightLargeFilter( DG_RESERVOIR_1 ); + loadCellCurrentDrift = fabs( loadCellPrimaryWeight - loadCellBackupWeight ); + + if ( reservoirFull ) + { + if ( lastFullWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] > (LOAD_CELL_ILLEGAL_WEIGHT_VALUE + 1) ) + { + // Weight has been previously saved, ok to test + loadCellPreviousDrift = fabs( lastFullWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] - + lastFullWeight[LOAD_CELL_RESERVOIR_1_BACKUP] ); + driftDiff = fabs ( loadCellCurrentDrift - loadCellPreviousDrift ); + } + // Save latest reading for next test time + lastFullWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] = loadCellPrimaryWeight; + lastFullWeight[LOAD_CELL_RESERVOIR_1_BACKUP] = loadCellBackupWeight; + } + else + { + if ( lastEmptyWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] > (LOAD_CELL_ILLEGAL_WEIGHT_VALUE + 1) ) + { + // Weight has been previously saved, ok to test + loadCellPreviousDrift = fabs( lastEmptyWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] - + lastEmptyWeight[LOAD_CELL_RESERVOIR_1_BACKUP] ); + driftDiff = fabs ( loadCellCurrentDrift - loadCellPreviousDrift ); + } + // Save latest reading for next test time + lastEmptyWeight[LOAD_CELL_RESERVOIR_1_PRIMARY] = loadCellPrimaryWeight; + lastEmptyWeight[LOAD_CELL_RESERVOIR_1_BACKUP] = loadCellBackupWeight; + } + } + else + { + // Reservoir 2 + loadCellPrimaryWeight = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); + loadCellBackupWeight = getReservoirBackupWeightLargeFilter( DG_RESERVOIR_2 ); + loadCellCurrentDrift = fabs( loadCellPrimaryWeight - loadCellBackupWeight ); + + if ( reservoirFull ) + { + if ( lastFullWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] > (LOAD_CELL_ILLEGAL_WEIGHT_VALUE + 1) ) + { + // Weight has been previously saved, ok to test + loadCellPreviousDrift = fabs( lastFullWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] - + lastFullWeight[LOAD_CELL_RESERVOIR_2_BACKUP] ); + driftDiff = fabs ( loadCellCurrentDrift - loadCellPreviousDrift ); + } + // Save latest reading for next test time + lastFullWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] = loadCellPrimaryWeight; + lastFullWeight[LOAD_CELL_RESERVOIR_2_BACKUP] = loadCellBackupWeight; + } + else + { + if ( lastEmptyWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] > (LOAD_CELL_ILLEGAL_WEIGHT_VALUE + 1) ) + { + // Weight has been previously saved, ok to test + loadCellPreviousDrift = fabs( lastEmptyWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] - + lastEmptyWeight[LOAD_CELL_RESERVOIR_2_BACKUP] ); + driftDiff = fabs ( loadCellCurrentDrift - loadCellPreviousDrift ); + } + // Save latest reading for next test time + lastEmptyWeight[LOAD_CELL_RESERVOIR_2_PRIMARY] = loadCellPrimaryWeight; + lastEmptyWeight[LOAD_CELL_RESERVOIR_2_BACKUP] = loadCellBackupWeight; + } + } + + // TODO Set proper limits and use separate Alarm Number + if ( driftDiff > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ) + { + //checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, isDriftOutOfRange, driftDiff, + // LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, loadCellCurrentDrift, loadCellPreviousDrift ) + } +} + + /**@}*/