Index: firmware/App/Controllers/AirTrap.c =================================================================== diff -u -r6a8d904f4316ed9d9f2f14f99afde63bef38eace -rcd5be724d5a3ba7457e761191d82f278654d7f5c --- firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 6a8d904f4316ed9d9f2f14f99afde63bef38eace) +++ firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision cd5be724d5a3ba7457e761191d82f278654d7f5c) @@ -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 AirTrap.c * * @author (last) Dara Navaei -* @date (last) 13-Dec-2022 +* @date (last) 13-Oct-2023 * * @author (original) Sean Nash * @date (original) 16-Sep-2020 @@ -21,6 +21,8 @@ #include "FPGA.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "PersistentAlarm.h" +#include "Switches.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" @@ -33,12 +35,14 @@ // ********** private definitions ********** -/// Interval (ms/task time) at which the air trap data is published on the CAN bus. -#define AIR_TRAP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) -#define AIR_PUMP_UPPER_LEVEL_PERSISTENCE ( 100 / TASK_GENERAL_INTERVAL ) ///< Persistence time for air pump operation after air trap upper level reads air. + +#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 ( 6 * MS_PER_SECOND ) ///< Air trap fill timeout period (in ms). +#define AIR_PUMP_UPPER_LEVEL_PERSISTENCE ( 300 / TASK_GENERAL_INTERVAL ) ///< Persistence time for air pump operation after air trap upper level reads air. +#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. /// Persistence period for illegal level sensors fault. -static const U32 AIR_TRAP_ILLEGAL_LEVELS_PERSISTENCE = ( MS_PER_SECOND * 2 / TASK_GENERAL_INTERVAL ); -static const U32 AIR_TRAP_UPPER_LEVEL_PERSISTENCE = ( MS_PER_SECOND * 2 / TASK_GENERAL_INTERVAL ); +#define AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Air trap illegal values timeout (in ms) /// Volume (in mL) of venous portion of blood circuit line. TODO - get actual volume from Systems. #define VENOUS_LINE_VOLUME_ML ( 200.0F ) @@ -60,7 +64,7 @@ static U32 airTrapDataPublicationTimerCounter; ///< Used to schedule air trap data publication to CAN bus. /// Interval (in ms) at which to publish air trap data to CAN bus. -static OVERRIDE_U32_T airTrapDataPublishInterval = { AIR_TRAP_DATA_PUB_INTERVAL, AIR_TRAP_DATA_PUB_INTERVAL, 0, 0 }; +static OVERRIDE_U32_T airTrapDataPublishInterval = { AIR_TRAP_DATA_PUB_INTERVAL, AIR_TRAP_DATA_PUB_INTERVAL, AIR_TRAP_DATA_PUB_INTERVAL, 0 }; static OVERRIDE_U32_T airTrapLevels[ NUM_OF_AIR_TRAP_LEVEL_SENSORS ]; ///< Detected air trap level for each level sensor. static BOOL pendingStartAirTrapController = FALSE; ///< Flag indicates an air trap controller start request is pending. @@ -69,8 +73,6 @@ static U32 fillStartTime = 0; ///< Time stamp for start of air trap fill. static U32 airPumpUpperLevelCtr = 0; ///< Timer count for air pump persistence. -static U32 airTrapUpperLevelCtr = 0; ///< Timer count for upper level persistence. -static U32 airTrapIllegalLevelSensorsCtr = 0; ///< Timer counter for illegal level sensor fault. // ********** private function prototypes ********** @@ -91,8 +93,8 @@ U32 i; resetAirTrap(); - airTrapIllegalLevelSensorsCtr = DATA_PUBLISH_COUNTER_START_COUNT; - airPumpUpperLevelCtr = 0; + airTrapDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + airPumpUpperLevelCtr = 0; for ( i = 0; i < NUM_OF_AIR_TRAP_LEVEL_SENSORS; i++ ) { @@ -101,6 +103,9 @@ airTrapLevels[i].ovInitData = 0; airTrapLevels[i].override = OVERRIDE_RESET; } + + initPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ); + } /*********************************************************************//** @@ -179,54 +184,30 @@ void execAirTrapMonitor( void ) { BOOL lower, upper; + BOOL isAirTrapLevelsValid = FALSE; + AIR_TRAP_LEVELS_T lowerAirTrap, upperAirTrap; // Get latest level readings getFPGAAirTrapLevels( &lower, &upper ); airTrapLevels[ AIR_TRAP_LEVEL_SENSOR_LOWER ].data = (U32)( TRUE == lower ? AIR_TRAP_LEVEL_AIR : AIR_TRAP_LEVEL_FLUID ); airTrapLevels[ AIR_TRAP_LEVEL_SENSOR_UPPER ].data = (U32)( TRUE == upper ? AIR_TRAP_LEVEL_AIR : AIR_TRAP_LEVEL_FLUID ); - if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) && - ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) ) + if ( STATE_OPEN == getSwitchStatus( PUMP_TRACK_SWITCH ) ) { - if ( ++airTrapUpperLevelCtr >= AIR_TRAP_UPPER_LEVEL_PERSISTENCE ) - { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ILLEGAL_AIR_TRAP_ALARM ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - activateAlarmNoData( ALARM_ID_HD_AIR_TRAP_OVERFILL ); - } - } + // If the pump track on open, zero the persistent counter to not check the air trap illegal level alarm + checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, FALSE, 0.0, 0.0 ); } else { - if ( airTrapUpperLevelCtr > 0 ) - { - airTrapUpperLevelCtr = 0; - } - } + lowerAirTrap = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); + upperAirTrap = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); + isAirTrapLevelsValid = ( ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_FLUID == upperAirTrap ) ) ? TRUE : FALSE; - // Check level readings are valid - if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && - ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) - { - if ( ++airTrapIllegalLevelSensorsCtr >= AIR_TRAP_ILLEGAL_LEVELS_PERSISTENCE ) - - { #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ILLEGAL_AIR_TRAP_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ILLEGAL_AIR_TRAP_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif - { - activateAlarmNoData( ALARM_ID_AIR_TRAP_ILLEGAL_LEVELS ); - } - } - } - else - { - if ( airTrapIllegalLevelSensorsCtr > 0 ) { - airTrapIllegalLevelSensorsCtr--; + checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, isAirTrapLevelsValid, lowerAirTrap, upperAirTrap ); } } } @@ -244,16 +225,13 @@ // Check air trap fill timeout during treatment if ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) { - F32 bldFlowRate = (F32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); // Function will never return zero - F32 fillTimeoutMS = ( VENOUS_LINE_VOLUME_ML / bldFlowRate ) * (F32)SEC_PER_MIN * (F32)MS_PER_SECOND; - - if ( TRUE == didTimeout( fillStartTime, fillTimeoutMS ) ) + if ( TRUE == didTimeout( fillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_TRAP_LEVELING_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - activateAlarmNoData( ALARM_ID_AIR_TRAP_FILL_DURING_TREATMENT ); + activateAlarmNoData( ALARM_ID_HD_AIR_TRAP_FILL_DURING_TREATMENT ); } } } @@ -345,57 +323,51 @@ { pendingStopAirTrapController = FALSE; result = AIR_TRAP_MANUAL_CONTROL_STATE; + + if ( AIR_PUMP_STATE_ON == getAirPumpState() ) + { + setAirPumpState( AIR_PUMP_STATE_OFF ); + airPumpUpperLevelCtr = 0; + } } + //Turn on air pump if fluid reaches upper level. else if ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) { -#ifndef _RELEASE_ - if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) -#endif + if ( AIR_PUMP_STATE_OFF == getAirPumpState() ) { - if ( AIR_PUMP_STATE_OFF == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_ON ); - } + setAirPumpState( AIR_PUMP_STATE_ON ); + airPumpUpperLevelCtr = 0; + signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); } } - else if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) + else if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) && + ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) ) { - -#ifndef _RELEASE_ - if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) -#endif + if ( AIR_PUMP_STATE_ON == getAirPumpState() ) { - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) + airPumpUpperLevelCtr++; + // Turn air pump off once we detect air at upper level and exceed persistence + if ( airPumpUpperLevelCtr >= AIR_PUMP_UPPER_LEVEL_PERSISTENCE ) { - airPumpUpperLevelCtr++; - // Turn air pump off once we detect air at upper level and exceed persistence - // But first, open the air valve. - if ( airPumpUpperLevelCtr >= AIR_PUMP_UPPER_LEVEL_PERSISTENCE ) - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - airPumpUpperLevelCtr = 0; - } + setAirPumpState( AIR_PUMP_STATE_OFF ); } } } // Transition to open valve state when air detected at lower level - else if ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) + else if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) ) { -#ifndef _RELEASE_ - if ( SW_CONFIG_DISABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_PUMP ) ) -#endif + if ( AIR_PUMP_STATE_ON == getAirPumpState() ) { - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF ); - airPumpUpperLevelCtr = 0; - } + setAirPumpState( AIR_PUMP_STATE_OFF ); } + setValveAirTrap( STATE_OPEN ); fillStartTime = getMSTimerCount(); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, 0, 0 ); result = AIR_TRAP_VALVE_OPEN_STATE; }