Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -r97e0100921ccad633b39b509a93a7237e4d80446 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 97e0100921ccad633b39b509a93a7237e4d80446) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -37,12 +37,11 @@ #define CONCENTRATE_PUMP_SPEED_INCREMENT 8.0 ///< Speed increase (mL/min) when controlling concentrate pump to target step speed. #define CONCENTRATE_PUMP_MIN_SPEED 3.0 ///< Minimum speed for concentrate pump in mL per min. -#define CONCENTRATE_PUMP_MAX_SPEED 49.0 ///< Maximum speed for concentrate pump in mL per min. #define CONCENTRATE_PUMP_ERROR_TOLERANCE 0.02 ///< Measured speed needs to be within 2% of commanded speed. #define CONCENTRATE_PUMP_ZERO_FLOW_RATE 0xFFFF ///< Pulse width value when zero flow rate or pump is off. -#define CONCENTRATE_PUMP_VOLUME_PER_REV 0.15 ///< Volume output every revolution (mL). -#define CONCENTRATE_PUMP_PULSE_PER_REV 4.0 ///< Number of pulses generate for every revolution. +#define CONCENTRATE_PUMP_VOLUME_PER_REV 0.1 ///< Volume output every revolution (mL). +#define CONCENTRATE_PUMP_PULSE_PER_REV 2.0 ///< Number of pulses generate for every revolution. #define CONCENTRATE_PUMP_STEP_PER_REV 200.0 ///< Number of steps for every revolution. #define CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION 100.0 ///< Hall sense period resolution in microseconds. @@ -53,7 +52,7 @@ #define CONCENTRATE_PUMP_VOLUME_PER_PULSE ( CONCENTRATE_PUMP_VOLUME_PER_REV / CONCENTRATE_PUMP_PULSE_PER_REV ) #define CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is monitored. -#define CONCENTRATE_PUMP_CONTROL_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is controlled. +#define CONCENTRATE_PUMP_CONTROL_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is controlled. #define CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for concentrate pump speed control error. /// Enumeration of concentrate pump states. @@ -102,7 +101,6 @@ static U32 getPublishConcentratePumpDataInterval( void ); static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ); -static F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ); static BOOL processCalibrationData( void ); /*********************************************************************//** @@ -158,7 +156,13 @@ if ( ++concentratePumpMonitorTimerCounter >= getPublishConcentratePumpDataInterval() ) { CONCENTRATE_PUMP_DATA_T data; + U08 const fpgaConcentratePumpsFault = getFPGAConcentratePumpsFault(); + if ( 0 != fpgaConcentratePumpsFault ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, fpgaConcentratePumpsFault ); + } + calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2_BICARB, getFPGACP2HallSensePulseWidth() ); @@ -167,10 +171,10 @@ data.cp2CurrentSetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; data.cp2MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); +#ifndef DISABLE_DIALYSATE_CHECK F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; -#ifndef DISABLE_DIALYSATE_CHECK 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 ); #endif @@ -308,6 +312,10 @@ { concentratePumps[ pumpId ].pumpTargetSpeed = targetSpeed_ml_min; } + else if ( targetSpeed_ml_min < CONCENTRATE_PUMP_MIN_SPEED ) + { + concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; + } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE, targetSpeed_ml_min ) @@ -321,6 +329,35 @@ /*********************************************************************//** * @brief + * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. + * @details Inputs: measuredPumpSpeed + * @details Outputs: none + * @param pumpId concentrate pump id to increase current step speed + * @return the current concentrate pump flow rate (in mL/min). + *************************************************************************/ +F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ) +{ + F32 result = 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; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return result; +} + +/*********************************************************************//** + * @brief * The getAcidConcentrateCalRecord function returns the acid concentrate * calibration record. * @details Inputs: none @@ -508,35 +545,6 @@ /*********************************************************************//** * @brief - * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. - * @details Inputs: measuredPumpSpeed - * @details Outputs: none - * @param pumpId concentrate pump id to increase current step speed - * @return the current concentrate pump flow rate (in mL/min). - *************************************************************************/ -static F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ) -{ - F32 result = 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; - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The processCalibrationData function gets the calibration data and makes * sure it is valid by checking the calibration date. The calibration date * should not be 0. @@ -666,7 +674,7 @@ { F32 const absSpeed = fabs( value ); - if ( ( CONCENTRATE_PUMP_MIN_SPEED <= absSpeed ) && ( absSpeed <= CONCENTRATE_PUMP_MAX_SPEED ) ) + if ( absSpeed <= CONCENTRATE_PUMP_MAX_SPEED ) { result = TRUE; setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, value ); Index: firmware/App/Controllers/ConcentratePumps.h =================================================================== diff -u -rc0160362dc799802ec589d5b6cf4c2bd1face77e -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision c0160362dc799802ec589d5b6cf4c2bd1face77e) +++ firmware/App/Controllers/ConcentratePumps.h (.../ConcentratePumps.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -31,6 +31,8 @@ // ********** public definitions ********** +#define CONCENTRATE_PUMP_MAX_SPEED 48.0 ///< Maximum speed for concentrate pump in mL per min. + /// Enumeration of concentrate pumps. typedef enum ConcentratePumps { @@ -60,6 +62,7 @@ void requestConcentratePumpsOff( CONCENTRATE_PUMPS_T pumpId ); void setConcentratePumpTargetSpeed( CONCENTRATE_PUMPS_T pumpId, F32 targetSpeed_ml_min ); +F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ); DG_ACID_CONCENTRATES_RECORD_T getAcidConcentrateCalRecord( void ); DG_BICARB_CONCENTRATES_RECORD_T getBicarbConcentrateCalRecord( void ); Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -45,17 +45,6 @@ #define COND_SENSOR_CPI_MAX_VALUE 2000 ///< Maximum inlet water conductivity. #define COND_SENSOR_CPI_MIN_VALUE 100 ///< Minimum inlet water conductivity. -#define MIN_ACID_CONCENTRATE_CONDUCTIVITY 11000 ///< Minimum conductivity for acid concentrate. -#define MAX_ACID_CONCENTRATE_CONDUCTIVITY 11850 ///< Maximum conductivity for acid concentrate. - -#define MIN_BICARB_CONCENTRATE_CONDUCTIVITY 2000 ///< Minimum conductivity for bicarbonate concentrate. -#define MAX_BICARB_CONCENTRATE_CONDUCTIVITY 3000 ///< Maximum conductivity for bicarbonate concentrate. - -///< Minimum conductivity value for dialysate solution. -#define MIN_DIALYSATE_CONDUCTIVITY ( MIN_ACID_CONCENTRATE_CONDUCTIVITY + MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) -///< Maximum conductivity value for dialysate solution. -#define MAX_DIALYSATE_CONDUCTIVITY ( MAX_ACID_CONCENTRATE_CONDUCTIVITY + MAX_BICARB_CONCENTRATE_CONDUCTIVITY ) - #define MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< New reading every 800 ms, expect to get valid new reading in 1s. #define MAX_CONDUCTIVITY_SENSOR_FAILURES 5 ///< maximum number of conductivity sensor errors within window period before alarm. #define MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ( 60 * MS_PER_SECOND ) ///< Conductivity sensor error window. @@ -69,6 +58,7 @@ #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. #pragma pack(push,1) @@ -260,55 +250,6 @@ /*********************************************************************//** * @brief - * The isAcidConductivityInRange function checks if acid conductivity value - * is in range. - * @details Inputs: CD1 sensor conductivity - * @details Outputs: none - * @return TRUE if acid conductivity is in range, otherwise FALSE - *************************************************************************/ -BOOL isAcidConductivityInRange( void ) -{ - F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - BOOL const isConductivityInRange = ( MIN_ACID_CONCENTRATE_CONDUCTIVITY <= acidConductivity ) && ( acidConductivity <= MAX_ACID_CONCENTRATE_CONDUCTIVITY ); - - return isConductivityInRange; -} - -/*********************************************************************//** - * @brief - * The isBicarbConductivityInRange function checks if bicarbonate conductivity - * value is in range. - * @details Inputs: CD2 sensor conductivity - * @details Outputs: none - * @return TRUE if bicarb conductivity is in range, otherwise FALSE - *************************************************************************/ -BOOL isBicarbConductivityInRange( void ) -{ - F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL const isConductivityInRange = ( MIN_BICARB_CONCENTRATE_CONDUCTIVITY <= bicarbConductivity ) && ( bicarbConductivity <= MAX_BICARB_CONCENTRATE_CONDUCTIVITY ); - - return isConductivityInRange; -} - -/*********************************************************************//** - * @brief - * The isDialysateConductivityInRange function checks if dialysate conductivity - * value is in range. - * @details Inputs: CD2 sensor conductivity - * @details Outputs: none - * @return TRUE if dialysate conductivity is in range, otherwise FALSE - *************************************************************************/ -BOOL isDialysateConductivityInRange( void ) -{ - F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL const isConductivityInRange = isAcidConductivityInRange() && ( MIN_DIALYSATE_CONDUCTIVITY <= bicarbConductivity ) && - ( bicarbConductivity <= MAX_DIALYSATE_CONDUCTIVITY ); - - return isConductivityInRange; -} - -/*********************************************************************//** - * @brief * The getConductivityValue function gets the compensated conductivity * value for a given conductivity sensor id. * @details Inputs: compensatedConductivityValues[] @@ -472,8 +413,9 @@ static void processMeasurementDataPackage( U32 sensorId ) { EMSTAT_VARIABLE_T const * const measurementPtr = (EMSTAT_VARIABLE_T *)&package; + U32 const status = hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ); - if ( EMSTAT_PICO_GOOD_STATUS == hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ) ) + if ( EMSTAT_PICO_GOOD_STATUS == status ) { U32 const prefix = prefixStrToSIFactor( measurementPtr->prefix ); F32 const resistance = ( ( F32 )( hexStrToDec( measurementPtr->value, sizeof( measurementPtr->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); @@ -486,14 +428,21 @@ } else { + compensatedConductivityValues[ sensorId ].data = 0.0; + } + + if ( EMSTAT_PICO_TIMING_NOT_MET_STATUS == status ) + { ++internalErrorCount[ sensorId ]; - if ( internalErrorCount[ sensorId ] > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) + if ( internalErrorCount[ sensorId ] > MAX_CONDUCTIVITY_SENSOR_FAILURES ) { -#ifndef DISABLE_COND_SENSOR_CHECK SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); -#endif } } + else + { + internalErrorCount[ sensorId ] = 0; + } } /*********************************************************************//** @@ -552,7 +501,7 @@ if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) { #ifndef DISABLE_COND_SENSOR_CHECK - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, CONDUCTIVITYSENSORS_CD1_SENSOR ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, CONDUCTIVITYSENSORS_CD1_SENSOR, CONDUCTIVITYSENSORS_CD2_SENSOR ); #endif } } Index: firmware/App/Controllers/ConductivitySensors.h =================================================================== diff -u -rdf0a0b9ce1414b00b381e516714f9089d8e4ae21 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision df0a0b9ce1414b00b381e516714f9089d8e4ae21) +++ firmware/App/Controllers/ConductivitySensors.h (.../ConductivitySensors.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -32,6 +32,17 @@ // ********** public definitions ********** +#define MIN_ACID_CONCENTRATE_CONDUCTIVITY 11000 ///< Minimum conductivity for acid concentrate. +#define MAX_ACID_CONCENTRATE_CONDUCTIVITY 11850 ///< Maximum conductivity for acid concentrate. + +#define MIN_BICARB_CONCENTRATE_CONDUCTIVITY 2000 ///< Minimum conductivity for bicarbonate concentrate. +#define MAX_BICARB_CONCENTRATE_CONDUCTIVITY 3000 ///< Maximum conductivity for bicarbonate concentrate. + +///< Minimum conductivity value for dialysate solution. +#define MIN_DIALYSATE_CONDUCTIVITY ( MIN_ACID_CONCENTRATE_CONDUCTIVITY + MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) +///< Maximum conductivity value for dialysate solution. +#define MAX_DIALYSATE_CONDUCTIVITY ( MAX_ACID_CONCENTRATE_CONDUCTIVITY + MAX_BICARB_CONCENTRATE_CONDUCTIVITY ) + /// Enumeration of conductivity sensors. typedef enum ConductivitySensors { @@ -62,10 +73,6 @@ void checkInletWaterConductivity( void ); void checkRORejectionRatio( void ); -BOOL isAcidConductivityInRange( void ); -BOOL isBicarbConductivityInRange( void ); -BOOL isDialysateConductivityInRange( void ); - F32 getConductivityValue( U32 sensorId ); BOOL testSetConductivityOverride( U32 sensorId, F32 value ); Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -40,15 +40,9 @@ // ********** private definitions ********** -#ifndef V_2_SYSTEM #define MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE 1.00 ///< Main primary heater (heater A) max duty cycle (100%). #define SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE 1.00 ///< Small Primary heater (heater B) max duty cycle (100%). #define TRIMMER_HEATER_MAX_DUTY_CYCLE 1.00 ///< Trimmer heater max duty cycle (100%). -#else -#define MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE 0.89 ///< Main primary heater (heater A) max duty cycle (89%). -#define SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE 0.50 ///< Small Primary heater (heater B) max duty cycle (50%). -#define TRIMMER_HEATER_MAX_DUTY_CYCLE 0.50 ///< Trimmer heater max duty cycle (50%). -#endif #define HEATERS_MIN_DUTY_CYCLE 0.00 ///< Primary and trimmer heaters minimum duty cycle (0.00%). #define PRIMARY_HEATERS_CUMULATIVE_DUTY_CYCLE ( MAIN_PRIMARY_HEATER_MAX_DUTY_CYCLE + \ SMALL_PRIMAY_HEATER_MAX_DUTY_CYCLE ) ///< Primary heaters cumulative duty cycle. @@ -218,6 +212,19 @@ /*********************************************************************//** * @brief + * The getPrimaryHeaterTargetTemperature function return the primary heater + * target temperature. + * @details Inputs: primaryHeaterTargetTemperature + * @details Outputs: none + * @return the current primary heater target temperature + *************************************************************************/ +F32 getPrimaryHeaterTargetTemperature( void ) +{ + return primaryHeaterTargetTemperature; +} + +/*********************************************************************//** + * @brief * The startPrimaryHeater function starts the primary heaters. It resets * the primary heaters state and sets the main primary heater duty cycle. * @details Inputs: primaryHeaterTargetTemperature @@ -267,8 +274,6 @@ *************************************************************************/ void stopPrimaryHeater( void ) { - setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); - setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); isPrimaryHeaterOn = FALSE; } @@ -281,7 +286,6 @@ *************************************************************************/ void stopTrimmerHeater( void ) { - setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); isTrimmerHeaterOn = FALSE; } @@ -543,6 +547,8 @@ // Switch to off state. Set the duty cycles to 0 mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); + setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); state = PRIMARY_HEATERS_EXEC_STATE_OFF; } @@ -609,6 +615,7 @@ { // Set the duty cycle to 0 and switch to off state trimmerHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); state = TRIMMER_HEATER_EXEC_STATE_OFF; } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -rc127dcd204e97f487256c3f14e1998bde0b7823d -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision c127dcd204e97f487256c3f14e1998bde0b7823d) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -50,8 +50,8 @@ /// Load cell data structure. typedef struct { - U32 rawReading; ///< Latest raw load cell reading. - OVERRIDE_F32_T weight; ///< Latest load cell weight. + U32 rawReading; ///< Latest raw load cell reading + OVERRIDE_F32_T weight; ///< Latest load cell weight F32 autoCalOffset; ///< Load cell auto-calibration offset F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. @@ -67,14 +67,14 @@ // ********** private data ********** static OVERRIDE_U32_T loadCellDataPublishInterval = { LOAD_CELL_REPORT_PERIOD, - LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data publish interval. -static LOADCELL_T loadcells[ NUM_OF_LOAD_CELLS ]; ///< Load cell data structures. -static U32 loadCellFilterTimerCount = 0; ///< Load cell filtering timer count. -static U32 loadCellDataPublicationTimerCounter = 0; ///< Load cell data publication timer counter to CAN bus. + LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data publish interval. +static LOADCELL_T loadcells[ NUM_OF_LOAD_CELLS ]; ///< Load cell data structures. +static U32 loadCellFilterTimerCount = 0; ///< Load cell filtering timer count. +static U32 loadCellDataPublicationTimerCounter = 0; ///< Load cell data publication timer counter to CAN bus. -static U32 smallReadingsIdx; ///< Index for next sample in load cell small rolling average sample array. -static U32 largeReadingsIdx; ///< Index for next sample in load cell large rolling average sample array. -static DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< Load cells calibration record. +static U32 smallReadingsIdx; ///< Index for next sample in load cell small rolling average sample array. +static U32 largeReadingsIdx; ///< Index for next sample in load cell large rolling average sample array. +static DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< Load cells calibration record. // ********** private function prototypes ********** @@ -127,7 +127,6 @@ loadcells[ i ].loadCellVelocity_g_min = 0.0; } - // Set all the load cells' calibration values to benign values for ( cell = CAL_DATA_LOAD_CELL_A1; cell < NUM_OF_CAL_DATA_LOAD_CELLS; cell++ ) { // Reset the calibration variables @@ -160,9 +159,9 @@ // update sums for load cell average calculations loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].rawReading = a1 & MASK_OFF_U32_MSB; - loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].rawReading = a2 & MASK_OFF_U32_MSB; + loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].rawReading = a2 & MASK_OFF_U32_MSB; loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].rawReading = b1 & MASK_OFF_U32_MSB; - loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].rawReading = b2 & MASK_OFF_U32_MSB; + loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].rawReading = b2 & MASK_OFF_U32_MSB; // Check error bits from new readings a1 = ( a1 >> 31 ) << SHIFT_24_BITS; @@ -175,7 +174,7 @@ } // Check if a new calibration is available - if ( isNewCalibrationRecordAvailable() == TRUE ) + if ( TRUE == isNewCalibrationRecordAvailable() ) { // Get the new calibration data and check its validity processCalibrationData(); @@ -191,22 +190,26 @@ for ( ii = 0; ii < NUM_OF_LOAD_CELLS; ++ii ) { loadcells[ ii ].weight.data = (F32)loadcells[ ii ].rawReading * ADC2GRAM; - // Apply the calibration factors to the data. - // load_cell_weight = fourth_order_coeff * (load_cell^4) + third_order_coeff * (load_cell^3) + second_order_coeff * (load_cell^2) + gain * load_cell + offset - loadcells[ ii ].weight.data = pow(loadcells[ ii ].weight.data, 4) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].fourthOrderCoeff + - pow(loadcells[ ii ].weight.data, 3) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].thirdOrderCoeff + - pow(loadcells[ ii ].weight.data, 2) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].secondOrderCoeff + - loadcells[ ii ].weight.data * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].gain + - loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].offset; + loadcells[ ii ].weight.data = loadcells[ ii ].weight.data - loadcells[ ii ].autoCalOffset; - loadcells[ ii ].loadCellVelocity_g_min = ( getLoadCellWeight( (LOAD_CELL_ID_T)ii ) - loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] ) * (F32)SEC_PER_MIN; + loadcells[ ii ].loadCellVelocity_g_min = ( getLoadCellWeight( (LOAD_CELL_ID_T)ii ) - + loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] ) * (F32)SEC_PER_MIN; // Update small filter with new weight sample loadcells[ ii ].smallFilterTotal -= loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ]; loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] = getLoadCellWeight( (LOAD_CELL_ID_T)ii ); loadcells[ ii ].smallFilterTotal += getLoadCellWeight( (LOAD_CELL_ID_T)ii ); - loadcells[ ii ].smallFilteredWeight = (F32)( loadcells[ ii ].smallFilterTotal / (F64)SIZE_OF_SMALL_LOAD_CELL_AVG ); + + // Calculate the load cell value before applying calibration to it + F32 loadCell = (F32)( loadcells[ ii ].smallFilterTotal / (F64)SIZE_OF_SMALL_LOAD_CELL_AVG ); + // Apply the calibration factors to the data. + // load_cell_weight = fourth_order_coeff * (load_cell^4) + third_order_coeff * (load_cell^3) + second_order_coeff * (load_cell^2) + gain * load_cell + offset + loadcells[ ii ].smallFilteredWeight = pow(loadCell, 4) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].fourthOrderCoeff + + pow(loadCell, 3) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].thirdOrderCoeff + + pow(loadCell, 2) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].secondOrderCoeff + + loadCell * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].gain + + loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].offset; } smallReadingsIdx = INC_WRAP( smallReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); @@ -230,13 +233,17 @@ // broadcast load cell data if we are at scheduled interval. if ( ++loadCellDataPublicationTimerCounter >= getLoadCellDataPublishInterval() ) { - loadCellDataPublicationTimerCounter = 0; + LOAD_CELL_DATA_T loadCellData; - // broadcast small filtered load cell data - broadcastLoadCellData( loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].smallFilteredWeight, - loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].smallFilteredWeight, - loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].smallFilteredWeight, - loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].smallFilteredWeight ); + loadCellData.loadCellA1inGram = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + loadCellData.loadCellA2inGram = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ); + loadCellData.loadCellB1inGram = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + loadCellData.loadCellB2inGram = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_BACKUP ); + + // Broadcast small filtered load cell data + broadcastLoadCellData( &loadCellData ); + + loadCellDataPublicationTimerCounter = 0; } } @@ -329,18 +336,14 @@ *************************************************************************/ F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ) { - F32 result = 0; + F32 result = loadcells[ loadCellID ].weight.data; if ( loadCellID < NUM_OF_LOAD_CELLS ) { if ( OVERRIDE_KEY == loadcells[ loadCellID ].weight.override ) { result = loadcells[ loadCellID ].weight.ovData; } - else - { - result = loadcells[ loadCellID ].weight.data; - } } else { @@ -352,20 +355,26 @@ /*********************************************************************//** * @brief - * The getLoadCellSmallFilteredWeight function gets the small filtered load cell - * weight for a given load cell ID. + * The getLoadCellSmallFilteredWeight function gets the small filtered + * load cell weight for a given load cell ID. * @details Inputs: load cell filtered weight * @details Outputs: none * @param loadCellID ID of load cell to get large filtered weight * @return the small filtered load cell weight for the given load cell ID. *************************************************************************/ F32 getLoadCellSmallFilteredWeight( LOAD_CELL_ID_T loadCellID ) { - F32 result = 0; + F32 result = 0.0; if ( loadCellID < NUM_OF_LOAD_CELLS ) { result = loadcells[ loadCellID ].smallFilteredWeight; + + // If the load cell is in override mode, return the override weight + if ( OVERRIDE_KEY == loadcells[ loadCellID ].weight.override ) + { + result = loadcells[ loadCellID ].weight.ovData; + } } else { @@ -449,7 +458,7 @@ * The processCalibrationData function gets the calibration data and makes * sure it is valid by checking the calibration date. The calibration date * should not be 0. - * @details Inputs: loadCellsCalRecord + * @details Inputs: none * @details Outputs: loadCellsCalRecord * @return TRUE if the calibration record is valid, otherwise FALSE *************************************************************************/ @@ -463,25 +472,23 @@ for ( cell = 0; cell < NUM_OF_CAL_DATA_LOAD_CELLS; cell++ ) { +#ifndef SKIP_CAL_CHECK // Check if the calibration data that was received from NVDataMgmt is legitimate // The calibration date item should not be zero. If the calibration date is 0, // then the load cells data is not stored in the NV memory or it was corrupted. - if ( calData.loadCells[ cell ].calibrationTime == 0 ) + if ( 0 == calData.loadCells[ cell ].calibrationTime ) { -#ifndef DISABLE_CAL_CHECK SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_LOAD_CELLS_INVALID_CALIBRATION, (U32)cell ); -#endif status = FALSE; } - else - { - // The calibration data was valid, update the local copy - loadCellsCalRecord.loadCells[ cell ].fourthOrderCoeff = calData.loadCells[ cell ].fourthOrderCoeff; - loadCellsCalRecord.loadCells[ cell ].thirdOrderCoeff = calData.loadCells[ cell ].thirdOrderCoeff; - loadCellsCalRecord.loadCells[ cell ].secondOrderCoeff = calData.loadCells[ cell ].secondOrderCoeff; - loadCellsCalRecord.loadCells[ cell ].gain = calData.loadCells[ cell ].gain; - loadCellsCalRecord.loadCells[ cell ].offset = calData.loadCells[ cell ].offset; - } +#endif + + // The calibration data was valid, update the local copy + loadCellsCalRecord.loadCells[ cell ].fourthOrderCoeff = calData.loadCells[ cell ].fourthOrderCoeff; + loadCellsCalRecord.loadCells[ cell ].thirdOrderCoeff = calData.loadCells[ cell ].thirdOrderCoeff; + loadCellsCalRecord.loadCells[ cell ].secondOrderCoeff = calData.loadCells[ cell ].secondOrderCoeff; + loadCellsCalRecord.loadCells[ cell ].gain = calData.loadCells[ cell ].gain; + loadCellsCalRecord.loadCells[ cell ].offset = calData.loadCells[ cell ].offset; } return status; Index: firmware/App/Controllers/Pressures.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -41,6 +41,9 @@ #define PRESSURE_SAMPLES_TO_AVERAGE ( 200 / TASK_PRIORITY_INTERVAL ) ///< Averaging pressure data over the reporting interval. #define PRESSURE_AVERAGE_MULTIPLIER ( 1.0 / (F32)PRESSURE_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. + +#define MIN_VALID_PRESSURE_RANGE 0.0 ///< Minimum valid range on pressure reading. +#define MAX_VALID_PRESSURE_RANGE 200.0 ///< Maximum valid range on pressure reading. #define MIN_INLET_WATER_PRESSURE 25 ///< Minimum water input pressure. #define INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error. @@ -259,9 +262,7 @@ *************************************************************************/ static PRESSURE_STATE_T handlePressuresInitState( void ) { - PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; - - return result; + return PRESSURE_CONTINUOUS_READ_STATE; } /*********************************************************************//** @@ -275,7 +276,9 @@ static PRESSURE_STATE_T handlePressuresContReadState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; - S32 measuredPressureReadingsRaw[ NUM_OF_PRESSURE_SENSORS ]; + S32 measuredPressureReadingsRaw[ NUM_OF_PRESSURE_SENSORS ]; + U32 sensorID; + F32 pressureReading; // get latest raw pressure readings measuredPressureReadingsRaw[ PRESSURE_SENSOR_RO_PUMP_INLET ] = (S32)getIntADCReading( INT_ADC_RO_PUMP_INLET_PRESSURE ) - PUMP_PRESSURE_ZERO; @@ -331,9 +334,16 @@ measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] = 0; measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] = 0; measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] = 0; - } + } - // TODO - any other checks + for ( sensorID = 0; sensorID < NUM_OF_PRESSURE_SENSORS; sensorID++ ) + { + pressureReading = getMeasuredDGPressure( sensorID ); + if ( ( pressureReading < MIN_VALID_PRESSURE_RANGE ) || ( pressureReading > MAX_VALID_PRESSURE_RANGE ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_PRESSURE_SENSOR_FAULT, sensorID, pressureReading ); + } + } return result; } Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r037f0edb0b880130563058c809ba50308f2a63e9 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 037f0edb0b880130563058c809ba50308f2a63e9) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -21,9 +21,10 @@ #include "mibspi.h" #include "FPGA.h" +#include "NVDataMgmt.h" #include "OperationModes.h" -#include "PIControllers.h" #include "PersistentAlarm.h" +#include "PIControllers.h" #include "Pressures.h" #include "ROPump.h" #include "SafetyShutdown.h" @@ -131,6 +132,7 @@ static S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging. static U32 flowFilterCounter = 0; ///< Flow filtering counter. +static DG_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< Flow sensors calibration record. // ********** private function prototypes ********** @@ -145,6 +147,7 @@ static void stopROPump( void ); static void publishROPumpData( void ); static U32 getPublishROPumpDataInterval( void ); +static BOOL processCalibrationData( void ); /*********************************************************************//** * @brief @@ -331,20 +334,38 @@ BOOL isPressureMax = actualPressure >= MAX_ALLOWED_MEASURED_PRESSURE_PSI; checkPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, isPressureMax, actualPressure, MAX_ALLOWED_MEASURED_PRESSURE_PSI ); + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + } + // Read flow at the control set if ( ++flowFilterCounter >= FLOW_SAMPLES_TO_AVERAGE ) { - F32 avgROFlow = (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER; + U32 sensor; + F32 flow = RO_FLOW_ADC_TO_LPM_FACTOR / ( (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER ); + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that // the flow is 0. Otherwise, convert the count to flow rate in mL/min - if ( ( roFlowReading == FLOW_SENSOR_ZERO_READING ) || ( roFlowReading == 0 ) ) + if ( ( FLOW_SENSOR_ZERO_READING == roFlowReading ) || ( 0 == roFlowReading ) ) { measuredROFlowRateLPM.data = 0.0; } else { - measuredROFlowRateLPM.data = RO_FLOW_ADC_TO_LPM_FACTOR / avgROFlow; + // Right now there is only one flow sensor but a for loop is used here to be able to automatically accommodate + // the future flow sensors + for( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) + { + measuredROFlowRateLPM.data = pow(flow, 4) * flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff + + pow(flow, 3) * flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff + + pow(flow, 2) * flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff + + flow * flowSensorsCalRecord.flowSensors[ sensor ].gain + + flowSensorsCalRecord.flowSensors[ sensor ].offset; + } } measuredFlowReadingsSum = 0; @@ -368,7 +389,6 @@ checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, isFlowOutOfUpperRange, currentFlow, targetFlow ); checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, isFlowOutOfLowerRange, currentFlow, targetFlow ); } -#endif // If the pump is off and PPi + 5psi < PPo for a certain period of time, activate safety shutdown if ( FALSE == isROPumpOn ) @@ -384,6 +404,7 @@ activateSafetyShutdown(); } } +#endif // Publish RO pump data on interval publishROPumpData(); @@ -449,6 +470,31 @@ /*********************************************************************//** * @brief + * The execROPumpSelfTest function executes the RO pump's self-test. + * @details Inputs: none + * @details Outputs: none + * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execROPumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + BOOL calStatus = processCalibrationData(); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + + return result; +} + +/*********************************************************************//** + * @brief * The isROPumpRunning function returns the on/off status of RO pump. * @details Inputs: isROPumpOn * @details Outputs: none @@ -462,6 +508,51 @@ /*********************************************************************//** * @brief + * The getTargetROPumpFlowRate function gets the current target RO pump + * flow rate. + * @details Inputs: targetROPumpFlowRate + * @details Outputs: targetROPumpFlowRate + * @return the current target RO flow rate (in L/min). + *************************************************************************/ +F32 getTargetROPumpFlowRate( void ) +{ + return targetROPumpFlowRate; +} + +/*********************************************************************//** + * @brief + * The getMeasuredROFlowRate function gets the measured RO pump flow rate. + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM + * @return the current RO pump flow rate (in L/min). + *************************************************************************/ +F32 getMeasuredROFlowRate( void ) +{ + F32 result = measuredROFlowRateLPM.data; + + if ( OVERRIDE_KEY == measuredROFlowRateLPM.override ) + { + result = measuredROFlowRateLPM.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTargetROPumpPressure function gets the current target RO pump + * pressure. + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure + * @return the current target RO targetROPumpPressure in psi. + *************************************************************************/ +F32 getTargetROPumpPressure( void ) +{ + return targetROPumpMaxPressure; +} + +/*********************************************************************//** + * @brief * The handleROPumpOffState function handles the RO pump off state of the * controller state machine. * @details Inputs: roPumpControlMode, roPumpPWMDutyCyclePctSet, @@ -717,51 +808,48 @@ /*********************************************************************//** * @brief - * The getTargetROPumpFlowRate function gets the current target RO pump - * flow rate. - * @details Inputs: targetROPumpFlowRate - * @details Outputs: targetROPumpFlowRate - * @return the current target RO flow rate (in L/min). + * The processCalibrationData function gets the calibration data and makes + * sure it is valid by checking the calibration date. The calibration date + * should not be 0. + * @details Inputs: none + * @details Outputs: flowSensorsCalRecord + * @return TRUE if the calibration record is valid, otherwise FALSE *************************************************************************/ -F32 getTargetROPumpFlowRate( void ) +static BOOL processCalibrationData( void ) { - return targetROPumpFlowRate; -} + BOOL status = TRUE; + U32 sensor; -/*********************************************************************//** - * @brief - * The getMeasuredROFlowRate function gets the measured RO pump flow rate. - * @details Inputs: measuredROFlowRateLPM - * @details Outputs: measuredROFlowRateLPM - * @return the current RO pump flow rate (in L/min). - *************************************************************************/ -F32 getMeasuredROFlowRate( void ) -{ - F32 result = measuredROFlowRateLPM.data; + // Get the calibration record from NVDataMgmt + DG_FLOW_SENSORS_CAL_RECORD_T calData = getDGFlowSensorsCalibrationRecord(); - if ( OVERRIDE_KEY == measuredROFlowRateLPM.override ) + for ( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) { - result = measuredROFlowRateLPM.ovData; +#ifndef SKIP_CAL_CHECK + // Check if the calibration data that was received from NVDataMgmt is legitimate + // The calibration date item should not be zero. If the calibration date is 0, + // then the flow sensors data is not stored in the NV memory or it was corrupted. + if ( 0 == calData.flowSensors[ sensor ].calibrationTime ) + { + + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_FLOW_SENSORS_INVALID_CAL_RECORD, (U32)sensor ); + status = FALSE; + } +#endif + + // The calibration data was valid, update the local copy + flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff = calData.flowSensors[ sensor ].fourthOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff = calData.flowSensors[ sensor ].thirdOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff = calData.flowSensors[ sensor ].secondOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].gain = calData.flowSensors[ sensor ].gain; + flowSensorsCalRecord.flowSensors[ sensor ].offset = calData.flowSensors[ sensor ].offset; } - return result; + return status; } /*********************************************************************//** * @brief - * The getTargetROPumpPressure function gets the current target RO pump - * pressure. - * @details Inputs: targetROPumpPressure - * @details Outputs: targetROPumpPressure - * @return the current target RO targetROPumpPressure in psi. - *************************************************************************/ -F32 getTargetROPumpPressure( void ) -{ - return targetROPumpMaxPressure; -} - -/*********************************************************************//** - * @brief * The publishROPumpData function publishes RO pump data at the set interval. * @details Inputs: roPumpDataPublicationTimerCounter * @details Outputs: roPumpDataPublicationTimerCounter @@ -785,6 +873,7 @@ } } + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r037f0edb0b880130563058c809ba50308f2a63e9 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 037f0edb0b880130563058c809ba50308f2a63e9) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -38,7 +38,6 @@ #define PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 1000U ///< Primary heater external temperature sensors zero degree 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_0_DEGREE_RESISTANCE 1000U ///< Temperature sensor for conductivity zero degree resistance. @@ -79,15 +78,20 @@ #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. -/// Temperature sensor self-test states. -typedef enum tempSensors_Self_Test_States -{ - TEMPSENSORS_SELF_TEST_START = 0, ///< Temperature sensors self-test start - TEMPSENSORS_SELF_TEST_ADC_CHECK, ///< Temperature sensors self ADC check - TEMPSENSORS_SELF_TEST_COMPLETE, ///< Temperature sensors self-test complete - NUM_OF_TEMPSENSORS_SELF_TEST_STATES ///< Total number of self-test states -} TEMPSENSORS_SELF_TEST_STATES_T; +#define TEMP_SENSORS_MIN_ALLOWED_DEGREE_C 0.0 ///< Temperature sensors minimum allowed temperature in C. +#define TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 120.0 ///< Temperature sensors maximum allowed temperature in C. +#define NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 80.0 ///< 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. +// The count cannot be within 0.1V of the rail on both sides therefore: +// ADC count = ((2^12) - 1 / ref voltage) * voltage +// Max allowed voltage = 3.0 - 0.1 = 2.0V +// Min allowed voltage = 0.1 - 0.0 = 0.1V +// Max count = ((2^12) - 1 / ref voltage) * voltage -> ((4096 - 1)/3.0) * (3.0 - 0.1) +// Min count = ((2^12) - 1 / ref voltage) * voltage -> ((4096 - 1)/3.0) * (0.1 - 0.0) +#define TEMP_SENSORS_MAX_ALLOWED_ADC_COUNT 3959U ///< Temperature sensors max allowed ADC count. +#define TEMP_SESNORS_MIN_ALLOWED_ADC_COUNT 137U ///< Temperature sensors min allowed ADC count. + /// Temperature sensor exec states. typedef enum tempSensors_Exec_States { @@ -108,12 +112,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 } TEMP_SENSOR_T; // ********** private data ********** -static SELF_TEST_STATUS_T tempSensorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; ///< Self-test result of the TemperatureSensors module. -static TEMPSENSORS_SELF_TEST_STATES_T tempSensorsSelfTestState; ///< TemperatureSensor self-test state. static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state. static TEMP_SENSOR_T tempSensors [ NUM_OF_TEMPERATURE_SENSORS ]; ///< Temperature sensors' data structure. static U32 fpgaRawADCReadInterval = 0; ///< FPGA raw ADC read interval count. @@ -143,16 +146,12 @@ -1.228034E-2, 9.804036E-4, -4.413030E-5, 1.057734E-6, -1.052755E-8 }; ///< Thermocouple inverse coefficient for positive cold junction temperature. -static const U32 TEMP_SENSORS_ADC_MAX_COUNT = ( 1 << TEMP_SENSORS_ADC_BITS ) - 1; ///< ADC 24 bit max count which is (2^24 - 1). static const U32 TEMP_EQUATION_RESISTOR_CALC = 1 << ( TEMP_SENSORS_ADC_BITS - 1 ); ///< Temperature sensors resistor calculation (2^(24 - 1)). static const F32 TEMP_EQUATION_COEFF_A = 3.9083E-3; ///< ADC to temperature conversion coefficient A. static const F32 TEMP_EQUATION_COEFF_B = -5.775E-7; ///< ADC to temperature conversion coefficient B. // ********** private function prototypes ********** -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart( void ); -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck( void ); - static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ); static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ); @@ -163,15 +162,14 @@ 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 U32 getPublishTemperatureSensorsDataInterval( void ); +static void publishTemperatureSensorsData( void ); +static void monitorTemperatureSnsrs( U32 sensorIndex, F32 temperature ); /*********************************************************************//** * @brief * The initTemperatureSensors function initializes the module. - * @details Inputs: tempSensorsSelfTestState, tempSensorsExecState, - * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, - * tempSensors, fpgaRawADCReadInterval + * @details Inputs: none * @details Outputs: tempSensorsSelfTestState, tempSensorsExecState, * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, * tempSensors, fpgaRawADCReadInterval @@ -182,13 +180,11 @@ U08 i; // Initialize the variables - tempSensorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_START; - tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; - elapsedTime = 0; - internalHeatersConversionTimer = 0; - dataPublicationTimerCounter = 0; - fpgaRawADCReadInterval = 0; + tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; + elapsedTime = 0; + internalHeatersConversionTimer = 0; + dataPublicationTimerCounter = 0; + fpgaRawADCReadInterval = 0; /* NOTE: The temperature sensors do not have conversion coefficient. * The conversion coefficients are used for the heaters internal temperature sensors and @@ -207,28 +203,34 @@ 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_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; // 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_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; // 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_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; // Initialize the heaters internal thermocouples constants tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].conversionCoeff = HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF; @@ -240,62 +242,75 @@ // 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; F32 const conversionCoeff = 1.0 / 13584.0; - // Board temperature sensors conversion coefficient - tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_THDO_RTD ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].conversionCoeff = conversionCoeff; - tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].conversionCoeff = conversionCoeff; + 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_A2_B2 ].conversionCoeff = conversionCoeff; + tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].maxAllowedTemperature = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; + + tempSensors[ TEMPSENSORS_INTERNAL_THDO_RTD ].conversionCoeff = conversionCoeff; + tempSensors[ TEMPSENSORS_INTERNAL_THDO_RTD ].maxAllowedTemperature = 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_COND_TEMP_SENSOR ].conversionCoeff = conversionCoeff; + tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].maxAllowedTemperature = 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_LOW_TEMPERATURE, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE, INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD, + INLET_WATER_TEMPERATURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_LOW_TEMPERATURE, 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 ); + + // 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 ); + + // 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 ); + // 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_ADC_FAULT, TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD, + TEMPERATURE_SENSORS_FPGA_ERROR_PERSISTENT_PERIOD ); } /*********************************************************************//** * @brief * The execTemperatureSensorsSelfTest function runs the TemperatureSensors * POST during the self-test. - * @details Inputs: tempSensorsSelfTestState - * @details Outputs: tempSensorsSelfTestState + * @details Inputs: none + * @details Outputs: none * @return tempSensorsSelfTestState which is the status of the self test *************************************************************************/ SELF_TEST_STATUS_T execTemperatureSensorsSelfTest( void ) { - switch ( tempSensorsSelfTestState ) - { - case TEMPSENSORS_SELF_TEST_START: - tempSensorsSelfTestState = handleSelfTestStart(); - break; + SELF_TEST_STATUS_T status = SELF_TEST_STATUS_IN_PROGRESS; - case TEMPSENSORS_SELF_TEST_ADC_CHECK: - tempSensorsSelfTestState = handleSelfTestADCCheck(); - break; + // TODO implement the calibration processing function. + // It returns a pass for now - case TEMPSENSORS_SELF_TEST_COMPLETE: - // Done with self-test, do nothing - break; + status = SELF_TEST_STATUS_PASSED; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, tempSensorsSelfTestState ); - tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_COMPLETE; - break; - } - - return tempSensorsSelfTestResult; + return status; } /*********************************************************************//** * @brief - * The execTemperatureSensors function executes the temperature sensors' state machine. + * The execTemperatureSensors function executes the temperature sensors' + * state machine. * @details Inputs: tempSensorsExecState * @details Outputs: tempSensorsExecState * @return none @@ -305,7 +320,7 @@ // Read the sensors all the time switch ( tempSensorsExecState ) { - case TEMPSENSORS_SELF_TEST_START: + case TEMPSENSORS_EXEC_STATE_START: tempSensorsExecState = handleExecStart(); break; @@ -645,6 +660,13 @@ // Calculate the average F32 const avgADCReads = tempSensors[ sensorIndex ].adcRunningSum >> SHIFT_BITS_BY_2_FOR_AVERAGING; + // 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 ) ) + { + // TODO investigate why the new count check is out of range + //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ADC_OUT_OF_RANGE, TRUE, sensorIndex, avgADCReads ); + } + // Different sensors have different ADC to temperature conversion methods switch( sensorIndex ) { @@ -689,51 +711,13 @@ // Update the temperature tempSensors[ sensorIndex ].temperatureValues.data = temperature; -} -/*********************************************************************//** - * @brief - * The handleSelfTestStart function transitions the self-test state to - * check ADC. - * @details Inputs: tempSensorsSelfTestResult - * @details Outputs: none - * @return the next state of state machine - *************************************************************************/ -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart( void ) -{ - tempSensorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - return TEMPSENSORS_SELF_TEST_ADC_CHECK; + // Monitor the temperature value + monitorTemperatureSnsrs( sensorIndex, temperature ); } /*********************************************************************//** * @brief - * The handleSelfTestADCCheck function checks whether the ADC reads. If the - * reads are above the maximum 24bit ADC count, it will throw an alarm and - * switches to the next state. - * @details Inputs: tempSensorsSelfTestResult - * @details Outputs: tempSensorsSelfTestResult - * @return the next state of the state machine - *************************************************************************/ -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck( void ) -{ - tempSensorsSelfTestResult = SELF_TEST_STATUS_PASSED; - - S32 const tpiADC = (S32)getFPGATPiTemp(); - - BOOL const isLessThanZero = tpiADC <= 0; - BOOL const isGreaterThanFullScale = tpiADC >= TEMP_SENSORS_ADC_MAX_COUNT; - - if ( ( TRUE == isLessThanZero ) || ( TRUE == isGreaterThanFullScale ) ) - { - tempSensorsSelfTestResult = SELF_TEST_STATUS_FAILED; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, TEMPSENSORS_SELF_TEST_ADC_CHECK ); - } - - return TEMPSENSORS_SELF_TEST_COMPLETE; -} - -/*********************************************************************//** - * @brief * The handleExecStart function waits for a period of time and switches to * the state that reads the ADC values from FPGA. * @details Inputs: elapsedTime @@ -744,7 +728,7 @@ { TEMPSENSORS_EXEC_STATES_T state = TEMPSENSORS_EXEC_STATE_START; - if ( elapsedTime == 0 ) + if ( 0 == elapsedTime ) { elapsedTime = getMSTimerCount(); } @@ -907,7 +891,32 @@ } } +/*********************************************************************//** + * @brief + * The monitorTemperatureSnsrs function monitors the temperature sensors' + * temperature value and raises an alarm if any of them are out of range + * for more than the specified time. + * @details Inputs: tempSensors + * @details Outputs: tempSensors + * @param sensorIndex the index of the temperature sensor + * @param temperature the temperature value to be checked + * @return none + *************************************************************************/ +static void monitorTemperatureSnsrs( U32 sensorIndex, F32 temperature ) +{ + // The maximum allowed temperature is different for the sensors that are in the fluid path + // with the ones that are not in the fluid path + F32 maxLimit = tempSensors[ sensorIndex ].maxAllowedTemperature; + // Check both temperature and to be in range + if ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > maxLimit ) ) + { + // TODO investigate + //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, TRUE, sensorIndex, temperature ); + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -942,8 +951,8 @@ /*********************************************************************//** * @brief - * The testSetMeasuredTemperatureOverride function resets the override value - * of a specified temperature sensor. + * The testSetMeasuredTemperatureOverride function resets the override + * value of a specified temperature sensor. * @details Inputs: tempSensors * @details Outputs: tempSensors * @param sensorIndex temperature sensor index Index: firmware/App/Controllers/Voltages.h =================================================================== diff -u -rc0160362dc799802ec589d5b6cf4c2bd1face77e -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision c0160362dc799802ec589d5b6cf4c2bd1face77e) +++ firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -34,23 +34,25 @@ /// Enumeration of voltages monitored by this module. typedef enum Voltages { - MONITORED_LINE_24V_MAIN = 0, ///< Main voltage (24V) - MONITORED_LINE_1_8V_FPGA, ///< FPGA logic voltage (1.8V) - MONITORED_LINE_1V_FPGA, ///< FPGA reference voltage (1V) - MONITORED_LINE_3_3V_SENSORS, ///< Sensors voltage (3.3V) - MONITORED_LINE_1_8V_PROC, ///< Processor voltage (1.8V) - MONITORED_LINE_5V_SENSORS, ///< Sensors voltage (5V) - MONITORED_LINE_5V_LOGIC, ///< Logic voltage (5V) - MONITORED_LINE_3_3V, ///< Logic voltage (3.3V) - MONITORED_LINE_1_2V_PROC, ///< Processor voltage (1.2V) - MONITORED_LINE_V_REF, ///< Reference voltage (3V) - MONITORED_LINE_EXT_ADC_1_REF_V, ///< External ADC 1 reference voltage (3V) - MONITORED_LINE_EXT_ADC_2_REF_V, ///< External ADC 2 reference voltage (3V) - MONITORED_LINE_PS_GATE_DRIVER_V, ///< INT_ADC_POWER_SUPPLY_GATE_DRIVER - MONITORED_LINE_LAST_RANGE_CHECKED_LINE = MONITORED_LINE_PS_GATE_DRIVER_V, ///< The last monitored line that is checked per fixed range. - MONITORED_LINE_24V_PRIM_HTR_V, ///< Primary heater voltage (24V) - MONITORED_LINE_24V_TRIM_HTR_V, ///< Trimmer heater voltage (24V) - NUM_OF_MONITORED_LINES ///< Number of monitored voltages + MONITORED_LINE_24V_MAIN = 0, ///< Main voltage (24V) + MONITORED_LINE_1_8V_FPGA, ///< FPGA logic voltage (1.8V) + MONITORED_LINE_1V_FPGA, ///< FPGA reference voltage (1V) + MONITORED_LINE_3_3V_SENSORS, ///< Sensors voltage (3.3V) + MONITORED_LINE_1_8V_PROC, ///< Processor voltage (1.8V) + MONITORED_LINE_5V_SENSORS, ///< Sensors voltage (5V) + MONITORED_LINE_5V_LOGIC, ///< Logic voltage (5V) + MONITORED_LINE_3_3V, ///< Logic voltage (3.3V) + MONITORED_LINE_1_2V_PROC, ///< Processor voltage (1.2V) + MONITORED_LINE_V_REF, ///< Reference voltage (3V) + MONITORED_LINE_EXT_ADC_1_REF_V, ///< External ADC 1 reference voltage (3V) + MONITORED_LINE_EXT_ADC_2_REF_V, ///< External ADC 2 reference voltage (3V) + MONITORED_LINE_PS_GATE_DRIVER_V, ///< P/S gate driver voltage (5V) + MONITORED_LINE_VM_CP1, ///< Concentrate pump CP1 voltage (10.1V) + MONITORED_LINE_VM_CP2, ///< Concentrate pump CP2 voltage (10.1V) + MONITORED_LINE_LAST_RANGE_CHECKED_LINE = MONITORED_LINE_VM_CP2, ///< The last monitored line that is checked per fixed range. + MONITORED_LINE_24V_PRIM_HTR_V, ///< Primary heater voltage (24V) + MONITORED_LINE_24V_TRIM_HTR_V, ///< Trimmer heater voltage (24V) + NUM_OF_MONITORED_LINES ///< Number of monitored voltages } MONITORED_VOLTAGES_T; /// Payload record structure for the voltages data message. @@ -68,6 +70,8 @@ F32 adc5VLogic; ///< Internal ADC channel for 5V to logic F32 adc5VSensors; ///< Internal ADC channel for 5V to sensors F32 adc5VPSGateDriver; ///< Internal ADC channel for 5V P/S gate driver + F32 adcVMCP1; ///< Internal ADC channel for concentrate pump CP1 + F32 adcVMCP2; ///< Internal ADC channel for concentrate pump CP2 F32 adc24V; ///< Internal ADC channel for 24V F32 adc24VPrimaryHtr; ///< Internal ADC channel for 24V to primary heater F32 adc24VTrimmerHtr; ///< Internal ADC channel for 24V to trimmer heater Index: firmware/App/DGCommon.h =================================================================== diff -u -rf021b587abd164342311764b9a525fd107761d2d -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision f021b587abd164342311764b9a525fd107761d2d) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -33,7 +33,6 @@ #ifndef _VECTORCAST_ // TODO: Removed debug build flags when release build is ready // #define BOARD_WITH_NO_HARDWARE 1 -// #define SIMULATE_UI 1 // #define TASK_TIMING_OUTPUT_ENABLED 1 // re-purposes drain pump enable pin for task timing // #define DISABLE_HEATERS_AND_TEMPS 1 // #define DISABLE_ACCELS 1 @@ -44,18 +43,20 @@ #define ALARMS_DEBUG 1 // #define HEATERS_DEBUG 1 // #define PRESSURES_DEBUG 1 - #define DISABLE_DIALYSATE_CHECK 1 #define IGNORE_DRAIN_PUMP_MONITOR 1 // #define IGNORE_HEATERS_MONITOR 1 #define IGNORE_RO_PUMP_MONITOR 1 // #define DISABLE_RO_RATIO_CHECK 1 - #define DISABLE_COND_SENSOR_CHECK 1 - #define DISABLE_MIXING 1 +// #define DISABLE_COND_SENSOR_CHECK 1 // #define DISABLE_WATER_QUALITY_CHECK 1 #define DISABLE_RTC_CONFIG 1 - //#define V_2_SYSTEM 1 #define THD_USING_TRO_CONNECTOR 1 #define IGNORE_CONC_PUMP_IN_HEAT_DISINFECT 1 + + // Turn these flags on to disable dialysate mixing + #define DISABLE_DIALYSATE_CHECK 1 + #define DISABLE_MIXING 1 + #include #include #endif Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rc0160362dc799802ec589d5b6cf4c2bd1face77e -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision c0160362dc799802ec589d5b6cf4c2bd1face77e) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -26,6 +26,7 @@ #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" +#include "SystemComm.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" @@ -43,38 +44,58 @@ #define TARGET_RO_FLOW_RATE_L 0.8 ///< Target flow rate for RO pump. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. +#define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. +///< Persistent time interval for concentrate pumps prime. +#define CONCENTRATE_PUMP_PRIME_INTERVAL ( 3 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) #define ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER 1.06 ///< Acid and bicarbonate concentrates make up around 6% to total volume. #define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1 ///< Flow integrated volume has 10% tolerance compare to load cell reading. -#define CONCENTRATE_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. +#define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0 ///< Concentrate pump additional speed during priming in mL/min. +#define CONCENTRATE_TEST_TIME_OUT_MS ( 45 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. #define WATER_QUALITY_CHECK_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality check time out period in ms. -#define CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity error. +#define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. -/// Multiplier to convert flow (L/min) into volume (mL) for period of general task interval. -static const F32 RO_FLOW_INTEGRATOR = ( ( ML_PER_LITER * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); +#define ACID_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of acid concentration in ml. +#define BICARB_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of bicarb concentration in ml. +#define CONCENTRATION_BOTTLE_LOW_VOLUME_ML 100.0 ///< Concentration bottle low volume in ml. +/// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. +static const F32 FLOW_INTEGRATOR = ( (F32)TASK_GENERAL_INTERVAL / (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); + // ********** private data ********** -static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. -static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. -static F32 reservoirBaseWeight; ///< Fill reservoir base weight. -static F32 totalROFlowRate_LPM; ///< Total RO flow rate over period of time. -static U32 concentrateTestStartTime; ///< Starting time for concentrate test. -static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. +static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. +static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. +static F32 reservoirBaseWeight; ///< Fill reservoir base weight. +static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. +static U32 concentrateTestStartTime; ///< Starting time for concentrate test. +static U32 concentratePumpPrimeCount; ///< Interval count for concentrate pump prime. + +static F32 totalROFlowRate_mL_min; ///< Total RO flow rate over period of time. +static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. +static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. +static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. + +static OVERRIDE_F32_T usedAcidVolume_mL = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in ml. +static OVERRIDE_F32_T usedBicarbVolume_mL = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in ml. + // ********** private function prototypes ********** -static BOOL isWaterQualityGood( void ); -static BOOL checkDialysateConductivity( void ); static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ); static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ); static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ); static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ); static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ); +static DG_FILL_MODE_STATE_T handlePausedState( void ); -static void handleDialysateMixing( void ); +static BOOL isWaterQualityGood( void ); +static BOOL checkDialysateTemperature( void ); +static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); +static F32 getUsedAcidVolume( void ); +static F32 getUsedBicarbVolume( void ); /*********************************************************************//** * @brief @@ -88,11 +109,15 @@ fillState = DG_FILL_MODE_STATE_START; dialysateFillStartTime = 0; reservoirBaseWeight = 0.0; - totalROFlowRate_LPM = 0.0; + totalROFlowRate_mL_min = 0.0; concentrateTestStartTime = 0; + acidConductivityTotal = 0.0; + dialysateConductivityTotal = 0.0; + conductivitySampleCount = 0; + concentratePumpPrimeCount = 0; - initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ); - initPersistentAlarm( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS, CONDUCTIVITY_ERROR_PERSISTENCE_PERIOD_MS ); + initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); + initPersistentAlarm( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); } /*********************************************************************//** @@ -104,11 +129,13 @@ *************************************************************************/ void transitionToFillMode( void ) { - initFillMode(); + DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); + initFillMode(); + reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); dialysateFillStartTime = getMSTimerCount(); - // set initial actuator states + // Set initial actuator states setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); @@ -131,22 +158,27 @@ *************************************************************************/ U32 execFillMode( void ) { - // check inlet water conductivity, temperature, pressure, and RO rejection ratio + // Check inlet water conductivity, temperature, pressure, and RO rejection ratio checkInletWaterConductivity(); checkInletWaterTemperature(); checkInletPressure(); checkRORejectionRatio(); // TODO: Check for open straw door status and alarm if closed - - // check if run out of time to fill the reservoir + // Check if run out of time to fill the reservoir if ( TRUE == didTimeout( dialysateFillStartTime, DIALYSATE_FILL_TIME_OUT ) ) { activateAlarmNoData( ALARM_ID_DG_DIALYSATE_FILL_OUT_OF_TIME ); - requestNewOperationMode( DG_MODE_CIRC ); + requestNewOperationMode( DG_MODE_GENE ); } - // execute current Fill state + // Transition to generation idle mode when HD is not communicating + if ( FALSE == isHDCommunicating() ) + { + requestNewOperationMode( DG_MODE_GENE ); + } + + // Execute current Fill state switch ( fillState ) { case DG_FILL_MODE_STATE_START: @@ -174,6 +206,10 @@ fillState = handleDeliverDialysateState(); break; + case DG_FILL_MODE_STATE_PAUSED: + fillState = handlePausedState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_FILL_MODE_INVALID_EXEC_STATE, fillState ) fillState = DG_FILL_MODE_STATE_START; @@ -185,59 +221,6 @@ /*********************************************************************//** * @brief - * The isWaterQualityGood function checks for inlet water quality. - * @details Inputs: Temperature and conductivity alarms - * @details Outputs: none - * @return TRUE if water quality is good, otherwise FALSE - *************************************************************************/ -static BOOL isWaterQualityGood( void ) -{ - BOOL const isInletPressureGood = !isAlarmActive( ALARM_ID_INLET_WATER_LOW_PRESSURE ); - BOOL const isWaterTemperatureGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ); - BOOL const isWaterConductivityGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY ) && - !isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ); - - return ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ); -} - -/*********************************************************************//** - * @brief - * The checkDialysateConductivity function checks dialysate conductivity - * after adding acid and bicarbonate and triggers an alarm when conductivity - * is out of range. - * @details Inputs: CD1 and CD2 sensor conductivity - * @details Outputs: Trigger alarms when dialysate conductivity is out of allowed range - * @return TRUE if dialysate conductivity is good, otherwise FALSE - *************************************************************************/ -static BOOL checkDialysateConductivity( void ) -{ - BOOL const isDialysateConductivityGood = isDialysateConductivityInRange(); - - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, !isDialysateConductivityGood ) ) - { -#ifndef DISABLE_DIALYSATE_CHECK - if ( FALSE == isAcidConductivityInRange() ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ) ); - } - else - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ) ); - } -#endif - } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE, !isDialysateConductivityGood ) ) - { - clearAlarmCondition( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE ); - clearAlarmCondition( ALARM_ID_DIALYSATE_CONDUCTIVITY_OUT_OF_RANGE ); - } - - return ( isDialysateConductivityGood && isWaterQualityGood() ); -} - -/*********************************************************************//** - * @brief * The handleCheckInletWaterState function checks for inlet water quality * before jumping to dialysate production state. * @details Inputs: Temperature and conductivity alarms @@ -247,25 +230,24 @@ static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; - DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - BOOL isInletWaterReady = isWaterQualityGood(); - #ifndef DISABLE_DIALYSATE_CHECK - if ( isInletWaterReady ) + if ( TRUE == isWaterQualityGood() ) #endif { - reservoirBaseWeight = getReservoirWeight( inactiveReservoir ); concentrateTestStartTime = getMSTimerCount(); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); +#ifndef DISABLE_MIXING + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); +#endif result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; } if ( TRUE == didTimeout( waterQualityCheckStartTime, WATER_QUALITY_CHECK_TIME_OUT_MS ) ) { activateAlarmNoData( ALARM_ID_DG_BAD_INLET_WATER_QUALITY ); - requestNewOperationMode( DG_MODE_CIRC ); + requestNewOperationMode( DG_MODE_GENE ); } return result; @@ -282,23 +264,44 @@ static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); + F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + F32 const bicarbPumpFlowRate_mL_min = measuredROFlowRate_mL_min * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio + + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; - handleDialysateMixing(); - #ifndef DISABLE_DIALYSATE_CHECK - if ( TRUE == isBicarbConductivityInRange() ) + F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); +#else + F32 const bicarbConductivity = MIN_BICARB_CONCENTRATE_CONDUCTIVITY; #endif + + if ( MIN_BICARB_CONCENTRATE_CONDUCTIVITY <= bicarbConductivity ) { - concentrateTestStartTime = getMSTimerCount(); - requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); - result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + // Reduce acid pump speed after reaching minimum conductivity + // This prevents conductivity value to go out of sensor's range + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbPumpFlowRate_mL_min ); + + if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + { + concentratePumpPrimeCount = 0; + concentrateTestStartTime = getMSTimerCount(); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); +#ifndef DISABLE_MIXING + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); +#endif + result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + } } + else + { + concentratePumpPrimeCount = 0; + } if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ) ); - requestNewOperationMode( DG_MODE_CIRC ); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, bicarbConductivity ); + requestNewOperationMode( DG_MODE_GENE ); } return result; @@ -315,22 +318,40 @@ static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); + F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + F32 const acidPumpFlowRate_mL_min = measuredROFlowRate_mL_min * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; - handleDialysateMixing(); - #ifndef DISABLE_DIALYSATE_CHECK - if ( TRUE == isAcidConductivityInRange() ) + F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); +#else + F32 const acidConductivity = MIN_ACID_CONCENTRATE_CONDUCTIVITY; #endif + + if ( MIN_ACID_CONCENTRATE_CONDUCTIVITY <= acidConductivity ) { - requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); - result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + // Reduce acid pump speed after reaching minimum conductivity + // This prevents conductivity value to go out of sensor's range + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidPumpFlowRate_mL_min ); + + if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + { + concentratePumpPrimeCount = 0; + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + } } + else + { + concentratePumpPrimeCount = 0; + } if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ) ); - requestNewOperationMode( DG_MODE_CIRC ); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, acidConductivity ); + requestNewOperationMode( DG_MODE_GENE ); } return result; @@ -340,24 +361,36 @@ * @brief * The handleDialysateProductionState function executes the dialysate production * state of the fill mode state machine. - * @details Inputs: none + * @details Inputs: inlet water quality and dialysate temperature * @details Outputs: none * @return the next state *************************************************************************/ static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - handleDialysateMixing(); - - // TODO - transition when temperature and mix is in range #ifndef DISABLE_DIALYSATE_CHECK - if ( TRUE == checkDialysateConductivity() ) + if ( ( TRUE == isWaterQualityGood() ) && ( TRUE == checkDialysateTemperature() ) ) +#else + if ( TRUE ) #endif { - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + // Prime mixing before deliver result to reservoir + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); + handleDialysateMixing( measuredROFlowRate_mL_min ); + + if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + { + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + } } + else + { + concentratePumpPrimeCount = 0; + } return result; } @@ -366,33 +399,79 @@ * @brief * The handleDeliverDialysateState function executes the deliver dialysate * state of the fill mode state machine. - * @details Inputs: none - * @details Outputs: Deliver dialysate + * @details Inputs: inlet water quality and dialysate temperature + * @details Outputs: Deliver dialysate to inactive reservoir * @return the next state *************************************************************************/ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { + F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; + F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 const dialysateConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + BOOL const isAcidConductivityOutOfRange = ( acidConductivity <= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) && ( MAX_ACID_CONCENTRATE_CONDUCTIVITY >= acidConductivity ); + BOOL const isDialysateConductivityOutOfRange = ( dialysateConductivity <= MIN_DIALYSATE_CONDUCTIVITY ) && ( MAX_DIALYSATE_CONDUCTIVITY >= dialysateConductivity ); + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - totalROFlowRate_LPM += getMeasuredROFlowRate(); + F32 integratedVolume_mL; - handleDialysateMixing(); + // Set concentrate pumps speed based off RO pump flow rate + handleDialysateMixing( measuredROFlowRate_mL_min ); - // TODO - transition back when temperature or mix out of range - if ( FALSE == checkDialysateConductivity() ) - { + totalROFlowRate_mL_min += measuredROFlowRate_mL_min; + integratedVolume_mL = totalROFlowRate_mL_min * FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER; + usedAcidVolume_mL.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; + usedBicarbVolume_mL.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; + + acidConductivityTotal += acidConductivity; + dialysateConductivityTotal += dialysateConductivity; + conductivitySampleCount++; + #ifndef DISABLE_DIALYSATE_CHECK + if ( ( isWaterQualityGood() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) + { + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + } + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, isAcidConductivityOutOfRange ) ) + { + usedAcidVolume_mL.data = 0.0; + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + result = DG_FILL_MODE_STATE_PAUSED; + } + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, isDialysateConductivityOutOfRange ) ) + { + usedBicarbVolume_mL.data = 0.0; + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + result = DG_FILL_MODE_STATE_PAUSED; + } #endif + + if ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getUsedAcidVolume() ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) + { + activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); } - // if we've reached our target fill to volume (by weight), we're done filling - go back to re-circ mode - if ( hasTargetFillVolumeBeenReached( inactiveReservoir ) ) + if ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getUsedBicarbVolume() ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) { + activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); + } + + // if we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode + if ( ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) || ( ( integratedVolume_mL - reservoirBaseWeight ) >= MAX_RESERVOIR_VOLUME_ML ) ) + { F32 const filledVolume_mL = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; - F32 const integratedVolume_mL = totalROFlowRate_LPM * RO_FLOW_INTEGRATOR * ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER; F32 const integratedVolumeToLoadCellReadingPercent = fabs( 1 - ( filledVolume_mL / integratedVolume_mL ) ); + F32 const avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; + F32 const avgDialysateConductivity = dialysateConductivityTotal / conductivitySampleCount; if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) { @@ -401,35 +480,142 @@ #endif } - requestNewOperationMode( DG_MODE_CIRC ); +#ifndef DISABLE_DIALYSATE_CHECK + if ( ( avgAcidConductivity < MIN_ACID_CONCENTRATE_CONDUCTIVITY ) || ( avgAcidConductivity > MAX_ACID_CONCENTRATE_CONDUCTIVITY ) || + ( avgDialysateConductivity < MIN_DIALYSATE_CONDUCTIVITY ) || ( avgDialysateConductivity > MAX_DIALYSATE_CONDUCTIVITY ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgAcidConductivity, avgDialysateConductivity ); + } +#endif + + requestNewOperationMode( DG_MODE_GENE ); } return result; } /*********************************************************************//** * @brief + * The handlePausedState function executes the paused state of the fill + * mode state machine. + * @details Inputs: Empty bottle alarm active + * @details Outputs: none + * @return the next state + *************************************************************************/ +static DG_FILL_MODE_STATE_T handlePausedState( void ) +{ + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PAUSED; + + if ( ( FALSE == isAlarmActive( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE ) ) && + ( FALSE == isAlarmActive( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE ) ) ) + { + result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isWaterQualityGood function checks for inlet water quality. + * @details Inputs: Temperature and conductivity alarms + * @details Outputs: none + * @return TRUE if water quality is good, otherwise FALSE + *************************************************************************/ +static BOOL isWaterQualityGood( void ) +{ + BOOL const isInletPressureGood = !isAlarmActive( ALARM_ID_INLET_WATER_LOW_PRESSURE ); + BOOL const isWaterTemperatureGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ); + BOOL const isWaterConductivityGood = !isAlarmActive( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY ) && !isAlarmActive( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY ) && + !isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ); + + return ( isInletPressureGood && isWaterTemperatureGood && isWaterConductivityGood ); +} + +/*********************************************************************//** + * @brief + * The checkDialysateTemperature function checks dialysate temperature after + * it gets heated up by primary heater. + * @details Inputs: TPo temperature value + * @details Outputs: None + * @return TRUE if dialysate temperature is in range, otherwise FALSE + *************************************************************************/ +static BOOL checkDialysateTemperature( void ) +{ + F32 const dialysateTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + F32 const targetTemp = getPrimaryHeaterTargetTemperature(); + + return ( ( fabs( dialysateTemp - targetTemp ) <= DIALYSATE_TEMPERATURE_TOLERANCE_C ) ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief * The handleDialysateMixing function handles the dialysate mixing by setting * the concentrate pump speed relative to the RO pump flow rate. * @details Inputs: none * @details Outputs: Set concentrate pump speed relative to RO pump flow rate + * @param measuredROFlowRate_mL_min measured RO flow rate in mL/min * @return none *************************************************************************/ -static void handleDialysateMixing( void ) +static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ) { #ifndef DISABLE_MIXING // TODO what should we do with start volume from the structure? DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); // Set concentrate pumps speed based off RO pump flow rate - F32 const measuredROFlowRate = getMeasuredROFlowRate(); - F32 const acidCP1PumpFlowRate = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio * measuredROFlowRate * ML_PER_LITER; - F32 const bicarbCP2PumpFlowRate = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio * measuredROFlowRate * ML_PER_LITER; + F32 const acidCP1PumpFlowRate = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio * measuredROFlowRate_mL_min; + F32 const bicarbCP2PumpFlowRate = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio * measuredROFlowRate_mL_min; setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidCP1PumpFlowRate ); setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbCP2PumpFlowRate ); #endif } +/*********************************************************************//** + * @brief + * The getUsedAcidVolume function returns the used volume of acid concentration. + * @details Inputs: usedAcidVolume_mL + * @details Outputs: none + * @return used acid concentration volume + *************************************************************************/ +static F32 getUsedAcidVolume( void ) +{ + F32 result = usedAcidVolume_mL.data; + + if ( OVERRIDE_KEY == usedAcidVolume_mL.override ) + { + result = usedAcidVolume_mL.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getUsedBicarbVolume function returns the used volume of bicarbonate concentration. + * @details Inputs: usedBicarbVolume_mL + * @details Outputs: none + * @return used bicarbonate concentration volume + *************************************************************************/ +static F32 getUsedBicarbVolume( void ) +{ + F32 result = usedBicarbVolume_mL.data; + + if ( OVERRIDE_KEY == usedBicarbVolume_mL.override ) + { + result = usedBicarbVolume_mL.ovData; + } + + return result; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + + /**@}*/ Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -304,13 +304,8 @@ // Request a tare for reservoir 1 tareReservoir(); -#ifndef V_2_SYSTEM // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); -#else - // Set the actuators to drain R1 - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -347,17 +342,11 @@ tareReservoir(); } -#ifndef V_2_SYSTEM // Close reservoir 1 drain setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2 // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); -#else - // Set the actuators to drain R2 - // NOTE: Drain pump is already on and VDr is already on drain state - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif stateTimerStart = getMSTimerCount(); rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; @@ -397,25 +386,17 @@ { // Set the actuators to flush drain setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif state = DG_FLUSH_STATE_FLUSH_DRAIN; } else { // Set the actuators to pull fresh water in to drain the circulation line setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); @@ -449,11 +430,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) { -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Turn on the UV reactors @@ -577,11 +554,8 @@ setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); stateTimerStart = getMSTimerCount(); @@ -631,9 +605,7 @@ { // Done with draining R1 signalDrainPumpHardStop(); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_CLOSED ); -#endif } // Reservoir 1 drain time out else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) @@ -670,11 +642,7 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { signalROPumpHardStop(); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); stateTimerStart = getMSTimerCount(); @@ -724,11 +692,7 @@ { // Set the actuators to transition to flush circulation // The valves are set to do flush drain and flush circulation -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); @@ -762,11 +726,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_CIRCULATION_WAIT_TIME_MS ) ) { -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); @@ -845,12 +805,8 @@ // Set the actuators setValveState( VPI, VALVE_STATE_CLOSED ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD2, VALVE_STATE_OPEN ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif // Set both reservoirs to be considered as full rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; @@ -877,13 +833,8 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - // Set the drain valve to reservoir 1 - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) @@ -899,9 +850,7 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { -#ifndef V_2_SYSTEM setValveState( VRD2, VALVE_STATE_CLOSED ); -#endif // Done with draining signalDrainPumpHardStop(); Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -r7ed011e79e1338f614cbcc7d3cedf07d359196b7 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 7ed011e79e1338f614cbcc7d3cedf07d359196b7) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -24,6 +24,7 @@ #include "FPGA.h" #include "Heaters.h" #include "ModeGenIdle.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" #include "ROPump.h" @@ -45,7 +46,6 @@ #define TARGET_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. #define TARGET_FLUSH_LINES_RO_FLOW_RATE_L 0.6 ///< Target flow rate for RO pump. -#define FLUSH_LINES_VOLUME_L 0.01 ///< Water volume (in Liters) to flush when starting generation idle mode. // ********** private data ********** @@ -154,6 +154,35 @@ /*********************************************************************//** * @brief + * The getCurrentGenIdleState function returns the current state of the + * generation idle mode. + * @details Inputs: recircState + * @details Outputs: none + * @return the current state of generation idle mode + *************************************************************************/ +DG_GEN_IDLE_MODE_STATE_T getCurrentGenIdleState( void ) +{ + return genIdleState; +} + +/*********************************************************************//** + * @brief + * The requestDGStop function handles an HD request to stop (return to standby mode). + * @details Inputs: none + * @details Outputs: DG standby mode requested + * @return TRUE if request accepted, FALSE if not. + *************************************************************************/ +BOOL requestDGStop( void ) +{ + BOOL result = TRUE; + + requestNewOperationMode( DG_MODE_STAN ); + + return result; +} + +/*********************************************************************//** + * @brief * The handleFlushLinesState function executes the flush lines state of the * generation idle mode state machine. * @details Inputs: flushLinesVolumeL @@ -169,9 +198,10 @@ // Integrate volume of water moved through line flushLinesVolumeL += waterVolume; - // When enough water volume has flowed to flush the lines, transition to flush water state - if ( flushLinesVolumeL >= FLUSH_LINES_VOLUME_L ) + // When enough water volume has flowed to flush the lines, transition to re-circ state + if ( flushLinesVolumeL >= getRecirculationDrainVol() ) { + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } @@ -192,33 +222,4 @@ return DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } -/*********************************************************************//** - * @brief - * The requestDGStop function handles an HD request to stop (return to standby mode). - * @details Inputs: none - * @details Outputs: DG standby mode requested - * @return TRUE if request accepted, FALSE if not. - *************************************************************************/ -BOOL requestDGStop( void ) -{ - BOOL result = TRUE; - - requestNewOperationMode( DG_MODE_STAN ); - - return result; -} - -/*********************************************************************//** - * @brief - * The getCurrentGenIdleState function returns the current state of the - * generation idle mode. - * @details Inputs: recircState - * @details Outputs: none - * @return the current state of generation idle mode - *************************************************************************/ -DG_GEN_IDLE_MODE_STATE_T getCurrentGenIdleState( void ) -{ - return genIdleState; -} - /**@}*/ Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -447,13 +447,8 @@ setValveState( VPI, VALVE_STATE_CLOSED ); // Request a tare for reservoir 1 tareReservoir(); -#ifndef V_2_SYSTEM // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); -#else - // Set the actuators to drain R1 - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); rsrvrFillStableTimeCounter = 0; @@ -492,12 +487,8 @@ // Set the valves to flush the recirculation line setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRD1, VALVE_STATE_CLOSED ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -518,17 +509,11 @@ // Request a tare for reservoir 2 tareReservoir(); -#ifndef V_2_SYSTEM // Done with draining R1, close it setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2. // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); -#else - // Set the actuators to drain R2. - // NOTE: Drain pump is already on and VDr is already on drain state - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; } @@ -567,23 +552,17 @@ { if ( TRUE == isThisLastDrain ) { -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; } else { signalDrainPumpHardStop(); -#ifndef V_2_SYSTEM // Done with draining R2, close it setValveState( VRD2, VALVE_STATE_CLOSED ); -#endif setValveState( VPI, VALVE_STATE_OPEN ); stateTrialCounter = 0; stateTimer = getMSTimerCount(); @@ -623,11 +602,7 @@ if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) { -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); stateTimer = getMSTimerCount(); stateTrialCounter = 0; @@ -784,11 +759,7 @@ setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); stateTimer = getMSTimerCount(); @@ -838,10 +809,8 @@ { // Done with draining R1 signalDrainPumpHardStop(); -#ifndef V_2_SYSTEM // Close VRD1 setValveState( VRD1, VALVE_STATE_CLOSED ); -#endif } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -882,18 +851,10 @@ // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); -#ifndef V_2_SYSTEM setValveState( VRD2, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); // Start the timer for drain timeout stateTimer = getMSTimerCount(); @@ -937,12 +898,8 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif // Start the timer for drain timeout stateTimer = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; @@ -984,21 +941,13 @@ // Prepare for filling the reservoirs and heating the water setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif // Turn on the RO pump setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); @@ -1060,11 +1009,7 @@ // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); @@ -1137,12 +1082,8 @@ requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); // Set the valves to transfer hot water from R1 to R2 and fill up R2. setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // Although there is fluid in both reservoirs, but they are set to empty @@ -1285,12 +1226,8 @@ setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif ROFCoolingTimer = getMSTimerCount(); stateTimer = getMSTimerCount(); @@ -1392,9 +1329,7 @@ { isDrainPumpInMixDrainOn = TRUE; -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); -#endif // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); } @@ -1406,15 +1341,10 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { -#ifndef V_2_SYSTEM // Done with draining reservoir 1 setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the drain valve to reservoir 2 setValveState( VRD2, VALVE_STATE_OPEN ); -#else - // Set the drain valve to reservoir 2 - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; stateTimer = getMSTimerCount(); @@ -1455,13 +1385,9 @@ // Set the valves to fill up R1 and overflow to R2 setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); // Done with draining reservoir 2 setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -1524,11 +1450,7 @@ // Set the valves to rinse R2 to R1 and drain R1 setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -1577,9 +1499,7 @@ { // Done with draining R1 signalDrainPumpHardStop(); -#ifndef V_2_SYSTEM setValveState( VRD1, VALVE_STATE_CLOSED ); -#endif } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -1619,18 +1539,10 @@ // De-energize all the valves and set the VDr to drain R2 setValveState( VPI, VALVE_STATE_CLOSED ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); -#ifndef V_2_SYSTEM setValveState( VRD2, VALVE_STATE_OPEN ); -#else - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -1756,11 +1668,7 @@ { // The fluid is hot so this is a mix drain. Set the VPd to direct the cold inlet fluid to drain setValveState( VPI, VALVE_STATE_OPEN ); -#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); -#else - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); -#endif targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; cancellationMode = CANCELLATION_MODE_HOT; @@ -1787,14 +1695,9 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { -#ifndef V_2_SYSTEM // Set the drain valve to reservoir 1 and close reservoir 2 setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - // Set the drain valve to reservoir 1 - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -107,7 +107,7 @@ SW_FAULT_ID_HEAT_DISINFECT_INVALID_EXEC_STATE, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, SW_FAULT_ID_STANDBY_MODE_INVALID_EXEC_STATE, - SW_FAULT_ID_RECIRC_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_GEN_IDLE_MODE_INVALID_EXEC_STATE, SW_FAULT_ID_DRAIN_MODE_INVALID_EXEC_STATE, // 80 SW_FAULT_ID_FILL_MODE_INVALID_EXEC_STATE, SW_FAULT_ID_SOLO_MODE_INVALID_EXEC_STATE, Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r037f0edb0b880130563058c809ba50308f2a63e9 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 037f0edb0b880130563058c809ba50308f2a63e9) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -18,12 +18,14 @@ #include // for memset(), memcpy() +#include "gio.h" #include "sci.h" #include "sys_dma.h" -#include "FPGA.h" #include "Comm.h" #include "Compatible.h" +#include "FPGA.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Utilities.h" @@ -79,6 +81,12 @@ #define FPGA_FLUIDLEAK_STATE_MASK 0x0004 ///< Bit mask for fluid leak detector. +#define FLUID_DOOR_SWITCH_MASK 0x08 ///< Fluid door switch bit mask. +#define DIALYSATE_CAP_SWITCH_MASK 0x10 ///< Dialysate cap switch bit mask. +#define CONCENTRATE_CAP_SWITCH_MASK 0x1A ///< Concentrate 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 + // FPGA header struct. #pragma pack(push,1) typedef struct @@ -245,6 +253,7 @@ static void startDMAReceiptOfReadResp( void ); static void consumeUnexpectedData( void ); +static void monitorFPGAPowerStatus( void ); /*********************************************************************//** * @brief @@ -358,6 +367,9 @@ // there shouldn't be any data pending yet consumeUnexpectedData(); + + // Initialize the persistent alarm for FPGA power out + initPersistentAlarm( ALARM_ID_DG_FPGA_POWER_OUT_TIMEOUT, FPGA_POWER_OUT_TIMEOUT_MS, FPGA_POWER_OUT_TIMEOUT_MS ); } /*********************************************************************//** @@ -480,6 +492,9 @@ // reset comm flags after processing incoming responses resetFPGACommFlags(); + + // Check the FPGA power status + monitorFPGAPowerStatus(); } /*********************************************************************//** @@ -924,6 +939,22 @@ /*********************************************************************//** * @brief + * The monitorFPGAPowerStatus function monitors the status of the FPGA power source. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorFPGAPowerStatus( void ) +{ + // If the GIO bit returned a 0 it mean the power is out, otherwise the power is not out + BOOL isPowerOut = ( TRUE == (BOOL)gioGetBit( gioPORTA, FPGA_GPIO_POWER_STATUS_PIN ) ? FALSE : TRUE ); + + // TODO check to make sure alarm is not raised when the power is good + checkPersistentAlarm( ALARM_ID_DG_FPGA_POWER_OUT_TIMEOUT, isPowerOut, 0, FPGA_POWER_OUT_TIMEOUT_MS ); +} + +/*********************************************************************//** + * @brief * The setFPGAValveStates function sets the DG valve states with a 16-bit * set of states - one bit per valve, with a 1 meaning "energized" and a 0 * meaning "de-energized". The bit positions for these bit states are as follows: @@ -1856,4 +1887,43 @@ return ( 0 == noFluidLeakDetected ? FALSE : TRUE ); } +/*********************************************************************//** + * @brief + * The getFPGAGFluidDoorStatus function gets the FPGA fluid door status + * bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return fluid door status bit + *************************************************************************/ +U08 getFPGAGFluidDoorStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & FLUID_DOOR_SWITCH_MASK ); +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateCapStatus function gets the FPGA dialysate cap status + * bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return dialysate cap status bit + *************************************************************************/ +U08 getFPGADialysateCapStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & DIALYSATE_CAP_SWITCH_MASK ); +} + +/*********************************************************************//** + * @brief + * The getFPGAConcentrateCapStatus function gets the FPGA concentrate cap + * status bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return concentrate cap status bit + *************************************************************************/ +U08 getFPGAConcentrateCapStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & CONCENTRATE_CAP_SWITCH_MASK ); +} + /**@}*/ Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r037f0edb0b880130563058c809ba50308f2a63e9 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 037f0edb0b880130563058c809ba50308f2a63e9) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -134,9 +134,13 @@ U08 getFPGAADC2ReadCount( void ); U08 getFPGAADC2ErrorCount( void ); +BOOL noFPGAFluidLeakDetected( void ); + U16 getFPGATimerCount( void ); -BOOL noFPGAFluidLeakDetected( void); +U08 getFPGAGFluidDoorStatus( void ); +U08 getFPGADialysateCapStatus( void ); +U08 getFPGAConcentrateCapStatus( void ); /**@}*/ Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -18,7 +18,7 @@ #include // for memcpy() #include "LoadCell.h" -#include "ModeRecirculate.h" +#include "ModeGenIdle.h" #include "OperationModes.h" #include "Reservoirs.h" #include "SystemCommMessages.h" @@ -34,7 +34,6 @@ // ********** private definitions ********** #define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. -#define MAX_RESERVOIR_VOLUME_ML 2000 ///< Maximum reservoir volume in mL. #define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. #define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum fill volume in mL. #define DEFAULT_DRAIN_VOLUME_ML 0 ///< Default drain volume in mL. @@ -155,20 +154,15 @@ cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - // switch reservoir command only valid in re-circulate mode - if ( DG_MODE_CIRC == getCurrentOperationMode() ) + // switch reservoir command only valid in generation idle mode + if ( DG_MODE_GENE == getCurrentOperationMode() ) { switch ( resID ) { case DG_RESERVOIR_1: activeReservoir.data = (U32)resID; cmdResponse.rejected = FALSE; setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); -#ifndef V_2_SYSTEM - setValveState( VRD1, VALVE_STATE_CLOSED ); -#else - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); -#endif setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); break; @@ -177,11 +171,6 @@ activeReservoir.data = (U32)resID; cmdResponse.rejected = FALSE; setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); -#ifndef V_2_SYSTEM - setValveState( VRD2, VALVE_STATE_CLOSED ); -#else - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); -#endif setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); break; @@ -217,8 +206,8 @@ cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - // valve setting command only valid in re-circulate mode - if ( DG_MODE_CIRC == getCurrentOperationMode() ) + // valve setting command only valid in generation idle mode + if ( DG_MODE_GENE == getCurrentOperationMode() ) { switch ( valveSettingID ) { @@ -264,8 +253,9 @@ cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - // fill command only valid in re-circulate mode - if ( ( DG_MODE_CIRC == getCurrentOperationMode() ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getCurrentRecirculateState() ) ) + // fill command only valid in generation idle mode + if ( ( DG_MODE_GENE == getCurrentOperationMode() ) && + ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getCurrentGenIdleState() ) ) { // validate parameters if ( fillToVolMl < MAX_FILL_VOLUME_ML ) @@ -291,7 +281,7 @@ * @brief * The stopFillCmd function handles a stop fill command from the HD. * @details Inputs: none - * @details Outputs: move to re-circulate mode + * @details Outputs: move to generation idle mode * @return none *************************************************************************/ void stopFillCmd( void ) @@ -306,7 +296,7 @@ if ( DG_MODE_FILL == getCurrentOperationMode() ) { fillVolumeTargetMl.data = 0; - requestNewOperationMode( DG_MODE_CIRC ); + requestNewOperationMode( DG_MODE_GENE ); cmdResponse.rejected = FALSE; } else @@ -321,7 +311,7 @@ * @brief * The startDrainCmd function handles a drain command from the HD. * @details Inputs: none - * @details Outputs: Start draining in re-circulate mode + * @details Outputs: Start draining in generation idle mode * @param drainCmd drain command data record * @return none *************************************************************************/ @@ -333,8 +323,8 @@ cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - // drain command only valid in re-circulate mode - if ( DG_MODE_CIRC == getCurrentOperationMode() ) + // drain command only valid in generation idle mode + if ( DG_MODE_GENE == getCurrentOperationMode() ) { // validate parameters if ( drainCmd.targetVolume <= MAX_DRAIN_VOLUME_ML ) @@ -361,7 +351,7 @@ * @brief * The stopDrainCmd function handles a stop drain command from the HD. * @details Inputs: none - * @details Outputs: move to re-circulate mode + * @details Outputs: move to generation idle mode * @return none *************************************************************************/ void stopDrainCmd( void ) @@ -376,7 +366,7 @@ if ( DG_MODE_DRAI == getCurrentOperationMode() ) { drainVolumeTargetMl.data = 0; - requestNewOperationMode( DG_MODE_CIRC ); + requestNewOperationMode( DG_MODE_GENE ); cmdResponse.rejected = FALSE; } else @@ -434,16 +424,16 @@ /*********************************************************************//** * @brief - * The getReservoirWeight function returns the large filtered weight + * The getReservoirWeight function returns the small filtered weight * of the reservoir's associated load cell. * @details Inputs: associatedLoadCell[] * @details Outputs: none * @param reservoirId id of reservoir to get weight from - * @return large filtered weight + * @return small filtered weight *************************************************************************/ F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ) { - return getLoadCellLargeFilteredWeight( associatedLoadCell[ reservoirId ] ); + return getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); } /*********************************************************************//** @@ -533,11 +523,17 @@ *************************************************************************/ void tareLoadCellsAtEmpty( DG_RESERVOIR_ID_T reservoirId ) { + U32 const targetDrainVolume = getReservoirDrainVolumeTargetMl(); + if ( TRUE == tareLoadCellRequest ) { tareLoadCellRequest = FALSE; - tareLoadCell( associatedLoadCell[ reservoirId ] ); - tareLoadCell( redundantLoadCell[ reservoirId ] ); + + if ( MIN_RESERVOIR_VOLUME_ML == targetDrainVolume ) + { + tareLoadCell( associatedLoadCell[ reservoirId ] ); + tareLoadCell( redundantLoadCell[ reservoirId ] ); + } } } Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r037f0edb0b880130563058c809ba50308f2a63e9 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 037f0edb0b880130563058c809ba50308f2a63e9) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -20,6 +20,7 @@ #include "DGCommon.h" #include "DGDefs.h" +#include "NVDataMgmt.h" /** * @defgroup Reservoirs Reservoirs @@ -70,8 +71,10 @@ // ********** public function prototypes ********** void initReservoirs( void ); -void execReservoirs( void ); +void execReservoirs( void ); +SELF_TEST_STATUS_T execReservoirsSelfTest( void ); + void setActiveReservoirCmd( DG_RESERVOIR_ID_T resID ); // handle switch reservoirs command from HD void changeValveSettingCmd( DG_VALVE_SETTING_ID_T valveSettingID ); // handle valve setting change command from HD void startFillCmd( U32 fillToVolMl ); // handle fill command from HD @@ -84,6 +87,8 @@ DG_RESERVOIR_ID_T getInactiveReservoir( void ); F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ); + +DG_RESERVOIR_VOLUME_RECORD_T getReservoirsCalRecord( void ); BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ); BOOL hasTargetDrainVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId, U32 timeout ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r3ca2e68a33885153648ba20346e3548438b58724 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 3ca2e68a33885153648ba20346e3548438b58724) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -25,8 +25,8 @@ #include "FPGA.h" #include "Heaters.h" #include "ModeFlush.h" +#include "ModeGenIdle.h" #include "ModeStandby.h" -#include "ModeRecirculate.h" #include "MsgQueues.h" #include "NVDataMgmt.h" #include "OperationModes.h" @@ -1572,11 +1572,11 @@ memcpy( &startingTreatment, message->payload, sizeof( U32 ) ); - if ( DG_MODE_STAN == getCurrentOperationMode() && TRUE == startingTreatment ) + if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( TRUE == startingTreatment ) ) { result = requestDGStart(); } - else if ( DG_MODE_CIRC == getCurrentOperationMode() && FALSE == startingTreatment ) + else if ( ( DG_MODE_GENE == getCurrentOperationMode() ) && ( FALSE == startingTreatment ) ) { result = requestDGStop(); } Index: firmware/App/Services/WatchdogMgmt.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -re6f3a632890f96a5aa282922d11df148bdd06587 --- firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) @@ -167,7 +167,7 @@ } else { - activateAlarmNoData( ALARM_ID_WATCHDOG_POST_TEST_FAILED ); + activateAlarmNoData( ALARM_ID_DG_WATCHDOG_POST_TEST_FAILED ); watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; } watchdogSelfTestTimerCount = getMSTimerCount();