/************************************************************************** * * Copyright (c) 2024-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 DialysatePumps.c * * @author (last) Vinayakam Mani * @date (last) 02-Oct-2024 * * @author (original) Vinayakam Mani * @date (original) 02-Oct-2024 * ***************************************************************************/ #include #include "DialysatePumps.h" #include "FpgaDD.h" #include "MessageSupport.h" #include "Messaging.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" #include "Pressure.h" #include "SafetyShutdown.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" #include "Utilities.h" /** * @addtogroup DialysatePumps * @{ */ // ********** private definitions ********** #define DIALYSATE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the dialysate pump data is published on the CAN bus. #define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. #define DP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate pump is controlled. #define DIALYSATE_PUMP_CONTROL_RUN 0x01 ///< Dialysate pump control run pump. #define DIALYSATE_PUMP_CONTROL_STOP 0x00 ///< Dialysate pump control stop pump. #define DIALYSATE_PUMP_FORWARD_DIR 1 ///< Dialysate pump forward direction. reverse direction is not allowed. #define DIALYSATE_PUMP_SPEED_INCREMENT 5.0F ///< Speed increase when controlling dialysate pump to target step speed. #define ZERO_SPEED 0.0F ///< Zero speed/RPM value. #define DIALYSATE_PUMP_MAX_CURRENT_WHEN_OFF_A 0.1F ///< Dialysate pump maximum current when the pump is off in amps. #define DIALYSATE_PUMP_MAX_CURRENT_A 2.2F ///< Dialysate pump maximum current in amps. #define DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Dialysate pump current out of range timeout in milliseconds. #define DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Dialysate pump direction out of range timeout in milliseconds. #define DIALYSATE_PUMP_DIR_BIT_MASK 0x80 ///< Dialysate pump direction bit clear mask. #define DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK 0x3F ///< Dialysate pump direction error count bit mask. #define DIALYSATE_PUMP_MIN_RPM_FOR_DIR_CHECK 100 ///< Dialysate pump minimum RPM for direction check. #define MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< FPGA dialysate pump direction fault window #define MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES 10 ///< FPGA dialysate pump direction fault failures per MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS #define FRESH_DIALYSATE_TARGET_PRESSURE_PSI (-12.0F) ///< Fresh dialysate pump recommended pressure(Pn/PHo) in psi. #define FRESH_DIALYSATE_MAX_PRESSURE_PSI (-15.0F) ///< Fresh dialysate pump maximum allowed (Pn/PHo) pressure in psi. #define SPENT_DIALYSATE_TARGET_PRESSURE_PSI 25.0F ///< Spent dialysate pump recommended pressure(PDs) in psi. #define SPENT_DIALYSATE_MAX_PRESSURE_PSI 30.0F ///< Spent dialysate pump maximum allowed (PDs) pressure in psi. #define DIALYSATE_PUMP_MIN_PRESSURE_PSI 0.0F ///< Minimum dialysate pump pressure in psi. #define DIALYSATE_PUMP_MAX_PRESSURE_PSI 40.0F ///< Maximum dialysate pump pressure in psi. #define DIALYSATE_PUMP_SPEED_ZERO_RPM 0 ///< Dialysate pump zero RPM speed. #define FRESH_DIALYSATE_PUMP_P_COEFFICIENT 1.0F ///< P term for fresh dialysate pump delta pressure control. #define FRESH_DIALYSATE_PUMP_I_COEFFICIENT 0.0F ///< I term for fresh dialysate pump delta pressure control. #define SPENT_DIALYSATE_PUMP_P_COEFFICIENT 1.0F ///< P term for spent dialysate pump delta pressure control. #define SPENT_DIALYSATE_PUMP_I_COEFFICIENT 0.0F ///< I term for spent dialysate pump delta pressure control. #define MAX_ALLOWED_RPM_OUT_OF_RANGE 300 ///< Maximum allowed RPM out of range from target RPM in open loop. #define PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD 20.0F ///< Speed change that alters the state to ramp during control state. #define RPM_OUT_OF_RANGE_TIME_OUT ( 10 * MS_PER_SECOND ) ///< Open loop RPM out of range time out in ms. #define SAFETY_SHUTDOWN_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Dialysate pump safety shutdown activation timeout. /// Enumeration of dialysate pump states. typedef enum DialysatePump_States { DIALYSATE_PUMP_OFF_STATE = 0, ///< Dialysate pump off state DIALYSATE_PUMP_RAMP_UP_STATE, ///< Dialysate pump ramp up state DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE, ///< Dialysate pump control to target state NUM_OF_DIALYSATE_PUMP_STATES ///< Number of dialysate pump states } DIALYSATE_PUMP_STATE_T; /// Enumeration of dialysate pump self-test states. typedef enum DialysatePump_Self_Test_States { DIALYSATE_PUMP_SELF_TEST_STATE_START = 0, ///< Dialysate pump self-test start state DIALYSATE_PUMP_TEST_STATE_IN_PROGRESS, ///< Dialysate pump self-test in progress state DIALYSATE_PUMP_TEST_STATE_COMPLETE, ///< Dialysate pump self-test completed state NUM_OF_DIALYSATE_PUMP_SELF_TEST_STATES ///< Number of dialysate pump self-test states } DIALYSATE_PUMP_SELF_TEST_STATE_T; /// Dialysate pump data structure typedef struct { U32 controlTimerCounter; ///< Timer counter to perform control on dialysate pump. DIALYSATE_PUMP_STATE_T dialysatePumpState; ///< Current state of dialysate pump controller state machine. BOOL isDialPumpOn; ///< Flag indicates dialysate pump On or Off state OVERRIDE_F32_T pumpTargetSpeed; ///< Target dialysate pumps' speed (mL/min).forward direction only, hence positive speed. F32 prevPumpTargetSpeed; ///< Previous target dialysate pumps' speed (mL/min). F32 currentPumpSpeed; ///< Current controlled dialysate pumps' speed (mL/min). OVERRIDE_F32_T measuredPumpSpeed; ///< Measured dialysate pump speed (mL/min). OVERRIDE_F32_T dialysatePumpMeasuredCurrentA; ///< Measured dialysate pump current feedback. OVERRIDE_U32_T measuredDirection; ///< Measured dialysate pump direction. U32 directionErrorCount; ///< dialysate pump direction error count from power up. U32 lastDirectionErrorCount; ///< last dialysate pump direction error count from power up. OVERRIDE_F32_T pumpTargetPressure; ///< Target dialysate pumps' pressure (PSI). U08 control; ///< Dialysate pump control } DIALYSATE_PUMP_DATA_T; // ********** private data ********** static U32 dialysatePumpDataPublicationTimerCounter; ///< Used to schedule dialysate pump data publication to CAN bus. static OVERRIDE_U32_T dialysatePumpDataPublishInterval = { DIALYSATE_PUMP_DATA_PUB_INTERVAL, DIALYSATE_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish dialysate pump data to CAN bus. //static DD_DIALYSATE_PUMP_CAL_RECORD_T dialysatePumpCalRecord; ///< Dialysate pump calibration record. static DIALYSATE_PUMP_DATA_T dialysatePumps[ NUM_OF_DIALYSATE_PUMPS ]; ///< Array of dialysate pumps data structure. //TODO : Validate once HDD defines the conversion. static const F32 CURRENT_CONVERSION_COEFF = (F32)( 2.5F / ( BITS_12_FULL_SCALE - 1.0F ) ); // ********** private function prototypes ********** static void publishDialysatePumpsData( void ); static DIALYSATE_PUMP_STATE_T handleDialysatePumpControlToTargetState( DIALYSATE_PUMPS_T pumpId ); static BOOL stepDialysatePumpToTargetSpeed( DIALYSATE_PUMPS_T pumpId ); static DIALYSATE_PUMP_STATE_T handleDialysatePumpRampToTargetState( DIALYSATE_PUMPS_T pumpId ); static DIALYSATE_PUMP_STATE_T handleDialysatePumpOffState( DIALYSATE_PUMPS_T pumpId ); static void monitorPumpDirectionErrorCount( DIALYSATE_PUMPS_T pumpId ); /*********************************************************************//** * @brief * The initDialysatePump function initializes the DialysatePumps unit. * @details \b Inputs: none * @details \b Outputs: Dialysate unit variables initialized. * @return none *************************************************************************/ void initDialysatePump( void ) { DIALYSATE_PUMPS_T pumpId; dialysatePumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) { dialysatePumps[ pumpId ].controlTimerCounter = 0; dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; dialysatePumps[ pumpId ].isDialPumpOn = FALSE; dialysatePumps[ pumpId ].measuredPumpSpeed.data = 0.0F; dialysatePumps[ pumpId ].measuredPumpSpeed.ovInitData = 0.0F; dialysatePumps[ pumpId ].measuredPumpSpeed.override = OVERRIDE_RESET; dialysatePumps[ pumpId ].measuredPumpSpeed.ovData = 0.0F; dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0F; dialysatePumps[ pumpId ].pumpTargetSpeed.ovInitData = 0.0F; dialysatePumps[ pumpId ].pumpTargetSpeed.override = OVERRIDE_RESET; dialysatePumps[ pumpId ].pumpTargetSpeed.ovData = 0.0F; dialysatePumps[ pumpId ].measuredDirection.data = DIALYSATE_PUMP_FORWARD_DIR; dialysatePumps[ pumpId ].measuredDirection.ovInitData = DIALYSATE_PUMP_FORWARD_DIR; dialysatePumps[ pumpId ].measuredDirection.ovData = DIALYSATE_PUMP_FORWARD_DIR; dialysatePumps[ pumpId ].measuredDirection.override = OVERRIDE_RESET; dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.data = 0.0F; dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.ovInitData = 0.0F; dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.ovData = 0.0F; dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.override = OVERRIDE_RESET; dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; dialysatePumps[ pumpId ].prevPumpTargetSpeed = 0.0F; dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; dialysatePumps[ pumpId ].directionErrorCount = 0; dialysatePumps[ pumpId ].lastDirectionErrorCount = 0; signalDialysatePumpHardStop( pumpId ); } dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.data = FRESH_DIALYSATE_TARGET_PRESSURE_PSI; dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.ovInitData = FRESH_DIALYSATE_TARGET_PRESSURE_PSI; dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.ovData = 0.0F; dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.override = OVERRIDE_RESET; dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.data = SPENT_DIALYSATE_TARGET_PRESSURE_PSI; dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.ovInitData = SPENT_DIALYSATE_TARGET_PRESSURE_PSI; dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.ovData = 0.0F; dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.override = OVERRIDE_RESET; // Initialize the fresh dialysate pump PI controller initializePIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI, FRESH_DIALYSATE_PUMP_P_COEFFICIENT, FRESH_DIALYSATE_PUMP_I_COEFFICIENT, DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_MAX_PRESSURE_PSI ); // Initialize spent dialysate pump PI controller initializePIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI, SPENT_DIALYSATE_PUMP_P_COEFFICIENT, SPENT_DIALYSATE_PUMP_I_COEFFICIENT, DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_MAX_PRESSURE_PSI ); // Initialize the persistent alarms for fresh dialysate pump initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, RPM_OUT_OF_RANGE_TIME_OUT, RPM_OUT_OF_RANGE_TIME_OUT ); initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ); //Initialize the persistent alarms for spent dialysate pump initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, RPM_OUT_OF_RANGE_TIME_OUT, RPM_OUT_OF_RANGE_TIME_OUT ); initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ); // initialize FPGA dialysate pump hall sensor error initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_FRESH_DIALYSATE_PUMP_HALL_SENSOR_ERROR, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ); initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_SPENT_DIALYSATE_PUMP_HALL_SENSOR_ERROR, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ); } /*********************************************************************//** * @brief * The setDialysatePumpTargetSpeed function sets a new target RPM for the * dialysate pump. * @details \b Inputs: none * @details \b Outputs: pumpTargetSpeed. * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump id supplied. * @param pumpId pump id to set the new speed. * @param rpm new dialysate pump target RPM * @return TRUE if new target RPM is set, FALSE if not *************************************************************************/ BOOL setDialysatePumpTargetRPM( DIALYSATE_PUMPS_T pumpId, U32 rpm ) { BOOL result = FALSE; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { if ( ( MIN_DIALYSATE_PUMP_RPM <= rpm ) && ( rpm <= MAX_DIALYSATE_PUMP_RPM ) ) { dialysatePumps[ pumpId ].pumpTargetSpeed.data = rpm; } else if ( rpm < MIN_DIALYSATE_PUMP_RPM ) { dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0; } else { dialysatePumps[ pumpId ].pumpTargetSpeed.data = MAX_DIALYSATE_PUMP_RPM; } //handle target speed update when pump is running if ( DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE == dialysatePumps[ pumpId ].dialysatePumpState ) { F32 diffSpeed = fabs( getDialysatePumpTargetSpeed( pumpId ) - dialysatePumps[ pumpId ].prevPumpTargetSpeed ); if ( diffSpeed > PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD ) { // change to ramp state dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_RAMP_UP_STATE; } } dialysatePumps[ pumpId ].prevPumpTargetSpeed = getDialysatePumpTargetSpeed( pumpId ); result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ) } return result; } /*********************************************************************//** * @brief * The signalDialysatePumpHardStop function stops the Dialysate pump immediately. * @details \b Inputs: none * @details \b Outputs: control,currentPumpSpeed,pumpTargetSpeed,dialysatePumpState, * controlTimerCounter,isDialPumpOn. * @param pumpId pump id to stop the given dialysate pump * @return none *************************************************************************/ void signalDialysatePumpHardStop( DIALYSATE_PUMPS_T pumpId ) { //Update control to stop the dialysate pump if ( FRESH_DIALYSATE_PUMP == pumpId ) { // dialysate pump control run enable dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; setFPGAFreshDialysatePumpControl( dialysatePumps[ pumpId ].control ); setFPGAFreshDialysatePumpSpeed( DIALYSATE_PUMP_SPEED_ZERO_RPM ); } else { dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; setFPGASpentDialysatePumpControl( dialysatePumps[ pumpId ].control ); setFPGASpentDialysatePumpSpeed( DIALYSATE_PUMP_SPEED_ZERO_RPM ); } // Reset all the variables to stop mode dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0F; dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; dialysatePumps[ pumpId ].controlTimerCounter = 0; dialysatePumps[ pumpId ].isDialPumpOn = FALSE; //Reset PI Controller if ( FRESH_DIALYSATE_PUMP == pumpId ) { resetPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); } else { resetPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); } } /*********************************************************************//** * @brief * The monitorPumpDirectionErrorCount function monitors the given dialysate pumps * direction error count and triggers the alarms if they are incrementing for * certain count with in defined time. * @details \b Inputs: directionErrorCount,lastDirectionErrorCount * @details \b Outputs: lastDirectionErrorCount * @details \b Alarm: ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT when * the direction error count increments for certian count with in defined time. * @details \b Alarm: ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT when * the direction error count increments for certian count with in defined time. * @param pumpId pump id to check the direction error count for the given dialysate * pump * @return none *************************************************************************/ static void monitorPumpDirectionErrorCount( DIALYSATE_PUMPS_T pumpId ) { if ( dialysatePumps[ pumpId ].directionErrorCount != dialysatePumps[ pumpId ].lastDirectionErrorCount ) { if ( FRESH_DIALYSATE_PUMP == pumpId ) { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_FRESH_DIALYSATE_PUMP_HALL_SENSOR_ERROR ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, dialysatePumps[ pumpId ].directionErrorCount ) } } else { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_SPENT_DIALYSATE_PUMP_HALL_SENSOR_ERROR ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, dialysatePumps[ pumpId ].directionErrorCount ) } } dialysatePumps[ pumpId ].lastDirectionErrorCount = dialysatePumps[ pumpId ].directionErrorCount; } } /*********************************************************************//** * @brief * The execDialysatePumpMonitor function executes the dialysate pump monitor. * @details \b Inputs: dialysate pumps speed, current and direction reported * by FPGA * @details \b Outputs: measuredPumpSpeed,dialysatePumpMeasuredCurrentA, * measuredDirection,directionErrorCount * @detail \b Alarms: ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, * ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE when speed mismatch * occurs between set and measured speed. * @detail \b Alarms: ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, * ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT when dialysate pump runs at * certain speed when not commanded to run. * @detail \b Alarms: ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, * ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID when dialysate pump is * not running in forward direction. * @detail \b Alarms:ALARM_ID_DD_FRESH_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, * ALARM_ID_DD_SPENT_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE when dialysate pump * is drawing more current than expected. * @return none *************************************************************************/ void execDialysatePumpMonitor( void ) { U16 freshDialCurrent = getFPGAFreshDialysatePumpCurrentFeedback(); U16 spentDialCurrent = getFPGAFreshDialysatePumpCurrentFeedback(); BOOL isOffCurrentOut = FALSE; BOOL isCurrentOutOfRange = FALSE; DIALYSATE_PUMPS_T pumpId; // Update the paramerters dialysatePumps[ FRESH_DIALYSATE_PUMP ].measuredPumpSpeed.data = getFPGAFreshDialysatePumpSpeed(); dialysatePumps[ SPENT_DIALYSATE_PUMP ].measuredPumpSpeed.data = getFPGASpentDialysatePumpSpeed(); dialysatePumps[ FRESH_DIALYSATE_PUMP ].dialysatePumpMeasuredCurrentA.data = (F32)freshDialCurrent * CURRENT_CONVERSION_COEFF; dialysatePumps[ SPENT_DIALYSATE_PUMP ].dialysatePumpMeasuredCurrentA.data = (F32)spentDialCurrent * CURRENT_CONVERSION_COEFF; dialysatePumps[ FRESH_DIALYSATE_PUMP ].measuredDirection.data = (U32)( ( getFPGAFreshDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_BIT_MASK ) >> SHIFT_BITS_BY_7 ); dialysatePumps[ SPENT_DIALYSATE_PUMP ].measuredDirection.data = (U32)( ( getFPGASpentDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_BIT_MASK ) >> SHIFT_BITS_BY_7 ); dialysatePumps[ FRESH_DIALYSATE_PUMP ].directionErrorCount = (U32)( getFPGAFreshDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK ); dialysatePumps[ SPENT_DIALYSATE_PUMP ].directionErrorCount = (U32)( getFPGASpentDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK ); // Monitor dialysate pumps for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) { switch ( dialysatePumps[ pumpId ].dialysatePumpState ) { case DIALYSATE_PUMP_OFF_STATE: { BOOL isRPMTooHigh = FALSE; isOffCurrentOut = ( getDialysatePumpMeasuredCurrentA( pumpId ) > DIALYSATE_PUMP_MAX_CURRENT_WHEN_OFF_A ? TRUE : FALSE ); isRPMTooHigh = ( getDialysatePumpMeasuredSpeed( pumpId ) > MIN_DIALYSATE_PUMP_RPM ? TRUE : FALSE ); if ( FRESH_DIALYSATE_PUMP == pumpId ) { checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MAX_ALLOWED_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, isRPMTooHigh, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, FALSE, getDialysatePumpMeasuredDirection( pumpId ), DIALYSATE_PUMP_FORWARD_DIR ); } else { checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MAX_ALLOWED_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, isRPMTooHigh, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, FALSE, getDialysatePumpMeasuredDirection( pumpId ), DIALYSATE_PUMP_FORWARD_DIR ); } // If the direction off fault alarm has become active, trigger the safety shutdown if ( ( TRUE == isAlarmActive( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT ) ) || ( TRUE == isAlarmActive( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT ) ) ) { //activateSafetyShutdown(); } } break; case DIALYSATE_PUMP_RAMP_UP_STATE: case DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE: { U32 direction = getDialysatePumpMeasuredDirection( pumpId ); U32 rpm = getDialysatePumpMeasuredSpeed( pumpId ); BOOL isRPMOutOfRange = FALSE; U32 rpmDiff = abs( getDialysatePumpTargetSpeed( pumpId ) - rpm ); BOOL isDirInvalid = ( ( direction != DIALYSATE_PUMP_FORWARD_DIR ) && ( rpm > DIALYSATE_PUMP_MIN_RPM_FOR_DIR_CHECK ) ? TRUE : FALSE ); isRPMOutOfRange = ( rpmDiff > MAX_ALLOWED_RPM_OUT_OF_RANGE ? TRUE : FALSE ); if ( FRESH_DIALYSATE_PUMP == pumpId ) { checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, isRPMOutOfRange, rpm, MAX_ALLOWED_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, isDirInvalid, (F32)direction, DIALYSATE_PUMP_FORWARD_DIR ); } else { checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, isRPMOutOfRange, rpm, MAX_ALLOWED_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, isDirInvalid, (F32)direction, DIALYSATE_PUMP_FORWARD_DIR ); } } break; default: // do nothing break; } //Monitor Direction error count monitorPumpDirectionErrorCount( pumpId ); // Check the persistent alarm for the maximum dialysate pump current F32 currentA = getDialysatePumpMeasuredCurrentA( pumpId ); isCurrentOutOfRange = ( currentA > DIALYSATE_PUMP_MAX_CURRENT_A ? TRUE : FALSE ) | isOffCurrentOut; if ( FRESH_DIALYSATE_PUMP == pumpId ) { checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, isCurrentOutOfRange, currentA, DIALYSATE_PUMP_MAX_CURRENT_A ); } else { checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, isCurrentOutOfRange, currentA, DIALYSATE_PUMP_MAX_CURRENT_A ); } } // Publish dialysate pumps data on interval publishDialysatePumpsData(); } /*********************************************************************//** * @brief * The execDialysatePumpController function executes the dialysate pumps controller. * @details \b Inputs: dialysatePumpState * @details \b Outputs: dialysatePumpState * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT if invalid dialysate pump * state machine found. * @return none *************************************************************************/ void execDialysatePumpController( void ) { DIALYSATE_PUMPS_T pumpId; // Check if a new calibration is available // if ( TRUE == isNewCalibrationRecordAvailable() ) // { // get updated record //getNVRecord2Driver( GET_CAL_DIALYSATE_PUMP_RECORD, (U08*)&dialysatePumpCalRecord, sizeof( DD_DIALYSATE_PUMP_CAL_RECORD_T ), 0, // ALARM_ID_DD_FRESH_DIALYSATE_PUMP_INVALID_CAL_RECORD ); // } for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) { switch ( dialysatePumps[ pumpId ].dialysatePumpState ) { case DIALYSATE_PUMP_OFF_STATE: dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpOffState( pumpId ); break; case DIALYSATE_PUMP_RAMP_UP_STATE: dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpRampToTargetState( pumpId ); break; case DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE: dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpControlToTargetState( 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_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_EXEC_INVALID_STATE, pumpId ) dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; break; #endif } } } /*********************************************************************//** * @brief * The execDialysatePumpSelfTest function executes the dialysate pump's self-test. * @details \b Inputs: Non volatile records. * @details \b Outputs: none * @return DialysatePumps SelfTest Result (SELF_TEST_STATUS_T) *************************************************************************/ SELF_TEST_STATUS_T execDialysatePumpSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; BOOL calStatus = TRUE; // TODO:initialize to false when calibration records avialble // This is only one record the number of items to check is 0 since the get NV data function does not do a for loop to check the calibration time // calStatus |= getNVRecord2Driver( GET_CAL_FRESH_DIALYSATE_PUMP_RECORD, (U08*)&freshDialysatePumpRecord, sizeof( DD_FRESH_DIALYSATE_PUMP_RECORD_T ), 0, // ALARM_ID_DD_FRESH_DIALYSATE_PUMP_INVALID_CAL_RECORD ); // calStatus |= getNVRecord2Driver( GET_CAL_SPENT_DIALYSATE_PUMP_RECORD, (U08*)&spentDialysatePumpRecord, sizeof( DD_SPENT_DIALYSATE_PUMP_RECORD_T ), 0, // ALARM_ID_DD_SPENT_DIALYSATE_PUMP_INVALID_CAL_RECORD ); // // calStatus |= getNVRecord2Driver( GET_CAL_DIALYSATE_PUMP_RECORD, (U08*)&dialysatePumpCalRecord, sizeof( DD_DIALYSATE_PUMP_CAL_RECORD_T ), 0, // ALARM_ID_NO_ALARM ); if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; } return result; } /*********************************************************************//** * @brief * The isDialysatePumpOn function determines whether the dialysate pump is on * or Off state. * @details \b Inputs: dialysatePumps[] * @details \b Outputs: none * @param pumpId dialysate pump id to return status of dialysate pump running state * @return TRUE if dialysate pump is on, FALSE if not. *************************************************************************/ BOOL isDialysatePumpOn( DIALYSATE_PUMPS_T pumpId ) { return ( dialysatePumps[ pumpId ].isDialPumpOn ); } /*********************************************************************//** * @brief * The handleDialysatePumpOffState function handles the dialysate pump off state of * the dialysate pump controller state machine. * @details \b Inputs: pumpTargetSpeed * @details \b Outputs: dialysatePumps[].control,isDialPumpOn * @param pumpId dialysate pump id to run the dialysate pump * @return next state for the controller state machine *************************************************************************/ static DIALYSATE_PUMP_STATE_T handleDialysatePumpOffState( DIALYSATE_PUMPS_T pumpId ) { DIALYSATE_PUMP_STATE_T result = DIALYSATE_PUMP_OFF_STATE; F32 targetSpeed = getDialysatePumpTargetSpeed( pumpId ); if ( targetSpeed > ZERO_SPEED ) { if ( FRESH_DIALYSATE_PUMP == pumpId ) { // dialysate pump control run enable, forward run only. dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_RUN; setFPGAFreshDialysatePumpControl( dialysatePumps[ pumpId ].control ); } else { dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_RUN; setFPGASpentDialysatePumpControl( dialysatePumps[ pumpId ].control ); } dialysatePumps[ pumpId ].isDialPumpOn = TRUE; result = DIALYSATE_PUMP_RAMP_UP_STATE; } else { dialysatePumps[ pumpId ].isDialPumpOn = FALSE; } return result; } /*********************************************************************//** * @brief * The handleDialysatePumpRampToTargetState function handles the dialysate pump * ramp to target state of the dialysate pump controller state machine. * @details \b Inputs: pumpTargetSpeed * @details \b Outputs: currentPumpSpeed * @param pumpId dialysate pump id to increase current step speed * @return next state for the controller state machine *************************************************************************/ static DIALYSATE_PUMP_STATE_T handleDialysatePumpRampToTargetState( DIALYSATE_PUMPS_T pumpId ) { DIALYSATE_PUMP_STATE_T state = DIALYSATE_PUMP_RAMP_UP_STATE; if ( TRUE == stepDialysatePumpToTargetSpeed( pumpId ) ) { if ( FRESH_DIALYSATE_PUMP == pumpId ) { resetPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); } else { resetPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); } state = DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE; } return state; } /*********************************************************************//** * @brief * The stepDialysatePumpToTargetSpeed function steps current step speed * toward target speed for the given dialysate pump,with predefined step increase. * @details \b Inputs: pumpTargetSpeed * @details \b Outputs: currentPumpSpeed * @param pumpId dialysate pump id to increase current step speed * @return TRUE if the pump has reached to target otherwise, FALSE *************************************************************************/ static BOOL stepDialysatePumpToTargetSpeed( DIALYSATE_PUMPS_T pumpId ) { F32 speedIncrease = 0.0F; BOOL hasTgtBeenReached = FALSE; F32 currentToTargetDiff = fabs( getDialysatePumpTargetSpeed( pumpId ) - dialysatePumps[ pumpId ].currentPumpSpeed ); if ( currentToTargetDiff > ZERO_SPEED ) { if ( currentToTargetDiff > DIALYSATE_PUMP_SPEED_INCREMENT ) { speedIncrease = DIALYSATE_PUMP_SPEED_INCREMENT; } else { speedIncrease = currentToTargetDiff; hasTgtBeenReached = TRUE; } // Subtract current speed when target speed is smaller if ( getDialysatePumpTargetSpeed( pumpId ) < dialysatePumps[ pumpId ].currentPumpSpeed ) { speedIncrease *= -1.0F; } dialysatePumps[ pumpId ].currentPumpSpeed += speedIncrease; // If the pump's target speed is set to be 0, do not ramp down set it to zero immediately if ( getDialysatePumpTargetSpeed( pumpId ) < ZERO_SPEED ) { dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; } } if ( dialysatePumps[ pumpId ].currentPumpSpeed > ZERO_SPEED ) { if ( FRESH_DIALYSATE_PUMP == pumpId ) { // Set fresh dialyate pump speed setFPGAFreshDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } else { // Set spent dialyate pump speed setFPGASpentDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } } return hasTgtBeenReached; } /*********************************************************************//** * @brief * The handleDialysatePumpControlToTargetState function handles the control to * target state of the dialysate pump controller state machine. * @details \b Inputs: controlTimerCounter * @details \b Outputs: currentPumpSpeed, controlTimerCounter * @return next state of the controller state machine *************************************************************************/ static DIALYSATE_PUMP_STATE_T handleDialysatePumpControlToTargetState( DIALYSATE_PUMPS_T pumpId ) { DIALYSATE_PUMP_STATE_T state = DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE; // control at set interval if ( ++dialysatePumps[ pumpId ].controlTimerCounter >= DP_CONTROL_INTERVAL ) { // Control based on the measured and target pressure if ( FRESH_DIALYSATE_PUMP == pumpId ) { F32 measuredPressure = getFilteredPressure( PRESSURE_SENSOR_FRESH_DIALYSATE ); F32 targetPressure = getDialysatePumpTargetPressure( pumpId ); F32 control = runPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, targetPressure, measuredPressure ); // TODO : get the equivalent speed for the given control F32 newSpeed = control * ( MAX_DIALYSATE_PUMP_RPM / DIALYSATE_PUMP_MAX_PRESSURE_PSI ); //Apply speed limit newSpeed = MIN( newSpeed, MAX_DIALYSATE_PUMP_RPM ); newSpeed = MAX( newSpeed, MIN_DIALYSATE_PUMP_RPM ); dialysatePumps[ pumpId ].currentPumpSpeed = newSpeed; //Set fresh dialyate pump speed setFPGAFreshDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } else { F32 measuredPressure = getFilteredPressure( PRESSURE_SENSOR_SPENT_DIALYSATE ); F32 targetPressure = getDialysatePumpTargetPressure( pumpId ); F32 control = runPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, targetPressure, measuredPressure ); // TODO : get the equivalent speed for the given control F32 newSpeed = control * ( MAX_DIALYSATE_PUMP_RPM / DIALYSATE_PUMP_MAX_PRESSURE_PSI ); //Apply speed limit newSpeed = MIN( newSpeed, MAX_DIALYSATE_PUMP_RPM ); newSpeed = MAX( newSpeed, MIN_DIALYSATE_PUMP_RPM ); dialysatePumps[ pumpId ].currentPumpSpeed = newSpeed; //Set spent dialyate pump speed setFPGASpentDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } dialysatePumps[ pumpId ].controlTimerCounter = 0; } return state; } /*********************************************************************//** * @brief * The getDialysatePumpTargetSpeed function gets the current target speed for the given * dialysate pump. * @details \b Inputs: pumpTargetSpeed * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @param pumpId dialysate pump id to get the current target speed * @return the current target speed for the given dialysate pump. *************************************************************************/ F32 getDialysatePumpTargetSpeed( DIALYSATE_PUMPS_T pumpId ) { F32 speed = 0.0F; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { speed = getF32OverrideValue( &dialysatePumps[ pumpId ].pumpTargetSpeed ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); } return speed; } /*********************************************************************//** * @brief * The getDialysatePumpMeasuredSpeed function gets the measured speed for the given * dialysate pump. * @details \b Inputs: measuredPumpSpeed * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @param pumpId dialysate pump id to get the measured speed * @return the measured speed for the given dialysate pump. *************************************************************************/ F32 getDialysatePumpMeasuredSpeed( DIALYSATE_PUMPS_T pumpId ) { F32 speed = 0.0F; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { speed = getF32OverrideValue( &dialysatePumps[ pumpId ].measuredPumpSpeed ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); } return speed; } /*********************************************************************//** * @brief * The getDialysatePumpTargetPressure function gets the target pressure for * the given dialysate pump. * @details \b Inputs: pumpTargetPressure * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @param pumpId dialysate pump id to get the target pressure * @return the target pressure for the given dialysate pump. *************************************************************************/ F32 getDialysatePumpTargetPressure( DIALYSATE_PUMPS_T pumpId ) { F32 pressure = 0.0F; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { pressure = getF32OverrideValue( &dialysatePumps[ pumpId ].pumpTargetPressure ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); } return pressure; } /*********************************************************************//** * @brief * The getDialysatePumpMeasuredCurrentA function returns the given dialysate * pump current feedback. * @details \b Inputs: dialysatePumpMeasuredCurrentA * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @return the given dialysate pump current feedback *************************************************************************/ F32 getDialysatePumpMeasuredCurrentA( DIALYSATE_PUMPS_T pumpId ) { F32 current = 0.0F; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { current = getF32OverrideValue( &dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); } return current; } /*********************************************************************//** * @brief * The getDialysatePumpMeasuredDirection function returns the given dialysate pump * direction. * @details \b Inputs: measuredDirection * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @return the given dialysate pump direction *************************************************************************/ U32 getDialysatePumpMeasuredDirection( DIALYSATE_PUMPS_T pumpId ) { U32 direction = 0; if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { direction = getU32OverrideValue( &dialysatePumps[ pumpId ].measuredDirection ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); } return direction; } /*********************************************************************//** * @brief * The publishDialysatePumpsData function publishes dialysate pumps data at the set * interval. * @details \b Inputs: dialysatePumpDataPublicationTimerCounter,dialysatePumps * @details \b Outputs: dialPump * @details \b Message \Sent: MSG_ID_DIALYSATE_PUMPS_DATA to pusblish dialysate * pumps data. * @return none *************************************************************************/ static void publishDialysatePumpsData( void ) { // publish Dialysate pump data on interval if ( ++dialysatePumpDataPublicationTimerCounter >= getU32OverrideValue( &dialysatePumpDataPublishInterval ) ) { DIALYSATE_PUMPS_PUBLISH_DATA_T dialPump; // Populate the data structure for publication dialPump.freshDialPumpTargetRPM = getDialysatePumpTargetSpeed( FRESH_DIALYSATE_PUMP ); dialPump.spentDialPumpTargetRPM = getDialysatePumpTargetSpeed( SPENT_DIALYSATE_PUMP ); dialPump.freshDialPumpMeasuredSpeed = getDialysatePumpMeasuredSpeed( FRESH_DIALYSATE_PUMP ); dialPump.spentDialPumpMeasuredSpeed = getDialysatePumpMeasuredSpeed( SPENT_DIALYSATE_PUMP ); dialPump.freshDialPumpCurrentSpeed = dialysatePumps[ FRESH_DIALYSATE_PUMP ].currentPumpSpeed; dialPump.spentDialPumpCurrentSpeed = dialysatePumps[ SPENT_DIALYSATE_PUMP ].currentPumpSpeed; dialPump.freshDialPumpState = (U32)dialysatePumps[ FRESH_DIALYSATE_PUMP ].dialysatePumpState; dialPump.spentDialPumpState = (U32)dialysatePumps[ SPENT_DIALYSATE_PUMP ].dialysatePumpState; dialPump.freshDialPumpTargetPressure = getDialysatePumpTargetPressure( FRESH_DIALYSATE_PUMP ); dialPump.spentDialPumpTargetPressure = getDialysatePumpTargetPressure( SPENT_DIALYSATE_PUMP ); dialPump.freshDialPumpMeasuredPressure = getFilteredPressure( PRESSURE_SENSOR_FRESH_DIALYSATE ); dialPump.spentDialPumpMeasuredPressure = getFilteredPressure( PRESSURE_SENSOR_SPENT_DIALYSATE ); dialPump.freshDialPumpMeasuredCurrent = getDialysatePumpMeasuredCurrentA( FRESH_DIALYSATE_PUMP ); dialPump.spentDialPumpMeasuredCurrent = getDialysatePumpMeasuredCurrentA( SPENT_DIALYSATE_PUMP ); dialPump.freshDialPumpControl = (U32)dialysatePumps[ FRESH_DIALYSATE_PUMP ].control; dialPump.spentDialPumpControl = (U32)dialysatePumps[ SPENT_DIALYSATE_PUMP ].control; dialPump.freshDialPumpDirErrCnt = dialysatePumps[ FRESH_DIALYSATE_PUMP ].directionErrorCount; dialPump.spentDialPumpDirErrCnt = dialysatePumps[ SPENT_DIALYSATE_PUMP ].directionErrorCount; dialPump.freshDialPumpMeasuredDir = getDialysatePumpMeasuredDirection( FRESH_DIALYSATE_PUMP ); dialPump.spentDialPumpMeasuredDir = getDialysatePumpMeasuredDirection( SPENT_DIALYSATE_PUMP ); broadcastData( MSG_ID_DIALYSATE_PUMPS_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&dialPump, sizeof( DIALYSATE_PUMPS_PUBLISH_DATA_T ) ); dialysatePumpDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testDialysatePumpsDataPublishIntervalOverride function overrides the * dialysate pump data publish interval. * @details \b Inputs: dialysatePumpDataPublishInterval * @details \b Outputs: dialysatePumpDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the dialysate pump data broadcast interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpsDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &dialysatePumpDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /*********************************************************************//** * @brief * The testDialysatePumpTargetSpeedOverride function overrides the target * speed value of given dialysate pump id. * @details \b Inputs: none * @details \b Outputs: pumpTargetSpeed * @param message Override message from Dialin which includes an ID of * the pump to override and the state to override the pump to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpTargetSpeedOverride( MESSAGE_T *message ) { BOOL result = f32ArrayOverride( message, &dialysatePumps[0].pumpTargetSpeed, NUM_OF_DIALYSATE_PUMPS - 1 ); return result; } /*********************************************************************//** * @brief * The testDialysatePumpMeasuredSpeedOverride function overrides the measured * speed value of given dialysate pump id. * @details \b Inputs: none * @details \b Outputs: measuredPumpSpeed * @param message Override message from Dialin which includes an ID of * the pump to override and the state to override the pump to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpMeasuredSpeedOverride( MESSAGE_T *message ) { BOOL result = f32ArrayOverride( message, &dialysatePumps[0].measuredPumpSpeed, NUM_OF_DIALYSATE_PUMPS - 1 ); return result; } /*********************************************************************//** * @brief * The testDialysatePumpTargetPressureOverride function overrides the target * pressure value of given dialysate pump id. * @details \b Inputs: none * @details \b Outputs: pumpTargetPressure * @param message Override message from Dialin which includes an ID of * the pump to override and the state to override the pump to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpTargetPressureOverride( MESSAGE_T *message ) { BOOL result = f32ArrayOverride( message, &dialysatePumps[0].pumpTargetPressure, NUM_OF_DIALYSATE_PUMPS - 1 ); return result; } /*********************************************************************//** * @brief * The testDialysatePumpMeasuredCurrentOverride function overrides the measured * current value of given dialysate pump id. * @details \b Inputs: none * @details \b Outputs: dialysatePumpMeasuredCurrentA * @param message Override message from Dialin which includes an ID of * the pump to override and the state to override the pump to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpMeasuredCurrentOverride( MESSAGE_T *message ) { BOOL result = f32ArrayOverride( message, &dialysatePumps[0].dialysatePumpMeasuredCurrentA, NUM_OF_DIALYSATE_PUMPS - 1 ); return result; } /*********************************************************************//** * @brief * The testDialysatePumpMeasuredDirectionOverride function overrides the measured * direction value of given dialysate pump id. * @details \b Inputs: none * @details \b Outputs: measuredDirection * @param message Override message from Dialin which includes an ID of * the pump to override and the state to override the pump to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDialysatePumpMeasuredDirectionOverride( MESSAGE_T *message ) { BOOL result = u32ArrayOverride( message, &dialysatePumps[0].measuredDirection, NUM_OF_DIALYSATE_PUMPS - 1, 0, DIALYSATE_PUMP_FORWARD_DIR ); return result; } /**@}*/