Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r2c08db070a6e09306caf461e7aceeb53097fd995 -rd06fe849f6395b3672abb9a0cacf364f0af3b891 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision d06fe849f6395b3672abb9a0cacf364f0af3b891) @@ -7,8 +7,8 @@ * * @file TemperatureSensors.c * -* @author (last) Dara Navaei -* @date (last) 21-Dec-2022 +* @author (last) Darren Cox +* @date (last) 13-Jul-2023 * * @author (original) Dara Navaei * @date (original) 08-Apr-2020 @@ -17,6 +17,7 @@ #include // For temperature calculation #include // For memset() +#include "FlowSensors.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" @@ -59,14 +60,15 @@ #define MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS 2U ///< Maximum allowed temperature delta between sensors. #define SHIFT_BITS_BY_2 2U ///< Shift bits by 2 to create a 4 for averaging 4 samples. #define SHIFT_BITS_BY_2_FOR_AVERAGING 2U ///< Shift the ADCs of the temperature sensors by 2 to average them. -#define INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Inlet water temperature sensors timeout in milliseconds. +#define INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water temperature sensors timeout in milliseconds. #define INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ( 1 * MS_PER_SECOND ) ///< Inlet water temperature sensors out of range clear in milliseconds. #define MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE 24.0F ///< Low range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE 26.0F ///< Low range maximum water input temperature. #define MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE 35.0F ///< High range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE 37.0F ///< High range maximum water input temperature. +#define MAX_CLEANING_MODE_WATER_TEMPERATURE_WARNING_HIGH_RANGE 45.0F ///< High range maximum cleaning mode water input temperature. #define HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL 20U ///< Time interval that is used to calculate the heaters internal temperature. #define HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF 0.25F ///< Heaters internal temperature sensors ADC to temperature conversion coefficient. @@ -94,9 +96,11 @@ #define BARO_SENSOR_REFERENCE_TEMP_C 2000 ///< Barometric sensor reference temperature in C. #define BARO_SENSOR_WAIT_FOR_COEFF_TIME_OUT_MS ( 20 * MS_PER_SECOND ) ///< Barometric sensor wait for coefficients timeout in milliseconds. -#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C 1.0F ///< Dialysate temperature sensors maximum allowed deviation in C. +#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C 3.0F ///< Dialysate temperature sensors maximum allowed deviation in C. #define DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. -#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C 3.0F ///< Dialysate temperature sensors maximum allowed deviation in heat disinfect in C. +#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C 5.0F ///< Dialysate temperature sensors maximum allowed deviation in heat disinfect in C. +#define DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES 30 ///< Dialysate temperature sensors moving average number of samples. +#define TDI_TRO_DATA_COLLECTION_TIME_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature sensors data collection time in milliseconds. /// Temperature sensor exec states. typedef enum tempSensors_Exec_States @@ -106,6 +110,15 @@ NUM_OF_TEMPSENSORS_EXEC_STATES, ///< Total number of exec states } TEMPSENSORS_EXEC_STATES_T; +/// Dialysate temperature sensors enums +typedef enum Dial_Temps_Sensors +{ + DIAL_TEMP_TRO = 0, ///< Dialysate temperature TRo. + DIAL_TEMP_FIRST = DIAL_TEMP_TRO, ///< Dialysate temperature first. + DIAL_TEMP_TDI, ///< Dialysate temperature TDi. + NUM_OF_DIAL_TEMPS ///< Number of Dialysate temperature sensors. +} DIAL_TEMPERATURE_SENSORS_T; + /// Temperature sensor struct. typedef struct { @@ -119,9 +132,7 @@ OVERRIDE_F32_T temperatureValues; ///< Temperature values with override F32 maxAllowedTemp; ///< Maximum allowed temperature of the sensor U32 alarmStartTime; ///< Alarm start time - U08 sensorErrorBitStatus; ///< Temperature sensor error bit status BOOL fpgaErrorStatus; ///< Temperature sensor FPGA error status - BOOL adcErrorStatus; ///< Temperature sensor ADC error status S32 baroTempSnsrDiff; ///< Barometric sensor temperature difference } TEMP_SENSOR_T; @@ -148,6 +159,17 @@ U16 crc; ///< Barometric sensor CRC of the coefficients. } BARO_SENSORS_COEFFS_T; +/// Dialysate temperature moving average structure +typedef struct +{ + BOOL dialTempColHasTimerBeenSet; ///< Dialysate temperature has data collection timer started boolean flag. + U32 dialTempDataColStartTimeMS; ///< Dialysate temperature data collection start time in milliseconds. + F32 dialTempRunningSumC; ///< Dialysate temperature running sum in C. + F32 dialTempAvgC; ///< Dialysate temperature average in C. + F32 dialTempSamplesC[ DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES ]; ///< Dialysate temperature samples array in C. + U32 dialTempSamplesNextIndex; ///< Dialysate temperature sample next index number. +} DIAL_TEMP_MOVING_AVG_DATA_T; + // ********** private data ********** static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state. @@ -159,6 +181,7 @@ static OVERRIDE_U32_T tempSensorsPublishInterval = { TEMP_SENSORS_DATA_PUBLISH_INTERVAL, TEMP_SENSORS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Temperature sensors publish time interval override. static DG_TEMP_SENSORS_CAL_RECORD_T tempSensorCalRecord; ///< Temperature sensors calibration record. +static DIAL_TEMP_MOVING_AVG_DATA_T dialTempMovingAvgData[ NUM_OF_DIAL_TEMPS ]; ///< Dialysate temperature moving average data. static const F32 POSITIVE_TC_EXP_A0 = 0.118597600000E0; ///< K TC positive temperature exponent coefficient A0. static const F32 POSITIVE_TC_EXP_A1 = -0.118343200000E-3; ///< K TC positive temperature exponent coefficient A1. static const F32 POSITIVE_TC_EXP_A2 = 0.126968600000E3; ///< K TC positive temperature exponent coefficient A2. @@ -184,12 +207,6 @@ static const U32 TWO_TO_POWER_OF_8 = ( 1 << 8 ); ///< 2^8. static const U32 TWO_TO_POWER_OF_23 = ( 1 << 23 ); ///< 2^23. -// The count cannot be within 0.1V of the rail on both sides therefore: -// Maximum ADC count -> (2^24) * ( 3.0V - 0.1V ) / 3V -// Minimum ADC count -> (2^24) * ( 0.1V - 0.0V ) / 3V -static const U32 TEMP_SENSORS_MAX_ADC_COUNT = ( BITS_24_FULL_SCALE * ( 3.0F - 0.1F ) ) / 3.0F; ///< Temperature sensors max allowed ADC count. -static const U32 TEMP_SESNORS_MIN_ADC_COUNT = ( BITS_24_FULL_SCALE * ( 0.1F - 0.0F ) ) / 3.0F; ///< Temperature sensors min allowed ADC count. - // ********** private function prototypes ********** static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ); @@ -202,21 +219,23 @@ static void processADCRead( U32 sensorIndex, S32 adc ); static void publishTemperatureSensorsData( void ); static void monitorTemperatureSenors( void ); -static void checkBaroSensorCRC( void ); static void adjustTemperatureSensorsRefResistance( void ); +static void checkBaroSensorCRC( void ); +static void processDialTemperatureData( void ); /*********************************************************************//** * @brief * The initTemperatureSensors function initializes the module. * @details Inputs: none * @details Outputs: tempSensorsSelfTestState, tempSensorsExecState, * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, - * tempSensors, baroConvConsts + * tempSensors, baroConvConsts, dialTempMovingAvgData * @return none *************************************************************************/ void initTemperatureSensors( void ) { U08 i; + DIAL_TEMPERATURE_SENSORS_T j; tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; elapsedTime = 0; @@ -243,6 +262,17 @@ // Initialize the barometric sensor's temperature conversion constants memset( &baroConvConsts, 0x0, sizeof( BARO_SENSOR_CONSTS_T ) ); + for ( j = DIAL_TEMP_FIRST; j < NUM_OF_DIAL_TEMPS; j++ ) + { + dialTempMovingAvgData[ j ].dialTempAvgC = 0.0F; + dialTempMovingAvgData[ j ].dialTempColHasTimerBeenSet = FALSE; + dialTempMovingAvgData[ j ].dialTempRunningSumC = 0.0F; + dialTempMovingAvgData[ j ].dialTempSamplesNextIndex = 0; + dialTempMovingAvgData[ j ].dialTempDataColStartTimeMS = getMSTimerCount(); + + memset( dialTempMovingAvgData[ j ].dialTempSamplesC, 0.0F, sizeof( F32 ) * DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES ); + } + // Initialize TPi, THd, and TPo constants tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].gain = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; @@ -324,16 +354,15 @@ tempSensors[ TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Persistent alarms for inlet water high/low temperature - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ); - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ); + initPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); // Persistent alarm for the temperature sensors range check initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ); // Persistent alarm for the temperature sensors range check - initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ); initPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, 0, DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ); // Initialize the FPGA persistent alarms @@ -404,6 +433,9 @@ // Monitor the temperature values monitorTemperatureSenors(); + // Process the moving average of the dialysate temperature sensors (TDi and TRo) + processDialTemperatureData(); + // Check the TDi/TRo drift checkDialysateTemperatureSensors(); @@ -421,56 +453,79 @@ *************************************************************************/ void checkInletWaterTemperature( void ) { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) -#endif + F32 temperature = getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ); + + if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) { - DG_OP_MODE_T opMode = getCurrentOperationMode(); - F32 temperature = getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ); - BOOL isWaterTempInHighRange = ( temperature > MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? TRUE : FALSE ); - BOOL isWaterTempInLowRange = ( temperature < MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ? TRUE : FALSE ); - switch( opMode ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - case DG_MODE_GENE: - case DG_MODE_FILL: - case DG_MODE_DRAI: - if ( ( temperature <= MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) ) + if ( getTestConfigStatus( TEST_CONFIG_DISABLE_INLET_WATER_TEMP_CHECK ) != TRUE ) + { + DG_OP_MODE_T opMode = getCurrentOperationMode(); + BOOL isWaterTempInHighRange = ( temperature > MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? TRUE : FALSE ); + BOOL isWaterTempInLowRange = ( temperature < MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ? TRUE : FALSE ); + + switch( opMode ) { - isWaterTempInHighRange = FALSE; - } + case DG_MODE_GENE: + case DG_MODE_FILL: + case DG_MODE_DRAI: + case DG_MODE_STAN: + if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) + { + isWaterTempInHighRange = ( temperature <= MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? FALSE : TRUE ); + } - // Per PRS 406 - checkPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, isWaterTempInHighRange, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); + // Per PRS 406 + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, isWaterTempInHighRange, temperature, + MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); - if ( ( temperature >= MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ) && ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) ) - { - isWaterTempInLowRange = FALSE; - } + if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) + { + isWaterTempInLowRange = ( temperature >= MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ? FALSE : TRUE ); + } - // Per PRS 405 - checkPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, isWaterTempInLowRange, temperature, MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); - break; + // Per PRS 405 + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, isWaterTempInLowRange, temperature, + MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); + break; - case DG_MODE_FLUS: - case DG_MODE_HEAT: - case DG_MODE_CHEM: - case DG_MODE_INIT: - case DG_MODE_STAN: - case DG_MODE_CHFL: - if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) - { - // Per PRS 557 - checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, isWaterTempInHighRange, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); - checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, isWaterTempInLowRange, temperature, MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ); - } - break; + case DG_MODE_FLUS: + case DG_MODE_HEAT: + case DG_MODE_HCOL: + case DG_MODE_CHEM: + case DG_MODE_CHFL: + case DG_MODE_ROPS: + isWaterTempInHighRange = ( temperature > MAX_CLEANING_MODE_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? TRUE : FALSE ); + // Per PRS 557 + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, isWaterTempInHighRange, temperature, + MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, isWaterTempInLowRange, temperature, + MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ); + break; - default: - // NOTE: Do nothing in the rest of the modes - break; + default: + // NOTE: Do nothing in the rest of the modes + break; + } + } } } + else + { + // VPI is closed - clear all alarms + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, FALSE, temperature, + MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, FALSE, temperature, + MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, FALSE, temperature, + MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, FALSE, temperature, + MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ); + } } /*********************************************************************//** @@ -563,13 +618,16 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - F32 TDi = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - F32 TRo = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); - DG_OP_MODE_T op = getCurrentOperationMode(); - F32 driftC = ( DG_MODE_HEAT == op ? TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C : TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C ); - BOOL isDriftOut = ( fabs( TDi - TRo ) > driftC ? TRUE : FALSE ); + if ( getMeasuredRawFlowRateLPM( DIALYSATE_FLOW_SENSOR ) > NEARLY_ZERO ) + { + F32 TDi = dialTempMovingAvgData[ DIAL_TEMP_TDI ].dialTempAvgC; + F32 TRo = dialTempMovingAvgData[ DIAL_TEMP_TRO ].dialTempAvgC; + DG_OP_MODE_T op = getCurrentOperationMode(); + F32 driftC = ( DG_MODE_HEAT == op ? TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C : TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C ); + BOOL isDriftOut = ( fabs( TDi - TRo ) > driftC ? TRUE : FALSE ); - checkPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, isDriftOut, fabs( TDi - TRo ), driftC ); + checkPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, isDriftOut, fabs( TDi - TRo ), driftC ); + } } } @@ -683,58 +741,10 @@ *************************************************************************/ static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc ) { - // Some of the temperature sensors have an MSB bit that is used as an error flag. This flag will be a TRUE by default. - BOOL isErrorBitNotValid = FALSE; - S32 convertedADC = (S32)( adc & MASK_OFF_U32_MSB ); + S32 convertedADC = (S32)( adc & MASK_OFF_U32_MSB ); - switch( sensorIndex ) - { - case TEMPSENSORS_LOAD_CELL_A1_B1: - case TEMPSENSORS_LOAD_CELL_A2_B2: - case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: - case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: - case TEMPSENSORS_OUTLET_PRIMARY_HEATER: - case TEMPSENSORS_INLET_PRIMARY_HEATER: - case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: - case TEMPSENSORS_OUTLET_REDUNDANT: - case TEMPSENSORS_INTERNAL_TRO_RTD: - case TEMPSENSORS_INLET_DIALYSATE: - case TEMPSENSORS_INTERNAL_TDI_RTD: - case TEMPSENSORS_HEAT_DISINFECT: - case TEMPSENSORS_INTERNAL_THD_RTD: - { - U08 i; - - // Shift bits by 31 to right to check the error bit status - tempSensors[ sensorIndex ].sensorErrorBitStatus = adc >> SHIFT_BITS_BY_31; - - for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) - { - // If that bit is a 1, there is either CRC error or Status error that are ored on top of each other - // NOTE: only a few sensors have the error bit available but for simplicity, all the sensors are looped. - // This variable is zeroed in the init function and the sensors that do not use this bit are never checked (and set) to - // any other values so those sensors will never trigger this fault. - // If any of the sensors have this bit to be 1, set the error occurred be 1 - if ( tempSensors[ i ].sensorErrorBitStatus > 0 ) - { - isErrorBitNotValid = TRUE; - } - } - } - break; - - default: - // Do nothing. FPGA board temperature sensor does not have error flag bit - // If a wrong temperature sensor name is picked, the function that converts - // ADC counts to temperature raises an alarm. - break; - } - - if ( FALSE == isErrorBitNotValid ) - { - // Make sure the error bit is not true before - processADCRead( sensorIndex, convertedADC ); - } + // Make sure the error bit is not true before + processADCRead( sensorIndex, convertedADC ); } /*********************************************************************//** @@ -770,36 +780,17 @@ *************************************************************************/ static void processADCRead( U32 sensorIndex, S32 adc ) { - U08 i; F32 temperature; F32 avgADCReads; - BOOL isADCNotValid = FALSE; - U32 index = tempSensors[ sensorIndex ].adcNextIndex; - S32 indexValue = tempSensors[ sensorIndex ].rawADCReads [ index ]; + U32 index = tempSensors[ sensorIndex ].adcNextIndex; + S32 indexValue = tempSensors[ sensorIndex ].rawADCReads[ index ]; // Update the temperature sensors' structure tempSensors[ sensorIndex ].rawADCReads[ index ] = adc; tempSensors[ sensorIndex ].adcNextIndex = INC_WRAP( index, 0, MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ); tempSensors[ sensorIndex ].adcRunningSum = tempSensors[ sensorIndex ].adcRunningSum - indexValue + adc; avgADCReads = tempSensors[ sensorIndex ].adcRunningSum >> SHIFT_BITS_BY_2_FOR_AVERAGING; // Calculate the average - // Check if the average ADC is within the accepted range - tempSensors[ sensorIndex ].adcErrorStatus = ( ( (U32)avgADCReads < TEMP_SESNORS_MIN_ADC_COUNT ) || - ( (U32)avgADCReads > TEMP_SENSORS_MAX_ADC_COUNT ) ? TRUE : FALSE ); - - for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) - { - // Loop through the temperature sensors and check the ADC range except the heater's temperature sensors. They are only - // used to display the temperature inside the heaters - if ( ( i != TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ) && ( i != TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ) && - ( i != TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ) && ( i != TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ) ) - { - isADCNotValid |= tempSensors[ sensorIndex ].adcErrorStatus; - } - } - - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, isADCNotValid, sensorIndex, avgADCReads ); - // Different sensors have different ADC to temperature conversion methods switch( sensorIndex ) { @@ -895,53 +886,49 @@ *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ) { - U32 errorCount = 0; U32 readCount = 0; - errorCount = (U32)getFPGARTDErrorCount(); readCount = (U32)getFPGARTDReadCount(); - checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TWO_WIRE_ADC_TEMP_SENSORS, errorCount, readCount ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TWO_WIRE_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, getFPGATPiTemp() ); processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, getFPGATPoTemp() ); processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, getFPGACD1Temp() ); processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, getFPGACD2Temp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp() ); -#ifndef _RELEASE_ - if ( ( getHardwareConfigStatus() != HW_CONFIG_BETA ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) -#endif + if ( getCurrentOperationMode() != DG_MODE_INIT ) { - errorCount = (U32)getFPGATHdErrorCount(); readCount = (U32)getFPGATHdReadCount(); - checkFPGAPersistentAlarms( FPGA_PERS_ERROR_THD_ADC_TEMP_SENSORS, errorCount, readCount ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_THD_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_HEAT_DISINFECT, getFPGATHdTemp() ); + + // Make sure the baro sensor coefficients are not corrupted + checkBaroSensorCRC(); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_THD_RTD, getFPGATHdInternalTemp() ); // Make sure the baro sensor coefficients are not corrupted checkBaroSensorCRC(); baroConvConsts.refTemperature = getFPGABaroReferenceTemperature(); baroConvConsts.temperatureCoeff = getFPGABaroTempCoeffOfTemperature(); - errorCount = getFPGABaroErrorCount(); readCount = getFPGABaroReadCount(); - checkFPGAPersistentAlarms( FPGA_PERS_ERROR_BARO_SENSOR, errorCount, readCount ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_BARO_SENSOR, readCount ); processTempSnsrsADCRead( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR, getFPGABaroTemperature() ); } - errorCount = (U32)getFPGATRoErrorCount(); readCount = (U32)getFPGATRoReadCount(); - checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TRO_ADC_TEMP_SENSORS, errorCount, readCount ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TRO_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, getFPGATRoTemp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp() ); - errorCount = (U32)getFPGATDiErrorCount(); readCount = (U32)getFPGATDiReadCount(); - checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TDI_ADC_TEMP_SENSORS, errorCount, readCount ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TDI_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, getFPGATDiTemp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp() ); @@ -1004,6 +991,8 @@ data.interalTHDRTD = getTemperatureValue( TEMPSENSORS_INTERNAL_THD_RTD ); data.internalCondSnsrTemp = getTemperatureValue( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ); data.baroTempSensor = getTemperatureValue( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ); + data.dialysateInletMovingAvg = dialTempMovingAvgData[ DIAL_TEMP_TDI ].dialTempAvgC; + data.redundantOutletMovingAvg = dialTempMovingAvgData[ DIAL_TEMP_TRO ].dialTempAvgC; broadcastData( MSG_ID_DG_TEMPERATURE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); dataPublicationTimerCounter = 0; @@ -1025,15 +1014,15 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - U08 i; - F32 temperature = 0.0F; - BOOL isTemperatureOutOfRange = FALSE; - F32 alarmTemperature = 0.0F; - U08 alarmIndex = 0; + TEMPERATURE_SENSORS_T sensorId; + TEMPERATURE_SENSORS_T sensorInAlarm = TEMPSENSORS_FIRST; + F32 temperature = 0.0F; + BOOL isTemperatureOutOfRange = FALSE; + F32 alarmTemperature = 0.0F; - for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) + for ( sensorId = TEMPSENSORS_FIRST; sensorId < NUM_OF_TEMPERATURE_SENSORS; sensorId++ ) { - switch ( i ) + switch ( sensorId ) { case TEMPSENSORS_INLET_PRIMARY_HEATER: case TEMPSENSORS_HEAT_DISINFECT: @@ -1043,23 +1032,15 @@ case TEMPSENSORS_OUTLET_REDUNDANT: case TEMPSENSORS_INLET_DIALYSATE: case TEMPSENSORS_FPGA_BOARD_SENSOR: - case TEMPSENSORS_LOAD_CELL_A1_B1: - case TEMPSENSORS_LOAD_CELL_A2_B2: - case TEMPSENSORS_INTERNAL_TRO_RTD: - case TEMPSENSORS_INTERNAL_TDI_RTD: - case TEMPSENSORS_INTERNAL_THD_RTD: - case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: - // All the temperature sensors are monitored except the heaters' temperature sensors. - // The heaters' temperature sensors are only broadcast for information - temperature = getTemperatureValue( i ); - + // All other temperature sensors are only broadcast for logging/dialin purposes. + temperature = getTemperatureValue( sensorId ); // Check both temperature and to be in range - if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ i ].maxAllowedTemp ) ) && - ( getCurrentOperationMode() != DG_MODE_INIT ) ) + if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ sensorId ].maxAllowedTemp ) ) && + ( getCurrentOperationMode() != DG_MODE_INIT ) ) { isTemperatureOutOfRange |= TRUE; - alarmIndex = i; + sensorInAlarm = sensorId; alarmTemperature = temperature; } break; @@ -1071,7 +1052,7 @@ } - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, alarmIndex, alarmTemperature ); + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, sensorInAlarm, alarmTemperature ); } } @@ -1091,11 +1072,11 @@ #ifndef _RELEASE_ if ( ( HW_CONFIG_BETA == getHardwareConfigStatus() ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) -#endif { primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; } +#endif tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; @@ -1151,7 +1132,43 @@ } } +/*********************************************************************//** + * @brief + * The processDialTemperatureData function processes the moving average + * of the dialysate temperature sensors (TDi and TRo). + * @details Inputs: dialTempMovingAvgData + * @details Outputs: dialTempMovingAvgData + * @return: none + *************************************************************************/ +static void processDialTemperatureData( void ) +{ + DIAL_TEMPERATURE_SENSORS_T i; + for ( i = DIAL_TEMP_FIRST; i < NUM_OF_DIAL_TEMPS; i++ ) + { + if ( FALSE == dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet ) + { + dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS = getMSTimerCount(); + dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet = TRUE; + } + else if ( TRUE == didTimeout( dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS, TDI_TRO_DATA_COLLECTION_TIME_MS ) ) + { + TEMPERATURE_SENSORS_T sensor = ( DIAL_TEMP_TDI == i ? TEMPSENSORS_INLET_DIALYSATE : TEMPSENSORS_OUTLET_REDUNDANT ); + F32 temperatureC = getTemperatureValue( sensor ); + U32 currentIndex = dialTempMovingAvgData[ i ].dialTempSamplesNextIndex; + F32 prevSampleToRemoveC = dialTempMovingAvgData[ i ].dialTempSamplesC[ currentIndex ]; + + dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS = getMSTimerCount(); + dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet = TRUE; + dialTempMovingAvgData[ i ].dialTempSamplesC[ currentIndex ] = temperatureC; + dialTempMovingAvgData[ i ].dialTempRunningSumC = dialTempMovingAvgData[ i ].dialTempRunningSumC + temperatureC - prevSampleToRemoveC; + dialTempMovingAvgData[ i ].dialTempSamplesNextIndex = INC_WRAP( dialTempMovingAvgData[ i ].dialTempSamplesNextIndex, 0, DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES - 1 ); + dialTempMovingAvgData[ i ].dialTempAvgC = dialTempMovingAvgData[ i ].dialTempRunningSumC / (F32)DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES; + } + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/