/************************************************************************** * * Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ConcentratePumps.c * * @author (last) Dara Navaei * @date (last) 04-Aug-2022 * * @author (original) Quang Nguyen * @date (original) 22-Oct-2020 * ***************************************************************************/ #include #include "ConcentratePumps.h" #include "FPGA.h" #include "MessageSupport.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" /** * @addtogroup ConcentratePumps * @{ */ // ********** private definitions ********** #define CONCENTRATE_PUMP_ON_CONTROL 0x1A ///< Configuration to turn on concentrate pump with 8 microsteps. #define CONCENTRATE_PUMP_OFF_CONTROL 0x3A ///< Configuration to turn off concentrate pump. #define CONCENTRATE_PUMP_FORWARD_DIR 0x1 ///< Concentrate pump forward direction configuration. #define CONCENTRATE_PUMP_REVERSE_DIR 0x0 ///< Concentrate pump reverse direction configuration. #define CONCENTRATE_PUMP_SPEED_INCREMENT 2.0F ///< Speed increase (mL/min) when controlling concentrate pump to target step speed. #define CONCENTRATE_PUMP_MIN_SPEED 3.0F ///< Minimum speed for concentrate pump in mL per min. #define CONCENTRATE_PUMP_ERROR_TOLERANCE 0.02F ///< 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.1F ///< Volume output every revolution (mL). #define CONCENTRATE_PUMP_PULSE_PER_REV 2.0F ///< Number of pulses generate for every revolution. #define CONCENTRATE_PUMP_STEP_PER_REV 200.0F ///< Number of steps for every revolution. #define CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION 100.0F ///< Hall sense period resolution in microseconds. #define CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT 1000 ///< Hall sensors minimum allowed value. #define CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS ( 5 * MS_PER_SECOND ) ///< Hall sensors out of range time in milliseconds. #define CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP 8.0F ///< Number of micro-steps ( fractions of step) per step. #define CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION ( 0.5F / ( US_PER_SECOND * SEC_PER_MIN ) ) ///< Convert step period resolution (0.5 us) to minute. /// Volume output per pulse. #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 ( 1 * MS_PER_SECOND / 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. #define NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK 1 ///< Number of acid and bicarb non-volatile data to check. #define DATA_PUBLISH_COUNTER_START_COUNT 0 ///< Data publish counter start count. /*************************DVT Definitions********************************************/ #define CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP 0x07 ///< Concentrate pump control 1/8th step. #define CONCENTRATE_PUMP_CONTROL_REVERSE_DIR 0x08 ///< Concentrate pump control reverse direction. #define CONCENTRATE_PUMP_CONTROL_FORWARD_DIR 0x00 ///< Concentrate pump control forward direction. #define CONCENTRATE_PUMP_CONTROL_ENABLE 0x00 ///< Concentrate pump control enable pump. #define CONCENTRATE_PUMP_CONTROL_NOT_RESET 0x20 ///< Concentrate pump control not reset. #define CONCENTRATE_PUMP_CONTROL_SLEEP_OFF 0x40 ///< Concentrate pump control sleep off. static const U32 CONCENTRATE_PUMP_CONTROL_FORWARD = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | CONCENTRATE_PUMP_CONTROL_NOT_RESET | CONCENTRATE_PUMP_CONTROL_ENABLE | CONCENTRATE_PUMP_CONTROL_FORWARD_DIR | CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control forward. static const U32 CONCENTRATE_PUMP_CONTROL_REVERSE = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | CONCENTRATE_PUMP_CONTROL_NOT_RESET | CONCENTRATE_PUMP_CONTROL_ENABLE | CONCENTRATE_PUMP_CONTROL_REVERSE_DIR | CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control reverse. /*************************DVT Definitions********************************************/ /// Enumeration of concentrate pump states. typedef enum ConcentratePumpState { CONCENTRATE_PUMP_OFF_STATE = 0, ///< Concentrate pump off state. CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE, ///< Concentrate pump ramp to target state. CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE, ///< Concentrate pump on state. NUM_OF_CONCENTRATE_PUMP_STATES ///< Number of concentrate pump states. } CONCENTRATE_PUMP_STATE_T; /// Concentrate pump data structure typedef struct { U32 controlTimerCounter; ///< Timer counter to perform control on concentrate pump. CONCENTRATE_PUMP_STATE_T execState; ///< Concentrate pump execute current state. BOOL hasTurnOnPumpsBeenRequested; ///< Flag indicates a request to turn concentrate pumps on. F32 pumpTargetSpeed; ///< Target concentrate pumps' speed (mL/min). F32 currentPumpSpeed; ///< Current controlled concentrate pumps' speed (mL/min). OVERRIDE_F32_T measuredPumpSpeed; ///< Measured concentrate pump speed (mL/min). U16 togglePeriodCount; ///< Converted pump speed (mL/min) to toggle period counts (0.5 uS increment counts per step). U08 direction; ///< Concentrate pump motor direction. U08 controlSet; ///< Concentrate pump control set. (Used in DVT) F32 pulseWidthUS; ///< Concentrate pump pulse width in microseconds. } CONCENTRATE_PUMP_T; // ********** private data ********** static U32 concentratePumpMonitorTimerCounter; ///< Timer counter to perform monitor on concentrate pump. /// Concentrate pump data publish interval. static OVERRIDE_U32_T concentratePumpDataPublishInterval = { CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, 0, 0 }; static CONCENTRATE_PUMP_T concentratePumps[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Array of concentrate pumps' data structure. static DG_ACID_CONCENTRATES_RECORD_T acidConcentrateCalRecord; ///< Acid concentrate calibration record. static DG_BICARB_CONCENTRATES_RECORD_T bicarbConcentrateCalRecord; ///< Bicarb concentrate calibration record. static DG_CONC_PUMPS_CAL_RECORD_T concentratePumpsCalRecord; ///< Concentrate pumps calibration record. // ********** private function prototypes ********** static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpRampToTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ); static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ); static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ); /*********************************************************************//** * @brief * The initConcentratePump function initializes the ConcentratePumps module. * @details Inputs: none * @details Outputs: ConcentratePumps module initialized * @return none *************************************************************************/ void initConcentratePump( void ) { CONCENTRATE_PUMPS_T pumpId; concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { concentratePumps[ pumpId ].controlTimerCounter = 0; concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT stopConcentratePump( pumpId ); } initPersistentAlarm( ALARM_ID_CP1_SPEED_CONTROL_ERROR, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_CP2_SPEED_CONTROL_ERROR, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS, CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS ); } /*********************************************************************//** * @brief * The execConcentratePumpMonitor function executes the concentrate pump monitor. * @details Inputs: none * @details Outputs: publish concentrate pump data * @return none *************************************************************************/ void execConcentratePumpMonitor( void ) { // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) { // Get the calibration values of acid and bicarb getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( acidConcentrateCalRecord ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( bicarbConcentrateCalRecord ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); } if ( ++concentratePumpMonitorTimerCounter >= getU32OverrideValue( &concentratePumpDataPublishInterval ) ) { CONCENTRATE_PUMP_DATA_T data; U08 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() ); U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); // Use the above values to prepare the broadcast data data.cp1CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1SetSpeed * -1.0 : cp1SetSpeed ); data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0 : cp2SetSpeed ); data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); data.cp1State = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].execState; data.cp2State = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].execState; data.cp1PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pulseWidthUS; data.cp2PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].pulseWidthUS; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS_SPEED_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { monitorPumpSpeed( CONCENTRATEPUMPS_CP1_ACID, ALARM_ID_CP1_SPEED_CONTROL_ERROR ); monitorPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB, ALARM_ID_CP2_SPEED_CONTROL_ERROR ); } concentratePumpMonitorTimerCounter = 0; broadcastData( MSG_ID_DG_CONCENTRATE_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( CONCENTRATE_PUMP_DATA_T ) ); } } /*********************************************************************//** * @brief * The execConcentratePumpController function executes the concentrate pump controller. * @details Inputs: execState * @details Outputs: execState * @return none *************************************************************************/ void execConcentratePumpController( void ) { CONCENTRATE_PUMPS_T pumpId; for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { switch ( concentratePumps[ pumpId ].execState ) { case CONCENTRATE_PUMP_OFF_STATE: concentratePumps[ pumpId ].execState = handleConcentratePumpOffState( pumpId ); break; case CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE: concentratePumps[ pumpId ].execState = handleConcentratePumpRampToTargetSpeedState( pumpId ); break; case CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE: concentratePumps[ pumpId ].execState = handleConcentratePumpControlTargetSpeedState( pumpId ); break; #ifndef _VECTORCAST_ // The switch case is in a for loop so the default case cannot be covered in VectorCAST default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, pumpId ) concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; break; #endif } } } /*********************************************************************//** * @brief * The execConcenratePumpsSelfTest function executes the concentrate pumps * self-test. * @details Inputs: none * @details Outputs: none * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) *************************************************************************/ SELF_TEST_STATUS_T execConcenratePumpsSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; BOOL calStatus = FALSE; calStatus |= getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( DG_ACID_CONCENTRATES_RECORD_T ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); calStatus |= getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( DG_BICARB_CONCENTRATES_RECORD_T ), NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); calStatus |= getNVRecord2Driver( GET_CAL_CONCENTRATE_PUMPS_RECORD, (U08*)&concentratePumpsCalRecord, sizeof( DG_CONC_PUMPS_CAL_RECORD_T ), NUM_OF_CAL_DATA_DG_CONC_PUMPS, ALARM_ID_NO_ALARM ); result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); return result; } /*********************************************************************//** * @brief * The requestConcentratePumpOn function requests the module to turn on * the concentrate pumps. * @details Inputs: none * @details Outputs: set flag isPumpOnRequested to TRUE * @param pumpId concentrate pump id * @return none *************************************************************************/ void requestConcentratePumpOn( CONCENTRATE_PUMPS_T pumpId ) { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS ) != SW_CONFIG_ENABLE_VALUE ) #endif { concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } } /*********************************************************************//** * @brief * The requestConcentratePumpOff function requests the module to turn off * the concentrate pumps. * @details Inputs: none * @details Outputs: set flag isPumpOffRequested to TRUE * @param pumpId concentrate pump id * @return none *************************************************************************/ void requestConcentratePumpOff( CONCENTRATE_PUMPS_T pumpId ) { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } } /*********************************************************************//** * @brief * The setConcentratePumpTargetSpeed function sets the target step speed based on * given speed in mL/min to specified concentrate pump. * @details Inputs: none * @details Outputs: set target step speed for given pump * @param pumpId pump id to set step speed * @param targetSpeed_ml_min target speed in mL/min * @return none *************************************************************************/ void setConcentratePumpTargetSpeed( CONCENTRATE_PUMPS_T pumpId, F32 targetSpeed_ml_min ) { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { if ( targetSpeed_ml_min >= 0.0 ) { concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT } else { concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; // For V3 concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_REVERSE; // For DV targetSpeed_ml_min *= -1.0; } if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) { concentratePumps[ pumpId ].pumpTargetSpeed = targetSpeed_ml_min; } else if ( targetSpeed_ml_min < CONCENTRATE_PUMP_MIN_SPEED ) { concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } else if ( targetSpeed_ml_min > CONCENTRATE_PUMP_MAX_SPEED ) { concentratePumps[ pumpId ].pumpTargetSpeed = CONCENTRATE_PUMP_MAX_SPEED; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } } /*********************************************************************//** * @brief * The getConcentratePumpTargetFlowMLPM function returns the concentrate pump's * flow rate in mL/min. * @details Inputs: concentratePumps * @details Outputs: none * @param pumpId concentrate pump id to get its target flow * @return the current concentrate pump flow rate (in mL/min). *************************************************************************/ F32 getConcentratePumpTargetFlowMLPM( CONCENTRATE_PUMPS_T pumpId ) { F32 flow = 0.0; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { flow = concentratePumps[ pumpId ].pumpTargetSpeed; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } return flow; } /*********************************************************************//** * @brief * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. * @details Inputs: measuredPumpSpeed * @details Outputs: none * @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 speed = 0.0; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { speed = getF32OverrideValue( &concentratePumps[ pumpId ].measuredPumpSpeed ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } return speed; } /*********************************************************************//** * @brief * The getAcidConcentrateCalRecord function returns the acid concentrate * calibration record. * @details Inputs: none * @details Outputs: acidConcentrateCalRecord * @return acid concentrate calibration record *************************************************************************/ DG_ACID_CONCENTRATES_RECORD_T getAcidConcentrateCalRecord( void ) { return acidConcentrateCalRecord; } /*********************************************************************//** * @brief * The getBicarbConcentrateCalRecord function returns the bicarb * concentrate calibration record. * @details Inputs: none * @details Outputs: bicarbConcentrateCalRecord * @return bicarb concentrate calibration record *************************************************************************/ DG_BICARB_CONCENTRATES_RECORD_T getBicarbConcentrateCalRecord( void ) { return bicarbConcentrateCalRecord; } /*********************************************************************//** * @brief * The stopConcentratePump function sets the concentrate pump step speed * to zero and turns off concentrate pumps. * @details Inputs: none * @details Outputs: targetPumpSpeed[], currentPumpSpeed[], turn * concentrate pumps off * @param pumpId concentrate pump id * @return none *************************************************************************/ static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ) { concentratePumps[ pumpId ].currentPumpSpeed = 0.0; concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) { if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) { setFPGAV3AcidPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); } else { setFPGAV3BicarbPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); } } #endif if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) { setFPGAAcidPumpSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); } else { setFPGABicarbSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); } } /*********************************************************************//** * @brief * The handleConcentratePumpOffState function turns on concentrate pumps and * switch to on state upon request. * @details Inputs: none * @details Outputs: concentrate pumps turn on * @param pumpId concentrate pump id * @return state *************************************************************************/ static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_OFF_STATE; if ( TRUE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { U08 controlSet = 0; #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) { controlSet = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAV3AcidPumpControl( controlSet ) : setFPGAV3BicarbPumpControl( controlSet ); } else #endif { controlSet = concentratePumps[ pumpId ].controlSet; CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpControl( controlSet ) : setFPGABicarbPumpControl( controlSet ); } state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; } return state; } /*********************************************************************//** * @brief * The handleConcentratePumpRampToTargetSpeedState function executes the * concentrate pump ramp up to target speed state. Once the speed is close * to target the state is transitioned to control target state. * @details Inputs: none * @details Outputs: none * @param pumpId concentrate pump id * @return next state of the state machine *************************************************************************/ static CONCENTRATE_PUMP_STATE_T handleConcentratePumpRampToTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; if ( TRUE == stepConcentratePumpToTargetSpeed( pumpId ) ) { state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; } return state; } /*********************************************************************//** * @brief * The handleConcentratePumpControlTargetSpeedState function turns off concentrate * pumps switch to off state upon request. While in on state, the function * controls concentrate pumps to a target step speed. * @details Inputs: currentPumpSpeed[] * @details Outputs: control concentrate pumps to target step speed * @param pumpId concentrate pump id * @return state *************************************************************************/ static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) { concentratePumps[ pumpId ].controlTimerCounter = 0; stepConcentratePumpToTargetSpeed( pumpId ); } if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { state = CONCENTRATE_PUMP_OFF_STATE; stopConcentratePump( pumpId ); } return state; } /*********************************************************************//** * @brief * The stepConcentratePumpToTargetSpeed function steps current step speed * toward target speed with predefined step increase. * @details Inputs: none * @details Outputs: currentPumpSpeed[] * @param pumpId concentrate pump id to increase current step speed * @return TRUE if the pump has reached to target otherwise, FALSE *************************************************************************/ static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ) { F32 speedIncrease; BOOL hasTgtBeenReached = FALSE; F32 currentToTargetDiff = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); if ( currentToTargetDiff > NEARLY_ZERO ) { if ( currentToTargetDiff > CONCENTRATE_PUMP_SPEED_INCREMENT ) { speedIncrease = CONCENTRATE_PUMP_SPEED_INCREMENT; } else { speedIncrease = currentToTargetDiff; hasTgtBeenReached = TRUE; } // Subtract current speed when target speed is smaller if ( concentratePumps[ pumpId ].pumpTargetSpeed < concentratePumps[ pumpId ].currentPumpSpeed ) { speedIncrease *= -1.0; } concentratePumps[ pumpId ].currentPumpSpeed += speedIncrease; } if ( concentratePumps[ pumpId ].currentPumpSpeed > NEARLY_ZERO ) { F32 timePerStep = CONCENTRATE_PUMP_VOLUME_PER_REV / ( concentratePumps[ pumpId ].currentPumpSpeed * CONCENTRATE_PUMP_STEP_PER_REV ); F32 stepPeriodCounts = timePerStep / ( CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION * CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ); concentratePumps[ pumpId ].togglePeriodCount = (U16)( stepPeriodCounts + FLOAT_TO_INT_ROUNDUP_OFFSET ); } else { concentratePumps[ pumpId ].togglePeriodCount = CONCENTRATE_PUMP_ZERO_FLOW_RATE; } CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ) : setFPGABicarbSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); return hasTgtBeenReached; } /*********************************************************************//** * @brief * The calcMeasuredPumpsSpeed function calculates the concentrate pump flow * rate using the hall sense pulse width count. * @details Inputs: none * @details Outputs: measuredPumpSpeed * @param pumpId concentrate pump id to increase current step speed * @param pulseWidthCount hall sense pulse width count reading from FPGA * @return none *************************************************************************/ static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ) { F32 pulseWidthInMicroSeconds = (F32)pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; BOOL isPulseWidthOut = ( pulseWidthInMicroSeconds <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); concentratePumps[ pumpId ].pulseWidthUS = pulseWidthInMicroSeconds; checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pulseWidthInMicroSeconds, CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); if ( FALSE == isPulseWidthOut ) { concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; } else if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) { concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; } } /*********************************************************************//** * @brief * The monitorPumpSpeed function monitors the concentrate pumps speed and * triggers the alarms if they are out of range. * @details Inputs: concentratePumps * @details Outputs: none * @param pumpId pump id to set step speed * @param alarm which the corresponding alarm of the concentrate pump * @return none *************************************************************************/ static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ) { F32 cpTargetSpeed = concentratePumps[ pumpId ].pumpTargetSpeed; F32 cpError = fabs( getMeasuredPumpSpeed( pumpId ) - cpTargetSpeed ); BOOL isCpSpeedOut = FALSE; if ( concentratePumps[ pumpId ].execState != CONCENTRATE_PUMP_OFF_STATE ) { // Check if the pump is not in the off state and if it is not, divide the error // to target speed. If the pump is off the target speed is 0 cpError = cpError / cpTargetSpeed; } isCpSpeedOut = ( cpError > CONCENTRATE_PUMP_ERROR_TOLERANCE ? TRUE : FALSE ); checkPersistentAlarm( alarm, isCpSpeedOut, cpError, CONCENTRATE_PUMP_ERROR_TOLERANCE ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetConcentratePumpDataPublishIntervalOverride function overrides the * concentrate pump data publish interval. * @details Inputs: none * @details Outputs: concentratePumpDataPublishInterval * @param value override concentrate pump data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConcentratePumpDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; concentratePumpDataPublishInterval.ovData = intvl; concentratePumpDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetConcentratePumpDataPublishIntervalOverride function resets the * override of the concentrate pump data publish interval. * @details Inputs: none * @details Outputs: concentratePumpDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetConcentratePumpDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; concentratePumpDataPublishInterval.override = OVERRIDE_RESET; concentratePumpDataPublishInterval.ovData = concentratePumpDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetConcentratePumpTargetSpeedOverride function overrides the target * speed value of given concentrate pump id. * @details Inputs: none * @details Outputs: targetPumpSpeed[] * @param pumpId concentrate pump id * @param value override concentrate pump target speed * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConcentratePumpTargetSpeedOverride( U32 pumpId, F32 value ) { BOOL result = FALSE; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS && isTestingActivated() ) { F32 const absSpeed = fabs( value ); if ( absSpeed <= CONCENTRATE_PUMP_MAX_SPEED ) { result = TRUE; setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, value ); } } return result; } /*********************************************************************//** * @brief * The testSetConcentratePumpMeasuredSpeedOverride function overrides the * measured speed value of given concentrate pump id. * @details Inputs: none * @details Outputs: measuredPumpSpeed[] * @param pumpId concentrate pump id * @param value override concentrate pump measured speed * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConcentratePumpMeasuredSpeedOverride( U32 pumpId, F32 value ) { BOOL result = FALSE; if ( ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) && isTestingActivated() ) { result = TRUE; concentratePumps[ pumpId ].measuredPumpSpeed.ovData = value; concentratePumps[ pumpId ].measuredPumpSpeed.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetConcentratePumpMeasuredSpeedOverride function resets the * measured speed value of given concentrate pump id. * @details Inputs: none * @details Outputs: measuredPumpSpeed[] * @param pumpId concentrate pump id * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetConcentratePumpMeasuredSpeedOverride( U32 pumpId ) { BOOL result = FALSE; if ( ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) && isTestingActivated() ) { result = TRUE; concentratePumps[ pumpId ].measuredPumpSpeed.ovData = 0.0; concentratePumps[ pumpId ].measuredPumpSpeed.override = OVERRIDE_RESET; } return result; } /**@}*/