Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r4cabd64c4ff295eb985f0a62132fef94c4e92921 -r67731d57db9a620418b3b848d8f75ff204902c36 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 4cabd64c4ff295eb985f0a62132fef94c4e92921) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 67731d57db9a620418b3b848d8f75ff204902c36) @@ -26,11 +26,13 @@ #include "ModeGenDialysate.h" #include "ModeStandby.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "Pressure.h" #include "TaskGeneral.h" #include "TDInterface.h" #include "Temperature.h" #include "Timers.h" +#include "Ultrafiltration.h" #include "Valves.h" /** @@ -40,15 +42,23 @@ // ********** private definitions ********** -#define HYD_CHAMBER_FLUID_TEMP_C_MIN 35.0F ///< Minimum hydraulics fluid temperature in deg celcius -#define GEN_DIALYSATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen dialysate mode data published. +#define HYD_CHAMBER_FLUID_TEMP_C_MIN 35.0F ///< Minimum hydraulics fluid temperature in deg celcius +#define GEN_DIALYSATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen dialysate mode data published. +#define DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C 2.0F ///< Dialysate temperature clear alarm tolerance C +#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 4.0F ///< Dialysate temperature out of target tolerance C. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 90 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. +#define DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C 46.0F ///< Dialysate upper bound maximum temperature limit in C. +#define DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature upper bound maximum safety timeout in milliseconds. +#define DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C 42.0F ///< Dialysate upper bound safety temperature limit in C. +#define DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C 33.0F ///< Dialysate lower bound safety temperature limit in C. +#define DIALYSATE_TEMP_CLEAR_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature clear persistence timeout. //Testing -#define DELAY_BC_SWITCHING_AT_START_UP ( 3 * MS_PER_SECOND ) ///< Provide a balancing chamber switching start up delay to stabilize pump speed etc., +#define DELAY_BC_SWITCHING_AT_START_UP ( 3 * MS_PER_SECOND ) ///< Provide a balancing chamber switching start up delay to stabilize pump speed etc., /// Payload record structure for Gen dialysate execution state set request typedef struct { - U32 execStateSet; ///< Gen dialysate execution state machine set request + U32 execStateSet; ///< Gen dialysate execution state machine set request } GEND_EXEC_STATE_SET_CMD_PAYLOAD_T; // ********** private data ********** @@ -57,7 +67,7 @@ static OVERRIDE_F32_T targetHydChamberFluidTemp; ///< Target hydraulics chamber fluid temperature. static OVERRIDE_U32_T isDialDeliveryInProgress; ///< To indicate dialysate started delivering to dialyzer for treatment (overrideable) static OVERRIDE_U32_T isDialysateGoodtoDeliver; ///< Flag indicating whether ready to deliver dialysate or not. -static OVERRIDE_U32_T pendingStopDDGenDialRequest; ///< Flag indicating TD has requested DD stop the generate dialysate (Overridable). +static BOOL pendingStopDDGenDialRequest; ///< Flag indicating TD has requested DD stop the generate dialysate. static U32 genDialysateDataPublicationTimerCounter; ///< Used to schedule generate dialysate data publication to CAN bus. static OVERRIDE_U32_T genDialysateDataPublishInterval; ///< Generate dialysate mode data publish interval. static BOOL isTreatmentParamUpdated; ///< To indicate change in treatment parameters @@ -73,6 +83,7 @@ static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryPauseState( void ); static DD_GEND_MODE_STATE_T handleGenDDialysateIsolatedUFState( void ); static F32 getGenDialysateTargetTemperature( void ); +static void checkDialysateTemperature( void ); static void publishGenDialysateModeData( void ); /*********************************************************************//** @@ -97,10 +108,7 @@ isDialDeliveryInProgress.ovData = FALSE; isDialDeliveryInProgress.ovInitData = FALSE; isDialDeliveryInProgress.override = OVERRIDE_RESET; - pendingStopDDGenDialRequest.data = FALSE; - pendingStopDDGenDialRequest.ovData = FALSE; - pendingStopDDGenDialRequest.ovInitData = FALSE; - pendingStopDDGenDialRequest.override = OVERRIDE_RESET; + pendingStopDDGenDialRequest = FALSE; genDialysateDataPublishInterval.data = GEN_DIALYSATE_DATA_PUBLISH_INTERVAL; genDialysateDataPublishInterval.ovData = GEN_DIALYSATE_DATA_PUBLISH_INTERVAL; genDialysateDataPublishInterval.ovInitData = 0; @@ -113,6 +121,10 @@ //Initialize balancing chamber module initBalanceChamber(); + + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ); } /*********************************************************************//** @@ -127,6 +139,7 @@ { initGenDialysateMode(); setCurrentSubState( NO_SUB_STATE ); + transitionToUltrafiltration(); return genDialysateState; } @@ -176,7 +189,7 @@ case DD_GEND_DIALYSATE_BYPASS_STATE: //Previous state - setValveState( M4_VALV, VALVE_STATE_OPEN ); + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); // Get the target temperature from TD targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); // Turn on the primary heater @@ -202,7 +215,7 @@ case DD_GEND_DIALYSATE_DELIVERY_STATE: //Previous state - setValveState( M4_VALV, VALVE_STATE_OPEN ); + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); // Get the target temperature from TD targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); @@ -226,6 +239,7 @@ signalDialysatePumpHardStop( D48_PUMP ); requestConcentratePumpOff( D11_PUMP, FALSE ); requestConcentratePumpOff( D10_PUMP, FALSE ); + requestConcentratePumpOff( D76_PUMP, FALSE ); stopHeater( D5_HEAT ); stopHeater( D45_HEAT ); @@ -235,7 +249,7 @@ setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve - //close the DD - water inlet and drain valves? + //TODO : close the DD - water inlet and drain valves? break; case DD_GEND_ISOLATED_UF_STATE: @@ -264,20 +278,20 @@ // Update any dynamic treatment parameter changes updateTreatmentSettings(); +#ifdef ENABLE_ALARM_2 + //Check dialysate temperature high/low alarms + checkDialysateTemperature(); +#endif + + //Check temperature drift between D30 and D28 + checkDialysateTemperatureSensors(); + //TODO: Transition to post gen dialysate then standby. - if ( TRUE == getU32OverrideValue( &pendingStopDDGenDialRequest ) ) + if ( TRUE == pendingStopDDGenDialRequest ) { - pendingStopDDGenDialRequest.data = FALSE; + pendingStopDDGenDialRequest = FALSE; requestNewOperationMode( DD_MODE_STAN ); } - // Continuous water inlet pressure check - else if ( ( genDialysateState != DD_GEND_DIALYSATE_DELIVERY_PAUSE ) && - ( TRUE == areInletWaterConditionsAlarmsActive() ) ) - { - //Check RO alarms as required - setModeGenDStateTransition( DD_GEND_DIALYSATE_DELIVERY_PAUSE ); - genDialysateState = DD_GEND_DIALYSATE_DELIVERY_PAUSE; - } else { // execute current gen dialysate state @@ -332,7 +346,7 @@ LEVEL_STATE_T floaterLevel = getLevelStatus( D6_LEVL ); //Make sure Water Inlet Valve is open - setValveState( M4_VALV, VALVE_STATE_OPEN ); + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); // High level is met if ( LEVEL_STATE_HIGH == floaterLevel ) @@ -364,7 +378,7 @@ { DD_GEND_MODE_STATE_T state = DD_GEND_ISOLATED_UF_STATE; - //TODO: define isoalted ultrafilteration. + //TODO: define isoalted ultrafiltration. return state; } @@ -423,8 +437,11 @@ //Execute balancing chamber execBalancingChamberControl(); + //Execute ultrafiltration + execUFControl(); + // if TD asks for bypass or dialysate is not good to deliver - //transition to produce dialystate state + //transition to bypass dialystate state if ( ( FALSE == getDialGoodToDeliverStatus() ) || ( TRUE == getTDDialyzerBypass() ) ) { setModeGenDStateTransition( DD_GEND_DIALYSATE_BYPASS_STATE ); @@ -449,7 +466,7 @@ if ( DD_MODE_GEND == getCurrentOperationMode() ) { - pendingStopDDGenDialRequest.data = TRUE; + pendingStopDDGenDialRequest = TRUE; status = TRUE; } @@ -523,6 +540,7 @@ setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); //TODO: update others parameters setting as needed. + signalUFRateUpdate(); //reset the flag isTreatmentParamUpdated = FALSE; @@ -591,6 +609,63 @@ /*********************************************************************//** * @brief + * The checkDialysateTemperature function checks the dialysate temperature + * against the target temperature and alarm if temperature is out of range. + * @details \b Inputs: targetTemp, dialysateTemp + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP when + * dialysate temp goes beyound high safety temperature limit + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP when + * dialysate temp goes beyound high temperature limit + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP when + * dialysate temp goes beyound low temperature limit + * @return none + *************************************************************************/ +static void checkDialysateTemperature( void ) +{ + F32 dialysateTemp = getConductivityTemperatureValue( D29_COND ); // Assuming the closest temp sensor to dialyzer + F32 targetTemp = getTDTargetDialysateTemperature(); + BOOL isDialTempAboveHighSafety = ( dialysateTemp >= DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isDialTempAboveLowSafety = ( dialysateTemp > DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isDialTempBelowLowSafety = ( dialysateTemp < DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ? TRUE : FALSE ); + F32 dialHigh = targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isDialTempAboveDialysateTarget = ( dialysateTemp > dialHigh ? TRUE : FALSE ); + F32 dialLow = targetTemp - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isDialTempBelowDialysateTarget = ( dialysateTemp < dialLow ? TRUE : FALSE ); + BOOL isTempBelowTrigger = (BOOL)( isDialTempBelowLowSafety || isDialTempBelowDialysateTarget ); + BOOL isTempAboveTrigger = (BOOL)( isDialTempAboveLowSafety || isDialTempAboveDialysateTarget ); + + if ( DD_GEND_DIALYSATE_DELIVERY_STATE == genDialysateState ) + { + // check clear condition first + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ) ) + { + isDialTempAboveHighSafety = ( dialysateTemp <= ( targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, isDialTempAboveHighSafety, dialysateTemp, targetTemp ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ) ) + { + isTempAboveTrigger = ( dialysateTemp <= ( targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTempAboveTrigger, dialysateTemp, targetTemp ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ) ) + { + isTempBelowTrigger = ( dialysateTemp >= ( targetTemp - DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTempBelowTrigger, dialysateTemp, targetTemp ); + } + else + { + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, FALSE, dialysateTemp, targetTemp ); + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, FALSE, dialysateTemp, targetTemp ); + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, FALSE, dialysateTemp, targetTemp ); + } +} + +/*********************************************************************//** + * @brief * The publishGenDialysateModeData function broadcasts the generate dialysate * mode data at defined interval. * @details \b Inputs: genDialysateDataPublicationTimerCounter @@ -697,23 +772,6 @@ /*********************************************************************//** * @brief - * The testDDStopGenDialysateOverride function sets the override value - * to stop the gen dialysate operation mode. - * @details Inputs: pendingStopDDGenDialRequest - * @details Outputs: pendingStopDDGenDialRequest - * @param message Override message from Dialin which includes the flag - * to override the operation mode. - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testDDStopGenDialysateOverride( MESSAGE_T *message ) -{ - BOOL result = u32Override( message, &pendingStopDDGenDialRequest, FALSE, TRUE ); - - return result; -} - -/*********************************************************************//** - * @brief * The testGenDExecStateOverride function sets the Gen dialysate execution state * machine to given state. * @details \b Inputs: tester logged in, execStateSet