/**********************************************************************//** * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file LoadCell.c * * @date 25-Feb-2020 * @author S. Nejatali * * @brief Processing sensor data. * **************************************************************************/ #include "LoadCell.h" #include "SystemCommMessages.h" #include "FPGA.h" #include "TaskPriority.h" /** * @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 initLoadCell function initializes the LoadCell module. * @details * Inputs : none * Outputs : LoadCell module initialized. * @return none *************************************************************************/ void initLoadCell( void ) { U32 i; 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; measuredLoadCellReadingsSum[ i ] = 0; filteredLoadCellWeights[ i ] = 0.0; } } /*********************************************************************//** * @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) { // get latest raw load cell readings measuredLoadCellReadingsRaw[ LOAD_CELL_A1 ].data = getFPGALoadCellA1(); measuredLoadCellReadingsRaw[ LOAD_CELL_A2 ].data = getFPGALoadCellA2(); measuredLoadCellReadingsRaw[ LOAD_CELL_B1 ].data = getFPGALoadCellB1(); measuredLoadCellReadingsRaw[ LOAD_CELL_B2 ].data = 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 ) { 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; } } /************************************************************************* * @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 ) { U32 result = 0; 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 ); } return result; } /************************************************************************* * @brief * The getLoadCellFilteredWeight function gets the measured filtered load cell \n * weight for a given load cell ID. * @details * 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. *************************************************************************/ F32 getLoadCellFilteredWeight( LOAD_CELL_ID_T loadCellID ) { F32 result = 0; if ( loadCellID < NUM_OF_LOAD_CELLS ) { result = filteredLoadCellWeights[ loadCellID ]; } else { activateAlarmNoData( ALARM_ID_SOFTWARE_FAULT ); } return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief * The testSetLoadCellOverride function overrides the measured \n * load cell A1. * @details * Inputs : none * 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 *************************************************************************/ BOOL testSetLoadCellOverride( U32 value, U32 loadCellID ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; measuredLoadCellReadingsRaw[ loadCellID ].ovData = value; measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_KEY; } return result; } /************************************************************************* * @brief * The testResetLoadCellOverride function resets the override of the \n * load cell A1. * @details * Inputs : none * Outputs : measuredLoadCellReadingsRaw[] * @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 ( TRUE == isTestingActivated() ) { result = TRUE; measuredLoadCellReadingsRaw[ loadCellID ].override = OVERRIDE_RESET; measuredLoadCellReadingsRaw[ loadCellID ].ovData = measuredLoadCellReadingsRaw[ loadCellID ].ovInitData; } return result; }