Index: firmware/App/Controllers/AirTrap.c =================================================================== diff -u -r961784c895cb8f551a2623cd02dcbfe42d04b7c2 -r285b5d82539c96524c93703d52a66fff76fb64fc --- firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 961784c895cb8f551a2623cd02dcbfe42d04b7c2) +++ firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 285b5d82539c96524c93703d52a66fff76fb64fc) @@ -18,6 +18,7 @@ #include "AirPump.h" #include "AirTrap.h" #include "AlarmMgmtTD.h" +#include "BloodFlow.h" #include "LevelSensors.h" #include "Messaging.h" #include "OperationModes.h" @@ -26,7 +27,7 @@ #include "TaskGeneral.h" #include "Timers.h" #include "Utilities.h" -#include "Valve2Way.h" +#include "Valve3Way.h" /** * @addtogroup AirTrap @@ -38,7 +39,7 @@ #define AIR_TRAP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the air trap data is published on the CAN bus. #define AIR_TRAP_FILL_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Air trap fill timeout period (in ms). #define AIR_PUMP_ON_DELAY_TIME_MS ( 10 * MS_PER_SECOND ) ///< Delay between air pump On (in ms). -#define AIR_PUMP_ON_STOP_TIME_MIN_MS 200 ///< Stop air Pump time. +#define AIR_PUMP_LOWER_OP_TIME_MIN_MS 200 ///< Air trap lower operation minimum time (in ms). #define AIR_PUMP_ON_ERROR_MAX_CNT 6 ///< Maximum number of air pump on events within time window before alarm triggered. Do not exceed MAX_TIME_WINDOWED_COUNT. #define AIR_PUMP_ON_ERROR_TIME_WIN_MS ( 60 * MS_PER_SECOND ) ///< Time window for Air Pump on count error. #define AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Air trap illegal values timeout (in ms) @@ -51,11 +52,12 @@ /// Defined states for the air trap controller state machine. typedef enum AirTrap_States { - AIR_TRAP_INIT_STATE = 0, ///< Initialization state - AIR_TRAP_MANUAL_CONTROL_STATE, ///< Manually control air trap valve state - AIR_TRAP_VALVE_CLOSED_STATE, ///< Valve closed state - until air detected at lower level - AIR_TRAP_VALVE_OPEN_STATE, ///< Valve open state - until fluid detected at upper level - NUM_OF_AIR_TRAP_STATES ///< Number of air trap controller states + AIR_TRAP_INIT_STATE = 0, ///< Initialization state. + AIR_TRAP_MANUAL_CONTROL_STATE, ///< Manually control air trap valve state. + AIR_TRAP_CLOSED_STATE, ///< Closed state - level between lower and upper sensors. + AIR_TRAP_RAISE_LEVEL_STATE, ///< Raise level state. + AIR_TRAP_LOWER_LEVEL_STATE, ///< Lower level state. + NUM_OF_AIR_TRAP_STATES ///< Number of air trap controller states. } AIR_TRAP_STATE_T; // ********** private data ********** @@ -65,21 +67,23 @@ static U32 airTrapDataPublicationTimerCounter; ///< Used to schedule air trap data publication to CAN bus. static OVERRIDE_U32_T airTrapDataPublishInterval; ///< Interval (in ms) at which to publish air trap data to CAN bus. -static BOOL pendingStartAirTrapController = FALSE; ///< Flag indicates an air trap controller start request is pending. -static BOOL pendingStopAirTrapController = FALSE; ///< Flag indicates an air trap controller stop request is pending. +static BOOL pendingStartAirTrapController; ///< Flag indicates an air trap controller start request is pending. +static BOOL pendingStopAirTrapController; ///< Flag indicates an air trap controller stop request is pending. -static U32 fillStartTime; ///< Time stamp for start of air trap fill. +static U32 airTrapFillStartTime; ///< Air trap fill (raise level) operation start time. +static U32 airTrapLowerStartTime; ///< Air trap lower level operation start time. +static U32 airTrapLowerDelayStartTime; ///< Air trap lower level operation delay start time. -static U32 airPumpOnDelayStartTime; ///< Air pump On start time. -static U32 stopAirPumpStartTime; ///< Stop air pump start time. +static BOOL airTrapWasFilledAtStartOfTreatement; ///< To ensure the fluid level high during start of treatment, we need to do a fill operation. -static BOOL airTrapValveOpenAtStartOfTreatement; ///< To Keep the fluid level high close to Air trap upper level during start of treatment +static BOOL airTrapHasDetectedFaultMode; ///< Flag indicates air trap unit has handled transition to fault mode. // ********** private function prototypes ********** static AIR_TRAP_STATE_T handleAirTrapManualControlState( void ); -static AIR_TRAP_STATE_T handleAirTrapValveClosedState( void ); -static AIR_TRAP_STATE_T handleAirTrapValveOpenState( void ); +static AIR_TRAP_STATE_T handleAirTrapClosedState( void ); +static AIR_TRAP_STATE_T handleAirTrapRaiseLevelState( void ); +static AIR_TRAP_STATE_T handleAirTrapLowerlevelState( void ); static void publishAirTrapData( void ); /*********************************************************************//** @@ -93,7 +97,7 @@ { // Initialize level sensors and valve drivers initLevelSensors(); - init2WayValves(); + init3WayValves(); // Initialize controller variables resetAirTrap(); @@ -102,10 +106,10 @@ airTrapDataPublishInterval.ovData = AIR_TRAP_DATA_PUB_INTERVAL; airTrapDataPublishInterval.ovInitData = AIR_TRAP_DATA_PUB_INTERVAL; airTrapDataPublishInterval.override = OVERRIDE_RESET; - fillStartTime = 0; - airPumpOnDelayStartTime = 0; - stopAirPumpStartTime = 0; - airTrapValveOpenAtStartOfTreatement = FALSE; + airTrapFillStartTime = 0; + airTrapLowerDelayStartTime = 0; + airTrapLowerStartTime = 0; + airTrapHasDetectedFaultMode = FALSE; } /*********************************************************************//** @@ -119,6 +123,7 @@ void resetAirTrap( void ) { airTrapControllerState = AIR_TRAP_INIT_STATE; + airTrapWasFilledAtStartOfTreatement = FALSE; pendingStartAirTrapController = FALSE; pendingStopAirTrapController = FALSE; } @@ -141,7 +146,6 @@ /*********************************************************************//** * @brief * The endAirTrapControl function requests a stop to air trap control. - * @details \b Message \b Sent: MSG_ID_TD_EVENT if air trap control ended. * @details \b Inputs: airTrapControllerState * @details \b Outputs: pendingStopAirTrapController * @return none @@ -151,9 +155,7 @@ if ( TRUE == isAirTrapControlling() ) { pendingStopAirTrapController = TRUE; - set2WayValveState( H13_VALV, STATE_CLOSED ); // Always exit air trap valve control w/ valve closed. - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - signalLowVenousPressureCheck(); // Venous pressure check should continue even after ending auto air trap control + signalLowVenousPressureCheck(); // Venous pressure check should continue even after ending auto air trap control } } @@ -169,7 +171,7 @@ { BOOL result = FALSE; - if ( airTrapControllerState >= AIR_TRAP_VALVE_CLOSED_STATE ) + if ( airTrapControllerState >= AIR_TRAP_CLOSED_STATE ) { result = TRUE; } @@ -189,10 +191,9 @@ void execAirTrapMonitor( void ) { BOOL isAirTrapLevelsValid = FALSE; - AIR_TRAP_LEVELS_T lowerAirTrap, upperAirTrap; - // Update level sensors from FPGA - readLevelSensors(); + // Update air trap level sensors from FPGA + readAirTrapLevelSensors(); // Check for illegal levels alarm if ( TRUE ) // TODO - need a way to determine whether a blood set is installed - if not installed, we would not trigger illegal levels alarm @@ -202,10 +203,11 @@ } else { - lowerAirTrap = getLevelSensorState( H17_LEVL ); - upperAirTrap = getLevelSensorState( H16_LEVL ); - isAirTrapLevelsValid = ( ( ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_FLUID == upperAirTrap ) ) ? TRUE : FALSE ); + AIR_TRAP_LEVELS_T lowerAirTrap = getLevelSensorState( H17_LEVL ); + AIR_TRAP_LEVELS_T upperAirTrap = getLevelSensorState( H16_LEVL ); + isAirTrapLevelsValid = ( ( ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_FLUID == upperAirTrap ) ) ? TRUE : FALSE ); + #ifndef _RELEASE_ // if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ILLEGAL_AIR_TRAP_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -225,12 +227,12 @@ * @details \b Outputs: none * @return none *************************************************************************/ -void execAirTrapMonitorTreatment( void ) +void execAirTrapMonitorTreatment( void ) // TODO - call from treatment mode when ready { // Check air trap fill timeout during treatment - if ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) + if ( AIR_TRAP_RAISE_LEVEL_STATE == airTrapControllerState ) { - if ( TRUE == didTimeout( fillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) + if ( TRUE == didTimeout( airTrapFillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) { #ifndef _RELEASE_ // if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_TRAP_LEVELING_ALARM ) != SW_CONFIG_ENABLE_VALUE ) @@ -255,12 +257,10 @@ void execAirTrapController( void ) { // If we have faulted, close valve and go to manual control - if ( MODE_FAUL == getCurrentOperationMode() ) + if ( ( MODE_FAUL == getCurrentOperationMode() ) && ( airTrapHasDetectedFaultMode != TRUE ) ) { - airTrapControllerState = AIR_TRAP_MANUAL_CONTROL_STATE; - set2WayValveState( H13_VALV, STATE_CLOSED ); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - pendingStartAirTrapController = FALSE; + endAirTrapControl(); + airTrapHasDetectedFaultMode = TRUE; } // Execute air trap state machine @@ -274,14 +274,18 @@ airTrapControllerState = handleAirTrapManualControlState(); break; - case AIR_TRAP_VALVE_CLOSED_STATE: - airTrapControllerState = handleAirTrapValveClosedState(); + case AIR_TRAP_CLOSED_STATE: + airTrapControllerState = handleAirTrapClosedState(); break; - case AIR_TRAP_VALVE_OPEN_STATE: - airTrapControllerState = handleAirTrapValveOpenState(); + case AIR_TRAP_RAISE_LEVEL_STATE: + airTrapControllerState = handleAirTrapRaiseLevelState(); break; + case AIR_TRAP_LOWER_LEVEL_STATE: + airTrapControllerState = handleAirTrapLowerlevelState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_AIR_TRAP_INVALID_STATE, (U32)airTrapControllerState ) airTrapControllerState = AIR_TRAP_INIT_STATE; @@ -308,137 +312,150 @@ if ( TRUE == pendingStartAirTrapController ) { pendingStartAirTrapController = FALSE; - set2WayValveState( H13_VALV, STATE_CLOSED ); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - result = AIR_TRAP_VALVE_CLOSED_STATE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + result = AIR_TRAP_CLOSED_STATE; } return result; } /*********************************************************************//** * @brief - * The handleAirTrapValveClosedState function handles the valve closed state - * of the air trap. - * @details \b Message \b Sent: MSG_ID_TD_EVENT if opening air trap valve. + * The handleAirTrapClosedState function handles the closed state of the + * air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if starting a level change. * @details \b Inputs: pendingStopAirTrapController * @details \b Outputs: none * @return next state *************************************************************************/ -static AIR_TRAP_STATE_T handleAirTrapValveClosedState( void ) +static AIR_TRAP_STATE_T handleAirTrapClosedState( void ) { - AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_CLOSED_STATE; + AIR_TRAP_STATE_T result = AIR_TRAP_CLOSED_STATE; - // Air pump stop time based on the blood flow rate - S32 qB = 0; // TODO abs( getTargetBloodFlowRate() ); - U32 qBx = 0; // TODO ( 0 == qB ? MIN_SET_BLOOD_FLOW_RATE : (U32)qB ); - U32 airPumpStopTime = 0; // TODO AIR_PUMP_ON_STOP_TIME_MIN_MS + ( ( qBx - MIN_SET_BLOOD_FLOW_RATE ) / 2 ); - - // Transition to manual valve control state when requested + // Transition to manual control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; result = AIR_TRAP_MANUAL_CONTROL_STATE; - - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - } } - // Open valve once at start of treatment (blood priming) - else if ( TRUE == airTrapValveOpenAtStartOfTreatement ) - { - airTrapValveOpenAtStartOfTreatement = FALSE; - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - } - - set2WayValveState( H13_VALV, STATE_OPEN ); - fillStartTime = getMSTimerCount(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; - } - - // Turn air pump off after defined time or air detected at upper level - else if ( ( AIR_PUMP_STATE_ON == getAirPumpState() ) && - ( ( TRUE == didTimeout( stopAirPumpStartTime, airPumpStopTime ) ) || - ( ( AIR_TRAP_LEVEL_AIR == getRawLevelSensorState( H16_LEVL ) ) && - ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) ) ) - - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - airPumpOnDelayStartTime = getMSTimerCount(); - } - - // Turn on air pump if fluid reaches upper level. + // Lower air trap level if fluid reaches upper level. else if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H16_LEVL ) ) { if ( ( AIR_PUMP_STATE_OFF == getAirPumpState() ) && - ( TRUE == didTimeout( airPumpOnDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) + ( TRUE == didTimeout( airTrapLowerDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) { - setAirPumpState( AIR_PUMP_STATE_ON ); - stopAirPumpStartTime = getMSTimerCount(); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); // open valve H13 to allow air to be pumped into air trap from atmosphere + setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_MOTOR_LOWER_PWM ); + airTrapLowerStartTime = getMSTimerCount(); signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_LOWER, ON, 0 ); + result = AIR_TRAP_LOWER_LEVEL_STATE; } } - // Transition to open valve state when air detected at lower level - else if ( ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H16_LEVL ) ) && - ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) ) + // Raise air trap level once at start of treatment (blood priming) or when air detected at upper level + else if ( ( TRUE == airTrapWasFilledAtStartOfTreatement ) || + ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H16_LEVL ) ) ) { - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - } - - set2WayValveState( H13_VALV, STATE_OPEN ); - fillStartTime = getMSTimerCount(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; + setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_MOTOR_FILL_PWM ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_OPEN_STATE ); // open valve H20 to allow air to be pumped out of air trap to atmosphere + airTrapFillStartTime = getMSTimerCount(); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, ON, 0 ); + result = AIR_TRAP_RAISE_LEVEL_STATE; } return result; } /*********************************************************************//** * @brief - * The handleAirTrapValveOpenState function handles the valve open state of - * the air trap. - * @details \b Message \b Sent: MSG_ID_TD_EVENT if closing air trap valve + * The handleAirTrapRaiseLevelState function handles the raise level state + * of the air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if raising level completed * @details \b Inputs: pendingStopAirTrapController * @details \b Outputs: none * @return next state *************************************************************************/ -static AIR_TRAP_STATE_T handleAirTrapValveOpenState( void ) +static AIR_TRAP_STATE_T handleAirTrapRaiseLevelState( void ) { - AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_OPEN_STATE; + AIR_TRAP_STATE_T result = AIR_TRAP_RAISE_LEVEL_STATE; // Transition to manual valve control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); result = AIR_TRAP_MANUAL_CONTROL_STATE; } - // Transition to closed valve state when fluid detected at upper level + // Transition back to closed state when air trap fill completed else if ( AIR_TRAP_LEVEL_FLUID == getRawLevelSensorState( H16_LEVL ) ) { - set2WayValveState( H13_VALV, STATE_CLOSED ); - airPumpOnDelayStartTime = u32DiffWithWrap( AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL, getMSTimerCount() ); + airTrapWasFilledAtStartOfTreatement = TRUE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + airTrapLowerDelayStartTime = calcTimeBetween( AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL, getMSTimerCount() ); signalLowVenousPressureCheck(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - result = AIR_TRAP_VALVE_CLOSED_STATE; + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, OFF, 0 ); + result = AIR_TRAP_CLOSED_STATE; } return result; } /*********************************************************************//** * @brief + * The handleAirTrapLowerlevelState function handles the lower level state + * of the air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if lowering air trap level completed. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static AIR_TRAP_STATE_T handleAirTrapLowerlevelState( void ) +{ + AIR_TRAP_STATE_T result = AIR_TRAP_LOWER_LEVEL_STATE; + // Air pump stop time based on the blood flow rate + S32 qB = 500; // TODO abs( getTargetBloodFlowRate() ); + U32 qBx = ( 0 == qB ? MIN_SET_BLOOD_FLOW_RATE : (U32)qB ); + U32 airPumpStopTime = AIR_PUMP_LOWER_OP_TIME_MIN_MS + ( ( qBx - MIN_SET_BLOOD_FLOW_RATE ) / 2 ); + + // Transition to manual valve control state when requested + if ( TRUE == pendingStopAirTrapController ) + { + pendingStopAirTrapController = FALSE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + result = AIR_TRAP_MANUAL_CONTROL_STATE; + } + // Transition back to closed state when air trap lower level operation completed + else if ( ( TRUE == didTimeout( airTrapLowerStartTime, airPumpStopTime ) ) || + ( AIR_TRAP_LEVEL_AIR == getRawLevelSensorState( H16_LEVL ) ) ) + + { + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + airTrapLowerDelayStartTime = getMSTimerCount(); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_LOWER, OFF, 0 ); + // if lower level operation times out, alarm + if ( TRUE == didTimeout( airTrapLowerStartTime, airPumpStopTime ) ) + { + // TODO - alarm??? + } + result = AIR_TRAP_CLOSED_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The publishAirTrapData function constructs and sends the air trap data * broadcast message. - * @details \b Message \b Sent: MSG_ID_TD_AIR_TRAP_DATA + * @details \b Message \b Sent: MSG_ID_TD_AIR_TRAP_DATA to publish air trap data * @details \b Inputs: airTrapDataPublicationTimerCounter, airTrapControllerState, TODO valvestate * @details \b Outputs: airTrapDataPublicationTimerCounter * @return none @@ -454,8 +471,9 @@ data.h16State = getLevelSensorState( H16_LEVL ); data.h17RawState = getRawLevelSensorState( H17_LEVL ); data.h16RawState = getRawLevelSensorState( H16_LEVL ); - data.h13State = get2WayValveState( H13_VALV ); - data.controlling = isAirTrapControlling(); + data.h13State = get3WayValveState( H13_VALV ); + data.h20State = get3WayValveState( H20_VALV ); + data.isAutoControlling = isAirTrapControlling(); broadcastData( MSG_ID_TD_AIR_TRAP_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&data, sizeof( AIR_TRAP_PAYLOAD_T ) ); airTrapDataPublicationTimerCounter = 0;