Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -rb8351b8ec0177ef7a10dea88b3eb830bb513bc41 -r7d0fd5ed6b9db0479af90477e5108f6d3fa8df17 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision b8351b8ec0177ef7a10dea88b3eb830bb513bc41) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 7d0fd5ed6b9db0479af90477e5108f6d3fa8df17) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2024 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) 24-Jan-2023 +* @date (last) 09-Apr-2024 * * @author (original) Quang Nguyen * @date (original) 22-Oct-2020 @@ -19,6 +19,7 @@ #include "ConcentratePumps.h" #include "FPGA.h" #include "MessageSupport.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -39,7 +40,9 @@ #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_SPD_OUT_OF_RANGE_TOL_WHEN_ON_PCT 0.02F ///< Concentrate pump speed out of range tolerance when on in percentage. +#define CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_SLOW_MLPM 1.0F ///< Concentrate pump speed out of range tolerance when slow in mL/min. +#define CONCENTRATE_PUMP_LOW_SPEED_THRESHOLD_MLPM 10.0F ///< Concentrate pump low speed threshold in mL/min. #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). @@ -55,16 +58,16 @@ /// 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_DATA_PUBLISH_INTERVAL ( 1000 / 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 CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Concentrate pumps speed out of range timeout in milliseconds. #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. -#define CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Concentrate pump park fault timeout in milliseconds. #define CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD 500 ///< Concentrate pump fault persistence period in milliseconds. +#define CONCENTRATE_PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD_MLPM 5.0F ///< Concentrate pump transition to ramp to target speed threshold in mL/min. /*************************DVT Definitions********************************************/ @@ -115,11 +118,14 @@ F32 pulseWidthUS; ///< Concentrate pump pulse width in microseconds. OVERRIDE_U32_T parked; ///< Concentrate pump is currently parked (T/F). OVERRIDE_U32_T parkFaulted; ///< Concentrate pump park command has faulted (T/F). + BOOL isConcPumpParkInProgress; ///< Concentrate pump park progress boolean flag (T/F). } CONCENTRATE_PUMP_T; // ********** private data ********** static U32 concentratePumpMonitorTimerCounter; ///< Timer counter to perform monitor on concentrate pump. +static BOOL acidConcentratePumpParkPersistenceClear; ///< Boolean acid park persistence clearing. +static BOOL bicarbConcentratePumpParkPersistenceClear; ///< Boolean for bicard park persistence clearing. /// Concentrate pump data publish interval. static OVERRIDE_U32_T concentratePumpDataPublishInterval = { CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, 0, 0 }; @@ -136,8 +142,9 @@ 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 calcMeasuredPumpsSpeed( void ); static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ); +static void checkConcentratePumpControlSet( CONCENTRATE_PUMPS_T pumpId ); /*********************************************************************//** * @brief @@ -150,9 +157,11 @@ { CONCENTRATE_PUMPS_T pumpId; - concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + acidConcentratePumpParkPersistenceClear = FALSE; + bicarbConcentratePumpParkPersistenceClear = FALSE; - for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) + for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; pumpId++ ) { concentratePumps[ pumpId ].controlTimerCounter = 0; concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; @@ -164,16 +173,14 @@ concentratePumps[ pumpId ].pumpTargetSpeed = 0.0F; concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT + concentratePumps[ pumpId ].isConcPumpParkInProgress = FALSE; 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_CP1_SPEED_CONTROL_ERROR, 0, CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CP2_SPEED_CONTROL_ERROR, 0, CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ); 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 ); - initPersistentAlarm( ALARM_ID_DG_ACID_CONCENTRATE_PUMP_PARK_FAULT, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_DG_BICARB_CONCENTRATE_PUMP_PARK_FAULT, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD ); - } /*********************************************************************//** @@ -185,8 +192,8 @@ *************************************************************************/ void execConcentratePumpMonitor( void ) { - U08 fpgaConcPumpsFault = getFPGAConcentratePumpsFault(); - BOOL isConcPumpFault = ( fpgaConcPumpsFault > 0 ? TRUE : FALSE ); + U08 fpgaConcPumpsFault = getFPGAConcentratePumpsFault(); + BOOL isConcPumpFault = ( fpgaConcPumpsFault > 0 ? TRUE : FALSE ); // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) @@ -198,57 +205,80 @@ NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); } - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2_BICARB, getFPGACP2HallSensePulseWidth() ); + // Calculate pump speed for each defined pump + calcMeasuredPumpsSpeed(); concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].parked.data = (U32)getFPGAAcidPumpIsParked(); concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].parked.data = (U32)getFPGABicarbPumpIsParked(); concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].parkFaulted.data = (U32)getFPGAAcidPumpParkFault(); concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].parkFaulted.data = (U32)getFPGABicarbPumpParkFault(); -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS_SPEED_ALARM ) != SW_CONFIG_ENABLE_VALUE ) -#endif + if ( ( TRUE == getConcPumpIsParked( CONCENTRATEPUMPS_CP1_ACID ) ) || ( TRUE == getConcPumpParkIsFaulted( CONCENTRATEPUMPS_CP1_ACID ) ) ) { - monitorPumpSpeed( CONCENTRATEPUMPS_CP1_ACID, ALARM_ID_CP1_SPEED_CONTROL_ERROR ); - monitorPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB, ALARM_ID_CP2_SPEED_CONTROL_ERROR ); + // If the pump has parked or faulted during the park, then it is not in progress + concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].isConcPumpParkInProgress = FALSE; } + if ( ( TRUE == getConcPumpIsParked( CONCENTRATEPUMPS_CP2_BICARB ) ) || ( TRUE == getConcPumpParkIsFaulted( CONCENTRATEPUMPS_CP2_BICARB ) ) ) + { + concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].isConcPumpParkInProgress = FALSE; + } + // Don't monitor persistence for cp speed alarms if we parked. + if ( TRUE == acidConcentratePumpParkPersistenceClear ) + { + // Clear flag and resume persistence checking once park bit is set. + if ( TRUE == getConcPumpIsParked( CONCENTRATEPUMPS_CP1_ACID ) ) + { + acidConcentratePumpParkPersistenceClear = FALSE; + } + else + { + resetPersistentAlarmTimer( ALARM_ID_DG_CP1_SPEED_CONTROL_ERROR ); + } + } + + if ( TRUE == bicarbConcentratePumpParkPersistenceClear ) + { + // Clear flag and resume persistence checking once park bit is set. + if ( TRUE == getConcPumpIsParked( CONCENTRATEPUMPS_CP2_BICARB ) ) + { + bicarbConcentratePumpParkPersistenceClear = FALSE; + } + else + { + resetPersistentAlarmTimer( ALARM_ID_DG_CP2_SPEED_CONTROL_ERROR ); + } + } + + #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONCENTRATE_PUMPS_PARK ) != SW_CONFIG_ENABLE_VALUE ) + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS_SPEED_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - BOOL isAcidPumpParked = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); - BOOL isBicarbPumpParked = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - - checkPersistentAlarm( ALARM_ID_DG_ACID_CONCENTRATE_PUMP_PARK_FAULT, isAcidPumpParked, isAcidPumpParked, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS ); - checkPersistentAlarm( ALARM_ID_DG_BICARB_CONCENTRATE_PUMP_PARK_FAULT, isBicarbPumpParked, isBicarbPumpParked, CONENTREATE_PUMP_PARK_FAULT_TIMEOUT_MS ); + monitorPumpSpeed( CONCENTRATEPUMPS_CP1_ACID, ALARM_ID_DG_CP1_SPEED_CONTROL_ERROR ); + monitorPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB, ALARM_ID_DG_CP2_SPEED_CONTROL_ERROR ); } - checkPersistentAlarm(ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, isConcPumpFault , fpgaConcPumpsFault, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD ); + checkPersistentAlarm( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, isConcPumpFault, fpgaConcPumpsFault, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD ); if ( ++concentratePumpMonitorTimerCounter >= getU32OverrideValue( &concentratePumpDataPublishInterval ) ) { CONCENTRATE_PUMP_DATA_T data; - U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; - F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; - F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); - F32 cp1TgtSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pumpTargetSpeed; - BOOL cp1Parked = getConcPumpIsParked( CONCENTRATEPUMPS_CP1_ACID ); - BOOL cp2ParkFault = getConcPumpParkIsFaulted( CONCENTRATEPUMPS_CP1_ACID ); - U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; - F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; - F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - F32 cp2TgtSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].pumpTargetSpeed; + U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; + F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; + F32 cp1TgtSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pumpTargetSpeed; + U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; + F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; + F32 cp2TgtSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].pumpTargetSpeed; // 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.cp1TargetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1TgtSpeed * -1.0 : cp1TgtSpeed ); - data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0 : cp2SetSpeed ); - data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); - data.cp2TargetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2TgtSpeed * -1.0 : cp2TgtSpeed ); + data.cp1CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1SetSpeed * -1.0F : cp1SetSpeed ); + data.cp1MeasuredSpeed = getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP1_ACID ); + data.cp1TargetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1TgtSpeed * -1.0F : cp1TgtSpeed ); + data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0F : cp2SetSpeed ); + data.cp2MeasuredSpeed = getMeasuredPumpSpeedMLPM( CONCENTRATEPUMPS_CP2_BICARB ); + data.cp2TargetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2TgtSpeed * -1.0F : cp2TgtSpeed ); data.cp1State = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].execState; data.cp2State = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].execState; data.cp1PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pulseWidthUS; @@ -274,7 +304,7 @@ { CONCENTRATE_PUMPS_T pumpId; - for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) + for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; pumpId++ ) { switch ( concentratePumps[ pumpId ].execState ) { @@ -346,6 +376,8 @@ #endif { concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; + acidConcentratePumpParkPersistenceClear = FALSE; + bicarbConcentratePumpParkPersistenceClear = FALSE; } } else @@ -356,6 +388,72 @@ /*********************************************************************//** * @brief + * The handleConcentratePumpParkRequest function accepts/rejects the park + * concentrate pumps request. + * @details Inputs: Pump state and DG operating mode + * @details Outputs: command response set to true if able to perform parking pump. + * @return result as true if park is accomplished. + *************************************************************************/ +BOOL handleConcentratePumpParkRequest( void ) +{ + DG_CMD_RESPONSE_T cmdResponse; + BOOL result = FALSE; + DG_OP_MODE_T opMode = getCurrentOperationMode(); + + cmdResponse.commandID = DG_CMD_PARK_CONCENTRATE_PUMPS; + cmdResponse.rejected = FALSE; + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + + // pumps should be not ON and DG operation mode is not in filling and fault mode + if ( ( concentratePumps[CONCENTRATEPUMPS_CP1_ACID].execState == CONCENTRATE_PUMP_OFF_STATE ) && + ( concentratePumps[CONCENTRATEPUMPS_CP2_BICARB].execState == CONCENTRATE_PUMP_OFF_STATE ) && + ( DG_MODE_FILL != opMode ) && + ( DG_MODE_FAUL != opMode ) ) + { + // Park concentrate pump + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, PARK_CONC_PUMPS ); + result = TRUE; + } + else + { + cmdResponse.rejected = TRUE; + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; + result = FALSE; + } + + sendCommandResponseMsg( &cmdResponse ); + + return result; +} + +/*********************************************************************//** + * @brief + * The isConcPumpParkInProgress function requests whether the concentrate + * pump park is in progress or not. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId concentrate pump id + * @return TRUE if the concentrate pump park is in progress otherwise, FALSE + *************************************************************************/ +BOOL isConcPumpParkInProgress( CONCENTRATE_PUMPS_T pumpId ) +{ + BOOL status = FALSE; + + if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) + { + status = concentratePumps[ pumpId ].isConcPumpParkInProgress; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return status; +} + +/*********************************************************************//** + * @brief * The requestConcentratePumpOff function requests the module to turn off * the concentrate pumps. * @details Inputs: none @@ -404,6 +502,11 @@ targetSpeed_ml_min *= -1.0; } + /* + * If 3 <= speed <= 48 set it + * If speed < 3 set to 0 + * else speed > 48 set to 48 + */ if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) { concentratePumps[ pumpId ].pumpTargetSpeed = targetSpeed_ml_min; @@ -412,7 +515,7 @@ { concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } - else if ( targetSpeed_ml_min > CONCENTRATE_PUMP_MAX_SPEED ) + else { concentratePumps[ pumpId ].pumpTargetSpeed = CONCENTRATE_PUMP_MAX_SPEED; } @@ -450,19 +553,20 @@ /*********************************************************************//** * @brief - * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. + * The getMeasuredPumpSpeedMLPM 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 getMeasuredPumpSpeedMLPM( CONCENTRATE_PUMPS_T pumpId ) { - F32 speed = 0.0; + F32 speed = 0.0F; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { speed = getF32OverrideValue( &concentratePumps[ pumpId ].measuredPumpSpeed ); + speed = ( CONCENTRATE_PUMP_REVERSE_DIR == concentratePumps[ pumpId ].direction ? speed * -1.0F : speed ); } else { @@ -574,10 +678,12 @@ if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) { setFPGAV3AcidPumpParkCmd(); + acidConcentratePumpParkPersistenceClear = TRUE; } else { setFPGAV3BicarbPumpParkCmd(); + bicarbConcentratePumpParkPersistenceClear = TRUE; } } } @@ -589,11 +695,14 @@ if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) { setFPGAAcidPumpParkCmd(); + acidConcentratePumpParkPersistenceClear = TRUE; } else { setFPGABicarbPumpParkCmd(); + bicarbConcentratePumpParkPersistenceClear = TRUE; } + concentratePumps[ pumpId ].isConcPumpParkInProgress = TRUE; } } #ifndef _RELEASE_ @@ -678,6 +787,12 @@ state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; } + if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) + { + state = CONCENTRATE_PUMP_OFF_STATE; + stopConcentratePump( pumpId ); + } + return state; } @@ -694,13 +809,22 @@ static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; + F32 targetToCurreSpeedDiffMLPM = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) { concentratePumps[ pumpId ].controlTimerCounter = 0; stepConcentratePumpToTargetSpeed( pumpId ); } + if ( targetToCurreSpeedDiffMLPM >= CONCENTRATE_PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD_MLPM ) + { + // If the requested target speed is greater than the threshold, transition back to ramp state regardless of the status of the + // control interval + stepConcentratePumpToTargetSpeed( pumpId ); + state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; + } + if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { state = CONCENTRATE_PUMP_OFF_STATE; @@ -740,29 +864,32 @@ // Subtract current speed when target speed is smaller if ( concentratePumps[ pumpId ].pumpTargetSpeed < concentratePumps[ pumpId ].currentPumpSpeed ) { - speedIncrease *= -1.0; + speedIncrease *= -1.0F; } concentratePumps[ pumpId ].currentPumpSpeed += speedIncrease; // If the pump's target speed is set to be 0, do not ramp down set it to zero immediately if ( fabs( concentratePumps[ pumpId ].pumpTargetSpeed < NEARLY_ZERO ) ) { - concentratePumps[ pumpId ].currentPumpSpeed = 0.0; + concentratePumps[ pumpId ].currentPumpSpeed = 0.0F; } } 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 ); + 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; } + // Check if the control set bit is set as desired and if not, correct it + checkConcentratePumpControlSet( pumpId ); if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) { @@ -778,32 +905,68 @@ /*********************************************************************//** * @brief - * The calcMeasuredPumpsSpeed function calculates the concentrate pump flow - * rate using the hall sense pulse width count. + * The calcMeasuredPumpsSpeed function iterates through the concentrate + * pumps and calculates the concentrate pump flow. It also checks that + * the hall sensor pulse width count for the concentrate pump is valid. * @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 ) +static void calcMeasuredPumpsSpeed( void ) { - F32 pulseWidthInMicroSeconds = (F32)pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; - BOOL isPulseWidthOut = ( pulseWidthInMicroSeconds <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); + CONCENTRATE_PUMPS_T pumpId; + U16 pulseWidthCount = 0; + F32 pulseWidthInMicroSeconds = 0.0F; + BOOL isPulseWidthOut = FALSE; + CONCENTRATE_PUMPS_T pumpInAlarm = CONCENTRATEPUMPS_FIRST; + F32 pumpInAlarmPulseWidthInMicroSeconds = 0.0F; + BOOL isPumpPulseWidthOut = FALSE; - concentratePumps[ pumpId ].pulseWidthUS = pulseWidthInMicroSeconds; + for ( pumpId = CONCENTRATEPUMPS_FIRST; pumpId < NUM_OF_CONCENTRATE_PUMPS; pumpId++ ) + { + switch ( pumpId ) + { + case CONCENTRATEPUMPS_CP1_ACID: + pulseWidthCount = getFPGACP1HallSensePulseWidth(); + break; - checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pulseWidthInMicroSeconds, - CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); + case CONCENTRATEPUMPS_CP2_BICARB: + pulseWidthCount = getFPGACP2HallSensePulseWidth(); + break; - if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) - { - concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0F; +#ifndef _VECTORCAST_ + // Disabled in VectorCAST since it cannot be reached in VectorCAST because the switch case is in a for loop + default: + // Loop only allows for valid concentrate pump Ids. + break; +#endif + } + + pulseWidthInMicroSeconds = pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; + concentratePumps[ pumpId ].pulseWidthUS = pulseWidthInMicroSeconds; + isPumpPulseWidthOut = ( pulseWidthInMicroSeconds <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); + + // Determine measured speed for the pump + if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) + { + concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0F; + } + else if ( FALSE == isPumpPulseWidthOut ) + { + concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; + } + + // If pulse width is out of range capture pump out of range, pumpId and pulse width + if ( TRUE == isPumpPulseWidthOut ) + { + // Pulse width for this concentrate pump is out of range + isPulseWidthOut = TRUE; + pumpInAlarm = pumpId; + pumpInAlarmPulseWidthInMicroSeconds = pulseWidthInMicroSeconds; + } } - else if ( FALSE == isPulseWidthOut ) - { - concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; - } + + checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pumpInAlarm, pumpInAlarmPulseWidthInMicroSeconds ); } /*********************************************************************//** @@ -819,22 +982,64 @@ static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ) { F32 cpTargetSpeed = concentratePumps[ pumpId ].currentPumpSpeed; - F32 cpError = fabs( getMeasuredPumpSpeed( pumpId ) - cpTargetSpeed ); + F32 cpError = fabs( fabs( getMeasuredPumpSpeedMLPM( pumpId ) ) - cpTargetSpeed ); BOOL isCpSpeedOut = FALSE; + F32 tolerance = CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_SLOW_MLPM; - if ( concentratePumps[ pumpId ].execState != CONCENTRATE_PUMP_OFF_STATE ) + if ( cpTargetSpeed > CONCENTRATE_PUMP_LOW_SPEED_THRESHOLD_MLPM ) { - // 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; + // Check if the pump is not in the off state and if it is not and greater than the minimum threshold, divide the error + // to target speed. If the pump is off the target speed is 0 so the speed check is done differently + cpError = cpError / cpTargetSpeed; + tolerance = CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_ON_PCT; } - isCpSpeedOut = ( cpError > CONCENTRATE_PUMP_ERROR_TOLERANCE ? TRUE : FALSE ); + isCpSpeedOut = ( cpError > tolerance ? TRUE : FALSE ); - checkPersistentAlarm( alarm, isCpSpeedOut, cpError, CONCENTRATE_PUMP_ERROR_TOLERANCE ); + checkPersistentAlarm( alarm, isCpSpeedOut, cpError, tolerance ); } +/*********************************************************************//** + * @brief + * The checkConcentratePumpControlSet function monitors the status of the + * concentrate pumps control set bit and if they are different from the + * required set bit, they are set again. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId pump id to check its control set bit + * @return none + *************************************************************************/ +static void checkConcentratePumpControlSet( CONCENTRATE_PUMPS_T pumpId ) +{ + U08 controlSetBits; + switch ( pumpId ) + { + case CONCENTRATEPUMPS_CP1_ACID: + controlSetBits = getFPGAAcidPumpControlStatus(); + + if ( controlSetBits != concentratePumps[ pumpId ].controlSet ) + { + setFPGAAcidPumpControl( concentratePumps[ pumpId ].controlSet ); + } + break; + + case CONCENTRATEPUMPS_CP2_BICARB: + controlSetBits = getFPGABicarbPumpControlStatus(); + + if ( controlSetBits != concentratePumps[ pumpId ].controlSet ) + { + setFPGABicarbPumpControl( concentratePumps[ pumpId ].controlSet ); + } + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + break; + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/