Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r6085153faf2a176c51a34653bdd3a36a4699e528 -r4930f437f97fdd4c44da75b88ab841dfdd0874a6 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 6085153faf2a176c51a34653bdd3a36a4699e528) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 4930f437f97fdd4c44da75b88ab841dfdd0874a6) @@ -28,31 +28,28 @@ // ********** private definitions ********** #define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. -#define LOAD_CELL_SAMPLES_TO_AVERAGE (100 / TASK_PRIORITY_INTERVAL) ///< Averaging load cell data over the reporting interval. -/// Optimization - multiplying is faster than dividing. -static const F32 LOAD_CELL_AVERAGE_MULTIPLIER = (1.0 / (F32)LOAD_CELL_SAMPLES_TO_AVERAGE); /// Conversion factor from ADC counts to grams. static const F32 ADC2GRAM = (0.0894 * 1.1338); #define LOAD_CELL_ZERO_OFFSET -1500.0 ///< Zero offset (in grams). TODO - right now, this is empty reservoir weight. #define LOAD_CELL_FILTER_ALPHA 0.05 ///< Alpha factor for the alpha filter used on load cell readings. -#define SIZE_OF_SMALL_LOAD_CELL_AVG 10 ///< Small load cell moving average has 10 samples. -#define SIZE_OF_LARGE_LOAD_CELL_AVG 40 ///< Large load cell moving average has 40 samples. +#define SIZE_OF_SMALL_LOAD_CELL_AVG 100 ///< Small load cell moving average has 100 raw samples @ 10ms intervals (1-second). +#define SIZE_OF_LARGE_LOAD_CELL_AVG 40 ///< Large load cell moving average has 40 samples from small filter @ 100ms intervals (4-second). /// Load cell data structure. typedef struct { - U32 measuredReadingSum; ///< Raw load cell sums for averaging - OVERRIDE_F32_T filteredWeight; ///< Latest filtered load cell weights + U32 rawReading; ///< Latest raw load cell reading + OVERRIDE_F32_T weight; ///< Latest load cell weight F32 autoCalOffset; ///< Load cell auto-calibration offset F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average - F32 smallFilteredWeight; ///< Load cell small filtered (8 sample) weight + 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 F32 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average - F32 largeFilteredWeight; ///< Load cell large filtered (32 sample) weight + F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight } LOADCELL_T; // ********** private data ********** @@ -89,12 +86,13 @@ for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - loadcells[ i ].filteredWeight.data = 0.0; - loadcells[ i ].filteredWeight.ovData = 0.0; - loadcells[ i ].filteredWeight.ovInitData = 0.0; - loadcells[ i ].filteredWeight.override = OVERRIDE_RESET; + loadcells[ i ].rawReading = 0; - loadcells[ i ].measuredReadingSum = 0; + loadcells[ i ].weight.data = 0.0; + loadcells[ i ].weight.ovData = 0.0; + loadcells[ i ].weight.ovInitData = 0.0; + loadcells[ i ].weight.override = OVERRIDE_RESET; + loadcells[ i ].autoCalOffset = 0.0; loadcells[ i ].largeFilterTotal = 0.0; @@ -128,37 +126,37 @@ U32 ii; // update sums for load cell average calculations - loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].measuredReadingSum += getFPGALoadCellA1(); - loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].measuredReadingSum += getFPGALoadCellA2(); - loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].measuredReadingSum += getFPGALoadCellB1(); - loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].measuredReadingSum += getFPGALoadCellB2(); + loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].rawReading = getFPGALoadCellA1(); + loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].rawReading = getFPGALoadCellA2(); + loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].rawReading = getFPGALoadCellB1(); + loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].rawReading = getFPGALoadCellB2(); + // Rolling average of last 100 raw samples in small filter + for ( ii = 0; ii < NUM_OF_LOAD_CELLS; ++ii ) + { + loadcells[ ii ].weight.data = (F32)loadcells[ ii ].rawReading * ADC2GRAM + LOAD_CELL_ZERO_OFFSET - loadcells[ ii ].autoCalOffset; + + // Update small filter with new weight sample + loadcells[ ii ].smallFilterTotal -= loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ]; + loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] = getLoadCellWeight( (LOAD_CELL_ID_T)ii ); + loadcells[ ii ].smallFilterTotal += getLoadCellWeight( (LOAD_CELL_ID_T)ii ); + loadcells[ ii ].smallFilteredWeight = loadcells[ ii ].smallFilterTotal / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; + smallReadingsIdx = INC_WRAP( smallReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); + } + // filter every 100ms - if ( ++loadCellFilterTimerCount >= LOAD_CELL_SAMPLES_TO_AVERAGE ) + if ( ++loadCellFilterTimerCount >= LOAD_CELL_REPORT_PERIOD ) { for ( ii = 0; ii < NUM_OF_LOAD_CELLS; ++ii ) { - // calculate load cell average weights - loadcells[ ii ].filteredWeight.data = (F32)loadcells[ ii ].measuredReadingSum * LOAD_CELL_AVERAGE_MULTIPLIER * - ADC2GRAM + LOAD_CELL_ZERO_OFFSET - loadcells[ ii ].autoCalOffset; - - // reset sums for next averaging - loadcells[ ii ].measuredReadingSum = 0; - - // Update filtered with new filtered weight sample and moving averages - loadcells[ ii ].smallFilterTotal -= loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ]; - loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] = loadcells[ ii ].filteredWeight.data; - loadcells[ ii ].smallFilterTotal += loadcells[ ii ].filteredWeight.data; - loadcells[ ii ].smallFilteredWeight = loadcells[ ii ].smallFilterTotal / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; - + // Update large filter with new small filter weight sample loadcells[ ii ].largeFilterTotal -= loadcells[ ii ].largeFilterReadings[ largeReadingsIdx ]; - loadcells[ ii ].largeFilterReadings[ largeReadingsIdx ] = loadcells[ ii ].filteredWeight.data; - loadcells[ ii ].largeFilterTotal += loadcells[ ii ].filteredWeight.data; + loadcells[ ii ].largeFilterReadings[ largeReadingsIdx ] = loadcells[ ii ].smallFilteredWeight; + loadcells[ ii ].largeFilterTotal += loadcells[ ii ].smallFilteredWeight; loadcells[ ii ].largeFilteredWeight = loadcells[ ii ].largeFilterTotal / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; } loadCellFilterTimerCount = 0; - smallReadingsIdx = INC_WRAP( smallReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); largeReadingsIdx = INC_WRAP( largeReadingsIdx, 0, SIZE_OF_LARGE_LOAD_CELL_AVG - 1 ); } @@ -167,9 +165,11 @@ { loadCellDataPublicationTimerCounter = 0; - // broadcast load cell data - broadcastLoadCellData( getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ), getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ), - getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ), getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_2_BACKUP ) ); + // broadcast small filtered load cell data + broadcastLoadCellData( loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].smallFilteredWeight, + loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].smallFilteredWeight, + loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].smallFilteredWeight, + loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].smallFilteredWeight ); } } @@ -184,7 +184,7 @@ void tareLoadCell( LOAD_CELL_ID_T loadCellID ) { // Add old auto calibration offset to get back to actual weight value - loadcells[ loadCellID ].autoCalOffset = ( loadcells[ loadCellID ].filteredWeight.data + loadcells[ loadCellID ].autoCalOffset ); + loadcells[ loadCellID ].autoCalOffset = ( loadcells[ loadCellID ].smallFilteredWeight + loadcells[ loadCellID ].autoCalOffset ); } /*********************************************************************//** @@ -202,26 +202,26 @@ /*********************************************************************//** * @brief - * The getLoadCellFilteredWeight function gets the measured filtered load cell - * weight for a given load cell ID. - * @details Inputs: load cell filtered weight + * The getLoadCellWeight function gets the measured load cell weight for + * a given load cell ID. + * @details Inputs: load cell weight * @details Outputs: none - * @param loadCellID ID of load cell to get filtered weight for - * @return the filtered load cell weight for the given load cell ID. + * @param loadCellID ID of load cell to get weight for + * @return the load cell weight for the given load cell ID. *************************************************************************/ -F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ) +F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ) { F32 result = 0; if ( loadCellID < NUM_OF_LOAD_CELLS ) { - if ( OVERRIDE_KEY == loadcells[ loadCellID ].filteredWeight.override ) + if ( OVERRIDE_KEY == loadcells[ loadCellID ].weight.override ) { - result = loadcells[ loadCellID ].filteredWeight.ovData; + result = loadcells[ loadCellID ].weight.ovData; } else { - result = loadcells[ loadCellID ].filteredWeight.data; + result = loadcells[ loadCellID ].weight.data; } } else @@ -241,7 +241,7 @@ * @param loadCellID ID of load cell to get small filtered weight for * @return the small filtered load cell weight for the given load cell ID. *************************************************************************/ -F32 getLoadCellSmallFilteredWeight( LOAD_CELL_ID_T loadCellID ) +F32 getLoadCellSmallFilteredWeight( LOAD_CELL_ID_T loadCellID ) { F32 result = 0; @@ -266,7 +266,7 @@ * @param loadCellID ID of load cell to get large filtered weight for * @return the large filtered load cell weight for the given load cell ID. *************************************************************************/ -F32 getLoadCellLargeFilteredWeight( LOAD_CELL_ID_T loadCellID ) +F32 getLoadCellLargeFilteredWeight( LOAD_CELL_ID_T loadCellID ) { F32 result = 0; @@ -325,8 +325,8 @@ if ( TRUE == isTestingActivated() ) { result = TRUE; - loadcells[ loadCellID ].filteredWeight.ovData = value; - loadcells[ loadCellID ].filteredWeight.override = OVERRIDE_KEY; + loadcells[ loadCellID ].weight.ovData = value; + loadcells[ loadCellID ].weight.override = OVERRIDE_KEY; } } @@ -350,8 +350,8 @@ if ( TRUE == isTestingActivated() ) { result = TRUE; - loadcells[ loadCellID ].filteredWeight.override = OVERRIDE_RESET; - loadcells[ loadCellID ].filteredWeight.ovData = loadcells[ loadCellID ].filteredWeight.ovInitData; + loadcells[ loadCellID ].weight.override = OVERRIDE_RESET; + loadcells[ loadCellID ].weight.ovData = loadcells[ loadCellID ].weight.ovInitData; } } Index: firmware/App/Controllers/LoadCell.h =================================================================== diff -u -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 -r4930f437f97fdd4c44da75b88ab841dfdd0874a6 --- firmware/App/Controllers/LoadCell.h (.../LoadCell.h) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) +++ firmware/App/Controllers/LoadCell.h (.../LoadCell.h) (revision 4930f437f97fdd4c44da75b88ab841dfdd0874a6) @@ -38,8 +38,7 @@ void tareLoadCell( LOAD_CELL_ID_T loadCellID ); void resetLoadCellOffset( LOAD_CELL_ID_T loadCellID ); -F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ); -F32 getLoadCellSmallFilteredWeight( LOAD_CELL_ID_T loadCellID ); +F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ); F32 getLoadCellLargeFilteredWeight( LOAD_CELL_ID_T loadCellID ); BOOL testSetLoadCellOverride( U32 loadCellID, F32 value );