Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r70f88b1f2610e5d03453f27c94fb2413d995ae40 -rc0d44be16f9951cce2835bcc8b21820d1b88515e --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 70f88b1f2610e5d03453f27c94fb2413d995ae40) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision c0d44be16f9951cce2835bcc8b21820d1b88515e) @@ -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" @@ -55,16 +56,27 @@ #define MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ( 60 * MS_PER_SECOND ) ///< Conductivity sensor error window. #define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0F ///< Out of range value for RO rejection ratio when CPi conductivity is zero. + #define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. #define MAX_CPO_CONDUCTIVITY_ALLOW 30.0F ///< Maximum CPo sensor conductivity value. #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 +91,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 +160,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 +218,37 @@ 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 ) ); } } @@ -221,30 +264,19 @@ 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 ); + 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; } /*********************************************************************//** * @brief * The checkInletWaterConductivity function checks inlet water conductivity value - * and triggers an alarm when conductivity value is not within the specified - * values. + * and triggers an alarm when conductivity value is out of allowed range. * @details Inputs: CPi sensor conductivity - * @details Outputs: Trigger warning alarm if conductivity is in the warning - * range. Trigger alarm if conductivity is below minimum conductivity. + * @details Outputs: Trigger alarms when conductivity is out of allowed range * @return none *************************************************************************/ void checkInletWaterConductivity( void ) @@ -321,7 +353,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 +380,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,9 +395,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; if ( fabs(cpi) >= NEARLY_ZERO ) @@ -380,31 +414,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 ) @@ -417,7 +453,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 ) @@ -461,110 +497,98 @@ /*********************************************************************//** * @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: + // Do nothing + // Software fault? + 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 @@ -573,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 @@ -591,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; } @@ -606,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 @@ -618,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; } } @@ -633,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 *************************************************************************/ @@ -644,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/ROPump.c =================================================================== diff -u -r70f88b1f2610e5d03453f27c94fb2413d995ae40 -rc0d44be16f9951cce2835bcc8b21820d1b88515e --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 70f88b1f2610e5d03453f27c94fb2413d995ae40) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision c0d44be16f9951cce2835bcc8b21820d1b88515e) @@ -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 @@ -371,12 +375,11 @@ measuredROFlowRateLPM.data = flow - ( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) / ML_PER_LITER ) - ( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) / ML_PER_LITER ); - // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that - // the flow is 0. - if ( FLOW_SENSOR_ZERO_READING == roFlowReading ) - { - measuredROFlowRateLPM.data = 0.0; - } + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that the flow is 0. + if ( FLOW_SENSOR_ZERO_READING == roFlowReading ) + { + measuredROFlowRateLPM.data = 0.0; + } measuredFlowReadingsSum = 0; flowFilterCounter = 0; @@ -401,7 +404,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 +449,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 +536,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,11 +611,11 @@ 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 && 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; } @@ -644,7 +647,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 +712,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 +748,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 +846,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/Modes/ModeFlush.c =================================================================== diff -u -rf548bc89ceec8f10b42db24129f5a2f7b0eb84d5 -rc0d44be16f9951cce2835bcc8b21820d1b88515e --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision f548bc89ceec8f10b42db24129f5a2f7b0eb84d5) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision c0d44be16f9951cce2835bcc8b21820d1b88515e) @@ -49,14 +49,15 @@ #define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo it was 2 minutes +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. // Flush dialysate state defines #define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. // Flush concentrate straws state defines #define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. todo was 3 minutes #define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid pump speed in mL/min. + // The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during flush #define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb pump speed in mL/min. @@ -306,6 +307,7 @@ // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); + // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); @@ -884,12 +886,6 @@ // Raise the alarm failFlushMode(); - - // If the caps alarm was active, clear it at the of the cancel water path - if ( TRUE == isAlarmActive( ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION ) ) - { - clearAlarmCondition( ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION ); - } } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) @@ -1075,7 +1071,7 @@ prevFlushState = flushState; flushState = DG_FLUSH_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; - } + } } } Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r4e605862b7ae972bad2191c2215509dab6baa63e -rc0d44be16f9951cce2835bcc8b21820d1b88515e --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 4e605862b7ae972bad2191c2215509dab6baa63e) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision c0d44be16f9951cce2835bcc8b21820d1b88515e) @@ -74,13 +74,13 @@ #define NUM_OF_TEMP_SENSORS_TO_AVG 4.0F ///< Number of temperature sensors to average to check the difference. #define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid concentrate pump speed in mL/min. // The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during heat disinfect -#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb concentrate pump speed in mL/min. +#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb concentrate pump speed in mL/min. // Flush and drain R1 and R2 #define RSRVRS_FULL_VOL_ML 1850.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 #define RSRVRS_PARTIAL_FILL_VOL_ML 500.0F ///< Reservoirs 1 & 2 partial volume in mL. #define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. -#define RSRVRS_FILL_UP_TIMEOUT_MS ( 8 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins #define RSRVRS_500ML_FILL_UP_TIMEOUT_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. TODO original value was 2 mins #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. @@ -95,7 +95,7 @@ #define HEAT_DISINFECT_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. #define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. #define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. TODO change this to 5 seconds -#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 150.0F ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. +#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 100.0F ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. #define HEAT_DISINFECT_MAX_TEMP_GRADIENT_C 15.0F ///< Heat disinfect maximum allowed temperature gradient in between hottest and coldest sensors. #define HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ( 0.16 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect temperature gradient out of range timeout in milliseconds. @@ -107,7 +107,7 @@ #define TARGET_THD_SENSOR_FOR_RINSING_C 44.0F ///< Target THd temperature sensor value before rinsing in C. // Mix drain R1 and R2 -#define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 20 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. +#define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. #define DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ( 5 * MS_PER_SECOND ) ///< Time to start the drain pump at mix drain after directing the flow to drain in ms. #define DRAIN_PUMP_RPM_IN_MIX_DRAIN 600 ///< The RPM that the drain pump should be run during mix drain. #define MIX_DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 15 * MS_PER_SECOND ) ///< Time period of unchanged weight during mix draining before timeout. @@ -717,7 +717,7 @@ areTempSensorsInRange = TRUE; // Turn the pumps on in reverse setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); // Turn on the concentrate pumps requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); @@ -1104,13 +1104,10 @@ { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: case HEAT_DISINFECT_HEAT_UP_TIMEOUT: + case HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE: state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; break; - case HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE: - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - break; - case HEAT_DISINFECT_DISINFECT_IN_PROGRESS: heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_1; break; @@ -1217,13 +1214,10 @@ { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: case HEAT_DISINFECT_HEAT_UP_TIMEOUT: + case HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE: state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; break; - case HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE: - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - break; - case HEAT_DISINFECT_COMPLETE: // Turn off the heaters stopHeater( DG_PRIMARY_HEATER ); @@ -2105,7 +2099,6 @@ // Set the variables to fail and go to cancel water path. Set the pending alarm to no alarm so the cancel water path // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function U32 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); - prevHeatDisinfectState = heatDisinfectState; heatDisinfectState = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION;