Index: firmware/App/Drivers/ConductivityTeensy.c =================================================================== diff -u -rfea37ad4659d4162d43f3e343cd5b266c2757ea9 -r0797158d6e367debb04e043798f1aeb1fb17063b --- firmware/App/Drivers/ConductivityTeensy.c (.../ConductivityTeensy.c) (revision fea37ad4659d4162d43f3e343cd5b266c2757ea9) +++ firmware/App/Drivers/ConductivityTeensy.c (.../ConductivityTeensy.c) (revision 0797158d6e367debb04e043798f1aeb1fb17063b) @@ -7,22 +7,23 @@ * * @file ConductivityTeensy.c * -* @author (last) Arpita Srivastava -* @date (last) 3-Nov-2025 +* @author (last) Michael Garthwaite +* @date (last) 06-Mar-2026 * * @author (original) Arpita Srivastava -* @date (original) 3-Nov-2025 +* @date (original) 03-Nov-2025 * ***************************************************************************/ -#include // Used for calculating the polynomial calibration equation. +#include // Used for calculating the polynomial calibration equation and INF #include // For memcpy #include "sci.h" #include "sys_dma.h" #include "Comm.h" #include "ConductivityTeensy.h" +#include "Messaging.h" #include "Timers.h" // ********** private definitions ********** @@ -46,25 +47,28 @@ #define RX_SIZE_UPDATE_MEASUREMENT_SETTINGS 1 ///< Expected response bytes length of update measurement settings cmd. #define RX_SIZE_GET_MEASUREMENT_SETTNGS ( sizeof( COND_MEASUREMENT_SETTINGS_T ) ) ///< Expected response bytes length of get measurement settings cmd. #define RX_SIZE_START_MEASUREMENT ( sizeof( COND_SENSOR_DATA_T ) ) ///< Expected response bytes length of start measurement cmd. -#define RX_SIZE_STOP_MEASUREMENT 0 ///< Expected response bytes length of stop measurement cmd. +#define RX_SIZE_STOP_MEASUREMENT 1 ///< Expected response bytes length of stop measurement cmd. #define RX_SIZE_GET_ALL_MEASUREMENTS ( 6 * RX_SIZE_START_MEASUREMENT ) ///< Expected response bytes length of get all sensor measurements cmd -#define RX_SIZE_SELECT_SENSOR 0 ///< Expected response bytes length of select sensor cmd. +#define RX_SIZE_SELECT_SENSOR 1 ///< Expected response bytes length of select sensor cmd. #define RX_SIZE_GET_SINGLE_MEASUREMENT ( sizeof( COND_SENSOR_DATA_T ) ) ///< Expected response bytes length of get single sensor measurement cmd. +#define COND_INIT_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Timeout before which we should transition to idle state. #define COND_STATUS_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Timeout before which we should receive acknowledgment from teensy #define COND_DATA_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Timeout before which we should receive data from teensy +#define COND_TEMP_OFFSET 25 ///< Temperature offset constant used in RTD calculations. +#define COND_CONVERSION_SM_TO_USCM 1000000.0F ///< Conductivity conversion from siemens per meter to micro siemens per centimeter. +#define COND_INFINITE_R_VALUE 800000 ///< Resistance value for when the driver detects INF from the sensor. // ********** private data ********** -static COND_COMM_STATE_T condCommState; +static COND_COMM_STATE_T condCommState; ///< Current Conductivity driver comm state. +static U32 condInitTime; ///< Tracks duration of init state. static U32 condResponseTime; ///< Tracks duration between cmd sent and its response received. static U32 condReceiptCounter; ///< Conductivity response receipt counter. static U32 condTransmitCounter; ///< Conductivity command transmit counter. static BOOL condAutomatedDataPolling; ///< Flag indicating automated conductivity measurements polling has started. static BOOL condWriteCommandInProgress; ///< Flag indicating an Conductivity write command is in progress. -static BOOL condReadCommandInProgress; ///< Flag indicating an Conductivity read command is in progress. -static BOOL condBulkWriteAndReadInProgress; ///< Flag indicating an Conductivity bulk write and read command are in progress. static BOOL condWriteCmdRspnsRcvd; ///< Flag indicating a response to an Conductivity write command has been received. // Conductivity comm buffers @@ -90,17 +94,19 @@ static COND_UPDATE_EEPROM_STATUS_T condUpdateEEPROMstatus; ///< Received update EEPROM status. static COND_UPDATE_MST_STATUS_T condUpdateSettingStatus[ MAX_COND_MST_PARAM_IDX ]; ///< Received update measurement settings status. static U08 condStopMeasurementSatus; ///< Received acknowledgment of stop measurement command +static U08 condSelectSensorStatus; ///< Received acknowledgment of select sensor status. static COND_SENSOR_DATA_T condRawMeasurement[ MAX_TEENSY_SENSOR ]; ///< Received raw sensor values (includes impedance and rtd). static COND_CALCULATED_MEASUREMENTS_T condCalculatedMeasurement[ MAX_TEENSY_SENSOR ]; ///< Calculated conductivity and temperature values static COND_COEFF_T condCoeff[ MAX_TEENSY_SENSOR ]; ///< Coefficients used to calculate conductivity and temperature values. static TEENSY_SENSOR_INDEX_T currentSelectedSensor; ///< Current selected sensor to get measurement of single sensor. Value 1 to 6. static COND_EEPROM_DATA_T eePromDataTX; ///< Transmitted EEPROM data to Teensy for update EEPROM cmd. -static COND_EEPROM_DATA_T eePromDataRX; ///< Received EEPROM data by get EEPROM data cmd. static COND_MEASUREMENT_SETTINGS_T measurementSettingsTX; ///< Transmitted measurement settings to Teensy for update measurement settings cmd. static COND_MEASUREMENT_SETTINGS_T measurementSettingsRX; ///< Received measurement settings by get measurement settings cmd. +static COND_MODELS_T currentConductivityModel; ///< Current Conductivity Model selected. +static BOOL eepromInit; ///< Boolean to determine if we are loading eeprom data from sensors. -// Command Map +// Teensy Command Map static const COND_CMD_DATA_T teensyCmdMap[] = { // Command Index / Sub state Command Length of expected response data { TEENSY_CMD_INIT_SENSOR , ( U08* )"a" , RX_SIZE_INIT_SENSOR }, @@ -113,18 +119,17 @@ { TEENSY_CMD_STOP_MEASUREMENT , ( U08* )"n" , RX_SIZE_STOP_MEASUREMENT }, { TEENSY_CMD_GET_ALL_MEASUREMENTS , ( U08* )"g" , RX_SIZE_GET_ALL_MEASUREMENTS }, { TEENSY_CMD_GET_SINGLE_MEASUREMENT , ( U08* )"h" , RX_SIZE_GET_SINGLE_MEASUREMENT }, + { TEENSY_CMD_SELECT_SENSOR , ( U08* )"u" , RX_SIZE_SELECT_SENSOR }, }; // ********** private function prototypes ********** static void initCondDMAchannels( void ); -static void initEEPROMdata( void ); -static void initMeasurementSettings( void ); +static COND_COMM_STATE_T handleConductivityInit( void ); static COND_COMM_STATE_T handleConductivityIdle( void ); static COND_COMM_STATE_T handleConductivityTX( void ); static COND_COMM_STATE_T handleConductivityRX( void ); -static COND_COMM_STATE_T handleFailedState( void ); static void consumeUnexpectedConductivityData( void ); static void setupConductivityDMAForWriteCmd( U32 bytes2Transmit ); @@ -169,15 +174,20 @@ static COND_COMM_STATE_T txGetSingleMeasurement( void); static COND_COMM_STATE_T rxGetSingleMeasurement( void ); -static void enqueueSingleMeasurement(TEENSY_SENSOR_INDEX_T sensorNum); -static COND_PARSE_STATUS parseMeasurementSettings( const U08 *buffer, U32 len ); +static COND_COMM_STATE_T txSelectSensor( void ); +static COND_COMM_STATE_T rxSelectSensor( void ); + static COND_PARSE_STATUS parseEEPROMdata( const U08 *buffer, U32 len ); -static COND_PARSE_STATUS parseConductivityMeasurements( const U08 *buffer, U32 len ); +static COND_PARSE_STATUS parseConductivityMeasurements( const U08 *buffer ); static U32 getTeensyCondId( CONDUCTIVITY_SENSORS_T sensorId ); static void calculateConductivity( TEENSY_SENSOR_INDEX_T sensorNum ); +static void calculateConductivityAly( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ); +static void calculateConductivityUpdatedStandard( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ); +static void calculateConductivityStandard( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ); static void calculateTemperature( TEENSY_SENSOR_INDEX_T sensorNum ); +static void calculateResistance( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ); /*********************************************************************//** * @brief @@ -188,14 +198,13 @@ *************************************************************************/ void initConductivityTeensy( void ) { - condCommState = COND_COMM_STATE_IDLE; + condCommState = COND_COMM_STATE_INIT; + condInitTime = getMSTimerCount(); condResponseTime = 0; condReceiptCounter = 0; condTransmitCounter = 0; condAutomatedDataPolling = FALSE; condWriteCommandInProgress = FALSE; - condReadCommandInProgress = FALSE; - condBulkWriteAndReadInProgress = FALSE; condWriteCmdRspnsRcvd = FALSE; memset( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); @@ -205,32 +214,29 @@ memset( &condCmdQ, 0, COND_CMD_Q_LEN ); memset( &condUpdateSettingStatus, 0, MAX_COND_MST_PARAM_IDX ); - memset( &condRawMeasurement, 0, MAX_TEENSY_SENSOR ); - memset( &condCalculatedMeasurement, 0, MAX_TEENSY_SENSOR ); - memset( &condCoeff, 0, MAX_TEENSY_SENSOR ); + memset( &condRawMeasurement, 0, ( sizeof( condRawMeasurement ) * MAX_TEENSY_SENSOR ) ); + memset( &condCalculatedMeasurement, 0, ( sizeof( condCalculatedMeasurement ) * MAX_TEENSY_SENSOR ) ); + memset( &condCoeff, 0, ( sizeof( condCoeff ) * MAX_TEENSY_SENSOR ) ); queueCount = 0; queueRearIndex = 0; queueFrontIndex = 0; currentCmd = TEENSY_CMD_INIT_SENSOR; - - condInitStatus = COND_INIT_STATUS_UNITIALIZED; - condUpdateEEPROMstatus = COND_UPDATE_EEPROM_STATUS_UNITIALIZED; + eepromInit = TRUE; + condInitStatus = COND_INIT_STATUS_UNINITIALIZED; + condUpdateEEPROMstatus = COND_UPDATE_EEPROM_STATUS_UNINITIALIZED; condStopMeasurementSatus = 0; + condSelectSensorStatus = 0; currentSelectedSensor = TEENSY_SENSOR_0; + currentConductivityModel = STANDARD; initCondDMAchannels(); - //TODO Clean up after testing. - // add init conductivity commands enqueue( TEENSY_CMD_STOP_MEASUREMENT ); enqueue( TEENSY_CMD_INIT_SENSOR ); enqueue( TEENSY_CMD_GET_INIT_STATUS ); -// initEEPROMdata( ); -// initMeasurementSettings( ); -// enqueueSingleMeasurement(2); - - + enqueue( TEENSY_CMD_SELECT_SENSOR ); + enqueue( TEENSY_CMD_GET_EEPROM_DATA ); } /*********************************************************************//** @@ -298,68 +304,6 @@ /*********************************************************************//** * @brief - * The initEEPROMdata function populates eePromDataTX structure and enqueues - * update EEPROM data command in the the command queue. - * @details \b Inputs: none - * @details \b Outputs: eePromDataTX : EEPROM data to be updated on Teensy. - * @return none - *************************************************************************/ -static void initEEPROMdata( void ) -{ - // TODO Update real values in eePromDataTX - eePromDataTX.doubleValue[ 0 ] = 0.0; - eePromDataTX.doubleValue[ 1 ] = 0.0; - eePromDataTX.doubleValue[ 2 ] = 0.0; - eePromDataTX.doubleValue[ 3 ] = 0.0; - eePromDataTX.doubleValue[ 4 ] = 0.0; - eePromDataTX.doubleValue[ 5 ] = 0.0; - eePromDataTX.doubleValue[ 6 ] = 0.0; - eePromDataTX.doubleValue[ 7 ] = 0.0; - - eePromDataTX.floatValue[ 0 ] = 0.0; - eePromDataTX.floatValue[ 1 ] = 0.0; - eePromDataTX.floatValue[ 2 ] = 0.0; - eePromDataTX.floatValue[ 3 ] = 0.0; - eePromDataTX.floatValue[ 4 ] = 0.0; - eePromDataTX.floatValue[ 5 ] = 0.0; - eePromDataTX.floatValue[ 6 ] = 0.0; - eePromDataTX.floatValue[ 7 ] = 0.0; - eePromDataTX.floatValue[ 8 ] = 0.0; - eePromDataTX.floatValue[ 8 ] = 0.0; - eePromDataTX.floatValue[ 10 ] = 0.0; - eePromDataTX.floatValue[ 11 ] = 0.0; - eePromDataTX.floatValue[ 12 ] = 0.0; - eePromDataTX.floatValue[ 13 ] = 0.0; - eePromDataTX.floatValue[ 14 ] = 0.0; - eePromDataTX.floatValue[ 15 ] = 0.0; - - enqueue( TEENSY_CMD_UPDATE_EEPROM_DATA ); -} - -/*********************************************************************//** - * @brief - * The initMeasurementSettings function populates measurementSettingsTX structure and enqueues - * update measurement settings command in the the command queue. - * @details \b Inputs:none - * @details \b Outputs:measurementSettingsTX - Measurement settings data to updated on Teensy. - * @return none - *************************************************************************/ -static void initMeasurementSettings( void ) -{ - // TODO Update real values in measurementSettingsTX - measurementSettingsTX.SinFreq = 11000.0; - measurementSettingsTX.DacVoltPP = 400.0; - measurementSettingsTX.BiasVolt = 200.0; - measurementSettingsTX.HstiaRtiaSel = 7; - measurementSettingsTX.AdcPgaGain = 2; - measurementSettingsTX.DftNum = 256; - measurementSettingsTX.ADCAvgNum = 16; - - enqueue( TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS ); -} - -/*********************************************************************//** - * @brief * The execConductivityTeensy function manages incoming data exchanges with * the Teensy board over UART. * @details \b Inputs: condCommState - Current state. @@ -370,6 +314,10 @@ { switch ( condCommState ) { + case COND_COMM_STATE_INIT: + condCommState = handleConductivityInit(); + break; + case COND_COMM_STATE_IDLE: condCommState = handleConductivityIdle(); break; @@ -382,10 +330,6 @@ condCommState = handleConductivityRX(); break; - case COND_COMM_STATE_FAILED: - condCommState = handleFailedState(); - break; - default: SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, ( U32 )condCommState ) break; @@ -394,6 +338,26 @@ /*********************************************************************//** * @brief + * The handleConductivityInit handles the init sequence and transitions to the respective + * comm state. + * @details \b Inputs: none + * @details \b Outputs: none + * @return state - Next state. + *************************************************************************/ +static COND_COMM_STATE_T handleConductivityInit( void ) +{ + COND_COMM_STATE_T state = COND_COMM_STATE_INIT; + + if ( TRUE == didTimeout( condInitTime, COND_INIT_TIMEOUT_MS ) ) + { + state = COND_COMM_STATE_IDLE; + consumeUnexpectedConductivityData(); + } + return state; +} + +/*********************************************************************//** + * @brief * The handleConductivityIdle handles the command queue and transitions to the respective * comm state. * @details \b Inputs: condAutomatedDataPolling @@ -417,20 +381,23 @@ } else { - // If queue is empty, q automated polling data cmd - // otherwise, we are already polling data, move to recv next data packet - if ( ( condAutomatedDataPolling == TRUE ) && ( currentCmd != TEENSY_CMD_STOP_MEASUREMENT ) ) + if( FALSE == eepromInit ) { - condWriteCommandInProgress = TRUE; // set to TRUE for recv interrupt to trigger with no sent msg - setupConductivityDMAForWriteResp( teensyCmdMap[ currentCmd ].rxSize ); - startConductivityDMAReceiptOfWriteResp(); - state = COND_COMM_STATE_RX; + // If queue is empty and we are done with init, q automated polling data cmd + // otherwise, we are already polling data, move to recv next data packet + if ( ( condAutomatedDataPolling == TRUE ) && ( currentCmd != TEENSY_CMD_STOP_MEASUREMENT ) ) + { + condWriteCommandInProgress = TRUE; // set to TRUE for recv interrupt to trigger with no sent msg + setupConductivityDMAForWriteResp( teensyCmdMap[ currentCmd ].rxSize ); + startConductivityDMAReceiptOfWriteResp(); + state = COND_COMM_STATE_RX; + } + else + { + condWriteCommandInProgress = TRUE; + enqueue( TEENSY_CMD_START_MEASUREMENT ); + } } - else - { - condAutomatedDataPolling = TRUE; - enqueue( TEENSY_CMD_START_MEASUREMENT ); - } } return state; @@ -480,7 +447,11 @@ case TEENSY_CMD_GET_SINGLE_MEASUREMENT: state = txGetSingleMeasurement(); break; + case TEENSY_CMD_SELECT_SENSOR: + state = txSelectSensor(); + break; default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_SENOR_INVALID_STATE, currentCmd ) break; } @@ -502,81 +473,43 @@ switch ( currentCmd ) { - case TEENSY_CMD_INIT_SENSOR: - state = rxInitSensor(); - break; - case TEENSY_CMD_GET_INIT_STATUS: - state = rxGetInitStatus(); - break; - case TEENSY_CMD_UPDATE_EEPROM_DATA: - state = rxUpdateEEPROMdata( ); - break; - case TEENSY_CMD_GET_EEPROM_DATA: - state = rxGetEEPROMdata(); - break; - case TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS: - state = rxUpdateMeasurementSettings( ); - break; - case TEENSY_CMD_GET_MEASUREMENT_SETTINGS: - state = rxGetMeasurementSettings(); - break; - case TEENSY_CMD_START_MEASUREMENT: - state = rxStartMeasurements(); - break; - case TEENSY_CMD_STOP_MEASUREMENT: - state = rxStopMeasurement(); - break; - case TEENSY_CMD_GET_ALL_MEASUREMENTS: - state = rxGetAllMeasurements(); - break; - case TEENSY_CMD_GET_SINGLE_MEASUREMENT: - state = rxGetSingleMeasurement( ); - break; - default: - break; - - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleFailedState function handles failure or errors of the states. - * @details \b Inputs: currentCmd - Current command being executed. - * The error occurred during TX or RX phase of this command. - * @details \b Outputs: none - * @details \b Outputs: none - * @return state - Next state. - *************************************************************************/ -static COND_COMM_STATE_T handleFailedState( void ) -{ - COND_COMM_STATE_T state = COND_COMM_STATE_FAILED; - - switch ( currentCmd ) - { case TEENSY_CMD_INIT_SENSOR: + state = rxInitSensor(); break; case TEENSY_CMD_GET_INIT_STATUS: + state = rxGetInitStatus(); break; case TEENSY_CMD_UPDATE_EEPROM_DATA: + state = rxUpdateEEPROMdata( ); break; case TEENSY_CMD_GET_EEPROM_DATA: + state = rxGetEEPROMdata(); break; case TEENSY_CMD_UPDATE_MEASUREMENT_SETTINGS: + state = rxUpdateMeasurementSettings( ); break; case TEENSY_CMD_GET_MEASUREMENT_SETTINGS: + state = rxGetMeasurementSettings(); break; case TEENSY_CMD_START_MEASUREMENT: + state = rxStartMeasurements(); break; case TEENSY_CMD_STOP_MEASUREMENT: + state = rxStopMeasurement(); break; case TEENSY_CMD_GET_ALL_MEASUREMENTS: + state = rxGetAllMeasurements(); break; case TEENSY_CMD_GET_SINGLE_MEASUREMENT: + state = rxGetSingleMeasurement( ); break; + case TEENSY_CMD_SELECT_SENSOR: + state = rxSelectSensor(); + break; default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_SENOR_INVALID_STATE, currentCmd ) break; + } return state; @@ -828,7 +761,7 @@ if ( written > 0 ) { // Clear the DMA write comand buffer - memcpy( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); + memset( &condWriteCmdBuffer, 0, COND_WRITE_CMD_BUFFER_LEN ); // Load the DMA write command buffer with contents of TX buffer. memcpy( &condWriteCmdBuffer, &condTxBuffer, written ); success = TRUE; @@ -862,9 +795,6 @@ success = TRUE; } - // Should not be any data received at this time - consumeUnexpectedConductivityData(); - return success; } @@ -925,7 +855,7 @@ switch ( condInitStatus ) { - case COND_INIT_STATUS_UNITIALIZED: + case COND_INIT_STATUS_UNINITIALIZED: break; case COND_INIT_STATUS_IN_PROGRESS: @@ -1012,7 +942,7 @@ switch ( condInitStatus ) { - case COND_INIT_STATUS_UNITIALIZED: + case COND_INIT_STATUS_UNINITIALIZED: break; case COND_INIT_STATUS_IN_PROGRESS: @@ -1181,7 +1111,6 @@ { COND_COMM_STATE_T state = COND_COMM_STATE_RX; COND_PARSE_STATUS parseStatus = COND_PARSE_NONE; - state = COND_COMM_STATE_IDLE; // Check if a response is received in the RX buffer BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_GET_EEPROM_DATA ); @@ -1191,12 +1120,24 @@ condResponseTime = 0; // Read the data from the receive buffer - memcpy(&eePromDataRX, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_GET_EEPROM_DATA ].rxSize ); -// parseStatus = parseEEPROMdata( condRxBuffer, COND_RX_BUFFER_LEN ); - + parseStatus = parseEEPROMdata(condRxBuffer, teensyCmdMap[ TEENSY_CMD_GET_EEPROM_DATA ].rxSize); // Check if parsing was done successfully if ( COND_PARSE_SUCCESS == parseStatus ) { + // Queue commands for next sensor to retrieve eeprom data. + // If this is init. + if( ( TRUE == eepromInit ) && ( currentSelectedSensor < MAX_TEENSY_SENSOR ) ) + { + currentSelectedSensor++; + enqueue( TEENSY_CMD_SELECT_SENSOR ); + enqueue( TEENSY_CMD_GET_EEPROM_DATA ); + + } + else + { + eepromInit = FALSE; + currentSelectedSensor = TEENSY_SENSOR_0; + } // Go to the idle state to execute next cmd in the queue state = COND_COMM_STATE_IDLE; } @@ -1441,7 +1382,7 @@ condResponseTime = getMSTimerCount(); // Read the data from the receive buffer - parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); + parseStatus = parseConductivityMeasurements( condRxBuffer ); // Check if parsing was done successfully if ( COND_PARSE_SUCCESS == parseStatus ) @@ -1604,7 +1545,7 @@ condResponseTime = 0; // Read the data from the receive buffer - parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); + parseStatus = parseConductivityMeasurements( condRxBuffer ); // Check if parsing was done successfully if ( COND_PARSE_SUCCESS == parseStatus ) @@ -1645,7 +1586,7 @@ COND_COMM_STATE_T state = COND_COMM_STATE_TX; U08 paramStr[ 8 ]; - snprintf( ( char* )paramStr, sizeof( paramStr ), "%d", currentSelectedSensor ); + snprintf( ( char* )paramStr, sizeof( paramStr ), "%d", ( currentSelectedSensor + 1 ) ); // Teensy doesn't 0 index // Assumes sensor has already been selected if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_GET_SINGLE_MEASUREMENT, paramStr ) ) @@ -1679,7 +1620,7 @@ condResponseTime = 0; // Read the data from the receive buffer - COND_PARSE_STATUS parseStatus = parseConductivityMeasurements( condRxBuffer, COND_RX_BUFFER_LEN ); + COND_PARSE_STATUS parseStatus = parseConductivityMeasurements( condRxBuffer ); // Check if parsing was done successfully if ( COND_PARSE_SUCCESS == parseStatus ) @@ -1708,54 +1649,74 @@ /*********************************************************************//** * @brief - * The enqueueSingleMeasurement function updates current select sensor in format - * acceptable to Teensy and enqueues get single measurement command. - * @details \b Inputs : none - * @details \b Outputs: currentSelectedSensor - Current Selected Sensor indexed 1 to 6. - * @param sensorNum - Teensy sensor index - * @return none + * The txSelectSensor function sends command to select a specific sensors + * connected to the Teensy. + * @details \b Inputs: none + * @details \b Outputs: condResponseTime - Time at which command was transmitted. + * @return state - Next state. *************************************************************************/ -static void enqueueSingleMeasurement(TEENSY_SENSOR_INDEX_T sensorNum) + +static COND_COMM_STATE_T txSelectSensor( void ) { - // Sensors are indexed 1 to 6 in Teensy. So send (sensorNum + 1) as parameter. - currentSelectedSensor = sensorNum + 1; + COND_COMM_STATE_T state = COND_COMM_STATE_TX; - // Enqueue get single measurement command. - enqueue(TEENSY_CMD_GET_SINGLE_MEASUREMENT); + U08 paramStr[ 8 ]; + snprintf( ( char* )paramStr, sizeof( paramStr ), "%d", ( currentSelectedSensor + 1 ) ); + + // If select sensor cmd was sent successfully + // Sensors start at 1 + if ( TRUE == txTeensyWriteCmd( TEENSY_CMD_SELECT_SENSOR, paramStr ) ) + { + // Get the current time + condResponseTime = getMSTimerCount(); + + // Go to receive state to receive the measurement data + state = COND_COMM_STATE_RX; + } + else + { + // Go to failed state + state = COND_COMM_STATE_FAILED; + } + + return state; } /*********************************************************************//** * @brief - * The parseMeasurementSettings Reads measurement settings from buffer and - * stores in measurementSettingsRX. - * @details \b Inputs : none - * @details \b Outputs: measurementSettingsRX - Received Measurement Settings - * @param buffer - Data to be parsed and stored. - * len - Length of the input data. - * @return COND_PARSE_STATUS to tell if parsing was successful or not. + * The rxSelectSensor function handles received response of + * select sensor command. + * @details \b Inputs: condResponseTime - Time at which command was transmitted, + * @details \b Inputs: condRxBuffer - Received response buffer + * @return state - Next state. *************************************************************************/ -static COND_PARSE_STATUS parseMeasurementSettings( const U08 *buffer, U32 len ) +static COND_COMM_STATE_T rxSelectSensor( void ) { - COND_PARSE_STATUS parseStatus = COND_PARSE_NONE; - U32 expectedDataLength = sizeof( COND_MEASUREMENT_SETTINGS_T ); + COND_COMM_STATE_T state = COND_COMM_STATE_RX; - // Validate buffer - if ( buffer == NULL ) + // Check if a response is received in the RX buffer + BOOL recvComplete = rxTeensyReadRsp( TEENSY_CMD_SELECT_SENSOR ); + if ( TRUE == recvComplete ) { - parseStatus = COND_PARSE_ERROR_NULL_BUFFER; + // Reset the timer for next use. + condResponseTime = 0; + + // Read the data from the receive buffer + memcpy(&condSelectSensorStatus, &condRxBuffer, teensyCmdMap[ TEENSY_CMD_SELECT_SENSOR ].rxSize ); + state = COND_COMM_STATE_IDLE; + } - else if ( len != expectedDataLength ) + else if ( TRUE == didTimeout( condResponseTime, COND_DATA_TIMEOUT_MS ) ) { - parseStatus = COND_PARSE_ERROR_INVALID_LENGTH; + // Go to failed state + state = COND_COMM_STATE_FAILED; } else { - // Parse and store the data - memcpy(&measurementSettingsRX, buffer, expectedDataLength ); - parseStatus = COND_PARSE_SUCCESS; + // Do Nothing. Wait until we either receive a response OR timeout happens. } - return parseStatus; + return state; } /*********************************************************************//** @@ -1786,7 +1747,7 @@ else { // Parse and Store the data - memcpy(&eePromDataRX, buffer, expectedDataLength ); + memcpy(&condCoeff[ currentSelectedSensor ], buffer, expectedDataLength ); parseStatus = COND_PARSE_SUCCESS; } @@ -1805,7 +1766,7 @@ * len - Length of the input data. * @return COND_PARSE_STATUS to tell if parsing was successful or not. *************************************************************************/ -static COND_PARSE_STATUS parseConductivityMeasurements( const U08 *buffer, U32 len ) +static COND_PARSE_STATUS parseConductivityMeasurements( const U08 *buffer ) { COND_PARSE_STATUS parseStatus = COND_PARSE_NONE; COND_SENSOR_DATA_T tempSensor; @@ -1828,7 +1789,7 @@ else { // Store Raw value in array index for position ( sensorNum - 1 ) - condRawMeasurement[ tempSensor.sensorNum - 1 ] = tempSensor; + memcpy( &condRawMeasurement[ tempSensor.sensorNum - 1 ], &tempSensor, sizeof( COND_SENSOR_DATA_T ) ); // Calculate and store Conductivity from raw values calculateConductivity( tempSensor.sensorNum - 1 ); @@ -1875,36 +1836,41 @@ case D43_COND: sensorNum = TEENSY_SENSOR_5; break; + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensorId ) + break; + } return sensorNum; } /*********************************************************************//** * @brief - * The getConductivityValue function gets the current calculated conductivity / + * The getTeensyConductivityValue function gets the current calculated conductivity / impedance value. * @details \b Inputs: condCalculatedMeasurement * @details \b Outputs: none - * @param sensor ID of conductivity sensor to get conductivity. + * @param sensorId ID of conductivity sensor to get conductivity. * @return The current conductivity of a given conductivity sensor. *************************************************************************/ F32 getTeensyConductivityValue( CONDUCTIVITY_SENSORS_T sensorId ) { U32 sensorNum = getTeensyCondId( sensorId ); F32 result = 0.0F; - if ( D74_COND != sensorId ) + result = condCalculatedMeasurement[ sensorNum ].Conductivity.data; + if ( OVERRIDE_KEY == condCalculatedMeasurement[ sensorNum ].Conductivity.override ) { - result = ( F32 )condCalculatedMeasurement[ sensorNum ].Conductivity; + result = condCalculatedMeasurement[ sensorNum ].Conductivity.ovData; } return result; } /*********************************************************************//** * @brief - * The getTemperatureValue function gets the current conductivity sensor + * The getTeensyConductivityTemperatureValue function gets the current conductivity sensor * temperature for a given conductivity sensor. * @details \b Inputs: condCalculatedMeasurement * @details \b Outputs: none @@ -1916,45 +1882,243 @@ U32 sensorNum = getTeensyCondId( sensorId ); F32 result = 0.0F; - if ( D74_COND != sensorId ) + result = condCalculatedMeasurement[ sensorNum ].Temperature.data; + if ( OVERRIDE_KEY == condCalculatedMeasurement[ sensorNum ].Temperature.override ) { - result = ( F32 )condCalculatedMeasurement[ sensorNum ].Temperature; + result = condCalculatedMeasurement[ sensorNum ].Temperature.ovData; } return result; } /*********************************************************************//** * @brief + * The getTeensyConductivityResistanceValue function gets the current conductivity sensor + * resistance for a given conductivity sensor. + * @details \b Inputs: condCalculatedMeasurement + * @details \b Outputs: none + * @param sensorId ID of conductivity sensor to get temperature. + * @return The current temperature of a given conductivity sensor. + *************************************************************************/ +F32 getTeensyConductivityResistanceValue( CONDUCTIVITY_SENSORS_T sensorId ) +{ + U32 sensorNum = getTeensyCondId( sensorId ); + F32 result = 0.0F; + + result = condCalculatedMeasurement[ sensorNum ].Resistance.data; + if ( OVERRIDE_KEY == condCalculatedMeasurement[ sensorNum ].Resistance.override ) + { + result = condCalculatedMeasurement[ sensorNum ].Resistance.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The calculateConductivity function calculates the conductivity value. + * @details \b Inputs: currentConductivityModel - conductivity model being used. + * @details \b Outputs: condCalculatedMeasurement - calculated conductivity value + * @param sensorNum - Teensy sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. + * @return + *************************************************************************/ +static void calculateConductivity( TEENSY_SENSOR_INDEX_T sensorNum ) +{ + BOOL isFPSensor = FALSE; + + if (sensorNum <= TEENSY_SENSOR_1 ) + { + isFPSensor = TRUE; + } + + switch ( currentConductivityModel ) + { + case ALY_LINEAR: + calculateConductivityAly( sensorNum, isFPSensor ); + break; + case UPDATED_STANDARD: + calculateConductivityUpdatedStandard( sensorNum, isFPSensor ); + break; + default: + calculateConductivityStandard( sensorNum, isFPSensor ); + break; + } +} +/*********************************************************************//** + * @brief + * The calculateConductivityAly function calculates the conductivity value + * using Aly's Linear model * @details \b Inputs: condCoeff - Conductivity Coefficients * @details \b Inputs: condRawMeasurement - Raw measurement values * @details \b Outputs: condCalculatedMeasurement - calculated conductivity value * @param sensorNum - Teensy sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. * @return *************************************************************************/ -static void calculateConductivity( TEENSY_SENSOR_INDEX_T sensorNum ) +static void calculateConductivityAly( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ) { - F64 calculatedConductivity = 0.0; - F64 B3 = condCoeff[ sensorNum ].B3; - F64 B2 = condCoeff[ sensorNum ].B2; - F64 B1 = condCoeff[ sensorNum ].B1; - F64 B0 = condCoeff[ sensorNum ].B0; - F64 R = condRawMeasurement[ sensorNum ].impRzMag; - F64 Z = condRawMeasurement[ sensorNum ].rtdRzMag; + F32 calculatedConductivity = 0.0; + F32 B3 = 0.0; + F32 B2 = 0.0; + F32 B1 = 0.0; + F32 B0 = 0.0; + F32 R = condRawMeasurement[ sensorNum ].impRzMag; + F32 Z = condRawMeasurement[ sensorNum ].rtdRzMag; + // Aly sensors are known to send the driver INF in unfavorable conditions for impedance. e.g: open air + // Change it to some high value that can be determined that we are reading INF. + // Otherwise we will publish no updated value or 0. + if ( R == INFINITY ) + { + R = COND_INFINITE_R_VALUE; + } + + if ( TRUE == isFPSensor ) + { + B3 = condCoeff[ sensorNum ].beta3FP; + B2 = condCoeff[ sensorNum ].beta2FP; + B1 = condCoeff[ sensorNum ].beta1FP; + B0 = condCoeff[ sensorNum ].beta0FP; + } + else + { + B3 = condCoeff[ sensorNum ].beta3DD; + B2 = condCoeff[ sensorNum ].beta2DD; + B1 = condCoeff[ sensorNum ].beta1DD; + B0 = condCoeff[ sensorNum ].beta0DD; + } + + // B3( 1000 / impRz ) + B2( rtdRz / impRz ) + B1( 100ln(rtdRz) / impRz ) + B0 calculatedConductivity = ( ( B3 * ( 1000.0 / R ) ) + ( B2 * ( Z / R ) ) + ( B1 * ( ( 100 * log( Z ) ) / R ) ) + B0 ); + calculatedConductivity = calculatedConductivity * COND_CONVERSION_SM_TO_USCM; + condCalculatedMeasurement[ sensorNum ].Conductivity.data = calculatedConductivity; +} - condCalculatedMeasurement[ sensorNum ].Conductivity = calculatedConductivity; +/*********************************************************************//** + * @brief + * The calculateConductivityUpdatedStandard function calculates the conductivity value. + * @details \b Inputs: condCoeff - Conductivity Coefficients + * @details \b Inputs: condRawMeasurement - Raw measurement values + * @details \b Outputs: condCalculatedMeasurement - calculated conductivity value + * @param sensorNum - Teensy sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. + * @return + *************************************************************************/ +static void calculateConductivityUpdatedStandard( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ) +{ + F32 calculatedConductivity = 0.0; + F64 alpha = 0.0; + F64 k = 0.0; + if ( TRUE == isFPSensor ) + { + alpha = condCoeff[ sensorNum ].alphaLowFPUS; + k = condCoeff[ sensorNum ].kLowFPUS; + } + else + { + alpha = condCoeff[ sensorNum ].alphaHighDDUS; + k = condCoeff[ sensorNum ].kHighDDUS; + } + calculateResistance( sensorNum, isFPSensor ); + calculateTemperature( sensorNum ); + // ( k / calculatedReistance ) * (1 + alpha*( 25 - calculatedTemperature ) ) + calculatedConductivity = ( ( k / condCalculatedMeasurement[ sensorNum ].Resistance.data ) * + ( 1 + ( alpha * ( COND_TEMP_OFFSET - condCalculatedMeasurement[ sensorNum ].Temperature.data ) ) ) ); + calculatedConductivity = calculatedConductivity * COND_CONVERSION_SM_TO_USCM; } /*********************************************************************//** * @brief + * The calculateConductivityUpdatedStandard function calculates the conductivity value. + * @details \b Inputs: condCoeff - Conductivity Coefficients + * @details \b Inputs: condRawMeasurement - Raw measurement values + * @details \b Outputs: condCalculatedMeasurement - calculated conductivity value + * @param sensorNum - Teensy sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. + * @return + *************************************************************************/ +static void calculateConductivityStandard( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ) +{ + F64 calculatedConductivity = 0.0; + F64 alpha = 0.0; + F64 k = 0.0; + F64 R = condRawMeasurement[ sensorNum ].impRzMag; + + // Aly sensors are known to send the driver INF in unfavorable conditions for impedance. e.g: open air + // Change it to some high value that can be determined that we are reading INF. + // Otherwise we will publish no updated value or 0. + if ( R == INFINITY ) + { + R = COND_INFINITE_R_VALUE; + } + + if ( TRUE == isFPSensor ) + { + alpha = condCoeff[ sensorNum ].alphaLowFPS; + k = condCoeff[ sensorNum ].kLowFPS; + } + else + { + alpha = condCoeff[ sensorNum ].alphaHighDDS; + k = condCoeff[ sensorNum ].kHighDDS; + } + calculateTemperature( sensorNum ); + + calculatedConductivity = ( ( k / R ) * + ( 1 + alpha * ( COND_TEMP_OFFSET - getTeensyConductivityTemperatureValue( sensorNum ) ) ) ); + + calculatedConductivity = calculatedConductivity * COND_CONVERSION_SM_TO_USCM; + condCalculatedMeasurement[ sensorNum ].Conductivity.data = (F32)calculatedConductivity; +} + +/*********************************************************************//** + * @brief + * The calculateResistance function calculates the temperature values. + * @details \b Inputs: condCoeff - Conductivity Coefficients + * @details \b Inputs: condRawMeasurement - Raw measurement values + * @details \b Outputs: condCalculatedMeasurement - calculated resistance value + * @param sensorNum - Teensy sensor index value. + * @param isFPSensor - T/F if sensor is on FP hardware. + * @return + *************************************************************************/ +static void calculateResistance( TEENSY_SENSOR_INDEX_T sensorNum, BOOL isFPSensor ) +{ + + F32 calculatedResistance = 0.0; + F64 eta = 0.0; + F64 zeta = 0.0; + F32 R = condRawMeasurement[ sensorNum ].impRzMag; + + // Aly sensors are known to send the driver INF in unfavorable conditions. e.g: open air + // Change it to some high value that can be determined that we are reading INF. + // Otherwise we will publish no updated value or 0. + if ( R == INFINITY ) + { + R = COND_INFINITE_R_VALUE; + } + + if ( TRUE == isFPSensor ) + { + eta = condCoeff[ sensorNum ].etaLowFPUS; + zeta = condCoeff[ sensorNum ].zetaLowFPUS; + } + else + { + eta = condCoeff[ sensorNum ].etaHighDDUS; + zeta = condCoeff[ sensorNum ].zetaHighDDUS; + } + calculatedResistance = ( ( eta * R ) + zeta ); + condCalculatedMeasurement[ sensorNum ].Resistance.data = calculatedResistance; +} + +/*********************************************************************//** + * @brief * The calculateTemperature function calculates the temperature values. * @details \b Inputs: condCoeff - Conductivity Coefficients * @details \b Inputs: condRawMeasurement - Raw measurement values @@ -1964,16 +2128,167 @@ *************************************************************************/ static void calculateTemperature( TEENSY_SENSOR_INDEX_T sensorNum ) { - F64 calculatedTemperature = 0.0; - F64 A1 = condCoeff[ sensorNum ].A1; - F64 A0 = condCoeff[ sensorNum ].A0; - F64 Z = condRawMeasurement[ sensorNum ].rtdRzMag; - calculatedTemperature = ( ( A1 * Z ) + A0 ); + F32 calculatedTemperature = 0.0; + F64 beta = condCoeff[ sensorNum ].beta; + F64 gamma = condCoeff[ sensorNum ].gamma; + F32 Z = condRawMeasurement[ sensorNum ].rtdRzMag; - condCalculatedMeasurement[ sensorNum ].Temperature = calculatedTemperature; + calculatedTemperature = ( ( beta * Z ) + gamma ); + condCalculatedMeasurement[ sensorNum ].Temperature.data = calculatedTemperature; } + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testTeensyConductivitySensorReadingsOverride function overrides the value of the + * specified conductivity sensor with a given value. + * @details \b Inputs: none + * @details \b Outputs: condCalculatedMeasurement[] + * @param message Override message from Dialin which includes an sensor + * ID and override value of the conductivity sensor. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testTeensyConductivitySensorReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); + + if ( payload.index <= LAST_FP_COND_SENSOR ) + { + // D74 is not connected to Teensy and does not have a data structure to override. + if ( LAST_DD_COND_SENSOR != payload.index ) + { + result = TRUE; + if ( OVERRIDE_OVERRIDE == ovType ) + { + F32 value = payload.state.f32; + + condCalculatedMeasurement[ payload.index ].Conductivity.ovData = value; + condCalculatedMeasurement[ payload.index ].Conductivity.override = OVERRIDE_KEY; + } + else + { + condCalculatedMeasurement[ payload.index ].Conductivity.override = OVERRIDE_RESET; + condCalculatedMeasurement[ payload.index ].Conductivity.ovData = condCalculatedMeasurement[ payload.index ].Conductivity.ovInitData; + } + } + } + return result; +} + +/*********************************************************************//** + * @brief + * The testTeensyConductivitySensorTemperatureReadingsOverride function overrides + * the value of the specified conductivity sensor temperature with a given value. + * @details \b Inputs: none + * @details \b Outputs: condCalculatedMeasurement[] + * @param message Override message from Dialin which includes an sensor + * ID and override value of the conductivity sensor temperature. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testTeensyConductivitySensorTemperatureReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); + + if ( payload.index <= LAST_FP_COND_SENSOR ) + { + // D74 is not connected to Teensy and does not have a data structure to override. + if ( LAST_DD_COND_SENSOR != payload.index ) + { + result = TRUE; + if ( OVERRIDE_OVERRIDE == ovType ) + { + F32 value = payload.state.f32; + + condCalculatedMeasurement[ getTeensyCondId( payload.index ) ].Temperature.ovData = value; + condCalculatedMeasurement[ getTeensyCondId( payload.index ) ].Temperature.override = OVERRIDE_KEY; + } + else + { + condCalculatedMeasurement[ getTeensyCondId( payload.index ) ].Temperature.override = OVERRIDE_RESET; + condCalculatedMeasurement[ getTeensyCondId( payload.index ) ].Temperature.ovData = condCalculatedMeasurement[ getTeensyCondId( payload.index ) ].Temperature.ovInitData; + } + } + + } + return result; +} + +/*********************************************************************//** + * @brief + * The testTeensyConductivitySensorResistanceReadingsOverride function overrides + * the value of the specified conductivity sensor resistance with a given value. + * @details \b Inputs: none + * @details \b Outputs: condCalculatedMeasurement[] + * @param message Override message from Dialin which includes an sensor + * ID and override value of the conductivity sensor temperature. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testTeensyConductivitySensorResistanceReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); + + if ( payload.index <= LAST_FP_COND_SENSOR ) + { + // D74 is not connected to Teensy and does not have a data structure to override. + if ( LAST_DD_COND_SENSOR != payload.index ) + { + result = TRUE; + if ( OVERRIDE_OVERRIDE == ovType ) + { + F32 value = payload.state.f32; + + condCalculatedMeasurement[ payload.index ].Resistance.ovData = value; + condCalculatedMeasurement[ payload.index ].Resistance.override = OVERRIDE_KEY; + } + else + { + condCalculatedMeasurement[ payload.index ].Resistance.override = OVERRIDE_RESET; + condCalculatedMeasurement[ payload.index ].Resistance.ovData = condCalculatedMeasurement[ payload.index ].Resistance.ovInitData; + } + } + + } + return result; +} +/*********************************************************************//** + * @brief + * The testSetTeenyConductivityModel function sets the given conductivity model + * @details \b Inputs: none + * @details \b Outputs: currentConductivityModel[] + * @param message Override message from Dialin which includes an ID of + * the conductivity model to switch to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetTeenyConductivityModel( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( sizeof( U32 ) == message->hdr.payloadLen ) + { + U32 newCondModel; + + memcpy( &newCondModel, &message->payload[0], sizeof( U32 ) ); + if ( newCondModel < NUM_OF_MODELS ) + { + currentConductivityModel = (COND_MODELS_T)newCondModel; + result = TRUE; + } + } + } + + return result; +}