Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r2f3090feeb06eb738aefc8eae5f080070a0a8919 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2f3090feeb06eb738aefc8eae5f080070a0a8919) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -31,6 +31,7 @@ #include "Reservoirs.h" #include "ROPump.h" #include "SystemComm.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" @@ -52,6 +53,7 @@ #define BICARB_PUMP_40_ML_PER_MIN 40.0 ///< Bicarb pump speed of 40.0 mL/minute. #define CONCENTRATE_PUMP_40_ML_PER_MIN 40.0 ///< Concentrate pump speed of 40.0 mL/minute. +#define FILL_MODE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the fill mode data is published on the CAN bus. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. #define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 1 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. @@ -97,6 +99,18 @@ BOOL isThisFirstFill; ///< Fill flag to indicate whether it is the first fill or not. } FILL_CONDITION_STATUS_T; +/// DG broadcast dialysate fill data structure. +typedef struct +{ + F32 averageBicardConductivity; ///< The average bicarb conductivity calculated in one fill. + F32 averageAcidConductivity; ///< The average acid conductivity calculated in one fill. + BOOL isThisTheFirstFill; ///< Indicate if this is the first fill. + F32 pctDiffInConductivity; ///< The percent difference between CD1 and CD2. + F32 usedAcidVolumeML; ///< The used acid volume in ML. + F32 usedBicarbVolumeML; ///< The used bicarb volume in ML. +} DG_FILL_DIALYSATE_DATA_T; + +static U32 fillModeDataPublicationTimerCounter; ///< Used to schedule dialysate fill data publication to CAN bus. static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. @@ -125,6 +139,9 @@ static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. static OVERRIDE_F32_T usedBicarbVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in mL. +static OVERRIDE_U32_T fillModeDataPublishInterval = { FILL_MODE_DATA_PUB_INTERVAL, + FILL_MODE_DATA_PUB_INTERVAL, + 0, 0 }; ///< Interval (in ms) at which to publish fill mode data to CAN bus. static F32 roPumpFlushBubblesSpeed[ RO_PUMP_LOOKUP_TABLE_SIZE ] = { RO_PUMP_400_ML_PER_MIN, ///< Lookup table to determine the desired RO speed in mL/min when flushing bubbles. RO_PUMP_800_ML_PER_MIN, @@ -149,6 +166,7 @@ static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); static void setFillInfoToRTCRAM( void ); static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ); +static void publishFillModeData( void ); /*********************************************************************//** * @brief @@ -164,6 +182,7 @@ { fillState = DG_FILL_MODE_STATE_START; dialysateFillStartTime = 0; + fillModeDataPublicationTimerCounter = 0; reservoirBaseWeight = 0.0; totalROFlowRateMLPM = 0.0; concentrateTestStartTime = 0; @@ -234,6 +253,7 @@ checkInletPressure(); checkRORejectionRatio(); checkDialysateTemperatureSensorsDrift(); + publishFillModeData(); // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir @@ -646,8 +666,9 @@ F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); - BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); + // Continuous conductivity testing will be implemented in the next phase + //BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); + //BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( measuredROFlowRateMLPM ); @@ -677,9 +698,9 @@ #endif #ifndef DISABLE_MIXING - // Detect empty bottles using integrated volumes and conductivity sensors - if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 437 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) + // Detect empty bottles using integrated volumes // TODO: empty bottles detection using conductivity sensors + if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 437 + //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) { usedAcidVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -689,8 +710,8 @@ result = DG_FILL_MODE_STATE_PAUSED; } - if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 438 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) + if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 438 + //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) { usedBicarbVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -903,4 +924,177 @@ setHeatersInfoRecord( (U08*)&record ); } +/*********************************************************************//** + * @brief + * The publishFillModeData function publishes dialysate fill data + * at the set interval. + * @details Inputs: fillModeDataPublicationTimerCounter + * @details Outputs: fillModeDataPublicationTimerCounter + * @return none + *************************************************************************/ +static void publishFillModeData( void ) +{ + // publish Drain pump data on interval + if ( ++fillModeDataPublicationTimerCounter >= getU32OverrideValue( &fillModeDataPublishInterval ) ) + { + DG_FILL_DIALYSATE_DATA_T fillModeData; + + // Populate the data structure for publication + fillModeData.averageAcidConductivity = averageAcidConductivity; + fillModeData.averageBicardConductivity = averageBicardConductivity; + fillModeData.isThisTheFirstFill = isThisTheFirstFill(); + fillModeData.pctDiffInConductivity = pctDiffInConductivity; + fillModeData.usedAcidVolumeML = usedAcidVolumeML.data; + fillModeData.usedBicarbVolumeML = usedBicarbVolumeML.data; + + broadcastData( MSG_ID_DRAIN_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&fillModeData, sizeof( DG_FILL_DIALYSATE_DATA_T ) ); + + fillModeDataPublicationTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetUsedAcidVolumeMLOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedAcidVolumeML.ovInitData = usedAcidVolumeML.data; + usedAcidVolumeML.ovData = value; + usedAcidVolumeML.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetUsedAcidVolumeMLOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedAcidVolumeML.data = usedAcidVolumeML.ovInitData; + usedAcidVolumeML.override = OVERRIDE_RESET; + usedAcidVolumeML.ovInitData = 0.0; + usedAcidVolumeML.ovData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetUsedBicarbVolumeMLOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedBicarbVolumeML.ovInitData = usedBicarbVolumeML.data; + usedBicarbVolumeML.ovData = value; + usedBicarbVolumeML.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetUsedBicarbVolumeMLOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedBicarbVolumeML.data = usedBicarbVolumeML.ovInitData; + usedBicarbVolumeML.override = OVERRIDE_RESET; + usedBicarbVolumeML.ovInitData = 0.0; + usedBicarbVolumeML.ovData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetDialysateFlowDataPublishIntervalOverride function overrides the + * Dialysate flow data publish interval. + * @details Inputs: dialysateFlowDataPublishInterval + * @details Outputs: dialysateFlowDataPublishInterval + * @param: value override Dialysate flow data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFillModeDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_GENERAL_INTERVAL; + fillModeDataPublishInterval.ovData = intvl; + fillModeDataPublishInterval.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetDialysateFlowDataPublishIntervalOverride function resets the + * override of the dialysate flow data publish interval. + * @details Inputs: dialysateFlowDataPublishInterval + * @details Outputs: dialysateFlowDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetFillModeDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + fillModeDataPublishInterval.override = OVERRIDE_RESET; + fillModeDataPublishInterval.ovData = fillModeDataPublishInterval.ovInitData; + result = TRUE; + } + + return result; +} + /**@}*/