Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r0774a37971585dacdc8398362393920c13d48426 -r8b56b0c617ac49536b8d53852b9621be873bade6 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 0774a37971585dacdc8398362393920c13d48426) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 8b56b0c617ac49536b8d53852b9621be873bade6) @@ -19,189 +19,202 @@ #include "FPGA.h" #include "TaskPriority.h" -DATA_DECL( U32, MeasuredLoadCellA1, loadCellA1raw, 0, 0 ); -DATA_DECL( U32, MeasuredLoadCellA2, loadCellA2raw, 0, 0 ); -DATA_DECL( U32, MeasuredLoadCellB1, loadCellB1raw, 0, 0 ); -DATA_DECL( U32, MeasuredLoadCellB2, loadCellB2raw, 0, 0 ); -static F32 Load_cell_a1_ave; -static F32 Load_cell_a2_ave; -static F32 Load_cell_b1_ave; -static F32 Load_cell_b2_ave; +/** + * @addtogroup LoadCells + * @{ + */ +// ********** 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 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. + +// ********** private data ********** + +static OVERRIDE_U32_T 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 U32 loadCellDataPublicationTimerCounter = 0; ///< used to schedule load cell data publication to CAN bus. + +// ********** private function prototypes ********** + /*********************************************************************//** * @brief - * The execLoadCell function gets load cell data from FPGA and advertises them over CAN. + * The initLoadCell function initializes the LoadCell module. * @details * Inputs : none - * Outputs : Advertising load call data. + * Outputs : LoadCell module initialized. * @return none *************************************************************************/ -void execLoadCell(void) +void initLoadCell( void ) { -#ifdef DEBUG_ENABLED - char debugStr[ 256 ]; -#endif - static U32 Counter = 0; - static U32 Load_cell_a1 = 0; - static U32 Load_cell_a2 = 0; - static U32 Load_cell_b1 = 0; - static U32 Load_cell_b2 = 0; - BOOL result; + U32 i; - loadCellA1raw.data = getFPGALoadCellA1() & 0x7FFFFFFF; // Temporary fix while FPGA code is being fixed - loadCellA2raw.data = getFPGALoadCellA2(); - loadCellB1raw.data = getFPGALoadCellB1(); - loadCellB2raw.data = getFPGALoadCellB2(); + 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; - Load_cell_a1 += getLoadCellA1raw(); - Load_cell_a2 += getLoadCellA2raw(); - Load_cell_b1 += getLoadCellB1raw(); - Load_cell_b2 += getLoadCellB2raw(); + measuredLoadCellReadingsSum[ i ] = 0; - Counter++; - if (Counter == LOAD_CELL_REPORT_PERIOD) - { - Counter = 0; - - Load_cell_a1_ave = (F32)(Load_cell_a1)*ADC2GRAM; // division for averaging folded into ADC2GRAM - Load_cell_a2_ave = (F32)(Load_cell_a2)*ADC2GRAM; - Load_cell_b1_ave = (F32)(Load_cell_b1)*ADC2GRAM; - Load_cell_b2_ave = (F32)(Load_cell_b2)*ADC2GRAM; - result = broadcastLoadCellData( Load_cell_a1_ave, Load_cell_a2_ave, Load_cell_b1_ave, Load_cell_b2_ave ); -#ifdef DEBUG_ENABLED - if (result == FALSE) - sprintf( debugStr, "Adding load cell data to CAN buffer failed" ); -#else - (void)result; -#endif - Load_cell_a1 = 0; - Load_cell_a2 = 0; - Load_cell_b1 = 0; - Load_cell_b2 = 0; - } + filteredLoadCellWeights[ i ] = 0.0; + } } -F32 getLoadCellA1Ave(void) +/*********************************************************************//** + * @brief + * The execLoadCell function gets load cell data from FPGA and advertises them over CAN. + * @details + * Inputs : none + * Outputs : Advertising load call data. + * @return none + *************************************************************************/ +void execLoadCell(void) { - return Load_cell_a1_ave; + // 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; + // 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 ) + { + loadCellDataPublicationTimerCounter = 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 ] ); + // 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; + } } -F32 getLoadCellA2Ave(void) +/************************************************************************* + * @brief + * The getMeasuredRawLoadCellReading function gets the measured raw load cell \n + * reading for a given load cell ID. + * @details + * Inputs : measuredLoadCellReadingsRaw + * 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. + *************************************************************************/ +U32 getMeasuredRawLoadCellReading( U32 loadCellID ) { - return Load_cell_a2_ave; -} + U32 result = 0; -F32 getLoadCellB1Ave(void) -{ - return Load_cell_b1_ave; -} + if ( loadCellID < NUM_OF_LOAD_CELLS ) + { + if ( OVERRIDE_KEY == measuredLoadCellReadingsRaw[ loadCellID ].override ) + { + result = measuredLoadCellReadingsRaw[ loadCellID ].ovData; + } + else + { + result = measuredLoadCellReadingsRaw[ loadCellID ].data; + } + } + else + { + activateAlarmNoData( ALARM_ID_SOFTWARE_FAULT ); + } -F32 getLoadCellB2Ave(void) -{ - return Load_cell_b2_ave; + return result; } /************************************************************************* - * @brief testSetLoadCellA1Override and testResetLoadCellA1Override - * The testSetLoadCellA1Override function overrides the measured \n - * load cell A1. \n - * The testResetLoadCellA1Override function resets the override of the \n - * load cell A1. \n + * @brief + * The getLoadCellFilteredWeight function gets the measured filtered load cell \n + * weight for a given load cell ID. * @details - * Inputs : none - * Outputs : loadCellA1raw - * @param value : override measured load cell A1 raw - * @return TRUE if override successful, FALSE if not + * Inputs : Load_cell_a1_ave[] + * 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. *************************************************************************/ -DATA_OVERRIDE_FUNC( U32, testSetLoadCellA1Override, testResetLoadCellA1Override, loadCellA1raw ) +F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ) +{ + F32 result = 0; -/************************************************************************* - * @brief testSetLoadCellA2Override and testResetLoadCellA2Override - * The testSetLoadCellA2Override function overrides the measured \n - * load cell A2. \n - * The testResetLoadCellA1Override function resets the override of the \n - * load cell A2. \n - * @details - * Inputs : none - * Outputs : loadCellA2raw - * @param value : override measured load cell A2 raw - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -DATA_OVERRIDE_FUNC( U32, testSetLoadCellA2Override, testResetLoadCellA2Override, loadCellA2raw ) + if ( loadCellID < NUM_OF_LOAD_CELLS ) + { + result = filteredLoadCellWeights[ loadCellID ]; + } + else + { + activateAlarmNoData( ALARM_ID_SOFTWARE_FAULT ); + } + return result; +} + + /************************************************************************* - * @brief testSetLoadCellB1Override and testResetLoadCellB1Override - * The testSetLoadCellB1Override function overrides the measured \n - * load cell B1. \n - * The testResetLoadCellB1Override function resets the override of the \n - * load cell B1. \n - * @details - * Inputs : none - * Outputs : loadCellB1raw - * @param value : override measured load cell B1 raw - * @return TRUE if override successful, FALSE if not + * TEST SUPPORT FUNCTIONS *************************************************************************/ -DATA_OVERRIDE_FUNC( U32, testSetLoadCellB1Override, testResetLoadCellB1Override, loadCellB1raw ) + /************************************************************************* - * @brief testSetLoadCellB2Override and testResetLoadCellB2Override - * The testSetLoadCellB2Override function overrides the measured \n - * load cell B2. \n - * The testResetLoadCellB2Override function resets the override of the \n - * load cell B2. \n + * @brief + * The testSetLoadCellOverride function overrides the measured \n + * load cell A1. * @details * Inputs : none - * Outputs : loadCellB2raw - * @param value : override measured load cell B2 raw + * Outputs : measuredLoadCellReadingsRaw[] + * @param value : override measured raw load cell reading + * @param loadCellID : ID of the load cell to override. * @return TRUE if override successful, FALSE if not *************************************************************************/ -DATA_OVERRIDE_FUNC( U32, testSetLoadCellB2Override, testResetLoadCellB2Override, loadCellB2raw ) +BOOL testSetLoadCellOverride( U32 value, U32 loadCellID ) +{ + BOOL result = FALSE; -/************************************************************************* - * @brief getLoadCellA1raw - * The getLoadCellA1raw function gets the measured load cell A1 \n - * current. - * @details - * Inputs : loadCellA1raw - * Outputs : none - * @param none - * @return the load cell A1 raw value. - *************************************************************************/ -DATA_GET( U32, getLoadCellA1raw, loadCellA1raw ) + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + measuredLoadCellReadingsRaw[ loadCellID ].ovData = value; + measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_KEY; + } -/************************************************************************* - * @brief getLoadCellA2raw - * The getLoadCellA2raw function gets the measured load cell A2 \n - * current. - * @details - * Inputs : loadCellA2raw - * Outputs : none - * @param none - * @return the load cell A2 raw value. - *************************************************************************/ -DATA_GET( U32, getLoadCellA2raw, loadCellA2raw ) + return result; +} /************************************************************************* - * @brief getLoadCellB1raw - * The getLoadCellB1raw function gets the measured load cell B1 \n - * current. + * @brief + * The testResetLoadCellOverride function resets the override of the \n + * load cell A1. * @details - * Inputs : loadCellB1raw - * Outputs : none - * @param none - * @return the load cell B1 raw value. + * Inputs : none + * Outputs : measuredLoadCellReadingsRaw[] + * @param loadCellID : ID of the load cell to override. + * @return TRUE if reset successful, FALSE if not *************************************************************************/ -DATA_GET( U32, getLoadCellB1raw, loadCellB1raw ) +BOOL testResetLoadCellOverride( U32 loadCellID ) +{ + BOOL result = FALSE; -/************************************************************************* - * @brief getLoadCellB2raw - * The getLoadCellB2raw function gets the measured load cell B2 \n - * current. - * @details - * Inputs : loadCellB2raw - * Outputs : none - * @param none - * @return the load cell B2 raw value. - *************************************************************************/ -DATA_GET( U32, getLoadCellB2raw, loadCellB2raw ) + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_RESET; + measuredLoadCellReadingsRaw[ loadCellID ].ovData = measuredLoadCellReadingsRaw[ loadCellID ].ovInitData; + } + + return result; +}