Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -re56a0b7c6fcae8ee61d247b3d89ea1874782eb0d -r47eae6b348bd1795718ccb7d085ae724dae53f4e --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision e56a0b7c6fcae8ee61d247b3d89ea1874782eb0d) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 47eae6b348bd1795718ccb7d085ae724dae53f4e) @@ -50,40 +50,42 @@ #define EMPTY_RESERVOIR_WEIGHT_GRAMS 1600 ///< Reservoirs empty weight in grams. #define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_FIRST_TARE_GRAMS 300 ///< Max allowed extra weight before first tare in grams. #define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 60 ///< Max allowed extra weight before tare in grams. +#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 60.0 ///< Load cell primary and backup maximum allowed weight drift in grams. /// Load cell data structure. typedef struct { - U32 rawReading; ///< Latest raw load cell reading - OVERRIDE_F32_T weight; ///< Latest load cell weight - F32 autoCalOffset; ///< Load cell auto-calibration offset - F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. + U32 rawReading; ///< Latest raw load cell reading + OVERRIDE_F32_T weight; ///< Latest load cell weight + F32 autoCalOffset; ///< Load cell auto-calibration offset + F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. - F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. - F64 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. - F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. + F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. + F64 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. + F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. - F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. - F64 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average. - F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight. + F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. + F64 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average. + F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight. } LOADCELL_T; // ********** private data ********** static OVERRIDE_U32_T loadCellDataPublishInterval = { LOAD_CELL_REPORT_PERIOD, - LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data publish interval. -static LOADCELL_T loadcells[ NUM_OF_LOAD_CELLS ]; ///< Load cell data structures. -static U32 loadCellFilterTimerCount = 0; ///< Load cell filtering timer count. -static U32 loadCellDataPublicationTimerCounter = 0; ///< Load cell data publication timer counter to CAN bus. + LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data publish interval. +static LOADCELL_T loadcells[ NUM_OF_LOAD_CELLS ]; ///< Load cell data structures. +static U32 loadCellFilterTimerCount = 0; ///< Load cell filtering timer count. +static U32 loadCellDataPublicationTimerCounter = 0; ///< Load cell data publication timer counter to CAN bus. -static U32 smallReadingsIdx; ///< Index for next sample in load cell small rolling average sample array. -static U32 largeReadingsIdx; ///< Index for next sample in load cell large rolling average sample array. -static DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< Load cells calibration record. +static U32 smallReadingsIdx; ///< Index for next sample in load cell small rolling average sample array. +static U32 largeReadingsIdx; ///< Index for next sample in load cell large rolling average sample array. +static DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< Load cells calibration record. // ********** private function prototypes ********** static BOOL processCalibrationData( void ); static void monitorLoadCellsWeightOutOfRange( LOAD_CELL_ID_T loadCell ); +static void monitorLoadCellsPrimaryBackupDriftOutOfRange( void ); /*********************************************************************//** * @brief @@ -94,7 +96,6 @@ *************************************************************************/ void initLoadCell( void ) { - U32 cell; U32 i; U32 j; @@ -131,18 +132,14 @@ loadcells[ i ].loadCellVelocity_g_min = 0.0; } - for ( cell = CAL_DATA_LOAD_CELL_A1; cell < NUM_OF_CAL_DATA_LOAD_CELLS; cell++ ) - { - // Reset the calibration variables - loadCellsCalRecord.loadCells[ cell ].fourthOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].thirdOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].secondOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].gain = 1.0; - loadCellsCalRecord.loadCells[ cell ].offset = 0.0; - } - // Initialize persistent alarm(s) initPersistentAlarm( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, 0, LOAD_CELL_ADC_ERROR_PERSISTENCE ); + + initPersistentAlarm( ALARM_ID_DG_LOAD_CELL_WEIGHT_OUT_OF_RANGE, LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS, + LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS ); + + initPersistentAlarm( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, LOAD_CELL_PRIMARY_BACKUP_MAX_DRIFT_PERSISTENT_PERIOD_MS, + LOAD_CELL_PRIMARY_BACKUP_MAX_DRIFT_PERSISTENT_PERIOD_MS ); } /*********************************************************************//** @@ -254,6 +251,9 @@ loadCellDataPublicationTimerCounter = 0; } + + // Monitor the load cells drift + monitorLoadCellsPrimaryBackupDriftOutOfRange(); } /*********************************************************************//** @@ -302,8 +302,8 @@ { // For the first tare, the weight of the reservoir should be considered // The current weight of the load cell should not be greater than the weight of the reservoir + the extra weight - F32 deltaWeight = fabs( weight - EMPTY_RESERVOIR_WEIGHT_GRAMS ); - isWeightOutOfRange = ( deltaWeight > MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_FIRST_TARE_GRAMS ? TRUE : FALSE ); + F32 deltaWeight = fabs( weight - LOAD_CELL_MIN_ALLOWED_WEIGHT_BEFORE_TARE_GRAMS ); + isWeightOutOfRange = ( deltaWeight > MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS ? TRUE : FALSE ); } else { @@ -378,12 +378,6 @@ if ( loadCellID < NUM_OF_LOAD_CELLS ) { result = loadcells[ loadCellID ].smallFilteredWeight; - - // If the load cell is in override mode, return the override weight - if ( OVERRIDE_KEY == loadcells[ loadCellID ].weight.override ) - { - result = loadcells[ loadCellID ].weight.ovData; - } } else { @@ -501,7 +495,44 @@ checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_WEIGHT_OUT_OF_RANGE, isWeightOutOfRange, weight, LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ); } +/*********************************************************************//** + * @brief + * The monitorLoadCellsPrimaryBackupDriftOutOfRange function monitors the + * load cells' primary and backup drift. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorLoadCellsPrimaryBackupDriftOutOfRange( void ) +{ + // TODO do we need this function at all? + F32 drift; + F32 loadCellADrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - + getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ) ); + + F32 loadCellBDrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - + getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_BACKUP ) ); + + BOOL isDriftOutOfRange = ( loadCellADrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ) || + ( loadCellBDrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); + + if ( TRUE == isDriftOutOfRange ) + { + drift = ( loadCellADrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ? loadCellADrift : loadCellBDrift ); + } + else + { + // Pick the biggest drift in between the two load cells when none of the is above range + drift = ( loadCellADrift > loadCellBDrift ? loadCellADrift : loadCellBDrift ); + } + + // TODO this alarm is disabled until a better drift algorithm is figured out. Drift check might be removed from the load cells + //checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, isDriftOutOfRange, drift, + // LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/