Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -62,6 +62,29 @@ #define DATA_PUBLISH_COUNTER_START_COUNT 0 ///< Data publish counter start count. +/*************************DVT Definitions********************************************/ + +#define CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP 0x07 ///< Concentrate pump control 1/8th step. +#define CONCENTRATE_PUMP_CONTROL_REVERSE_DIR 0x08 ///< Concentrate pump control reverse direction. +#define CONCENTRATE_PUMP_CONTROL_FORWARD_DIR 0x00 ///< Concentrate pump control forward direction. +#define CONCENTRATE_PUMP_CONTROL_ENABLE 0x00 ///< Concentrate pump control enable pump. +#define CONCENTRATE_PUMP_CONTROL_NOT_RESET 0x20 ///< Concentrate pump control not reset. +#define CONCENTRATE_PUMP_CONTROL_SLEEP_OFF 0x40 ///< Concentrate pump control sleep off. + +static const U32 CONCENTRATE_PUMP_CONTROL_FORWARD = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | + CONCENTRATE_PUMP_CONTROL_NOT_RESET | + CONCENTRATE_PUMP_CONTROL_ENABLE | + CONCENTRATE_PUMP_CONTROL_FORWARD_DIR | + CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control forward. + +static const U32 CONCENTRATE_PUMP_CONTROL_REVERSE = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | + CONCENTRATE_PUMP_CONTROL_NOT_RESET | + CONCENTRATE_PUMP_CONTROL_ENABLE | + CONCENTRATE_PUMP_CONTROL_REVERSE_DIR | + CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control reverse. + +/*************************DVT Definitions********************************************/ + /// Enumeration of concentrate pump states. typedef enum ConcentratePumpState { @@ -77,15 +100,13 @@ U32 controlTimerCounter; ///< Timer counter to perform control on concentrate pump. CONCENTRATE_PUMP_STATE_T execState; ///< Concentrate pump execute current state. BOOL hasTurnOnPumpsBeenRequested; ///< Flag indicates a request to turn concentrate pumps on. - F32 pumpTargetSpeed; ///< Target concentrate pumps' speed (mL/min). F32 currentPumpSpeed; ///< Current controlled concentrate pumps' speed (mL/min). OVERRIDE_F32_T measuredPumpSpeed; ///< Measured concentrate pump speed (mL/min). U16 togglePeriodCount; ///< Converted pump speed (mL/min) to toggle period counts (0.5 uS increment counts per step). - U08 direction; ///< Concentrate pump motor direction. - void ( *control )( U08 ); ///< Concentrate pump FPGA control function pointer. - void ( *setStepSpeed )( U16 ); ///< Concentrate pump FPGA set step speed function pointer. + U08 controlSet; ///< Concentrate pump control set. (Used in DVT) + F32 pulseWidthUS; ///< Concentrate pump pulse width in microseconds. } CONCENTRATE_PUMP_T; // ********** private data ********** @@ -100,19 +121,15 @@ static DG_BICARB_CONCENTRATES_RECORD_T bicarbConcentrateCalRecord; ///< Bicarb concentrate calibration record. static DG_CONC_PUMPS_CAL_RECORD_T concentratePumpsCalRecord; ///< Concentrate pumps calibration record. -static F32 cp1PulsetemporaryRemove; -static F32 cp2PulsetemporaryRemove; - - // ********** private function prototypes ********** static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpRampToTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); - static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ); static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ); +static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ); /*********************************************************************//** * @brief @@ -127,20 +144,14 @@ concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].control = &setFPGACP1Control; - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].setStepSpeed = &setFPGACP1SetStepSpeed; - - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].control = &setFPGACP2Control; - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].setStepSpeed = &setFPGACP2SetStepSpeed; - for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { concentratePumps[ pumpId ].controlTimerCounter = 0; concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; - + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT stopConcentratePump( pumpId ); } @@ -165,7 +176,6 @@ // Get the calibration values of acid and bicarb getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( acidConcentrateCalRecord ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); - getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( bicarbConcentrateCalRecord ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); } @@ -180,40 +190,32 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, fpgaConcentratePumpsFault ); } - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); + calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2_BICARB, getFPGACP2HallSensePulseWidth() ); - // Get CP1 specifications - U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; - F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; - F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; + F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; + F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; + F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; + F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - // Get CP2 specifications - U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; - F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; - F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - + // Use the above values to prepare the broadcast data data.cp1CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1SetSpeed * -1.0 : cp1SetSpeed ); data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0 : cp2SetSpeed ); data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); data.cp1State = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].execState; data.cp2State = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].execState; + data.cp1PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pulseWidthUS; + data.cp2PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].pulseWidthUS; - data.cp1PulseInSeconds = cp1PulsetemporaryRemove; - data.cp2PulseInSeconds = cp2PulsetemporaryRemove; - #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS_SPEED_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - F32 cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) - - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; - F32 cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) - - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; - - checkPersistentAlarm( ALARM_ID_CP1_SPEED_CONTROL_ERROR, cp1Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp1Error, CONCENTRATE_PUMP_ERROR_TOLERANCE ); - checkPersistentAlarm( ALARM_ID_CP2_SPEED_CONTROL_ERROR, cp2Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp2Error, CONCENTRATE_PUMP_ERROR_TOLERANCE ); + monitorPumpSpeed( CONCENTRATEPUMPS_CP1_ACID, ALARM_ID_CP1_SPEED_CONTROL_ERROR ); + monitorPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB, ALARM_ID_CP2_SPEED_CONTROL_ERROR ); } concentratePumpMonitorTimerCounter = 0; @@ -248,10 +250,13 @@ concentratePumps[ pumpId ].execState = handleConcentratePumpControlTargetSpeedState( pumpId ); break; +#ifndef _VECTORCAST_ + // The switch case is in a for loop so the default case cannot be covered in VectorCAST default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, pumpId ) concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; break; +#endif } } } @@ -278,14 +283,7 @@ calStatus |= getNVRecord2Driver( GET_CAL_CONCENTRATE_PUMPS_RECORD, (U08*)&concentratePumpsCalRecord, sizeof( DG_CONC_PUMPS_CAL_RECORD_T ), NUM_OF_CAL_DATA_DG_CONC_PUMPS, ALARM_ID_NO_ALARM ); - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } + result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); return result; } @@ -329,10 +327,8 @@ { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { -#ifndef DISABLE_CONC_PUMPS concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; - concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; -#endif + concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } else { @@ -356,12 +352,14 @@ { if ( targetSpeed_ml_min >= 0.0 ) { - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT } else { - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; - targetSpeed_ml_min *= -1.0; + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_REVERSE; // For DV + targetSpeed_ml_min *= -1.0; } if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) @@ -385,6 +383,31 @@ /*********************************************************************//** * @brief + * The getConcentratePumpTargetFlowMLPM function returns the concentrate pump's + * flow rate in mL/min. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId concentrate pump id to get its target flow + * @return the current concentrate pump flow rate (in mL/min). + *************************************************************************/ +F32 getConcentratePumpTargetFlowMLPM( CONCENTRATE_PUMPS_T pumpId ) +{ + F32 flow = 0.0; + + if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) + { + flow = concentratePumps[ pumpId ].pumpTargetSpeed; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return flow; +} + +/*********************************************************************//** + * @brief * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. * @details Inputs: measuredPumpSpeed * @details Outputs: none @@ -393,23 +416,18 @@ *************************************************************************/ F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ) { - F32 result = 0.0; + F32 speed = 0.0; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { - result = concentratePumps[ pumpId ].measuredPumpSpeed.data; - - if ( OVERRIDE_KEY == concentratePumps[ pumpId ].measuredPumpSpeed.override ) - { - result = concentratePumps[ pumpId ].measuredPumpSpeed.ovData; - } + speed = getF32OverrideValue( &concentratePumps[ pumpId ].measuredPumpSpeed ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } - return result; + return speed; } /*********************************************************************//** @@ -453,8 +471,28 @@ concentratePumps[ pumpId ].currentPumpSpeed = 0.0; concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; - concentratePumps[ pumpId ].control( CONCENTRATE_PUMP_OFF_CONTROL ); - concentratePumps[ pumpId ].setStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) + { + setFPGAV3AcidPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); + } + else + { + setFPGAV3BicarbPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); + } + } +#endif + + if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) + { + setFPGAAcidPumpSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); + } + else + { + setFPGABicarbSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); + } } /*********************************************************************//** @@ -472,9 +510,20 @@ if ( TRUE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { - U08 controlValue = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); + U08 controlSet = 0; +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + controlSet = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAV3AcidPumpControl( controlSet ) : setFPGAV3BicarbPumpControl( controlSet ); + } + else +#endif + { + controlSet = concentratePumps[ pumpId ].controlSet; + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpControl( controlSet ) : setFPGABicarbPumpControl( controlSet ); + } - concentratePumps[ pumpId ].control( controlValue ); state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; } @@ -520,7 +569,6 @@ if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) { concentratePumps[ pumpId ].controlTimerCounter = 0; - stepConcentratePumpToTargetSpeed( pumpId ); } @@ -545,7 +593,6 @@ static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ) { F32 speedIncrease; - BOOL hasTgtBeenReached = FALSE; F32 currentToTargetDiff = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); @@ -581,7 +628,8 @@ concentratePumps[ pumpId ].togglePeriodCount = CONCENTRATE_PUMP_ZERO_FLOW_RATE; } - concentratePumps[ pumpId ].setStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ) : + setFPGABicarbSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); return hasTgtBeenReached; } @@ -598,35 +646,17 @@ *************************************************************************/ static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ) { - if ( ( concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].execState != CONCENTRATE_PUMP_OFF_STATE ) && - ( concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].execState != CONCENTRATE_PUMP_OFF_STATE ) ) - { - F32 pulseWidthInMicroSecond = (F32)pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; - BOOL isPulseWidthOut = ( pulseWidthInMicroSecond <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); + F32 pulseWidthInMicroSeconds = (F32)pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; + BOOL isPulseWidthOut = ( pulseWidthInMicroSeconds <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); - // TODO once the pulse is figured out remove this code - if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) - { - cp1PulsetemporaryRemove = pulseWidthInMicroSecond; - } - else - { - cp2PulsetemporaryRemove = pulseWidthInMicroSecond; - } - // TODO once the pulse is figured out remove this code + concentratePumps[ pumpId ].pulseWidthUS = pulseWidthInMicroSeconds; - checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pulseWidthInMicroSecond, - CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); + checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pulseWidthInMicroSeconds, + CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); - if ( FALSE == isPulseWidthOut ) - { - concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSecond ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; - } - } - else + if ( FALSE == isPulseWidthOut ) { - // Clear the alarm condition - checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, FALSE, 0, CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); + concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; } if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) @@ -635,7 +665,35 @@ } } +/*********************************************************************//** + * @brief + * The monitorPumpSpeed function monitors the concentrate pumps speed and + * triggers the alarms if they are out of range. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId pump id to set step speed + * @param alarm which the corresponding alarm of the concentrate pump + * @return none + *************************************************************************/ +static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ) +{ + F32 cpTargetSpeed = concentratePumps[ pumpId ].pumpTargetSpeed; + F32 cpError = fabs( getMeasuredPumpSpeed( pumpId ) - cpTargetSpeed ); + BOOL isCpSpeedOut = FALSE; + if ( concentratePumps[ pumpId ].execState != CONCENTRATE_PUMP_OFF_STATE ) + { + // Check if the pump is not in the off state and if it is not, divide the error + // to target speed. If the pump is off the target speed is 0 + cpError = cpError / cpTargetSpeed; + } + + isCpSpeedOut = ( cpError > CONCENTRATE_PUMP_ERROR_TOLERANCE ? TRUE : FALSE ); + + checkPersistentAlarm( alarm, isCpSpeedOut, cpError, CONCENTRATE_PUMP_ERROR_TOLERANCE ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r852597f3be2578331b0b947b38969b3c9553f889 -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 852597f3be2578331b0b947b38969b3c9553f889) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -20,6 +20,7 @@ #include "FPGA.h" #include "NVDataMgmt.h" #include "MessageSupport.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -61,10 +62,20 @@ #define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. #define RO_REJECTION_RATIO_PERSISTENCE_PERIOD ( 10 * MS_PER_SECOND ) ///< Persistence period for RO rejection ratio. -#define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Measurement offset for emstat pico measurement data. -#define EMSTAT_PICO_GOOD_STATUS 0x10 ///< Measurement good status. -#define EMSTAT_PICO_TIMING_NOT_MET_STATUS 0x11 ///< Measurement takes too long status. -#define EMSTAT_PICO_FIFO_EMPTY_MASK 0x8000 ///< Emstat Pico buffer empty indication bit. +#define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Emstat measurement offset. +// The below Emstat status values come from the MethodScript-v1_2-1.pdf. See page 10 table 4 for further information +// The first hex value is the status ID meaning that all of these are the status of the sensor. The second hex value is the content. +#define EMSTAT_PICO_STATUS_OK 0x10 ///< Emstat measurement good status. +#define EMSTAT_PICO_STATUS_TIMING_NOT_MET 0x11 ///< Emstat measurement takes too long status. +#define EMSTAT_PICO_STATUS_95_PCT_OF_MAX_ADC 0x12 ///< Emstat measurement overload, >95% of max ADC value status. +#define EMSTAT_PICO_STATUS_2_PCT_OF_MAX_ADC 0x14 ///< Emstat measurement underload, <2% of max ADC value status. +#define EMSTAT_PICO_STATUS_80_PCT_OF_MAX_ADC 0x18 ///< Emstat measurement overload warning, >80% of max ADC value status. + +#define EMSTAT_PICO_FIFO_EMPTY_MASK 0x8000 ///< Emstat buffer empty indication bit. +#define EMSTAT_NUM_OF_SENSORS_PER_BOARD 2 ///< Emstat Pico number of sensors per board. +#define EMSTAT_CPI_OR_CD1_INDEX 0 ///< Emstat board CPi index number. +#define EMSTAT_CPO_OR_CD2_INDEX 1 ///< Emstat board CPo index number. + #define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. #define COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ( 1 * MS_PER_SECOND ) ///< Conductivity sensor bad status persistence period. @@ -79,44 +90,64 @@ U16 status; ///< Status for measurement data package U08 reserved2[4]; ///< Comma separator and index of current range } EMSTAT_VARIABLE_T; + +/// Emstat conductivity sensor and its corresponding temperature sensor +typedef struct +{ + CONDUCTIVITY_SENSORS_T condSnsr; ///< Emstat conductivity sensor 1 on the board. + TEMPERATURE_SENSORS_T condSnsrTempSnsr; ///< Emstat conductivity sensor 1 temperature sensor. +} EMSTAT_COND_AND_TEMP_T; + +/// Emstat board structure +typedef struct +{ + BOOL packageStarted; ///< Emstat package started flag. + U08 packageIndex; ///< Emstat package index number. + U08 package[ 50 ]; ///< Emstat read buffer package. + EMSTAT_COND_AND_TEMP_T sensors[ EMSTAT_NUM_OF_SENSORS_PER_BOARD ]; ///< Emstat conductivity and corresponding temperature sensors + U16 fpgaPreviousCount; ///< Emstat FPGA previous count. + U08 fpgaPreviousErrorCount; ///< Emstat FPGA previous error count. +} EMSTAT_READ_T; + +/// Conductivity sensors structure +typedef struct +{ + U08 readCount; ///< Conductivity sensor FPGA read count. + U32 internalErrorCount; ///< Conductivity sensor internal error count. + OVERRIDE_F32_T compensatedCondValue; ///< Conductivity sensor compensated value + F32 rawCondValue; ///< Conductivity sensor raw value. + U32 sensorStatus; ///< Conductivity sensor status. +} COND_SENSOR_STATUS_T; #pragma pack(pop) // ********** private data ********** -/// Conductivity sensors' associated temperature sensors -static U32 associateTempSensor[ NUM_OF_CONDUCTIVITY_SENSORS ] = +/// Emstat boards for CPi/CPo and CD1/CD2 +typedef enum EmstatBoards { - TEMPSENSORS_INLET_PRIMARY_HEATER, ///< Inlet temperature sensor - TEMPSENSORS_OUTLET_PRIMARY_HEATER, ///< Outlet temperature sensor - TEMPSENSORS_CONDUCTIVITY_SENSOR_1, ///< Post-acid temperature sensor - TEMPSENSORS_CONDUCTIVITY_SENSOR_2, ///< Post-bicarbonate temperature sensor -}; + EMSTAT_CPI_CPO_BOARD = 0, ///< Emstat CPi/CPo board. + EMSTAT_CD1_CD2_BOARD, ///< Emstat CD1/CD2 board. + NUM_OF_EMSTAT_BOARDS ///< Number of Emstat boards. +} EMSTAT_BOARD_T; -static U08 readCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Read count for conductivity readings. -static U32 internalErrorCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Internal error count for conductivity readings. -static OVERRIDE_F32_T compensatedConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest compensated conductivity values. -static F32 rawConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest raw conductivity values. -static F32 roRejectionRatio; ///< Latest RO rejection ratio. -static U32 sensorStatus[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest sensor hardware status. - static OVERRIDE_U32_T conductivityDataPublishInterval = { COND_SENSOR_REPORT_PERIOD, COND_SENSOR_REPORT_PERIOD, 0, 0 }; ///< Conductivity sensors publish time interval override. -static U32 conductivityDataPublicationTimerCounter; ///< Conductivity sensors data publish timer counter. - -static BOOL packageStarted; ///< Flag to indicate the start of a package measurement data. -static U08 packageIndex; ///< Current package measurement data bytes index. -static U08 package[ 50 ]; ///< Storage of package bytes until ready to process. +static F32 roRejectionRatio; ///< Latest RO rejection ratio. +static U32 condDataPublishCounter; ///< Conductivity sensors data publish timer counter. +static EMSTAT_READ_T emstatBoardRead[ NUM_OF_EMSTAT_BOARDS ]; ///< EMSTAT board read. +static COND_SENSOR_STATUS_T condSensorStatus[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Conductivity sensors status. static DG_COND_SENSORS_CAL_RECORD_T condSensorsCalRecord; ///< Conductivity sensors' calibration record. // ********** private function prototypes ********** static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ); static void calcRORejectionRatio( void ); -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); static U32 prefixStrToSIFactor( U08 prefix ); -static void processMeasurementDataPackage( U32 sensorId ); -static void processCD1CD2SensorRead( U16 fpgaReadCount, U08 fpgaErrorCount ); +static void processEmstatBoard( EMSTAT_BOARD_T board ); +static void processEmstatSensorRead( EMSTAT_READ_T* readPackage, U08 emstatByte, U16 fpgaReadCount, U08 fpgaErrorCount ); +static void processEmstatMeasurementDataPackets( U08 boardSensorIndex, EMSTAT_READ_T* readPackage, EMSTAT_VARIABLE_T* receivedPackets ); static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ); /*********************************************************************//** @@ -128,36 +159,44 @@ *************************************************************************/ void initConductivitySensors( void ) { - U32 i; + U08 i; + roRejectionRatio = 0.0; + condDataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; - roRejectionRatio = 0.0; - packageIndex = 0U; - packageStarted = FALSE; - conductivityDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - for ( i = 0; i < NUM_OF_CONDUCTIVITY_SENSORS; i++ ) { - readCount[ i ] = 0; - internalErrorCount[ i ] = 0; - rawConductivityValues[ i ] = 0.0; - - compensatedConductivityValues[ i ].data = 0.0; - compensatedConductivityValues[ i ].ovData = 0.0; - compensatedConductivityValues[ i ].ovInitData = 0.0; - compensatedConductivityValues[ i ].override = OVERRIDE_RESET; - + memset( &condSensorStatus[ i ], 0x0, sizeof( COND_SENSOR_STATUS_T ) ); benignPolynomialCalRecord( &condSensorsCalRecord.condSensors[ i ] ); } + // Reset all the read packages of the Emstat boards + for ( i = 0; i < NUM_OF_EMSTAT_BOARDS; i++ ) + { + memset( &emstatBoardRead[ i ], 0x0, sizeof( EMSTAT_BOARD_T ) ); + } + + // Each Emstat board covers two conductivity sensors + // CPi/CPo Emstat board conductivity sensors and their corresponding temperature sensors + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CPI_SENSOR; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrTempSnsr = TEMPSENSORS_INLET_PRIMARY_HEATER; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CPO_SENSOR; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrTempSnsr = TEMPSENSORS_OUTLET_PRIMARY_HEATER; + // CD1/CD2 Emstat board conductivity sensors and their corresponding temperature sensors + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CD1_SENSOR; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrTempSnsr = TEMPSENSORS_CONDUCTIVITY_SENSOR_1; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CD2_SENSOR; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrTempSnsr = TEMPSENSORS_CONDUCTIVITY_SENSOR_2; + + // For V3 conductivity sensors setFPGACPiProbeType( COND_CPI_SENSOR_PROBE_TYPE ); setFPGACPoProbeType( COND_CPO_SENSOR_PROBE_TYPE ); - initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); - initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, RO_REJECTION_RATIO_PERSISTENCE_PERIOD, RO_REJECTION_RATIO_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, RO_REJECTION_RATIO_PERSISTENCE_PERIOD, RO_REJECTION_RATIO_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); } /*********************************************************************//** @@ -178,34 +217,38 @@ NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); } - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); - processCD1CD2SensorRead( getFPGAEmstatRxFifoCount(), getFPGAEmstatRxErrCount() ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, EMSTAT_CPI_OR_CD1_INDEX, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, EMSTAT_CPO_OR_CD2_INDEX, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); + } + else +#endif + { + processEmstatBoard( EMSTAT_CPI_CPO_BOARD ); + } + processEmstatBoard( EMSTAT_CD1_CD2_BOARD ); - if ( ++conductivityDataPublicationTimerCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) + if ( ++condDataPublishCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) { CONDUCTIVITY_DATA_T data; calcRORejectionRatio(); - - conductivityDataPublicationTimerCounter = 0; - data.roRejectionRatio = roRejectionRatio; - - data.cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - data.cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - data.cd1 = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - data.cd2 = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - - data.cpiRaw = rawConductivityValues[ CONDUCTIVITYSENSORS_CPI_SENSOR ]; - data.cpoRaw = rawConductivityValues[ CONDUCTIVITYSENSORS_CPO_SENSOR ]; - data.cd1Raw = rawConductivityValues[ CONDUCTIVITYSENSORS_CD1_SENSOR ]; - data.cd2Raw = rawConductivityValues[ CONDUCTIVITYSENSORS_CD2_SENSOR ]; - - data.cpiSensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ]; - data.cpoSensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ]; - data.cd1SensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ]; - data.cd2SensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ]; - + data.roRejectionRatio = roRejectionRatio; + data.cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + data.cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + data.cd1 = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + data.cd2 = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + data.cpiRaw = condSensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ].rawCondValue; + data.cpoRaw = condSensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ].rawCondValue; + data.cd1Raw = condSensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ].rawCondValue; + data.cd2Raw = condSensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ].rawCondValue; + data.cpiSensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ].sensorStatus; + data.cpoSensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ].sensorStatus; + data.cd1SensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ].sensorStatus; + data.cd2SensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ].sensorStatus; + condDataPublishCounter = 0; broadcastData( MSG_ID_DG_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); } } @@ -220,20 +263,10 @@ *************************************************************************/ SELF_TEST_STATUS_T execConductivitySensorsSelfTest( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - - BOOL calStatus = getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( condSensorsCalRecord ), + BOOL calStatus = getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( condSensorsCalRecord ), NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); + SELF_TEST_STATUS_T result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } - return result; } @@ -321,7 +354,10 @@ if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - result = getF32OverrideValue( &compensatedConductivityValues[ sensorId ] ); + // NOTE: the compensated value is set into a local variable and then passed to the override function + // to prevent memory failure + OVERRIDE_F32_T value = condSensorStatus[ sensorId ].compensatedCondValue; + result = getF32OverrideValue( &value ); } else { @@ -345,7 +381,7 @@ static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ) { // EC = EC_25 * (1 + temp_coef * ( temperature - 25 )) - F32 const compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); + F32 compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); return conductivity / compensatedCoef; } @@ -360,8 +396,8 @@ *************************************************************************/ static void calcRORejectionRatio( void ) { - F32 const cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); roRejectionRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; @@ -379,31 +415,33 @@ * @details Inputs: none * @details Outputs: none * @param sensorId Conductivity sensor id to process + * @param emstatBoardSensorIndex the sensor index number on an EMSTAT board * @param fgpaRead FPGA conductivity reading value * @param fpgaReadCount FPGA read count * @param fpgaErrorCount FPGA error count * @param fpgaSensorFault FPGA sensor fault * @return none *************************************************************************/ -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) { if ( ( 0 == fpgaErrorCount ) && ( 0 == fpgaSensorFault ) ) { - if ( ( readCount[ sensorId ] != fpgaReadCount ) ) + if ( ( condSensorStatus[ sensorId ].readCount != fpgaReadCount ) ) { - F32 temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); + // The corresponding temperature sensor of a conductivity sensor is maintained in the EMSTAT boards' structure since the + // EMSTAT sensors will be the permanent sensors from DVT onward. + F32 temperature = getTemperatureValue( emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ emstatBoardSensorIndex ].condSnsrTempSnsr ); + F32 conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); - readCount[ sensorId ] = fpgaReadCount; - internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); - rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CPi and CPo + condSensorStatus[ sensorId ].readCount = fpgaReadCount; + condSensorStatus[ sensorId ].internalErrorCount = 0; + condSensorStatus[ sensorId ].compensatedCondValue.data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); + condSensorStatus[ sensorId ].rawCondValue = conductivity; // store raw conductivity data from CPi and CPo } else { - ++internalErrorCount[ sensorId ]; - if ( internalErrorCount[ sensorId ] > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) + if ( ++condSensorStatus[ sensorId ].internalErrorCount > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) @@ -416,7 +454,7 @@ } else { - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) // TODO remove time windowed { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) @@ -460,110 +498,97 @@ /*********************************************************************//** * @brief - * The processMeasurementDataPackage function processes incoming measurement data - * package variables from Emstat Pico and convert it to conductivity. The conductivity - * value is then compensated based on associating temperature sensor's value. - * @details Inputs: none - * @details Outputs: none - * @param sensorId Conductivity sensor id to process + * The processEmstatBoard function processes the Emsat boards + * @details Inputs: emstatBoardRead + * @details Outputs: emstatBoardRead + * @param board the enum of the Emstat board * @return none *************************************************************************/ -static void processMeasurementDataPackage( U32 sensorId ) +static void processEmstatBoard( EMSTAT_BOARD_T board ) { - EMSTAT_VARIABLE_T const * const measurementPtr = (EMSTAT_VARIABLE_T *)&package; - U32 status = hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ); - sensorStatus[ sensorId ] = status; + U08 emstatByte = 0; + U08 fpgaErrorCount = 0; + U16 fpgaReadCount = 0; - if ( EMSTAT_PICO_GOOD_STATUS == status ) + switch ( board ) { - U32 prefix = prefixStrToSIFactor( measurementPtr->prefix ); - F32 resistance = ( ( F32 )( hexStrToDec( measurementPtr->value, sizeof( measurementPtr->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); - F32 temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 conductivity = ( 1.0 / resistance * SIEMENS_TO_MICROSIEMENS_CONVERSION ); - F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + case EMSTAT_CPI_CPO_BOARD: + emstatByte = getFPGAEmstatCPiCPoByteOut(); + fpgaErrorCount = getFPGAEmstatCPiCPoRxErrCount(); + fpgaReadCount = getFPGAEmstatCPiCPoRxFifoCount(); + processEmstatSensorRead( &emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ], emstatByte, fpgaReadCount, fpgaErrorCount ); + break; - internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); - rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CD1 and CD2 + case EMSTAT_CD1_CD2_BOARD: + emstatByte = getFPGAEmstatCD1CD2OutByte(); + fpgaErrorCount = getFPGAEmstatCD1CD2RxErrCount(); + fpgaReadCount = getFPGAEmstatCD1CD2RxFifoCount(); + processEmstatSensorRead( &emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ], emstatByte, fpgaReadCount, fpgaErrorCount ); + break; - // Clear the alarm - checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, FALSE, status, EMSTAT_PICO_GOOD_STATUS ); + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_EMSTAT_CONDUCTIVITY_BOARD_SELECTED, board ); + break; } - else - { -#ifndef DISABLE_COND_STATUS_CHECK - checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, TRUE, status, EMSTAT_PICO_GOOD_STATUS ); -#endif - } - - if ( EMSTAT_PICO_TIMING_NOT_MET_STATUS == status ) - { - if ( ++internalErrorCount[ sensorId ] > MAX_CONDUCTIVITY_SENSOR_FAILURES ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); - } - } - else - { - internalErrorCount[ sensorId ] = 0; - } } /*********************************************************************//** * @brief - * The processCD1CD2SensorRead function checks if there is an error with Emstat - * conductivity sensors. If there is any error with the Emstat conductivity sensors, - * it raises an alarm. If the read count has changed, the new reading will be processed. + * The processEmstatSensorRead function processes the Emsat boards' data + * that is received from the boards * @details Inputs: none * @details Outputs: none - * @param fpgaReadCount FPGA read count for rx fifo - * @param fpgaErrorCount FPGA error count + * @param read package the structure of each Emstat board + * @param emstatByte the received byte from the sensor + * @param fpgaReadCount the FPGA read count + * @param fpgaErrorCount the FGPA error count * @return none *************************************************************************/ -static void processCD1CD2SensorRead( U16 fpgaReadCount, U08 fpgaErrorCount ) +static void processEmstatSensorRead( EMSTAT_READ_T* readPackage, U08 emstatByte, U16 fpgaReadCount, U08 fpgaErrorCount ) { - if ( fpgaErrorCount == 0 ) + switch ( emstatByte ) { - if ( ( fpgaReadCount > 0 ) && ( ( fpgaReadCount & EMSTAT_PICO_FIFO_EMPTY_MASK ) == 0 ) ) - { - U08 const emstatByte = getFPGAEmstatOutByte(); + case 'P': + readPackage->packageStarted = TRUE; + readPackage->packageIndex = 0; + break; - switch ( emstatByte ) + case ';': + if ( TRUE == readPackage->packageStarted ) { - case 'P': - packageStarted = TRUE; - packageIndex = 0; - break; + processEmstatMeasurementDataPackets( EMSTAT_CPI_OR_CD1_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageIndex = 0; + } + break; - case ';': - if ( packageStarted ) - { - processMeasurementDataPackage( CONDUCTIVITYSENSORS_CD1_SENSOR ); - packageIndex = 0; - } - break; + case '\n': + if ( TRUE == readPackage->packageStarted ) + { + processEmstatMeasurementDataPackets( EMSTAT_CPO_OR_CD2_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageStarted = FALSE; + } + break; - case '\n': - if ( packageStarted ) - { - processMeasurementDataPackage( CONDUCTIVITYSENSORS_CD2_SENSOR ); - packageStarted = FALSE; - } - break; - - default: - if ( packageStarted ) - { - package[ packageIndex++ ] = emstatByte; - } - break; + default: + if ( TRUE == readPackage->packageStarted ) + { + readPackage->package[ readPackage->packageIndex++ ] = emstatByte; } - } + break; } - else + +#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT + // Only process the FPGA error and count values if the DG Software is not in the POST mode + if ( getCurrentOperationMode() != DG_MODE_INIT ) { - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) + if ( ( fpgaReadCount != readPackage->fpgaPreviousCount ) && ( 0 == ( fpgaReadCount & EMSTAT_PICO_FIFO_EMPTY_MASK ) ) && + ( fpgaErrorCount != readPackage->fpgaPreviousErrorCount ) ) { + // Everything is fine update the previous read with the current read + readPackage->fpgaPreviousCount = fpgaReadCount; + } + else if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) // TODO remove time windowed + { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -572,10 +597,58 @@ } } } +#endif } /*********************************************************************//** * @brief + * The processEmstatMeasurementDataPackets function processes the Emsat boards' + * received data packets. + * @details Inputs: condSensorStatus, + * @details Outputs: condSensorStatus + * @param boardSenosrIndex the sensor index on each board (i.e CPi = 0 & CPo = 1 + * in EMSTAT_CPI_CPO_BOARD) + * @param read package the structure of each Emstat board + * @return none + *************************************************************************/ +static void processEmstatMeasurementDataPackets( U08 boardSensorIndex, EMSTAT_READ_T* readPackage, EMSTAT_VARIABLE_T* receivedPackets ) +{ + CONDUCTIVITY_SENSORS_T sensorId = readPackage->sensors[ boardSensorIndex ].condSnsr; + condSensorStatus[ sensorId ].sensorStatus = hexStrToDec( (U08*)&receivedPackets->status, sizeof( receivedPackets->status ) ); + BOOL isSensorStatusBad = ( EMSTAT_PICO_STATUS_TIMING_NOT_MET == condSensorStatus[ sensorId ].sensorStatus ? TRUE : FALSE ); + + if ( FALSE == isSensorStatusBad ) + { + U32 prefix = prefixStrToSIFactor( receivedPackets->prefix ); + F32 resistance = ( ( F32 )( hexStrToDec( receivedPackets->value, sizeof( receivedPackets->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); + F32 temperature = getTemperatureValue( readPackage->sensors[ boardSensorIndex ].condSnsrTempSnsr ); + F32 conductivity = ( 1.0 / resistance ) * SIEMENS_TO_MICROSIEMENS_CONVERSION; + F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + + condSensorStatus[ sensorId ].internalErrorCount = 0; + condSensorStatus[ sensorId ].compensatedCondValue.data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); + condSensorStatus[ sensorId ].rawCondValue = conductivity; + } + + // Check the conductivity sensors bad status alarm + checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, isSensorStatusBad, condSensorStatus[ sensorId ].sensorStatus, + EMSTAT_PICO_STATUS_TIMING_NOT_MET ); + + if ( EMSTAT_PICO_STATUS_TIMING_NOT_MET == condSensorStatus[ sensorId ].sensorStatus ) + { + if ( ++condSensorStatus[ sensorId ].internalErrorCount > MAX_CONDUCTIVITY_SENSOR_FAILURES ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); + } + } + else + { + condSensorStatus[ sensorId ].internalErrorCount = 0; + } +} + +/*********************************************************************//** + * @brief * The getCalibrationAppliedConductivityValue function gets the temperature * compensated conductivity value and applies calibration to it. * @details Inputs: condSensorsCalRecord @@ -590,7 +663,7 @@ F32 conductivity = pow(compensatedValue, 4) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].fourthOrderCoeff + pow(compensatedValue, 3) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].thirdOrderCoeff + pow(compensatedValue, 2) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].secondOrderCoeff + - compensatedValue * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].gain + + compensatedValue * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].gain + condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].offset; return conductivity; } @@ -605,8 +678,8 @@ * @brief * The testSetConductivityOverride function overrides the compensated * conductivity value of given sensor id. - * @details Inputs: compensatedConductivityValues[] - * @details Outputs: compensatedConductivityValues[] + * @details Inputs: none + * @details Outputs: condSensorStatus * @param sensorId conductivity sensor id * @param value override compensated conductivity value * @return TRUE if override successful, FALSE if not @@ -617,11 +690,11 @@ if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = value; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_KEY; + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = value; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_KEY; } } @@ -632,8 +705,8 @@ * @brief * The testResetConductivityOverride function resets the override of the * conductivity sensor value. - * @details Inputs: compensatedConductivityValues[] - * @details Outputs: compensatedConductivityValues[] + * @details Inputs: none + * @details Outputs: condSensorStatus * @param sensorId conductivity sensor id * @return TRUE if reset successful, FALSE if not *************************************************************************/ @@ -643,11 +716,11 @@ if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = compensatedConductivityValues[ sensorId ].ovInitData; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_RESET; + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = condSensorStatus[ sensorId ].compensatedCondValue.ovInitData; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_RESET; } } Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -53,22 +53,15 @@ #define MINIMUM_TARGET_TEMPERATURE 10.0F ///< Minimum allowed target temperature for the heaters. #define MAXIMUM_TARGET_TEMPERATURE 90.0F ///< Maximum allowed target temperature for the heaters. -#define MAXIMUM_IDLE_DRAIN_TARGET_TEMPERATURE 58.0F ///< Maximum allowed target temperature for the idle and drain modes. -#define HEATERS_CONTROL_STATE_CHECK_INTERVAL_COUNT ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Temperature sensors interval count. -#define HEATERS_ON_WITH_NO_FLOW_TIMEOUT_COUNT ( ( 3 * MS_PER_SECOND ) / TASK_PRIORITY_INTERVAL ) ///< Heaters are on but there is no sufficient flow timeout in counts. -#define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 170.0F ///< Heaters max allowed internal temperature in C. -#define HEATERS_MAX_ALLOWED_COLD_JUNCTION_TEMPERATURE_C 80.0F ///< Heaters max allowed cold junction temperature in C. -#define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters max allowed internal temperature timeout in milliseconds. #define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. #define HEATERS_MAX_OPERATING_VOLTAGE_V 24.0F ///< Heaters max operating voltage in volts. #define HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heaters voltage out of range time out in milliseconds. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heaters max voltage out of range tolerance. -#define HEATERS_MIN_RAMP_TIME_MS ( 6 * MS_PER_SECOND ) ///< Heaters minimum time that they have to stay in the ramp state in milliseconds. -#define TEMPERATURES_MOVING_AVG_SIZE 3U ///< Heaters ramp state temperatures moving average size. +#define TRIMMER_HEATER_MAX_POWER_W 66.5F ///< Trimmer heater maximum power in Watts. +#define TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. #define DELTA_TEMPERATURE_TIME_COSNTANT_C 8.6F ///< Delta temperature calculated from time constant. -#define MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C 0.25F ///< Maximum allowed temperature deviation from target temperature in C. #define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.03F ///< Primary heaters duty cycle per temperature in C. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. @@ -95,16 +88,17 @@ BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. F32 dutycycle; ///< Heater duty cycle. - F32 targetROFlow; ///< Heater target flow. + F32 targetFlow; ///< Heater target flow. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. F32 heaterEfficiency; ///< Heater efficiency during the run. BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. - - F32 temporaryInterimTemperature; ///< TODO remove + F32 calculatedTemperature; ///< Heater calculated temperature. + DG_RESERVOIR_ID_T inactiveRsrvr; ///< Heater inactive reservoir. } HEATER_STATUS_T; static HEATER_STATUS_T heatersStatus[ NUM_OF_DG_HEATERS ]; ///< Heaters status. static U32 dataPublicationTimerCounter; ///< Data publication timer counter. +static U32 trimmerHeaterControlCounter; ///< Trimmer heater control counter. static OVERRIDE_U32_T heatersDataPublishInterval = { HEATERS_DATA_PUBLISH_INTERVAL, HEATERS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Heaters data publish time interval. // ********** private function prototypes ********** @@ -132,13 +126,15 @@ * The initHeaters initializes the heaters driver. * @details Inputs: none * @details Outputs: voltageMonitorTimeCounter, heaterStatus, - * hasTreatmentInternalTempBeenSet, dataPublicationTimerCounter + * hasTreatmentInternalTempBeenSet, dataPublicationTimerCounter, + * trimmerHeaterControlCounter * @return none *************************************************************************/ void initHeaters( void ) { DG_HEATERS_T heater; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + trimmerHeaterControlCounter = 0; for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) { @@ -147,7 +143,7 @@ heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].isHeaterOn = FALSE; heatersStatus[ heater ].dutycycle = 0.0; - heatersStatus[ heater ].targetROFlow = 0.0; + heatersStatus[ heater ].targetFlow = 0.0; heatersStatus[ heater ].hasTargetTempChanged = FALSE; heatersStatus[ heater ].heaterEfficiency = 1.0; // Assuming 100% efficiency during initialization until it is updated heatersStatus[ heater ].hasTargetBeenReached = FALSE; @@ -174,10 +170,12 @@ * @param heater: heater ID that its target temperature is set * @param targetTemperature: target temperature of that the heater has to * heat the fluid - * @return none + * @return TRUE if the temperature was set otherwise, FALSE *************************************************************************/ -void setHeaterTargetTemperature( DG_HEATERS_T heater, F32 targetTemperature ) +BOOL setHeaterTargetTemperature( DG_HEATERS_T heater, F32 targetTemperature ) { + BOOL result = FALSE; + if( heater < NUM_OF_DG_HEATERS ) { // Assume the target temperature has not changed @@ -188,13 +186,15 @@ { heatersStatus[ heater ].targetTemp = targetTemperature; heatersStatus[ heater ].hasTargetTempChanged = TRUE; - // TODO alarm if temperature if out of range or just reject? + result = TRUE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_HEATER_ID_SELECTED, heater ) } + + return result; } /*********************************************************************//** @@ -225,7 +225,7 @@ { if ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) { - status = TRUE; + status = TRUE; heatersStatus[ heater ].startHeaterSignal = TRUE; } } @@ -311,51 +311,6 @@ /*********************************************************************//** * @brief - * The handleTrimmerHeaterCmd handles a start trimmer heater command from the HD. - * It resets the trimmer heater's state and sets the duty cycle of the trimmer heater. - * @details Inputs: none - * @details Outputs: process command and send back response - * @param heaterCmdPtr pointer to heater command data record - * @return status - *************************************************************************/ -void handleTrimmerHeaterCmd( TRIMMER_HEATER_CMD_T *heaterCmdPtr ) -{ - DG_CMD_RESPONSE_T cmdResponse; - - cmdResponse.commandID = DG_CMD_START_TRIMMER_HEATER; - cmdResponse.rejected = TRUE; - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - if ( TRUE == heaterCmdPtr->startHeater ) - { - if ( ( heaterCmdPtr->targetTemp >= MINIMUM_TARGET_TEMPERATURE ) && ( heaterCmdPtr->targetTemp <= MAXIMUM_TARGET_TEMPERATURE ) ) - { - cmdResponse.rejected = FALSE; - heatersStatus[ DG_TRIMMER_HEATER ].targetTemp = heaterCmdPtr->targetTemp; // TODo do we need to remove this since the trimmer heater is set in the reservoirs - -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TRIMMER_HEATER ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - heatersStatus[ DG_TRIMMER_HEATER ].startHeaterSignal = TRUE; - } - } - else - { - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; - } - } - else - { - cmdResponse.rejected = FALSE; - stopHeater( DG_TRIMMER_HEATER ); - } - - sendCommandResponseMsg( &cmdResponse ); -} - -/*********************************************************************//** - * @brief * The execHeatersMonitor function monitors the status of the heaters. * The internal temperature sensors and the voltages of the heaters are * monitored. The flow is continuously checked and if there is no flow @@ -457,31 +412,29 @@ if ( DG_MODE_FILL == opMode ) { // If the previous average fill flow rate is 0, use the nominal target RO flow from the RO pump - targetFlow = ( getAvgFillFlowRate() - 0.0 > NEARLY_ZERO ? getAvgFillFlowRate() : getTargetROPumpFlowRate() ); + targetFlow = ( getAvgFillFlowRateLPM() - 0.0 > NEARLY_ZERO ? getAvgFillFlowRateLPM() : getTargetROPumpFlowRateLPM() ); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, TRUE ); state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } else if ( ( DG_MODE_GENE == opMode ) || ( DG_MODE_DRAI == opMode ) ) { targetTemperature += DELTA_TEMPERATURE_TIME_COSNTANT_C; // Use target flow rate during Idle and drain - targetFlow = getTargetROPumpFlowRate(); + targetFlow = getTargetROPumpFlowRateLPM(); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } else if ( ( DG_MODE_HEAT == opMode ) || ( DG_MODE_CHEM == opMode ) ) { // If the mode is any of the disinfects, especially heat, use the target flow rate instead of the avg. flow // Most of the times the heater should be running at 100% duty cycle since the target temperature is 81 C - targetFlow = getTargetROPumpFlowRate(); + targetFlow = getTargetROPumpFlowRateLPM(); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; } - // TODO remove once dialysate heating is done - heatersStatus[ DG_PRIMARY_HEATER ].temporaryInterimTemperature = targetTemperature; - // TODO remove - + // Update the calculated target temperature + heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature = targetTemperature; setHeaterDutyCycle( heater, dutyCycle ); return state; @@ -564,15 +517,15 @@ HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; DG_HEATERS_T heater = DG_TRIMMER_HEATER; F32 currentTemperature = 0.0; - F32 targetFlow = getTargetDialysateFlowLPM(); + F32 targetFlowLPM = getTargetDialysateFlowLPM(); F32 dutyCycle = 0.0; F32 targetTemperature = heatersStatus[ heater ].targetTemp; DG_OP_MODE_T opMode = getCurrentOperationMode(); if ( ( DG_MODE_FILL == opMode ) || ( DG_MODE_GENE == opMode ) || ( DG_MODE_DRAI == opMode ) ) { - currentTemperature = getReservoirActualTemperature(); - dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlow, TRUE ); + currentTemperature = getTrimmerHeaterTargetTemperature(); + dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlowLPM, TRUE ); state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; } else if ( DG_MODE_HEAT == opMode ) @@ -581,11 +534,16 @@ // Most of the times the heater should be running at 100% duty cycle since the target temperature is 81 C and // it is far from the inlet temperature. currentTemperature = getTemperatureValue( (U32)TEMPSENSORS_HEAT_DISINFECT ); - targetFlow = getTargetROPumpFlowRate(); - dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlow, FALSE ); + targetFlowLPM = getTargetROPumpFlowRateLPM(); + dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlowLPM, FALSE ); state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; } + // Update the calculated target temperature + heatersStatus[ heater ].calculatedTemperature = currentTemperature; + heatersStatus[ heater ].inactiveRsrvr = getInactiveReservoir(); + heatersStatus[ heater ].targetFlow = targetFlowLPM; + trimmerHeaterControlCounter = 0; setHeaterDutyCycle( heater, dutyCycle ); return state; @@ -594,20 +552,32 @@ /*********************************************************************//** * @brief * The handleHeaterStateTrimmerControlToTarget function handles the trimmer - * heater's control to target. - * @details Inputs: heaterStatus - * @details Outputs: heaterStatus + * heater's control to target state. + * @details Inputs: heaterStatus, trimmerHeaterControlCounter + * @details Outputs: heaterStatus, trimmerHeaterControlCounter * @return next state of the state machine *************************************************************************/ static HEATERS_STATE_T handleHeaterStateTrimmerControlToTarget( void ) { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; - DG_HEATERS_T heater = DG_TRIMMER_HEATER; - if ( TRUE == haveHeaterControlConditionsChanged( heater ) ) // TODO do we need this kind of check from trimmer?? + // If the inactive reservoir has changed from the last run transition to ramp state to recalculate the + // duty cycle for the next delivery + if ( heatersStatus[ DG_TRIMMER_HEATER ].inactiveRsrvr != getInactiveReservoir() ) { state = HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET; } + else if ( ++trimmerHeaterControlCounter > TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ) + { + // When the trimmer heater is on, its duty cycle is adjusted at the control interval. For this control check, + // dialysate inlet temperature sensor is used rather than the theoretical calculations. + F32 outletRedundantTemperature = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); // TODO Change to TRo in DVT + F32 targetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; + F32 targetFlowLPM = heatersStatus[ DG_TRIMMER_HEATER ].targetFlow; + F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, outletRedundantTemperature, targetFlowLPM, TRUE ); + trimmerHeaterControlCounter = 0; + setHeaterDutyCycle( DG_TRIMMER_HEATER, dutyCycle ); + } return state; } @@ -671,7 +641,7 @@ // If the last fill temperature > target temperature, it means the primary heater overshot the duty cycle // so with its efficiency is toned down for the next fill cycle // If the heater under-shoots the duty cycle, the efficiency increases the duty cycle for the next fill cycle - if ( lastFillTemperature - primaryTargetTemperature > MAXIMUM_ALLOWED_TARGET_TEMPERATURE_DEVIATION_C ) + if ( lastFillTemperature - primaryTargetTemperature < 0.0F ) { heaterEfficiency -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; } @@ -680,7 +650,9 @@ heaterEfficiency += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; } - heaterEfficiency = heaterEfficiency <= 0.0 ? 0.0 : heaterEfficiency; + // If the efficiency is less than 0, set it to 0 but if the efficiency is greater than 100, it is not enforced + // to be 100 since the duty cycle range check will cap the duty cycle to 100 anyways. + heaterEfficiency = MAX( heaterEfficiency, 0.0 ); // Update the heaters efficiency heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency = heaterEfficiency; @@ -693,8 +665,8 @@ fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ) * heaterEfficiency; // Check the boundaries of the calculated duty cycle - dutyCycle = ( dutyCycle > HEATERS_MAX_DUTY_CYCLE ? HEATERS_MAX_DUTY_CYCLE : dutyCycle ); - dutyCycle = ( dutyCycle < HEATERS_MIN_DUTY_CYCLE ? HEATERS_MIN_DUTY_CYCLE : dutyCycle ); + dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); return dutyCycle; } @@ -718,18 +690,23 @@ F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEfficiency; F32 dutyCycle = 0.0; -#ifndef DISABLE_HEATERS_EFFICIENCY - if ( TRUE == checkEfficiency ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - // TODO Do we need to recalculate the efficiency? + if ( TRUE == checkEfficiency ) + { + // TODO Do we need efficiency for the trimmer heater? + } } -#endif - dutyCycle = flow * WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * ( targetTemperature - currentTemperature ) * heaterEfficiency; + // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) and multiply the duty cycle to the heater efficiency + dutyCycle = ( ( flow * WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * + ( targetTemperature - currentTemperature ) * heaterEfficiency ) / TRIMMER_HEATER_MAX_POWER_W ) * heaterEfficiency; // Check the boundaries of the calculated duty cycle dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MIN( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); return dutyCycle; } @@ -747,16 +724,14 @@ static BOOL haveHeaterControlConditionsChanged( DG_HEATERS_T heater ) { BOOL status = FALSE; - F32 targetFlow = ( DG_PRIMARY_HEATER == heater ? getTargetROPumpFlowRate() : getTargetDialysateFlowLPM() ); - BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetROFlow ) > NEARLY_ZERO ? TRUE : FALSE ); + F32 targetFlow = ( DG_PRIMARY_HEATER == heater ? getTargetROPumpFlowRateLPM() : getTargetDialysateFlowLPM() ); + BOOL hasFlowChanged = ( fabs( targetFlow - heatersStatus[ heater ].targetFlow ) > NEARLY_ZERO ? TRUE : FALSE ); // Check if the target flow has changed or the target temperature has changed. if ( ( TRUE == hasFlowChanged ) || ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) ) { - status = TRUE; - - // Moving back from control to target to ramp. - heatersStatus[ heater ].targetROFlow = targetFlow; + status = TRUE; + heatersStatus[ heater ].targetFlow = targetFlow; heatersStatus[ heater ].hasTargetTempChanged = FALSE; } @@ -816,21 +791,19 @@ { HEATERS_DATA_T data; - data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; + data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; // The duty cycle of the primary heater is divided into 2 parts and is applied to main // and small primary heaters. So they are always the same. - data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; - data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutycycle * 100.0; - data.primaryTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; - data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; - data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; - data.trimmerHeaterState = heatersStatus[ DG_TRIMMER_HEATER ].state; - data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency * 100; + data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; + data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutycycle * 100.0; + data.primaryTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; + data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; + data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; + data.trimmerHeaterState = heatersStatus[ DG_TRIMMER_HEATER ].state; + data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEfficiency * 100; + data.primaryCalcTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature; + data.trimmerCalcCurrentTemp = heatersStatus[ DG_TRIMMER_HEATER ].calculatedTemperature; - data.dialysateTargetLPM = getTargetDialysateFlowLPM(); - data.interimTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].temporaryInterimTemperature; - data.targetHeaterFlowLPM = heatersStatus[ DG_PRIMARY_HEATER ].targetROFlow; - broadcastData( MSG_ID_DG_HEATERS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( HEATERS_DATA_T ) ); dataPublicationTimerCounter = 0; @@ -866,16 +839,9 @@ BOOL isSmallPriOut = ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * smallPri ) - smallPriVoltage ) > smallPriVoltageTol ? TRUE : FALSE ); BOOL isTrimmerOut = ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * trimmer ) - trimmerVoltage ) > trimmerVoltageTol ? TRUE : FALSE ); - checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPri, mainPriVoltageTol ); - checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPri, smallPriVoltageTol ); - //checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmer, trimmerVoltageTol ); // TODO check this voltage - - // TODO test code remove - if ( TRUE == isAlarmActive(ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE)) - { - BOOL test = FALSE; - } - // TODO test code remove + //checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPri, mainPriVoltageTol ); + //checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPri, smallPriVoltageTol ); + //checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmer, trimmerVoltageTol ); } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r224b86c0847207c168d38fa1713a1e9116642267 -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 224b86c0847207c168d38fa1713a1e9116642267) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -8,7 +8,7 @@ * @file LoadCell.c * * @author (last) Dara Navaei -* @date (last) 02-May-2022 +* @date (last) 13-Jul-2022 * * @author (original) Saeed Nejatali * @date (original) 25-Feb-2020 @@ -290,6 +290,29 @@ /*********************************************************************//** * @brief + * The isLoadCellTared function returns load cell tare status + * for a given load cell ID. + * @details Inputs: none + * @details Outputs: load cell tare status + * @param loadCellID ID of load cell tare status + *************************************************************************/ +BOOL isLoadCellTared( LOAD_CELL_ID_T loadCellID ) +{ + BOOL tared = FALSE; + + if ( fabs( loadcells[ loadCellID ].autoCalOffset ) < NEARLY_ZERO ) + { + tared = FALSE; + } + else + { + tared = TRUE; + } + return tared; +} + +/*********************************************************************//** + * @brief * The tareLoadCell function sets the load cell auto calibration offset * for a given load cell ID. * @details Inputs: none @@ -469,31 +492,38 @@ *************************************************************************/ static void monitorLoadCellsPrimaryBackupDriftOutOfRange( void ) { - // TODO do we need this function at all? - F32 drift; + F32 drift = 0.0; + F32 loadCellADrift = 0.0; + F32 loadCellBDrift = 0.0; + BOOL isDriftOutOfRange = FALSE; - F32 loadCellADrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - + // Test is valid after load cells are tared + if ( isLoadCellTared( LOAD_CELL_RESERVOIR_1_PRIMARY ) && isLoadCellTared( LOAD_CELL_RESERVOIR_1_BACKUP ) ) + { + loadCellADrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ) ); - - F32 loadCellBDrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - + } + if ( isLoadCellTared( LOAD_CELL_RESERVOIR_2_PRIMARY ) && isLoadCellTared( LOAD_CELL_RESERVOIR_2_BACKUP ) ) + { + loadCellBDrift = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_BACKUP ) ); + } - BOOL isDriftOutOfRange = ( loadCellADrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ) || - ( loadCellBDrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); - - if ( TRUE == isDriftOutOfRange ) + if ( ( loadCellADrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ) || + ( loadCellBDrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ) ) { + isDriftOutOfRange = TRUE; drift = ( loadCellADrift > LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ? loadCellADrift : loadCellBDrift ); } else { + isDriftOutOfRange = FALSE; // Pick the biggest drift in between the two load cells when none of the is above range drift = ( loadCellADrift > loadCellBDrift ? loadCellADrift : loadCellBDrift ); } - // TODO this alarm is disabled until a better drift algorithm is figured out. Drift check might be removed from the load cells - //checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, isDriftOutOfRange, drift, - // LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); + checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_PRIMARY_BACKUP_DRIFT_OUT_OF_RANGE, isDriftOutOfRange, drift, + LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS ); } Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -55,8 +55,8 @@ #define ROP_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the RO pump is controlled. #define ROP_RAMP_UP_CONTROL_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the RO pump is controlled. #define ROP_RAMP_UP_P_COEFFICIENT 0.22F ///< P term for RO pump ramp up to flow control. -#define ROP_FLOW_CONTROL_P_COEFFICIENT 0.25F ///< P term for RO pump flow control. -#define ROP_FLOW_CONTROL_I_COEFFICIENT 0.25F ///< I term for RO pump flow control. +#define ROP_FLOW_CONTROL_P_COEFFICIENT 0.4F ///< P term for RO pump flow control. +#define ROP_FLOW_CONTROL_I_COEFFICIENT 0.05F ///< I term for RO pump flow control. #define ROP_MAX_PRESSURE_P_COEFFICIENT 0.01F ///< P term for RO pump max pressure control. #define ROP_MAX_PRESSURE_I_COEFFICIENT 0.01F ///< I term for RO pump max pressure control. @@ -68,8 +68,11 @@ #define FLOW_SAMPLES_TO_AVERAGE ( 250 / TASK_PRIORITY_INTERVAL ) ///< Averaging flow data over 250 ms intervals. #define FLOW_AVERAGE_MULTIPLIER ( 1.0F / (F32)FLOW_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. -#define RO_FLOW_ADC_TO_LPM_FACTOR 300.0F ///< Conversion factor from ADC counts to LPM (liters/min) for RO flow rate (multiply this by inverse of FPGA reading). - +// The ADC to LPM factor is calculated using the following steps: +// 0.1 to 2 LPM range +// 110000 pulses/liter +// For 2 LPM => 2LPM x 110000 pulses/liter * 1 edges/pulse * 1 min/60 seconds = 3666.66 counts/sec => 272.72 microseconds => for 1 LPM = 136.36 counts +#define RO_FLOW_ADC_TO_LPM_FACTOR 272.72F ///< Conversion factor from ADC counts to LPM (liters/min) for RO flow rate (multiply this by inverse of FPGA reading). #define ROP_FLOW_TO_PWM_SLOPE 0.1F ///< Slope of flow to PWM line equation. #define ROP_FLOW_TO_PWM_INTERCEPT 0.0F ///< Intercept of flow to PWM line equation. @@ -126,7 +129,7 @@ static F32 pendingROPumpCmdTargetFlow = 0.0; ///< Delayed (pending) RO pump target flow rate (in mL/min) setting. static U32 pendingROPumpCmdCountDown = 0; ///< Delayed (pending) RO pump command count down timer (in task intervals). -static F32 targetROPumpFlowRate = 0.0; ///< Target RO flow rate (in L/min). +static F32 targetROPumpFlowRateLPM; ///< Target RO flow rate (in L/min). static F32 targetROPumpMaxPressure = 0.0; ///< Target RO max allowed pressure (in PSI). static OVERRIDE_U32_T roPumpDataPublishInterval = { RO_PUMP_DATA_PUB_INTERVAL, @@ -201,6 +204,7 @@ isROPumpOn = FALSE; roPumpFeedbackDutyCyclePct = 0.0; roVolumeL = 0.0; + targetROPumpFlowRateLPM = 0.0; } /*********************************************************************//** @@ -229,7 +233,7 @@ // For now maximum allowed pressure is inserted into the target pressure override // if the target flow rate exceeded the max pressure, it will set the maximum pressure targetROPumpMaxPressure = maxPressure; - targetROPumpFlowRate = roFlowRate; + targetROPumpFlowRateLPM = roFlowRate; roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; roPumpState = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; // Get the initial guess of the duty cycle @@ -241,13 +245,13 @@ // Requested max pressure is out of range else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, maxPressure ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, maxPressure ) } } // Requested flow rate is out of range else { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, roFlowRate ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, roFlowRate ) } return result; @@ -284,13 +288,13 @@ // Requested max pressure is out of range else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, maxPressure ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, maxPressure ) } } // Requested flow rate is out of range else { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, roFlowRate ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, roFlowRate ) } return result; @@ -311,7 +315,7 @@ void signalROPumpHardStop( void ) { stopROPump(); - targetROPumpFlowRate = 0; + targetROPumpFlowRateLPM = 0; roPumpState = RO_PUMP_OFF_STATE; roPumpPWMDutyCyclePct = 0.0; roPumpOpenLoopTargetDutyCycle = 0.0; @@ -353,7 +357,7 @@ if ( TRUE == isNewCalibrationRecordAvailable() ) { getNVRecord2Driver( GET_CAL_FLOW_SENSORS, (U08*)&flowSensorsCalRecord, sizeof( DG_FLOW_SENSORS_CAL_RECORD_T ), - NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_FLOW_SENSORS_INVALID_CAL_RECORD ); + NUM_OF_CAL_DATA_FLOW_SENSORS, ALARM_ID_DG_RO_FLOW_SENSOR_INVALID_CAL_RECORD ); } // Read flow at the control set @@ -401,7 +405,7 @@ if ( ( PUMP_CONTROL_MODE_CLOSED_LOOP == roPumpControlMode ) && ( RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE == roPumpState ) ) { F32 currentFlow = getMeasuredROFlowRateLPM(); - F32 targetFlow = getTargetROPumpFlowRate(); + F32 targetFlow = getTargetROPumpFlowRateLPM(); // The flow cannot be out of range for than 10% of the target flow BOOL isFlowOutOfRange = ( fabs( 1.0 - ( currentFlow / targetFlow ) ) > MAX_ALLOWED_FLOW_DEVIATION ? TRUE : FALSE ); // Figure out whether flow is out of range from which side @@ -446,13 +450,13 @@ if ( 0 == pendingROPumpCmdCountDown ) { targetROPumpMaxPressure = pendingROPumpCmdMaxPressure; - targetROPumpFlowRate = pendingROPumpCmdTargetFlow; + targetROPumpFlowRateLPM = pendingROPumpCmdTargetFlow; pendingROPumpCmdMaxPressure = 0.0; pendingROPumpCmdTargetFlow = 0.0; roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; roPumpState = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; // Get the initial guess of the duty cycle - roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( targetROPumpFlowRate ); + roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( targetROPumpFlowRateLPM ); roControlTimerCounter = 0; isROPumpOn = TRUE; } @@ -533,15 +537,15 @@ /*********************************************************************//** * @brief - * The getTargetROPumpFlowRate function gets the current target RO pump + * The getTargetROPumpFlowRateLPM function gets the current target RO pump * flow rate. - * @details Inputs: targetROPumpFlowRate - * @details Outputs: targetROPumpFlowRate + * @details Inputs: targetROPumpFlowRateLPM + * @details Outputs: none * @return the current target RO flow rate (in L/min). *************************************************************************/ -F32 getTargetROPumpFlowRate( void ) +F32 getTargetROPumpFlowRateLPM( void ) { - return targetROPumpFlowRate; + return targetROPumpFlowRateLPM; } /*********************************************************************//** @@ -608,17 +612,17 @@ RO_PUMP_STATE_T state = RO_PUMP_OFF_STATE; // If there is a flow, transition to the PI controller to get the corresponding pressure of that flow - if ( getTargetROPumpFlowRate() > 0 && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) + if ( getTargetROPumpFlowRateLPM() > 0.0F && roPumpControlMode == PUMP_CONTROL_MODE_CLOSED_LOOP ) { // Set pump to on isROPumpOn = TRUE; - roPumpDutyCyclePctSet = ROP_FLOW_TO_PWM_DC( getTargetROPumpFlowRate() ); + roPumpDutyCyclePctSet = ROP_FLOW_TO_PWM_DC( getTargetROPumpFlowRateLPM() ); setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); state = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; } // If the target duty cycle is greater than zero (minimum is 10%) and the mode has been set to open // loop, set the duty cycle - if ( roPumpOpenLoopTargetDutyCycle > 0 && roPumpControlMode == PUMP_CONTROL_MODE_OPEN_LOOP ) + if ( roPumpOpenLoopTargetDutyCycle > 0.0F && roPumpControlMode == PUMP_CONTROL_MODE_OPEN_LOOP ) { setROPumpControlSignalDutyCycle( roPumpOpenLoopTargetDutyCycle ); isROPumpOn = TRUE; @@ -644,7 +648,7 @@ // Get the current pressure from the sensor F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); - F32 targetFlowRate = getTargetROPumpFlowRate(); + F32 targetFlowRate = getTargetROPumpFlowRateLPM(); F32 actualFlowRate = (F32)getMeasuredROFlowRateLPM(); F32 flowRateDeviation = fabs( targetFlowRate - actualFlowRate ) / targetFlowRate; BOOL isFlowOutOfRange = flowRateDeviation > ROP_FLOW_TARGET_TOLERANCE; @@ -709,7 +713,7 @@ } else { - roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRate(), getMeasuredROFlowRateLPM() ); + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, getTargetROPumpFlowRateLPM(), getMeasuredROFlowRateLPM() ); } setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); @@ -745,7 +749,7 @@ } else { - roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, getTargetROPumpFlowRate(), getMeasuredROFlowRateLPM() ); + roPumpDutyCyclePctSet = runPIController( PI_CONTROLLER_ID_RO_PUMP_MAX_PRES, getTargetROPumpFlowRateLPM(), getMeasuredROFlowRateLPM() ); } setROPumpControlSignalDutyCycle( roPumpDutyCyclePctSet ); @@ -843,7 +847,7 @@ { RO_PUMP_DATA_T pumpData; - pumpData.roPumpTgtFlowRateLM = getTargetROPumpFlowRate(); + pumpData.roPumpTgtFlowRateLM = getTargetROPumpFlowRateLPM(); pumpData.roPumpTgtPressure = getTargetROPumpPressure(); pumpData.measROFlowRate = getMeasuredROFlowRateLPM(); pumpData.roPumpDutyCycle = roPumpDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -19,6 +19,8 @@ #include "FPGA.h" #include "MessageSupport.h" +#include "NVDataMgmt.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TemperatureSensors.h" @@ -35,25 +37,27 @@ // ********** private definitions ********** #define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 8U ///< Primary heater external temperature sensors gain. -#define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 19600U ///< Primary heater external temperature sensors reference resistance. +#define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 20000 ///< Primary heater external temperature sensors reference resistance. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 1000U ///< Primary heater external temperature sensors zero degree resistance. +#define PRIMARY_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE 19600 ///< Primary heater external temperature sensors V3 reference resistance. #define COND_SENSORS_TEMP_SENSOR_GAIN 8U ///< Temperature sensor for conductivity gain. -#define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 19600U ///< Temperature sensor for conductivity reference resistance. +#define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 20000 ///< Temperature sensor for conductivity reference resistance. #define COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE 1000U ///< Temperature sensor for conductivity zero degree resistance. +#define COND_SENSORS_TEMP_SENSOR_V3_REF_RESISTANCE 19600 ///< Temperature sensor for conductivity V3 reference resistance. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN 32U ///< Trimmer heater external temperature sensors gain. -#define TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 5110U ///< Trimmer heater external temperature sensors reference resistance. +#define TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 4990 ///< Trimmer heater external temperature sensors reference resistance. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 100U ///< Trimmer heater external temperature sensors zero degree resistance. +#define TRIMMER_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE 5110 ///< Trimmer heater external temperature sensors V3 reference resistance. #define TEMP_SENSORS_ADC_BITS 24U ///< External temperature sensors ADC bits. - #define ADC_FPGA_READ_DELAY 30U ///< Delay in ms before reading the ADC values from FPGA. #define MAX_NUM_OF_RAW_ADC_SAMPLES 4U ///< Number of ADC reads for moving average calculations. #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_TEMPERATURE_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for temperature sensors out of range error period. +#define INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Inlet water temperature sensors timeout in milliseconds. #define MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE 22.0F ///< Low range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE 24.0F ///< Low range maximum water input temperature. @@ -79,15 +83,15 @@ #define HEATERS_INTERNAL_TEMP_SENSOR_FAULT 0x01 ///< Heaters internal temperature sensor fault. #define TEMP_SENSORS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Temperature sensors publish data time interval. -#define TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD ( 5 * MS_PER_SECOND ) ///< Temperature sensors FPGA error persistent period. -#define TEMPERATURE_SENSORS_INTERNAL_ERROR_PERSISTENT_PERIOD ( 3 * MS_PER_SECOND ) ///< Temperature sensors internal error persistent period. +#define TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors FPGA error timeout in milliseconds. #define FPGA_RAW_ADC_READ_INTERVAL_COUNT 8 ///< Time interval in counts to read the raw ADC reads from FPGA. -#define TEMPERATURE_SENSORS_ERROR_FLAG_PERSISTENT_PERIOD ( 5 * MS_PER_SECOND ) ///< Temperature sensors error flag persistent period. +#define TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors error bit timeout in milliseconds. #define TEMP_SENSORS_MIN_ALLOWED_DEGREE_C 0.0F ///< Temperature sensors minimum allowed temperature in C. #define TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 120.0F ///< Temperature sensors maximum allowed temperature in C. +#define HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 200.0F ///< Heaters' internal temperature sensors maximum allowed temperature in C. #define NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 80.0F ///< Non fluid temperature sensors path maximum allowed temperature in C. -#define TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS ( 5 * MS_PER_SECOND ) ///< Temperature sensor out of range persistent period in milliseconds. +#define TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ( 5 * MS_PER_SECOND ) ///< Temperature sensor out of range persistent period in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 30 ///< Data publish counter start count. // The count cannot be within 0.1V of the rail on both sides therefore: @@ -119,8 +123,11 @@ S32 adcRunningSum; ///< ADC running sum U32 readCount; ///< Read counts from FPGA OVERRIDE_F32_T temperatureValues; ///< Temperature values with override - F32 maxAllowedTemperature; ///< Maximum allowed temperature of the sensor + 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 } TEMP_SENSOR_T; // ********** private data ********** @@ -135,7 +142,6 @@ 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 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. @@ -166,14 +172,13 @@ static F32 getADC2TempConversion( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance, F32 adcConversionCoeff ); static void getHeaterInternalTemp( U32 TCIndex, U32 CJIndex ); - -static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ); +static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount, BOOL fpgaCheck ); static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc, U32 fpgaError, U32 fpgaCount ); static BOOL isADCReadValid( U32 sensorIndex, U32 fpgaError, U32 fpgaCount ); static void processADCRead( U32 sensorIndex, S32 adc ); static void publishTemperatureSensorsData( void ); -static void monitorTemperatureSnsrs( U32 sensorIndex ); -static void checkAlarmStatus( U32 sensorIndex, ALARM_ID_T alarm, BOOL alarmOccurred, U32 alarmTimeout ); +static void monitorTemperatureSenors( void ); +static void adjustTemperatureSensorsV3DVTRefResistance( void ); /*********************************************************************//** * @brief @@ -206,103 +211,107 @@ for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; ++i ) { memset( &tempSensors[ i ], 0x0, sizeof( TEMP_SENSOR_T ) ); - benignPolynomialCalRecord( &tempSensorCalRecord.tempSensors[ i ] ); } - // Initialize TPi and TPo constants + // 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; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].zeroDegreeResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; + tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; + tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; + tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].gain = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].refResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].zeroDegreeResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize TD1 and TD2 constants tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].gain = COND_SENSORS_TEMP_SENSOR_GAIN; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].refResistance = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].zeroDegreeResistance = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].gain = COND_SENSORS_TEMP_SENSOR_GAIN; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].refResistance = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].zeroDegreeResistance = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize TRo and TDi constants tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize the heaters internal thermocouples constants tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].conversionCoeff = HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF; - tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ].conversionCoeff = HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF; - tempSensors[ TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize the heaters cold junction constants tempSensors[ TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ].conversionCoeff = HEATERS_COLD_JUNCTION_ADC_TO_TEMP_CONVERSION_COEFF; - tempSensors[ TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ].conversionCoeff = HEATERS_COLD_JUNCTION_ADC_TO_TEMP_CONVERSION_COEFF; - tempSensors[ TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ].maxAllowedTemperature = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + // Initialize the heaters internal temperature sensors + tempSensors[ TEMPSENSORS_PRIMARY_HEATER_INTERNAL ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_TRIMMER_HEATER_INTERNAL ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + // FPGA board temperature conversion coefficient tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].conversionCoeff = 503.975 / (F32)TWELVE_BIT_RESOLUTION; - tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; - F32 const conversionCoeff = 1.0 / 13584.0; + F32 conversionCoeff = 1.0 / 13584.0; // Board temperature sensors conversion coefficient tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; - tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].conversionCoeff = conversionCoeff; + tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INTERNAL_THD_RTD ].conversionCoeff = conversionCoeff; + tempSensors[ TEMPSENSORS_INTERNAL_THD_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + 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_HIGH_TEMPERATURE, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD, - INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD, - INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ); - - initPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD, - INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ); - // Persistent alarm for the temperature sensors range check - initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS, - TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS ); + 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_SENSOR_ADC_OUT_OF_RANGE, TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS, - TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS ); + initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ); // Persistent alarm for the temperature sensors error bit fault check - initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_FAULT, TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS, - TEMP_SENSORS_OUT_OF_RANGE_PERSISTENT_PEROID_MS ); // TODO remove? + initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ERROR_BIT_FAULT, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ); // Persistent alarm for temperature sensors ADC error // When the FPGA read count does not increment for a period of time, it is considered as an internal error of the temperature sensors // driver. This is internal because FPGA does not error out if the FPGA read count does not increment. - initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD, - TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ); } /*********************************************************************//** @@ -342,6 +351,9 @@ *************************************************************************/ void execTemperatureSensors( void ) { + // Check the status of the software configuration + adjustTemperatureSensorsV3DVTRefResistance(); + // Read the sensors all the time switch ( tempSensorsExecState ) { @@ -359,6 +371,9 @@ break; } + // Monitor the temperature values + monitorTemperatureSenors(); + // Publish the data publishTemperatureSensorsData(); } @@ -373,7 +388,6 @@ *************************************************************************/ void checkInletWaterTemperature( void ) { -#ifndef DISABLE_WATER_QUALITY_CHECK #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -405,7 +419,6 @@ checkPersistentAlarm( ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, FALSE, temperature, MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); } } -#endif } /*********************************************************************//** @@ -423,26 +436,15 @@ if ( sensorIndex < NUM_OF_TEMPERATURE_SENSORS ) { - if ( OVERRIDE_KEY == tempSensors[ sensorIndex ].temperatureValues.override ) + temperature = getF32OverrideValue( &tempSensors[ sensorIndex ].temperatureValues ); + // If the system is V3 and THd or its ADC internal temperature is requested, return TRo instead. V3 does not have + // the electrical connection of THd sensor. + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) { - temperature = tempSensors[ sensorIndex ].temperatureValues.ovData; - } - else - { -#ifdef THD_USING_TRO_CONNECTOR - // In V3 THd is connected to TRo - // In V3 TDi represents TRo since they are very close to each other - if ( TEMPSENSORS_HEAT_DISINFECT == sensorIndex ) + if ( ( TEMPSENSORS_HEAT_DISINFECT == sensorIndex ) || ( TEMPSENSORS_INTERNAL_THD_RTD == sensorIndex ) ) { - temperature = tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues.data; + temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); } - else - { - temperature = tempSensors[ sensorIndex ].temperatureValues.data; - } -#else - temperature = tempSensors[ sensorIndex ].temperatureValues.data; -#endif } } else @@ -562,14 +564,22 @@ * @param adc ADC value for the temperature sensor * @param fpgaError reported FPGA error status * @param fpgaCount reported FPGA read count + * @param fpgaCheck whether to check the FPGA error and count prior to converting + * the ADC to temperature * @return none *************************************************************************/ -static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ) +static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount, BOOL fpgaCheck ) { + BOOL isADCValid = TRUE; S32 convertedADC = (S32)( adc & MASK_OFF_U32_MSB ); - // All the sensors have ADC read and count values that have to be checked - BOOL isADCValid = isADCReadValid( sensorIndex, fpgaError, fpgaCount ); + if ( TRUE == fpgaCheck ) + { + // All the sensors have ADC read and count values that have to be checked + // but the FPGA read and error counts are shared among some of the sensors so if that counts has been checked + // once, do not check it again + isADCValid = isADCReadValid( sensorIndex, fpgaError, fpgaCount ); + } // Some of the temperature sensors have an MSB bit that is used as an // error flag. This flag will be a TRUE by default. @@ -588,28 +598,34 @@ case TEMPSENSORS_INTERNAL_TRO_RTD: // 307 case TEMPSENSORS_INLET_DIALYSATE: // 311 case TEMPSENSORS_INTERNAL_TDI_RTD: // 315 + case TEMPSENSORS_HEAT_DISINFECT: + case TEMPSENSORS_INTERNAL_THD_RTD: { - // The MSB bit of the last byte is the error flag, so that MSB - // is shifted 31 bits to the first bit of the U32 variable. - // If that bit is a 1, there is either CRC error or Status error - // that are ored on top of each other - U32 errorBit = adc >> 31; - isTemperatureNotValid = ( errorBit > 0 ? TRUE : FALSE ); + 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 + isTemperatureNotValid |= ( tempSensors[ i ].sensorErrorBitStatus > 0 ? TRUE : FALSE ); + } + +#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT // TODO for debugging only remove if ( TRUE == isTemperatureNotValid ) { BOOL test = FALSE; } - // TODO remove + // TODO remove for debugging only - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_TEMPERATURE_SENSOR_FAULT, sensorIndex ); - - //checkAlarmStatus( sensorIndex, ALARM_ID_DG_TEMPERATURE_SENSOR_FAULT, isTemperatureNotValid, TEMPERATURE_SENSORS_ERROR_FLAG_PERSISTENT_PERIOD ); - - // TODO remove this - //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_FAULT, isTemperatureNotValid, sensorIndex, - // TEMPERATURE_SENSORS_ERROR_FLAG_PERSISTENT_PERIOD ); + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ERROR_BIT_FAULT, isTemperatureNotValid, sensorIndex, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ); +#endif } break; @@ -667,29 +683,33 @@ *************************************************************************/ static BOOL isADCReadValid( U32 sensorIndex, U32 fpgaError, U32 fpgaCount ) { - BOOL isADCValid = FALSE; - + U08 i; + BOOL isADCValid = FALSE; + BOOL isTemperatureNotValid = FALSE; // Check the status of FPGA error and FPGA count - BOOL isFPGAErrorZero = ( fpgaError == 0 ? TRUE : FALSE ); + BOOL isFPGAErrorZero = ( 0 == fpgaError ? TRUE : FALSE ); BOOL isFPGACountChanging = ( tempSensors[ sensorIndex ].readCount != fpgaCount ? TRUE : FALSE ); - if ( TRUE == isFPGAErrorZero ) + if ( ( TRUE == isFPGAErrorZero ) && ( TRUE == isFPGACountChanging ) ) { - if ( TRUE == isFPGACountChanging ) - { - tempSensors[ sensorIndex ].readCount = fpgaCount; - isADCValid = TRUE; - } + tempSensors[ sensorIndex ].readCount = fpgaCount; + isADCValid = TRUE; } - BOOL isThereAnError = ( ( FALSE == isFPGACountChanging ) || ( FALSE == isFPGAErrorZero ) ? TRUE : FALSE ); + tempSensors[ sensorIndex ].fpgaErrorStatus = ( ( FALSE == isFPGACountChanging ) || ( FALSE == isFPGAErrorZero ) ? TRUE : FALSE ); - //checkAlarmStatus( sensorIndex, ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, isThereAnError, TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD ); + for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) + { + // Loop through all the sensors and read their FPGA error status + isTemperatureNotValid |= tempSensors[ sensorIndex ].fpgaErrorStatus; + } +#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_FPGA_FAULT, isTemperatureNotValid, sensorIndex, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ); - // TODO remove - //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, isThereAnError, sensorIndex, TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD ); - return isADCValid; +#else + return TRUE; +#endif } /*********************************************************************//** @@ -705,28 +725,31 @@ *************************************************************************/ 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 - // Calculate the average - F32 avgADCReads = tempSensors[ sensorIndex ].adcRunningSum >> SHIFT_BITS_BY_2_FOR_AVERAGING; + // Check if the average ADC is within the accepted range + tempSensors[ sensorIndex ].adcErrorStatus = ( ( (U32)avgADCReads < TEMP_SESNORS_MIN_ALLOWED_ADC_COUNT ) || + ( (U32)avgADCReads > TEMP_SENSORS_MAX_ALLOWED_ADC_COUNT ) ? TRUE : FALSE ); - // Check if the ADC value of the sensor is not out of range - if ( ( (U32)avgADCReads < TEMP_SESNORS_MIN_ALLOWED_ADC_COUNT ) || ( (U32)avgADCReads > TEMP_SENSORS_MAX_ALLOWED_ADC_COUNT ) ) + for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) { - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ADC_OUT_OF_RANGE, TRUE, sensorIndex, avgADCReads ); + // Loop through the ADC errors + isADCNotValid |= tempSensors[ sensorIndex ].adcErrorStatus; } - else - { - // Clear the alarm if it there was no alarm - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ADC_OUT_OF_RANGE, FALSE, sensorIndex, avgADCReads ); - } +#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, isADCNotValid, sensorIndex, avgADCReads ); +#endif // Different sensors have different ADC to temperature conversion methods switch( sensorIndex ) @@ -741,7 +764,8 @@ case TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE: case TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION: case TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION: - temperature = getADC2TempConversion( avgADCReads, (U32)tempSensors [ sensorIndex ].gain,(U32)tempSensors [ sensorIndex ].refResistance, + case TEMPSENSORS_HEAT_DISINFECT: + temperature = getADC2TempConversion( avgADCReads, (U32)tempSensors [ sensorIndex ].gain, (U32)tempSensors [ sensorIndex ].refResistance, (U32)tempSensors [ sensorIndex ].zeroDegreeResistance, tempSensors [ sensorIndex ].conversionCoeff ); break; @@ -755,13 +779,18 @@ 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: // Temperature(C) = ((ADC - 0x800000)/13584) - 272.5 // The value 1/13584 has been calculated and stored in the conversion coefficient variable of the structure temperature = ( ( avgADCReads - ADC_BOARD_TEMP_SENSORS_CONST ) * tempSensors[ sensorIndex ].conversionCoeff ) - ADC_BOARD_TEMP_SENSORS_CONVERSION_CONST; break; + case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: + temperature = 30.0; + break; + default: // Wrong sensor was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED, sensorIndex ); @@ -772,9 +801,6 @@ // Update the temperature tempSensors[ sensorIndex ].temperatureValues.data = temperature; - - // Monitor the temperature value - monitorTemperatureSnsrs( sensorIndex ); } /*********************************************************************//** @@ -814,64 +840,59 @@ *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ) { - U32 rawADC = 0; U32 errorCount = 0; U32 readCount = 0; // Look at the error counter and the specific error flag to make sure the error is a temperature sensor // Add a byte array to have bits for each sensor to find out exactly what sensor failed if ( ++fpgaRawADCReadInterval >= FPGA_RAW_ADC_READ_INTERVAL_COUNT ) { - rawADC = getFPGATPiTemp(); errorCount = (U32)getFPGARTDErrorCount(); readCount = (U32)getFPGARTDReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, rawADC, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, getFPGATPiTemp(), errorCount, readCount, TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, getFPGATPoTemp(), errorCount, readCount, FALSE ); + processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, getFPGACD1Temp(), errorCount, readCount, FALSE ); + processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, getFPGACD2Temp(), errorCount, readCount, FALSE ); - rawADC = getFPGATPoTemp(); - processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, rawADC, errorCount, readCount ); +#ifndef _RELEASE_ + if ( ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) != SW_CONFIG_ENABLE_VALUE ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) +#endif + { + errorCount = (U32)getFPGATHdErrorCount(); + readCount = (U32)getFPGATHdReadCount(); + processTempSnsrsADCRead( TEMPSENSORS_HEAT_DISINFECT, getFPGATHdTemp(), errorCount, readCount, TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_THD_RTD, getFPGATHdInternalTemp(), errorCount, readCount, FALSE ); + } - rawADC = getFPGACD1Temp(); - processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, rawADC, errorCount, readCount ); - - rawADC = getFPGACD2Temp(); - processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, rawADC, errorCount, readCount ); - - rawADC = getFPGATRoTemp(); errorCount = (U32)getFPGATRoErrorCount(); readCount = (U32)getFPGATRoReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, rawADC, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, getFPGATRoTemp(), errorCount, readCount, TRUE ); - rawADC = getFPGATDiTemp(); errorCount = (U32)getFPGATDiErrorCount(); readCount = (U32)getFPGATDiReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, rawADC, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, getFPGATDiTemp(), errorCount, readCount, TRUE ); - rawADC = getFPGAPrimaryHeaterTemp(); errorCount = (U32)getFPGAPrimaryHeaterFlags(); readCount = (U32)getFPGAPrimaryHeaterReadCount(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, rawADC, errorCount, readCount ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, getFPGAPrimaryHeaterTemp(), errorCount, readCount ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION, getFPGAPrimaryColdJunctionTemp(), errorCount, readCount ); - rawADC = getFPGAPrimaryColdJunctionTemp(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION, rawADC, errorCount, readCount ); - - rawADC = getFPGATrimmerHeaterTemp(); errorCount = (U32)getFPGATrimmerHeaterFlags(); readCount = (U32)getFPGATrimmerHeaterReadCount(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, rawADC, errorCount, readCount ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, getFPGATrimmerHeaterTemp(), errorCount, readCount ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION, getFPGATrimmerColdJunctionTemp(), errorCount, readCount ); - rawADC = getFPGATrimmerColdJunctionTemp(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION, rawADC, errorCount, readCount ); - // NOTE: FPGA board temperature sensor is different from the rest of the sensors. This sensor does not have FPGA count and error // coming from FPGA. It is kept here to do moving average on the values. The supporting functions need to see the FPGA read count // incrementing internally so there will not be any errors. U32 simulatedCounter = tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].readCount; - processTempSnsrsADCRead( TEMPSENSORS_FPGA_BOARD_SENSOR, getFPGABoardTemp(), 0, ++simulatedCounter ); - processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A1_B1, getFPGALoadCellsA1B1Temp(), getFPGAADC1ErrorCount(), getFPGAADC1ReadCount() ); - processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A2_B2, getFPGALoadCellsA2B2Temp(), getFPGAADC2ErrorCount(), getFPGAADC2ReadCount() ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp(), getFPGATRoErrorCount(), getFPGATRoReadCount() ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp(), getFPGATDiErrorCount(), getFPGATDiReadCount() ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp(), getFPGARTDErrorCount(), getFPGARTDReadCount() ); + processTempSnsrsADCRead( TEMPSENSORS_FPGA_BOARD_SENSOR, getFPGABoardTemp(), 0, ++simulatedCounter, TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A1_B1, getFPGALoadCellsA1B1Temp(), getFPGAADC1ErrorCount(), getFPGAADC1ReadCount(), TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A2_B2, getFPGALoadCellsA2B2Temp(), getFPGAADC2ErrorCount(), getFPGAADC2ReadCount(), TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp(), getFPGATRoErrorCount(), getFPGATRoReadCount(), TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp(), getFPGATDiErrorCount(), getFPGATDiReadCount(), TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp(), getFPGARTDErrorCount(), getFPGARTDReadCount(), TRUE ); + processTempSnsrsADCRead( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR, getFPGABaroTemperature(), getFPGABaroErrorCount(), getFPGABaroReadCount(), TRUE ); // Check if time has elapsed to calculate the internal temperature of the heaters if ( ++internalHeatersConversionTimer >= HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL ) @@ -928,7 +949,6 @@ data.cond2Raw = tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].rawADCReads[ MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ]; broadcastData( MSG_ID_DG_TEMPERATURE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); - dataPublicationTimerCounter = 0; } } @@ -940,57 +960,61 @@ * for more than the specified time. * @details Inputs: tempSensors * @details Outputs: tempSensors - * @param sensorIndex the index of the temperature sensor * @return none *************************************************************************/ -static void monitorTemperatureSnsrs( U32 sensorIndex ) +static void monitorTemperatureSenors( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - F32 temperature = getTemperatureValue( sensorIndex ); + U08 i; + F32 temperature = 0.0; + BOOL isTemperatureOutOfRange = FALSE; - // Check both temperature and to be in range - if ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ sensorIndex ].maxAllowedTemperature ) ) + for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) { - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, TRUE, sensorIndex, temperature ); + temperature = getTemperatureValue( i ); + + // Check both temperature and to be in range + if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ i ].maxAllowedTemp ) ) && + ( getCurrentOperationMode() != DG_MODE_INIT ) ) + { + isTemperatureOutOfRange |= TRUE; + } } + + //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, i, temperature ); } } /*********************************************************************//** * @brief - * The checkAlarmStatus function checks the status of an alarm and check whether - * it has timed out. + * The adjustTemperatureSensorsV3DVTRefResistance function adjusts the temperature + * sensors V3 or DVT reference resistance values. * @details Inputs: tempSensors * @details Outputs: tempSensors - * @param sensorIndex the index of the temperature sensor - * @param alarm the alarm ID - * @param alarmOccures the boolean signal that indicates whether the error has - * occurred. - * @param alarmTimeout the timeout of the provided timeout * @return none *************************************************************************/ -static void checkAlarmStatus( U32 sensorIndex, ALARM_ID_T alarm, BOOL alarmOccurred, U32 alarmTimeout ) +static void adjustTemperatureSensorsV3DVTRefResistance( void ) { - U32 startTime = tempSensors[ sensorIndex ].alarmStartTime; + // The default are DVT changes + U32 primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; + U32 externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; - if ( TRUE == alarmOccurred ) + if ( ( getCurrentOperationMode() != DG_MODE_INIT ) && ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) ) { - if ( 0 == startTime ) - { - tempSensors[ sensorIndex ].alarmStartTime = getMSTimerCount(); - } - else if ( TRUE == didTimeout( startTime, alarmTimeout ) ) - { - SET_ALARM_WITH_2_U32_DATA( alarm, sensorIndex, alarmTimeout ); - } + primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; + externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; } - else if ( ( FALSE == alarmOccurred ) && ( startTime != 0 ) ) - { - tempSensors[ sensorIndex ].alarmStartTime = 0; - } + + tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; + tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; + tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].refResistance = primaryAndCondSensorsRefResistance; + tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].refResistance = primaryAndCondSensorsRefResistance; + tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].refResistance = externalTempSesnorsRefResitance; + tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].refResistance = externalTempSesnorsRefResitance; + tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].refResistance = externalTempSesnorsRefResitance; } Index: firmware/App/DGCommon.h =================================================================== diff -u -rf639bbc47806ddcefdbdce78a377cd87050872e5 -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision f639bbc47806ddcefdbdce78a377cd87050872e5) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -25,7 +25,7 @@ #define DG_VERSION_MAJOR 0 #define DG_VERSION_MINOR 6 #define DG_VERSION_MICRO 0 -#define DG_VERSION_BUILD 26 +#define DG_VERSION_BUILD 27 // ********** build switches ********** Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -69,6 +69,8 @@ #define RO_PUMP_LOOKUP_TABLE_SIZE 4 ///< Size of array used as RO pump speed lookup table. #define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0F ///< Concentrate pump additional speed during priming in mL/min. #define CONCENTRATE_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. +// 2m long tubing to cap = 19.5 mL (acid line) + 7.92 mL/m * 2 m (tubing to cap) + 20.82 mL (straw) = 56.15 mL +// Prime time in seconds = ( 56.15 mL / 48 mL/min ) x 60 second/min + 25 seconds margin time = 95 seconds. #define PRIME_CONCENTRATE_LINES_TIME_OUT_MS ( 95 * MS_PER_SECOND ) ///< Time required to prime the concentrate lines. #define FLUSH_BUBBLES_PUMP_TIME_OUT_MS ( 2 * MS_PER_SECOND ) ///< RO pump on during flush bubble interval in ms. #define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0F ///< Dialysate temperature tolerance in degree C. @@ -93,7 +95,7 @@ U32 fillSampleCounter; ///< Fill flow sample counter. F32 fillTemperatureRunningSum; ///< Fill temperature running sum. F32 fillTemperatureAverage; ///< Fill temperature average value. - F32 fillFlowRateAverage; ///< Fill flow average value. + F32 fillFlowRateAverageLPM; ///< Fill flow average value in L/min. F32 fillLastTemperature; ///< Fill last temperature value. BOOL isThisFirstFill; ///< Fill flag to indicate whether it is the first fill or not. } FILL_CONDITION_STATUS_T; @@ -282,15 +284,15 @@ /*********************************************************************//** * @brief - * The getAvgFillFlowRate function returns the average fill flow rate in + * The getAvgFillFlowRateLPM function returns the average fill flow rate in * each fill. * @details Inputs: none - * @details Outputs: fillFlowRateAverage + * @details Outputs: fillFlowRateAverageLPM * @return average of the fill flow rate *************************************************************************/ -F32 getAvgFillFlowRate( void ) +F32 getAvgFillFlowRateLPM( void ) { - return fillStatus.fillFlowRateAverage; + return fillStatus.fillFlowRateAverageLPM; } /*********************************************************************//** @@ -334,7 +336,7 @@ getNVRecord2Driver( GET_INF_HEATERS_RECORD, (U08*)&heaterInfo, sizeof( DG_HEATERS_RECORD_T ), 0, ALARM_ID_NO_ALARM ); // If the data in the NV data management was not initialized properly, set it to 0 otherwise, set the average flow rate - fillStatus.fillFlowRateAverage = ( heaterInfo.averageFillFlow < NEARLY_ZERO ? 0.0 : heaterInfo.averageFillFlow ); + fillStatus.fillFlowRateAverageLPM = ( heaterInfo.averageFillFlow < NEARLY_ZERO ? 0.0 : heaterInfo.averageFillFlow ); fillStatus.fillFlowRateRunningSum = 0.0; fillStatus.fillSampleCounter = 0; fillStatus.fillTemperatureRunningSum = 0.0; @@ -770,7 +772,7 @@ // Done with this fill. Calculate the average fill flow rate and average temperature // Reset the variables for the next fill // Get the last fill temperature before leaving to Generation Idle - fillStatus.fillFlowRateAverage = fillStatus.fillFlowRateRunningSum / (F32)fillStatus.fillSampleCounter; + fillStatus.fillFlowRateAverageLPM = fillStatus.fillFlowRateRunningSum / (F32)fillStatus.fillSampleCounter; fillStatus.fillTemperatureAverage = fillStatus.fillTemperatureRunningSum / (F32)fillStatus.fillSampleCounter; fillStatus.fillFlowRateRunningSum = 0.0; fillStatus.fillTemperatureRunningSum = 0.0; @@ -935,7 +937,7 @@ { DG_HEATERS_RECORD_T record; - record.averageFillFlow = fillStatus.fillFlowRateAverage; + record.averageFillFlow = fillStatus.fillFlowRateAverageLPM; setHeatersInfoRecord( (U08*)&record, sizeof( DG_HEATERS_RECORD_T ) ); } Index: firmware/App/Modes/ModeService.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Modes/ModeService.c (.../ModeService.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Modes/ModeService.c (.../ModeService.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -52,6 +52,7 @@ *************************************************************************/ U32 transitionToServiceMode( void ) { + // TODO Deenergize all the actuators return 0; } Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -67,7 +67,7 @@ SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, SW_FAULT_ID_HEATERS_INVALID_HEATER_ID_SELECTED, SW_FAULT_ID_HEATERS_INVALID_EXEC_STATE, - SW_FAULT_ID______AVAILABLE, + SW_FAULT_ID_INVALID_EMSTAT_CONDUCTIVITY_BOARD_SELECTED, SW_FAULT_ID_VALVES_INVALID_VALVE_STATE_NAME, // 40 SW_FAULT_ID_VALVES_INVALID_VALVE_ID, SW_FAULT_ID_CAN_PARITY_ERROR, Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -25,6 +25,8 @@ #include "Comm.h" #include "Compatible.h" #include "FPGA.h" +#include "NVDataMgmt.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Utilities.h" @@ -84,7 +86,11 @@ #define CONCENTRATE_CAP_SWITCH_MASK 0x10 ///< Concentrate cap switch bit mask #define DIALYSATE_CAP_SWITCH_MASK 0x20 ///< Dialysate cap switch bit mask.. #define FPGA_POWER_OUT_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< FPGA power out timeout in milliseconds. -#define FPGA_GPIO_POWER_STATUS_PIN 7 ///< FPGA GPIO power status pin +#define FPGA_GPIO_POWER_STATUS_PIN 7 ///< FPGA GPIO power status pin. +#define FPGA_READ_V3_START_BYTE_NUM 256 ///< FPGA V3 read sensors start byte number. +#define FPGA_READ_V3_END_BYTE_NUM 412 ///< FPGA V3 read sensors end byte number. +/// FPGA size of V3 read bytes. +#define FPGA_SIZE_OF_V3_READ_BYTES ( FPGA_READ_V3_END_BYTE_NUM - FPGA_READ_V3_START_BYTE_NUM ) // FPGA header struct. #pragma pack(push,1) @@ -97,7 +103,7 @@ } FPGA_HEADER_T; // read only on FPGA /// FPGA sensors' readings struct. -typedef struct // TODO - add all sensor readings to this structure per FPGA register map +typedef struct { U32 fpgaLCA1; ///< Reg 256. ADC1 channel 0 - load cell A1 U32 fpgaLCB1; ///< Reg 260. ADC1 channel 1 - load cell B1 @@ -156,6 +162,7 @@ U08 fpgaPrimaryHeaterReadCnt; ///< Reg 365. Primary heater read count U08 fpgaTrimmerHeaterFlags; ///< Reg 366. Trimmer heater flags U08 fpgaTrimmerHeaterReadCnt; ///< Reg 367. Trimmer heater read count + U08 fpgaCPoFault; ///< Reg 368. CPo conductivity sensor fault U08 fpgaCPoReadCnt; ///< Reg 369. CPo conductivity sensor read count U08 fpgaCPoErrorCnt; ///< Reg 370. CPo conductivity sensor error count @@ -169,12 +176,12 @@ U16 fpgaFanIn1Pulse; ///< Reg 378. Fan inlet 1 pulse time in 2.5 us resolution U16 fpgaFanOut1Pulse; ///< Reg 380. Fan outlet 1 pulse time in 2.5 us resolution - U08 fpgaEmstatOutByte; ///< Reg 382. Emstat output FIFO - data from the Emstat device - U08 fpgaEmstatRxErrorCount; ///< Reg 383. Number of receive errors since power-up - U16 fpgaEmstatTxFifoCount; ///< Reg 384. Number of bytes in the Emstat Tx FIFO buffer - U16 fpgaEmstatRxFifoCount; ///< Reg 386. Number of bytes in the Emstat Rx FIFO buffer - U16 fpgaCP1HallSense; ///< Reg 388. Concentrate pump CP1 hall sensor pulse width. - U16 fpgaCP2HallSense; ///< Reg 390. Concentrate pump CP2 hall sensor pulse width. + U08 fpgaCD1CD2EmstatOutByte; ///< Reg 382. Emstat output FIFO - data from the Emstat device + U08 fpgaCD1CD2EmstatRxErrorCount; ///< Reg 383. Number of receive errors since power-up + U16 fpgaCD1CD2EmstatTxFifoCount; ///< Reg 384. Number of bytes in the Emstat Tx FIFO buffer + U16 fpgaCD1CD2EmstatRxFifoCount; ///< Reg 386. Number of bytes in the Emstat Rx FIFO buffer + U16 fpgaCP1HallSense; ///< Reg 388. Concentrate pump CP1 hall sensor pulse width + U16 fpgaCP2HallSense; ///< Reg 390. Concentrate pump CP2 hall sensor pulse width U08 fpgaGPIO; ///< Reg 392. FGPA GPIO register U08 fpgaDummyByte2Addr; ///< Reg 393. Dummy byte address to maintain an even addressing scheme @@ -184,14 +191,41 @@ U16 fpgaFanOut2Pulse; ///< Reg 398. Fan outlet 2 pulse time in 2.5 resolution U16 fpgaFanIn3Pulse; ///< Reg 400. Fan inlet 3 pulse time in 2.5 resolution U16 fpgaFanOut3Pulse; ///< Reg 402. Fan outlet 3 pulse time in 2.5 resolution - U16 fpgaTimerCount_ms; ///< Reg 404. Internal FPGA timer count in ms. + U16 fpgaTimerCountMS; ///< Reg 404. Internal FPGA timer count in milliseconds U16 fpgaADCVccInt; ///< Reg 406. Internal FPGA Vcc Voltage. - U16 fpgaADCVccAux; ///< Reg 408. Internal FPGA Vcc auxiliary voltage. - U16 fpgaADCVPVN; ///< Reg 410. Internal FPGA VPVN voltage. - U16 fpgaOpenRegister; ///< Reg 412. Open register. - U16 fpgaDrainPumpSpeedFeedback; ///< Reg 414. Drain pump speed feedback. - U16 fpgaDrainPumpCurrentFeedback; ///< Reg 416. Drain pump current feedback. + U16 fpgaADCVccAux; ///< Reg 408. Internal FPGA Vcc auxiliary voltage + U16 fpgaADCVPVN; ///< Reg 410. Internal FPGA VPVN voltage + + // DVT changes + U08 fpgaBaroReadCount; ///< Reg 412. Barometric sensor read count + U08 fpgaBaroErroCount; ///< Reg 413. Barometric sensor error count + U16 fpgaDrainPumpSpeedFeedback; ///< Reg 414. Drain pump speed feedback + U16 fpgaDrainPumpCurrentFeedback; ///< Reg 416. Drain pump current feedback U16 fpgaDialysateFlowRate; ///< Req 418. Dialysate flow rate measurement + U16 fpgaHeaterGateADC; ///< Reg 420. Heater gate ADC + U16 fpgaHeaterGNDADC; ///< Reg 422. Heater ground ADC + U08 fpgaHeater1ADCReadCount; ///< Reg 424. Heater 1 ADC read count + U08 fpgaHeater1ADCErrorCount; ///< Reg 425. Heater 1 ADC error count + U16 fpgaBaroManufacInfo; ///< Reg 426. Barometric sensor manufacturing information + U16 fpgaBaroPROMCoeff1; ///< Reg 428. Barometric sensor PROM coefficient 1 + U16 fpgaBaroPROMCoeff2; ///< Reg 430. Barometric sensor PROM coefficient 2 + U16 fpgaBaroPROMCoeff3; ///< Reg 432. Barometric sensor PROM coefficient 3 + U16 fpgaBaroPROMCoeff4; ///< Reg 434. Barometric sensor PROM coefficient 4 + U16 fpgaBaroPROMCoeff5; ///< Reg 436. Barometric sensor PROM coefficient 5 + U16 fpgaBaroPROMCoeff6; ///< Reg 438. Barometric sensor PROM coefficient 6 + U16 fpgaBaroPROMCRC; ///< Reg 440. Barometric sensor PROM CRC + U32 fpgaBaroPressure; ///< Reg 442. Barometric sensor pressure value + U32 fpgaBaroTemperature; ///< Reg 446. Barometric sensor temperature sensor + U08 fpgaTHdRTDReadCount; ///< Reg 450. THD RTD read count + U08 fpgaTHdRTDErrorCount; ///< Reg 451. THD RTD error count + U32 fpgaTHdTemp; ///< Reg 452. THD channel 0 read data - temperature sensor + U32 fpgaTHdInternalTemp; ///< Reg 456. THD channel 1 read data - ADC internal temperature sensor + U08 fpgaCPiCPoEmstatOutByte; ///< Reg 460. CPi/CPo Emstat out byte + U08 fpgaCPiCPoEmstatRxErrCount; ///< Reg 461. CPi/CPo Emstat Rx error count + U16 fpgaCPiCPoEmstatTxFIFOCount; ///< Reg 462. CPi/CPo Emstat Tx FIFO count + U16 fpgaCPiCPoEmstatRxFIFOCount; ///< Reg 464. CPi/CPo Emstat Rx FIFO count + U16 fpgaPowerSupply2; ///< Reg 466. power supply 2 count + U16 fpgaOnBoardThermistor; ///< Reg 468. onboard thermistor } DG_FPGA_SENSORS_T; typedef struct @@ -208,13 +242,68 @@ U16 fpgaCP2StepSpeed; ///< Reg 26. Concentrate pump CP2 step speed register U08 fpgaCP2Control; ///< Reg 28. Concentrate pump CP2 control register U08 fpgaEmstatControl; ///< Reg 29. Emstat conductivity sensor control register + U16 fpgaVRfPWMLow; ///< Reg 30. VRf PWM low + U16 fpgaVRfPWMPeriod; ///< Reg 32. VRf PWM period + U16 fpgaVRiPWMLow; ///< Reg 34. VRi PWM low + U16 fpgaVRiPWMPeriod; ///< Reg 36. VRi PWM period + U16 fpgaVRdPWMLow; ///< Reg 38. VRd PWM low + U16 fpgaVRdPWMPeriod; ///< Reg 40. VRD PWM period + U16 fpgaVRoPWMLow; ///< Reg 42. VRo PWM low + U16 fpgaVRoPWMPeriod; ///< Reg 44. VRo PWM period + U16 fpgaVPoPWMLow; ///< Reg 46. VPo PWM low + U16 fpgaVPoPWMPeriod; ///< Reg 48. VPo PWM period + U16 fpgaVBfPWMLow; ///< Reg 50. VBf PWM low + U16 fpgaVBFPWMPeriod; ///< Reg 52. VBf PWM period + U16 fpgaVRcPWMLow; ///< Reg 54. VRc PWM low + U16 fpgaVRcPWMPeriod; ///< Reg 56. VRc PWM period + U16 fpgaVDrPWMLow; ///< Reg 58. VDr PWM Low + U16 fpgaVDrPWMPeriod; ///< Reg 60. VDr PWM period + U16 fpgaVPiPWMLow; ///< Reg 62. VPi PWM low + U16 fpgaVPiPWMPeriod; ///< Reg 64. VPi PWM period + U16 fpgaVSPPWMLow; ///< Reg 66. VSP PWM low + U16 fpgaVSPPWMPeriod; ///< Reg 68. VSP PWM period + U16 fpgaVRd1PWMLow; ///< Reg 70. VRd1 PWM low + U16 fpgaVRd1PWMPeriod; ///< Reg 72. VRd1 PWM period + U16 fpgaVRd2PWMLow; ///< Reg 74. VRd2 PWM low + U16 fpgaVRd2PWMPeriod; ///< Reg 76. VRd2 PWM period + U16 fpgaVPdPWMLow; ///< Reg 78. VPd PWM low + U16 fpgaVPdPWMPeriod; ///< Reg 80. VPd PWM period + U16 fpgaVSOLPWMLow; ///< Reg 82. VSOL PWM low + U16 fpgaVSOLPWMPeriod; ///< Reg 84. VSOL PWM period + U16 fpgaVRfPWMPullin; ///< Reg 86. VRf PWM pull in + U16 fpgaVRiPWMPullin; ///< Reg 88. VRi PWM pull in + U16 fpgaVRdPWMPullin; ///< Reg 90. VRd PWM pull in + U16 fpgaVRoPWMPullin; ///< Reg 92. VRo PWM pull in + U16 fpgaVPoPWMPullin; ///< Reg 94. VPo PWM pull in + U16 fpgaVBfPWMPullin; ///< Reg 96. VBf PWM pull in + U16 fpgaVRcPWMPullin; ///< Reg 98. VRc PWM pull in + U16 fpgaVDrPWMPullin; ///< Reg 100. VDr PWM pull in + U16 fpgaVPiPWMPullin; ///< Reg 102. VPi PWM pull in + U16 fpgaVSPPWMPullin; ///< Reg 104. VSP PWM pull in + U16 fpgaVRd1PWMPullin; ///< Reg 106. VRd1 PWM pull in + U16 fpgaVRd2PWMPullin; ///< Reg 108. VRd2 PWM pull in + U16 fpgaVPdPWMPullin; ///< Reg 110. VPd PWM pull in + U16 fpgaVSPR2PWMPullin; ///< Reg 112. VSPR2 PWM pull in + U16 fpgaValvePWMEnable; ///< Reg 114. valve PWM enable + + // DVT Registers + U08 fpgaTHdControlReg; ///< Reg 116. THd control register + U08 fpgaCPiCPoEmstatControl; ///< Reg 117. CPi/CPo Emstat control + U16 fpgaDACRegBIn; ///< Reg 118. Debug DAC channel B output + U16 fpgaDACRegCIn; ///< Reg 120. Debug DAC channel C output + U16 fpgaDACRegDIn; ///< Reg 122. Debug DAC channel D output + U16 fpgaDACRegEIn; ///< Reg 124. Debug DAC channel E output + U16 fpgaDACRegFIn; ///< Reg 126. Debug DAC channel F output + U16 fpgaDACRegGIn; ///< Reg 128. Debug DAC channel G output + U16 fpgaDACRegHIn; ///< Reg 130. Debug DAC channel H output + U08 fgpaNewCP2Control; ///< Reg 132. Concentrate pump 2 control + U08 fpgaNewCP1Control; ///< Reg 133. Concentrate pump 1 control } FPGA_ACTUATORS_T; #pragma pack(pop) // ********** private data ********** static FPGA_STATE_T fpgaState = FPGA_STATE_START; ///< FPGA current state. - static U32 fpgaCommRetryCount = 0; ///< FPGA communication retry count. static U32 fpgaReceiptCounter = 0; ///< FPGA receipt completed counter. static U32 fpgaTransmitCounter = 0; ///< FPGA transmit completed counter. @@ -240,6 +329,7 @@ static FPGA_HEADER_T fpgaHeader; ///< FPGA header structure. static DG_FPGA_SENSORS_T fpgaSensorReadings; ///< DG FPGA sensors structure. static FPGA_ACTUATORS_T fpgaActuatorSetPoints; ///< FPGA actuator set points structure. +static U08 fpgaReadByteSize; ///< FPGA read byte size. // ********** private function prototypes ********** @@ -452,6 +542,15 @@ *************************************************************************/ void execFPGAIn( void ) { + fpgaReadByteSize = sizeof( DG_FPGA_SENSORS_T ); + +#ifndef _RELEASE_ + if( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) || ( DG_MODE_INIT == getCurrentOperationMode() ) ) + { + fpgaReadByteSize = FPGA_SIZE_OF_V3_READ_BYTES; + } +#endif + // FPGA incoming state machine switch ( fpgaState ) { @@ -512,6 +611,15 @@ *************************************************************************/ void execFPGAOut( void ) { + fpgaReadByteSize = FPGA_SIZE_OF_V3_READ_BYTES; + +#ifndef _RELEASE_ + if( ( SW_CONFIG_ENABLE_VALUE != getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) + { + fpgaReadByteSize = sizeof( DG_FPGA_SENSORS_T ); + } +#endif + // FPGA outgoing state machine switch ( fpgaState ) { @@ -591,7 +699,7 @@ // did FPGA Ack the read command? if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T); + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_HEADER_T ); U32 crcPos = rspSize; U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); @@ -641,7 +749,7 @@ fpgaWriteCmdBuffer[ 0 ] = FPGA_WRITE_CMD_CODE; fpgaWriteCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); fpgaWriteCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); - fpgaWriteCmdBuffer[ 3 ] = sizeof(FPGA_ACTUATORS_T); + fpgaWriteCmdBuffer[ 3 ] = sizeof( FPGA_ACTUATORS_T ); memcpy( &( fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN ] ), &fpgaActuatorSetPoints, sizeof( FPGA_ACTUATORS_T ) ); crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ); fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ] = GET_MSB_OF_WORD( crc ); @@ -651,7 +759,7 @@ fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); - fpgaReadCmdBuffer[ 3 ] = sizeof(DG_FPGA_SENSORS_T); + fpgaReadCmdBuffer[ 3 ] = fpgaReadByteSize; //sizeof( DG_FPGA_SENSORS_T ); crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); @@ -662,7 +770,7 @@ // prep DMA for sending the bulk read cmd and receiving its response setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); - setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( DG_FPGA_SENSORS_T ) + FPGA_CRC_LEN ); + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + fpgaReadByteSize + FPGA_CRC_LEN ); // set fpga comm flags for bulk write cmd and follow-up bulk read command fpgaWriteCommandInProgress = TRUE; @@ -698,7 +806,7 @@ // did FPGA Ack the read command? if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(DG_FPGA_SENSORS_T); + U32 rspSize = FPGA_READ_RSP_HDR_LEN + fpgaReadByteSize; U32 crcPos = rspSize; U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); @@ -707,7 +815,7 @@ { fpgaCommRetryCount = 0; // capture the read values - memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( DG_FPGA_SENSORS_T ) ); + memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], fpgaReadByteSize ); result = FPGA_STATE_WRITE_ALL_ACTUATORS; } else // bad CRC @@ -742,32 +850,25 @@ { SELF_TEST_STATUS_T result; - // check FPGA reported correct ID - if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) + // TODO the FPGA self test has been implemented in DEN-13460. + /*if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) { // Check FPGA compatibility w/ firmware - if ( fpgaHeader.fpgaRevMajor > MIN_DG_FPGA_MAJOR ) + if ( DG_FPGA_COMPATIBILITY_REV == fpgaSensorReadings.fpgaCompatibilityRev ) { result = SELF_TEST_STATUS_PASSED; } else { - if ( ( MIN_DG_FPGA_MAJOR == fpgaHeader.fpgaRevMajor ) && ( fpgaHeader.fpgaRevMinor >= MIN_DG_FPGA_MINOR ) ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaRevMajor, (U32)fpgaHeader.fpgaRevMinor ) - } + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_POST_TEST_FAILED, (U32)DG_FPGA_COMPATIBILITY_REV, (U32)fpgaSensorReadings.fpgaCompatibilityRev ) } } else { result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaId ) - } + }*/ return result; } @@ -1032,60 +1133,90 @@ /*********************************************************************//** * @brief - * The setFPGACP1Control function sets the control configuration for + * The setFPGAcidPumpControl function sets the control configuration for * concentrate pump CP1. * @details Inputs: none * @details Outputs: fpgaActuatorSetPoints.fpgaCP1Control * @param pumpControl The concentrate pump control configuration * @return none *************************************************************************/ -void setFPGACP1Control( U08 pumpControl ) +void setFPGAV3AcidPumpControl( U08 pumpControl ) { fpgaActuatorSetPoints.fpgaCP1Control = pumpControl; } /*********************************************************************//** * @brief - * The setFPGACP2Control function sets the control configuration for + * The setFPGABicarbPumpControl function sets the control configuration for * concentrate pump CP2. * @details Inputs: none * @details Outputs: fpgaActuatorSetPoints.fpgaCP2Control * @param pumpControl The concentrate pump control configuration * @return none *************************************************************************/ -void setFPGACP2Control( U08 pumpControl ) +void setFPGAV3BicarbPumpControl( U08 pumpControl ) { fpgaActuatorSetPoints.fpgaCP2Control = pumpControl; } /*********************************************************************//** * @brief - * The setFPGACP1SetStepSpeed function sets the step speed period for concentrate pump CP1. + * The setFPGAAcidPumpSetStepSpeed function sets the step speed period for + * concentrate pump CP1. * @details Inputs: none * @details Outputs: fpgaActuatorSetPoints.fpgaCP1StepSpeed * @param stepSpeed The concentrate pump step speed period * @return none *************************************************************************/ -void setFPGACP1SetStepSpeed( U16 stepSpeed ) +void setFPGAAcidPumpSetStepSpeed( U16 stepSpeed ) { fpgaActuatorSetPoints.fpgaCP1StepSpeed = stepSpeed; } /*********************************************************************//** * @brief - * The setFPGACP2SetStepSpeed function sets the step speed period for concentrate pump CP2. + * The setFPGABicarbSetStepSpeed function sets the step speed period for + * concentrate pump CP2. * @details Inputs: none * @details Outputs: fpgaActuatorSetPoints.fpgaCP2StepSpeed * @param stepSpeed The concentrate pump step speed period * @return none *************************************************************************/ -void setFPGACP2SetStepSpeed( U16 stepSpeed ) +void setFPGABicarbSetStepSpeed( U16 stepSpeed ) { fpgaActuatorSetPoints.fpgaCP2StepSpeed = stepSpeed; } /*********************************************************************//** * @brief + * The setFPGAAcidPumpControl function sets the DVT concentrate pump 1 + * (acid pump) control mode. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints.fpgaNewCP1Control + * @param control Concentrate pump control set + * @return none + *************************************************************************/ +void setFPGAAcidPumpControl( U08 control ) +{ + fpgaActuatorSetPoints.fpgaNewCP1Control = control; +} + +/*********************************************************************//** + * @brief + * The setFPGABicarbPumpControl function sets the DVT concentrate pump 2 + * (bicarb pump) control mode. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints.fgpaNewCP2Control + * @param control Concentrate pump control set + * @return none + *************************************************************************/ +void setFPGABicarbPumpControl( U08 control ) +{ + fpgaActuatorSetPoints.fgpaNewCP2Control = control; +} + +/*********************************************************************//** + * @brief * The getFPGAVersions function gets the FPGA version numbers. * @details Inputs: fpgaHeader * @details Outputs: none @@ -1625,34 +1756,35 @@ * @details Outputs: none * @return Emstat conductivity sensor output byte *************************************************************************/ -U08 getFPGAEmstatOutByte( void ) +U08 getFPGAEmstatCD1CD2OutByte( void ) { - return fpgaSensorReadings.fpgaEmstatOutByte; + return fpgaSensorReadings.fpgaCD1CD2EmstatOutByte; } /*********************************************************************//** * @brief - * The getFPGAEmstatRxErrCount function gets Emstat conductivity sensor error count. + * The getFPGAEmstatCD1CD2RxErrCount function gets Emstat conductivity sensor + * error count. * @details Inputs: fpgaSensorReadings.fpgaEmstatRxErrorCount * @details Outputs: none * @return Emstat conductivity sensor receive error count *************************************************************************/ -U08 getFPGAEmstatRxErrCount( void ) +U08 getFPGAEmstatCD1CD2RxErrCount( void ) { - return fpgaSensorReadings.fpgaEmstatRxErrorCount; + return fpgaSensorReadings.fpgaCD1CD2EmstatRxErrorCount; } /*********************************************************************//** * @brief - * The getFPGAEmstatRxFifoCount function gets Emstat conductivity sensor receive - * fifo buffer count. + * The getFPGAEmstatCD1CD2RxFifoCount function gets Emstat conductivity + * sensor receive fifo buffer count. * @details Inputs: fpgaSensorReadings.fpgaEmstatTxFifoCount * @details Outputs: none * @return Emstat conductivity sensor receive fifo buffer count *************************************************************************/ -U16 getFPGAEmstatRxFifoCount( void ) +U16 getFPGAEmstatCD1CD2RxFifoCount( void ) { - return fpgaSensorReadings.fpgaEmstatRxFifoCount; + return fpgaSensorReadings.fpgaCD1CD2EmstatRxFifoCount; } /*********************************************************************//** @@ -1883,7 +2015,7 @@ *************************************************************************/ U16 getFPGATimerCount( void ) { - return fpgaSensorReadings.fpgaTimerCount_ms; + return fpgaSensorReadings.fpgaTimerCountMS; } /*********************************************************************//** @@ -1927,4 +2059,221 @@ return ( fpgaSensorReadings.fpgaGPIO & CONCENTRATE_CAP_SWITCH_MASK ); } +/*********************************************************************//** + * @brief + * The getFPGABaroReadCount function gets the FPGA barometric sensor read count. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor read count + *************************************************************************/ +U08 getFPGABaroReadCount( void ) +{ + return fpgaSensorReadings.fpgaBaroReadCount; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroErrorCount function gets the FPGA barometric sensor error count. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor error count + *************************************************************************/ +U08 getFPGABaroErrorCount( void ) +{ + return fpgaSensorReadings.fpgaBaroErroCount; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroPressureSensitivity function gets the FPGA barometric pressure + * sensor sensitivity. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor sensitivity + *************************************************************************/ +U16 getFPGABaroPressureSensitivity( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff1; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroPressureOffset function gets the FPGA barometric pressure + * sensor offset. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor offset + *************************************************************************/ +U16 getFPGABaroPressureOffset( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff2; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroTempCoeffOfPressSensitvity function gets the FPGA barometric + * pressure sensor temperature coefficient of pressure sensitivity. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor temperature coefficient of pressure sensitivity + *************************************************************************/ +U16 getFPGABaroTempCoeffOfPressSensitvity( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff3; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroTempCoeffOfPressOffset function gets the FPGA barometric + * pressure sensor temperature coefficient of pressure offset. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor temperature coefficient of pressure offset + *************************************************************************/ +U16 getFPGABaroTempCoeffOfPressOffset( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff4; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroReferenceTemp function gets the FPGA barometric pressure + * sensor reference temperature. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor reference temperature + *************************************************************************/ +U16 getFPGABaroReferenceTemp( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff5; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroTempCoeffOfTemperature function gets the FPGA barometric pressure + * sensor temperature coefficient of temperature. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor temperature coefficient of temperature + *************************************************************************/ +U16 getFPGABaroTempCoeffOfTemperature( void ) +{ + return fpgaSensorReadings.fpgaBaroPROMCoeff6; +} + +/*********************************************************************//** + * @brief + * The getFPGABaroPressure function gets the FPGA barometric pressure sensor + * pressure. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor pressure + *************************************************************************/ +U32 getFPGABaroPressure( void ) +{ + return ( fpgaSensorReadings.fpgaBaroPressure & MASK_OFF_U32_MSB ); +} + +/*********************************************************************//** + * @brief + * The getFPGABaroTemperature function gets the FPGA barometric pressure sensor + * temperature. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return barometric pressure sensor temperature + *************************************************************************/ +U32 getFPGABaroTemperature( void ) +{ + return ( fpgaSensorReadings.fpgaBaroTemperature & MASK_OFF_U32_MSB ); +} + +/*********************************************************************//** + * @brief + * The getFPGAEmstatCPiCPoByteOut function gets the FPGA Emstat CPi/CPo + * byte out data. + * @details Inputs: fpgaSensorReadings.fpgaCPiCPoEmstatOutByte + * @details Outputs: none + * @return CPi/CPo Emstat byte out + *************************************************************************/ +U08 getFPGAEmstatCPiCPoByteOut( void ) +{ + return fpgaSensorReadings.fpgaCPiCPoEmstatOutByte; +} + +/*********************************************************************//** + * @brief + * The getFPGAEmstatCPiCPoRxFifoCount function gets the FPGA Emstat CPi/CPo + * receive FIFO count. + * @details Inputs: fpgaSensorReadings.fpgaCD1CD2EmstatRxFifoCount + * @details Outputs: none + * @return CPi/CPo Rx FIFO count + *************************************************************************/ +U16 getFPGAEmstatCPiCPoRxFifoCount( void ) +{ + return fpgaSensorReadings.fpgaCPiCPoEmstatRxFIFOCount; +} + +/*********************************************************************//** + * @brief + * The getFPGAEmstatCPiCPoRxErrCount function gets the FPGA Emstat CPi/CPo + * receive FIFO error count. + * @details Inputs: fpgaSensorReadings.fpgaCD1CD2EmstatRxErrorCount + * @details Outputs: none + * @return CPi/CPo Rx FIFO error count + *************************************************************************/ +U08 getFPGAEmstatCPiCPoRxErrCount( void ) +{ + return fpgaSensorReadings.fpgaCPiCPoEmstatRxErrCount; +} + +/*********************************************************************//** + * @brief + * The getFPGATHdTemp function gets the FPGA THd temperature sensor. + * @details Inputs: fpgaSensorReadings.fpgaTHdTemp + * @details Outputs: none + * @return THd temperature sensor + *************************************************************************/ +U32 getFPGATHdTemp( void ) +{ + return fpgaSensorReadings.fpgaTHdTemp; +} + +/*********************************************************************//** + * @brief + * The getFPGATHdInternalTemp function gets the FPGA THd internal ADC temperature sensor. + * @details Inputs: fpgaSensorReadings.fpgaTHdInternalTemp + * @details Outputs: none + * @return THd internal ADC temperature sensor + *************************************************************************/ +U32 getFPGATHdInternalTemp( void ) +{ + return fpgaSensorReadings.fpgaTHdInternalTemp; +} + +/*********************************************************************//** + * @brief + * The getFPGATHdReadCount function gets the FPGA THd temperature sensor read + * count. + * @details Inputs: fpgaSensorReadings.fpgaTHdRTDReadCount + * @details Outputs: none + * @return THd FPGA read count + *************************************************************************/ +U08 getFPGATHdReadCount( void ) +{ + return fpgaSensorReadings.fpgaTHdRTDReadCount; +} + +/*********************************************************************//** + * @brief + * The getFPGATHdErrorCount function gets the FPGA THd temperature sensor error + * count. + * @details Inputs: fpgaSensorReadings.fpgaTHdRTDErrorCount + * @details Outputs: none + * @return THd FPGA error count + *************************************************************************/ +U08 getFPGATHdErrorCount( void ) +{ + return fpgaSensorReadings.fpgaTHdRTDErrorCount; +} + /**@}*/ Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r22176ce95e49213c48454f34ddf5d29b8109f2cb -rf1cb4be5fb8201cec188589e683c8bf20d895ec0 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 22176ce95e49213c48454f34ddf5d29b8109f2cb) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision f1cb4be5fb8201cec188589e683c8bf20d895ec0) @@ -17,6 +17,7 @@ #include // for memcpy() +#include "ConcentratePumps.h" #include "DrainPump.h" #include "Heaters.h" #include "LoadCell.h" @@ -50,6 +51,7 @@ #define MAX_REDUNDANT_LOAD_CELL_DIFF 50.0F ///< Maximum difference in redundant load cells when determining if fill completed. #define MAX_DRAIN_RPM_MLP 2400.0F ///< Maximum drain RPM in mL/min. #define DATA_PUBLISH_COUNTER_START_COUNT 5 ///< Data publish counter start count. +#define ENVIRONMENT_TEMPERATURE_C 23.5F ///< Device's environment temperature in C. // TODO add this to the cal records // ********** private data ********** @@ -66,6 +68,9 @@ F32 tempReservoirEndFill; ///< Temperature reservoir at the end of the fill in C. F32 tempTargetTrimmer; ///< Temperature target trimmer heater in C. F32 flowTargetDialysateLPM; ///< Dialysate target flow rate in L/min. + F32 tempRsrvr0ActualTrimmer; ///< Temperature actual reservoir in C. + F32 tempFillMixAvgTrimmer; ///< Temperature fill mix average trimmer in C. + F32 tempRsrvrEndFillTrimmer; ///< Temperature reservoir end fill trimmer in C. } HEATERS_TEMPERATURE_CALC_DATA_T; /// Reservoirs previous status @@ -94,7 +99,7 @@ static DG_RESERVOIR_VOLUME_RECORD_T reservoirsCalRecord; ///< DG reservoirs non-volatile record. static DG_HEATING_CAL_RECORD_T heatingConstsCalRecord; ///< DG heating calibration record. static F32 targetFillFlowRateLPM; ///< Target fill flow rate in L/min. -static BOOL isThisTheFirstCycle = TRUE; ///< Boolean flag to indicate whether this is the first cycle. +static BOOL isThisTheFirstCycle; ///< Boolean flag to indicate whether this is the first cycle. static RESERVOIRS_PREVIOUS_STATUS reservoirPreviousStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoirs previous status. /*********************************************************************//** @@ -142,8 +147,7 @@ // publish active reservoir, fill/drain volume targets at 1 Hz. if ( ++dataPublishCounter >= RESERVOIR_DATA_PUB_INTERVAL ) { - RESERVOIR_DATA_T data; - + RESERVOIR_DATA_T data; data.activeReservoir = getU32OverrideValue( &activeReservoir ); data.fillToVolumeMl = getU32OverrideValue( &fillVolumeTargetMl ); data.drainToVolumeMl = getU32OverrideValue( &drainVolumeTargetMl ); @@ -204,9 +208,8 @@ void setActiveReservoirCmd( DG_RESERVOIR_ID_T resID ) { DG_CMD_RESPONSE_T cmdResponse; - - cmdResponse.commandID = DG_CMD_SWITCH_RESERVOIR; - cmdResponse.rejected = TRUE; + cmdResponse.commandID = DG_CMD_SWITCH_RESERVOIR; + cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; // switch reservoir command only valid in generation idle mode @@ -257,8 +260,8 @@ { DG_CMD_RESPONSE_T cmdResponse; - cmdResponse.commandID = DG_CMD_VALVE_SETTING; - cmdResponse.rejected = TRUE; + cmdResponse.commandID = DG_CMD_VALVE_SETTING; + cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; // valve setting command only valid in generation idle mode @@ -535,9 +538,6 @@ heatersTempCalc.tempTargetTrimmer = params.trimmerTargetTemperature; heatersTempCalc.flowTargetDialysateLPM = params.dialysateFlowLPM; - // Set the trimmer heater target temperature since this value is needed for calculations - setHeaterTargetTemperature( DG_TRIMMER_HEATER, heatersTempCalc.tempTargetTrimmer ); - // Check if this is the first time that the dialysate heating parameters are set in DG if ( TRUE == isThisTheFirstCycle ) { @@ -574,7 +574,7 @@ F32 fillPart = ( ( targetFillVolML - heatingConstsCalRecord.ultrafilterVolmL ) / targetFillVolML ) * tempAvgFill; F32 tempReservoir0Actual = ultrafilterPart + fillPart; - F32 tempReservoirEndfillActual = tempReservoir0Actual + ( ( heatersTempCalc.timeReservoirFillMS * 0.5 ) * RsrvrTauCPerMS ); + F32 tempReservoirEndfillActual = tempReservoir0Actual + ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * RsrvrTauCPerMS ); heatersTempCalc.tempReservoirUseActual = tempReservoirEndfillActual + ( heatersTempCalc.timeReservoirFill2SwitchMS * RsrvrTauCPerMS ); } else @@ -589,19 +589,24 @@ * @brief * The getPrimaryHeaterTargetTemperature function calculates the primary * heater target temperature and returns target temperature value. - * @details Inputs: none + * @details Inputs: heatingConstsCalRecord * @details Outputs: heatersTempCalc * @return primary heater target temperature *************************************************************************/ F32 getPrimaryHeaterTargetTemperature( void ) { // TODO once the equations are solidified, add the equations as comments to the lines - F32 tempTarget = 0.0; - F32 targetFillVolML = getTargetFillVolumeML(); - F32 UFTimeConstant = 0.0; - F32 tempLastFill = getLastFillTemperature(); - F32 UFTauCPerMS = heatingConstsCalRecord.ultrafilterTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); - F32 RsrvrTauCPerMS = heatingConstsCalRecord.reservoirTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); + F32 tempTarget = 0.0; + F32 priTargetTemp = 0.0; + F32 targetFillVolML = getTargetFillVolumeML(); + F32 UFTimeConstant = 0.0; + F32 tempLastFill = getLastFillTemperature(); + F32 UFTauCPerMS = heatingConstsCalRecord.ultrafilterTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); + F32 RsrvrTauCPerMS = heatingConstsCalRecord.reservoirTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); + F32 targetROFlowLPM = getTargetROPumpFlowRateLPM(); + F32 tgtAicdFlowLPM = getConcentratePumpTargetFlowMLPM( CONCENTRATEPUMPS_CP1_ACID ) / ML_PER_LITER; + F32 tgtBicarbFlowLPM = getConcentratePumpTargetFlowMLPM( CONCENTRATEPUMPS_CP2_BICARB ) / ML_PER_LITER; + F32 tgtTotalFlowLPM = targetROFlowLPM + tgtAicdFlowLPM + tgtBicarbFlowLPM; if ( FALSE == isThisTheFirstFill() ) { @@ -611,7 +616,7 @@ tempReservoirUse = heatersTempCalc.tempTargetTrimmer + RESERVOIR_EXTRA_TEMPERATURE; heatersTempCalc.tempReservoirEndFill = tempReservoirUse - ( heatersTempCalc.timeReservoirFill2SwitchMS * RsrvrTauCPerMS ); - heatersTempCalc.tempReservoir0 = heatersTempCalc.tempReservoirEndFill - ( ( heatersTempCalc.timeReservoirFillMS * 0.5 ) * RsrvrTauCPerMS ); + heatersTempCalc.tempReservoir0 = heatersTempCalc.tempReservoirEndFill - ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * RsrvrTauCPerMS ); heatersTempCalc.timeUFDecayMS = (F32)heatersTempCalc.timeReservoirCycleMS - heatersTempCalc.timeReservoirFillMS; UFTimeConstant = heatersTempCalc.timeUFDecayMS * UFTauCPerMS; @@ -626,11 +631,57 @@ tempTarget = heatersTempCalc.tempTargetTrimmer + RESERVOIR_EXTRA_TEMPERATURE; } - return tempTarget; + if ( targetROFlowLPM > 0 ) + { + priTargetTemp = ( tempTarget * ( tgtTotalFlowLPM / targetROFlowLPM ) ) - ( ENVIRONMENT_TEMPERATURE_C * ( tgtAicdFlowLPM / targetROFlowLPM ) ) - + ( ENVIRONMENT_TEMPERATURE_C * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); + } + + return priTargetTemp; } /*********************************************************************//** * @brief + * The getTrimmerHeaterTargetTemperature function calculates the trimmer + * heater target temperature and returns target temperature value. + * @details Inputs: heatingConstsCalRecord + * @details Outputs: heatersTempCalc + * @return primary heater target temperature + *************************************************************************/ +F32 getTrimmerHeaterTargetTemperature( void ) +{ + F32 tempRsrvrActual = 0.0; + F32 fillROAvgActual = getAvgFillTemperature(); + F32 targetFillVolML = getTargetFillVolumeML(); + F32 UFTauCPerMS = heatingConstsCalRecord.ultrafilterTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); + F32 tempLastFill = getLastFillTemperature(); + F32 tempUFFill = tempLastFill + ( heatersTempCalc.timeUFDecayMS * UFTauCPerMS ); + F32 rsrvrTauCPerMS = heatingConstsCalRecord.reservoirTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); + F32 targetROFlowLPM = getTargetROPumpFlowRateLPM(); + F32 tgtAicdFlowLPM = getConcentratePumpTargetFlowMLPM( CONCENTRATEPUMPS_CP1_ACID ) / ML_PER_LITER; + F32 tgtBicarbFlowLPM = getConcentratePumpTargetFlowMLPM( CONCENTRATEPUMPS_CP2_BICARB ) / ML_PER_LITER; + F32 tgtTotalFlowLPM = targetROFlowLPM + tgtAicdFlowLPM + tgtBicarbFlowLPM; + + if ( tgtTotalFlowLPM > 0 ) + { + heatersTempCalc.tempFillMixAvgTrimmer = ( fillROAvgActual * ( tgtTotalFlowLPM / targetROFlowLPM ) ) + + ( ENVIRONMENT_TEMPERATURE_C * ( tgtAicdFlowLPM / targetROFlowLPM ) ) + + ( ENVIRONMENT_TEMPERATURE_C * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); + + heatersTempCalc.tempRsrvr0ActualTrimmer = ( ( heatingConstsCalRecord.ultrafilterVolmL / targetFillVolML ) * tempUFFill ) + + ( ( ( targetFillVolML - heatingConstsCalRecord.ultrafilterVolmL ) / targetFillVolML ) * + heatersTempCalc.tempFillMixAvgTrimmer ); + + heatersTempCalc.tempRsrvrEndFillTrimmer = heatersTempCalc.tempRsrvr0ActualTrimmer + ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * rsrvrTauCPerMS ); + + tempRsrvrActual = heatersTempCalc.tempRsrvrEndFillTrimmer + ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * rsrvrTauCPerMS ); + } + + return tempRsrvrActual; +} + +/*********************************************************************//** + * @brief * The getReservoirsCalRecord function returns the reservoirs' calibration * record. * @details Inputs: reservoirsCalRecord