Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -rdd3356035996866e5db7678d352f933fc22ad789 -r4545a748791772cb1f21ea5e8fbbf661b7f8a062 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision dd3356035996866e5db7678d352f933fc22ad789) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 4545a748791772cb1f21ea5e8fbbf661b7f8a062) @@ -28,18 +28,24 @@ #define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. #define LOAD_CELL_SAMPLES_TO_AVERAGE LOAD_CELL_REPORT_PERIOD ///< Averaging load cell data over the reporting interval. -//#define ADC2GRAM (0.0894 / LOAD_CELL_SAMPLES_TO_AVERAGE) ///< Conversion factor from ADC counts to grams. Division for averaging is folded into this value. -#define ADC2GRAM (0.01183 / LOAD_CELL_SAMPLES_TO_AVERAGE) ///< Conversion factor from ADC counts to grams. Division for averaging is folded into this value. +#define LOAD_CELL_AVERAGE_MULTIPLIER (1.0 / (F32)LOAD_CELL_SAMPLES_TO_AVERAGE) ///< Optimization - multiplying is faster than dividing. +// TODO - gain and offset for load cells should be read from NV Data calibration record. +#define ADC2GRAM (0.0894 * 1.1338) ///< Conversion factor from ADC counts to grams. Division for averaging is folded into this value. +#define LOAD_CELL_ZERO_OFFSET -1215.0 ///< Zero offset (in grams). TODO - right now, this is empty reservoir weight. // ********** private data ********** -static OVERRIDE_U32_T measuredLoadCellReadingsRaw[ NUM_OF_LOAD_CELLS ]; ///< Latest measured raw load cell readings. +static OVERRIDE_U32_T loadCellDataPublishInterval = { LOAD_CELL_REPORT_PERIOD, LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data interval in ms/task interval. +static U32 measuredLoadCellReadingsRaw[ NUM_OF_LOAD_CELLS ]; ///< Latest measured raw load cell readings. static U32 measuredLoadCellReadingsSum[ NUM_OF_LOAD_CELLS ]; ///< Raw load cell sums for averaging. -static F32 filteredLoadCellWeights[ NUM_OF_LOAD_CELLS ]; ///< Latest filtered load cell weights. +static OVERRIDE_F32_T filteredLoadCellWeights[ NUM_OF_LOAD_CELLS ]; ///< Latest filtered load cell weights. +static U32 loadCellFilterTimerCount = 0; ///< used to schedule load cell filtering. static U32 loadCellDataPublicationTimerCounter = 0; ///< used to schedule load cell data publication to CAN bus. // ********** private function prototypes ********** +static U32 getLoadCellDataPublishInterval( void ); + /*********************************************************************//** * @brief * The initLoadCell function initializes the LoadCell module. @@ -54,14 +60,13 @@ for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - measuredLoadCellReadingsRaw[ i ].data = 0; - measuredLoadCellReadingsRaw[ i ].ovData = 0; - measuredLoadCellReadingsRaw[ i ].ovInitData = 0; - measuredLoadCellReadingsRaw[ i ].override = OVERRIDE_RESET; + filteredLoadCellWeights[ i ].data = 0.0; + filteredLoadCellWeights[ i ].ovData = 0.0; + filteredLoadCellWeights[ i ].ovInitData = 0.0; + filteredLoadCellWeights[ i ].override = OVERRIDE_RESET; measuredLoadCellReadingsSum[ i ] = 0; - - filteredLoadCellWeights[ i ] = 0.0; + measuredLoadCellReadingsRaw[ i ] = 0; } } @@ -76,58 +81,72 @@ void execLoadCell(void) { // get latest raw load cell readings - measuredLoadCellReadingsRaw[ LOAD_CELL_A1 ].data = getFPGALoadCellA1() & 0x7FFFFFFF; // Temporary neg sign removal fix while FPGA code is being fixed - measuredLoadCellReadingsRaw[ LOAD_CELL_A2 ].data = getFPGALoadCellA2() & 0x7FFFFFFF; - measuredLoadCellReadingsRaw[ LOAD_CELL_B1 ].data = getFPGALoadCellB1() & 0x7FFFFFFF; - measuredLoadCellReadingsRaw[ LOAD_CELL_B2 ].data = getFPGALoadCellB2() & 0x7FFFFFFF; + measuredLoadCellReadingsRaw[ LOAD_CELL_A1 ] = getFPGALoadCellA1(); + measuredLoadCellReadingsRaw[ LOAD_CELL_A2 ] = getFPGALoadCellA2(); + measuredLoadCellReadingsRaw[ LOAD_CELL_B1 ] = getFPGALoadCellB1(); + measuredLoadCellReadingsRaw[ LOAD_CELL_B2 ] = getFPGALoadCellB2(); // update sums for load cell average calculations - measuredLoadCellReadingsSum[ LOAD_CELL_A1 ] += getMeasuredRawLoadCellReading( LOAD_CELL_A1 ); - measuredLoadCellReadingsSum[ LOAD_CELL_A2 ] += getMeasuredRawLoadCellReading( LOAD_CELL_A2 ); - measuredLoadCellReadingsSum[ LOAD_CELL_B1 ] += getMeasuredRawLoadCellReading( LOAD_CELL_B1 ); - measuredLoadCellReadingsSum[ LOAD_CELL_B2 ] += getMeasuredRawLoadCellReading( LOAD_CELL_B2 ); - // broadcast load cell data if we are at scheduled interval. - if ( ++loadCellDataPublicationTimerCounter == LOAD_CELL_REPORT_PERIOD ) + measuredLoadCellReadingsSum[ LOAD_CELL_A1 ] += measuredLoadCellReadingsRaw[ LOAD_CELL_A1 ]; + measuredLoadCellReadingsSum[ LOAD_CELL_A2 ] += measuredLoadCellReadingsRaw[ LOAD_CELL_A2 ]; + measuredLoadCellReadingsSum[ LOAD_CELL_B1 ] += measuredLoadCellReadingsRaw[ LOAD_CELL_B1 ]; + measuredLoadCellReadingsSum[ LOAD_CELL_B2 ] += measuredLoadCellReadingsRaw[ LOAD_CELL_B2 ]; + + // filter every 100ms + if ( ++loadCellFilterTimerCount >= LOAD_CELL_SAMPLES_TO_AVERAGE ) { - loadCellDataPublicationTimerCounter = 0; + loadCellFilterTimerCount = 0; + // calculate load cell average weights - filteredLoadCellWeights[ LOAD_CELL_A1 ] = (F32)(measuredLoadCellReadingsSum[ LOAD_CELL_A1 ]) * ADC2GRAM; // division for averaging folded into ADC2GRAM - filteredLoadCellWeights[ LOAD_CELL_A2 ] = (F32)(measuredLoadCellReadingsSum[ LOAD_CELL_A2 ]) * ADC2GRAM; - filteredLoadCellWeights[ LOAD_CELL_B1 ] = (F32)(measuredLoadCellReadingsSum[ LOAD_CELL_B1 ]) * ADC2GRAM; - filteredLoadCellWeights[ LOAD_CELL_B2 ] = (F32)(measuredLoadCellReadingsSum[ LOAD_CELL_B2 ]) * ADC2GRAM; - // broadcast load cell data - broadcastLoadCellData( filteredLoadCellWeights[ LOAD_CELL_A1 ], filteredLoadCellWeights[ LOAD_CELL_A2 ], - filteredLoadCellWeights[ LOAD_CELL_B1 ], filteredLoadCellWeights[ LOAD_CELL_B2 ] ); + filteredLoadCellWeights[ LOAD_CELL_A1 ].data = (F32)measuredLoadCellReadingsSum[ LOAD_CELL_A1 ] * + LOAD_CELL_AVERAGE_MULTIPLIER * ADC2GRAM + LOAD_CELL_ZERO_OFFSET; + filteredLoadCellWeights[ LOAD_CELL_A2 ].data = (F32)measuredLoadCellReadingsSum[ LOAD_CELL_A2 ] * + LOAD_CELL_AVERAGE_MULTIPLIER * ADC2GRAM + LOAD_CELL_ZERO_OFFSET; + filteredLoadCellWeights[ LOAD_CELL_B1 ].data = (F32)measuredLoadCellReadingsSum[ LOAD_CELL_B1 ] * + LOAD_CELL_AVERAGE_MULTIPLIER * ADC2GRAM + LOAD_CELL_ZERO_OFFSET; + filteredLoadCellWeights[ LOAD_CELL_B2 ].data = (F32)measuredLoadCellReadingsSum[ LOAD_CELL_B2 ] * + LOAD_CELL_AVERAGE_MULTIPLIER * ADC2GRAM + LOAD_CELL_ZERO_OFFSET; + // reset sums for next averaging measuredLoadCellReadingsSum[ LOAD_CELL_A1 ] = 0; measuredLoadCellReadingsSum[ LOAD_CELL_A2 ] = 0; measuredLoadCellReadingsSum[ LOAD_CELL_B1 ] = 0; measuredLoadCellReadingsSum[ LOAD_CELL_B2 ] = 0; } + + // broadcast load cell data if we are at scheduled interval. + if ( ++loadCellDataPublicationTimerCounter >= getLoadCellDataPublishInterval() ) + { + loadCellDataPublicationTimerCounter = 0; + + // broadcast load cell data + broadcastLoadCellData( getLoadCellFilteredWeight( LOAD_CELL_A1 ), getLoadCellFilteredWeight( LOAD_CELL_A2 ), + getLoadCellFilteredWeight( LOAD_CELL_B1 ), getLoadCellFilteredWeight( LOAD_CELL_B2 ) ); + } } -/************************************************************************* +/*********************************************************************//** * @brief - * The getMeasuredRawLoadCellReading function gets the measured raw load cell \n - * reading for a given load cell ID. + * The getLoadCellFilteredWeight function gets the measured filtered load cell \n + * weight for a given load cell ID. * @details - * Inputs : measuredLoadCellReadingsRaw + * Inputs : filteredLoadCellWeights[] * Outputs : none - * @param loadCellID : ID of load cell to get raw reading for. - * @return the measured raw load cell reading for the given load cell ID. + * @param loadCellID : ID of load cell to get filtered weight for. + * @return the filtered load cell weight for the given load cell ID. *************************************************************************/ -U32 getMeasuredRawLoadCellReading( U32 loadCellID ) +F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ) { - U32 result = 0; + F32 result = 0; if ( loadCellID < NUM_OF_LOAD_CELLS ) { - if ( OVERRIDE_KEY == measuredLoadCellReadingsRaw[ loadCellID ].override ) + if ( OVERRIDE_KEY == filteredLoadCellWeights[ loadCellID ].override ) { - result = measuredLoadCellReadingsRaw[ loadCellID ].ovData; + result = filteredLoadCellWeights[ loadCellID ].ovData; } else { - result = measuredLoadCellReadingsRaw[ loadCellID ].data; + result = filteredLoadCellWeights[ loadCellID ].data; } } else @@ -138,28 +157,23 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief - * The getLoadCellFilteredWeight function gets the measured filtered load cell \n - * weight for a given load cell ID. + * The getLoadCellDataPublishInterval function gets the load cell data \n + * publication interval. * @details - * Inputs : Load_cell_a1_ave[] + * Inputs : loadCellDataPublishInterval * Outputs : none - * @param loadCellID : ID of load cell to get filtered weight for. - * @return the measured filtered load cell weight for the given load cell ID. + * @return the current load cell data publication interval (in ms/task interval). *************************************************************************/ -F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ) +static U32 getLoadCellDataPublishInterval( void ) { - F32 result = 0; + U32 result = loadCellDataPublishInterval.data; - if ( loadCellID < NUM_OF_LOAD_CELLS ) + if ( OVERRIDE_KEY == loadCellDataPublishInterval.override ) { - result = filteredLoadCellWeights[ loadCellID ]; + result = loadCellDataPublishInterval.ovData; } - else - { - activateAlarmNoData( ALARM_ID_SOFTWARE_FAULT ); - } return result; } @@ -170,51 +184,108 @@ *************************************************************************/ -/************************************************************************* +/*********************************************************************//** * @brief * The testSetLoadCellOverride function overrides the measured \n * load cell A1. * @details * Inputs : none - * Outputs : measuredLoadCellReadingsRaw[] - * @param value : override measured raw load cell reading + * Outputs : filteredLoadCellWeights[] * @param loadCellID : ID of the load cell to override. + * @param value : override filtered load cell weight * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetLoadCellOverride( U32 value, U32 loadCellID ) +BOOL testSetLoadCellOverride( U32 loadCellID, F32 value ) { BOOL result = FALSE; - if ( TRUE == isTestingActivated() ) + if ( loadCellID < NUM_OF_LOAD_CELLS ) { - result = TRUE; - measuredLoadCellReadingsRaw[ loadCellID ].ovData = value; - measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_KEY; + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + filteredLoadCellWeights[ loadCellID ].ovData = value; + filteredLoadCellWeights[ loadCellID ].override = OVERRIDE_KEY; + } } return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetLoadCellOverride function resets the override of the \n * load cell A1. * @details * Inputs : none - * Outputs : measuredLoadCellReadingsRaw[] + * Outputs : filteredLoadCellWeights[] * @param loadCellID : ID of the load cell to override. * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetLoadCellOverride( U32 loadCellID ) { BOOL result = FALSE; + if ( loadCellID < NUM_OF_LOAD_CELLS ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + filteredLoadCellWeights[ loadCellID ].override = OVERRIDE_RESET; + filteredLoadCellWeights[ loadCellID ].ovData = filteredLoadCellWeights[ loadCellID ].ovInitData; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetLoadCellDataPublishIntervalOverride function overrides the \n + * load cell data publish interval. + * @details + * Inputs : none + * Outputs : loadCellDataPublishInterval + * @param value : override load cell data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetLoadCellDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + if ( TRUE == isTestingActivated() ) { + U32 intvl = value / TASK_PRIORITY_INTERVAL; + result = TRUE; - measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_RESET; - measuredLoadCellReadingsRaw[ loadCellID ].ovData = measuredLoadCellReadingsRaw[ loadCellID ].ovInitData; + loadCellDataPublishInterval.ovData = intvl; + loadCellDataPublishInterval.override = OVERRIDE_KEY; } return result; } + +/*********************************************************************//** + * @brief + * The testResetLoadCellDataPublishIntervalOverride function resets the override \n + * of the load cell data publish interval. + * @details + * Inputs : none + * Outputs : loadCellDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetLoadCellDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + loadCellDataPublishInterval.override = OVERRIDE_RESET; + loadCellDataPublishInterval.ovData = loadCellDataPublishInterval.ovInitData; + } + + return result; +} + +/**@}*/