Index: firmware/App/Controllers/MixingControl.c =================================================================== diff -u -ra631e128cd6be44aa232e23b58a229bfb8fe9043 -rc7d90a953d526f987d4f41f24b59ed64548e6fee --- firmware/App/Controllers/MixingControl.c (.../MixingControl.c) (revision a631e128cd6be44aa232e23b58a229bfb8fe9043) +++ firmware/App/Controllers/MixingControl.c (.../MixingControl.c) (revision c7d90a953d526f987d4f41f24b59ed64548e6fee) @@ -208,10 +208,7 @@ static F32 getDialysateDeltaConductivity( void ); static F32 getDialysateTargetConductivity( void ); -static F32 getTotalConductivity( void ); -static F32 getAcidConducivityPost( void ); static F32 getBicarbConductivityPost( void ); -static F32 getBicarbConductivityPre( void ); static F32 getBicarbKpGainCoefficient( void ); static F32 getBicarbKiGainCoefficient( void ); @@ -576,7 +573,7 @@ * @details \b Outputs: none * @return conductivity *************************************************************************/ -static F32 getTotalConductivity( void ) +F32 getTotalConductivity( void ) { return TOTAL_CONDUCTIVITY; } @@ -588,7 +585,7 @@ * @details \b Outputs: none * @return conductivity *************************************************************************/ -static F32 getAcidConducivityPost( void ) +F32 getAcidConducivityPost( void ) { return ACID_CONDUCTIVITY_POST; } @@ -612,7 +609,7 @@ * @details \b Outputs: none * @return conductivity *************************************************************************/ -static F32 getBicarbConductivityPre( void ) +F32 getBicarbConductivityPre( void ) { return BICARB_CONDUCTIVITY_PRE; } Index: firmware/App/Controllers/MixingControl.h =================================================================== diff -u -r145fd716a856f864f39fb0f9884865f6e45b9256 -rc7d90a953d526f987d4f41f24b59ed64548e6fee --- firmware/App/Controllers/MixingControl.h (.../MixingControl.h) (revision 145fd716a856f864f39fb0f9884865f6e45b9256) +++ firmware/App/Controllers/MixingControl.h (.../MixingControl.h) (revision c7d90a953d526f987d4f41f24b59ed64548e6fee) @@ -66,6 +66,10 @@ F32 getBicarbMixVol( void ); F32 getAcidMixVol( void ); +F32 getBicarbConductivityPre( void ); +F32 getAcidConducivityPost( void ); +F32 getTotalConductivity( void ); + BOOL testMixingControlDataPublishIntervalOverride( MESSAGE_T *message ); BOOL testMixingControlAcidVolumeOverride( MESSAGE_T *message ); Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r145fd716a856f864f39fb0f9884865f6e45b9256 -rc7d90a953d526f987d4f41f24b59ed64548e6fee --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 145fd716a856f864f39fb0f9884865f6e45b9256) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision c7d90a953d526f987d4f41f24b59ed64548e6fee) @@ -21,6 +21,7 @@ #include "ConcentratePumps.h" #include "Conductivity.h" #include "DialysatePumps.h" +#include "MixingControl.h" #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" @@ -58,6 +59,9 @@ #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. +#define DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_PERCENT 5.0F ///< Dialysate conductivity out of target tolerance percent. +#define DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Dialysate conductivity out of target timeout in milliseconds. +#define DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate conductivity clear persistence timeout. #define ZERO_DIAL_FLOW_RATE 0.0F ///< Zero dialysate flow rate #define SPENT_CHAMBER_FILL_MAX_COUNT 10 ///< Total number of spent chamber fill allowed. #define BICARB_CHAMBER_FILL_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Bicarb chamber fill timeout. @@ -107,6 +111,7 @@ static F32 getGenDialysateTargetTemperature( void ); static void updateDialysateToDialyzerFlowRate( void ); static void checkDialysateTemperature( void ); +static void checkDialysateConductivity( void ); static void monitorChamberLevelStatus( void ); static void publishGenDialysateModeData( void ); static U32 getFreshDialPumpInitialRpm( void ); @@ -155,6 +160,13 @@ 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 ); + + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); } /*********************************************************************//** @@ -508,6 +520,9 @@ #ifdef ENABLE_ALARM_2 //Check dialysate temperature high/low alarms checkDialysateTemperature(); + + //Check dialysate, acid, and bicarbonate conductivity high/low alarms + checkDialysateConductivity(); #endif // Update dialysate flow rate only when in the Dialysate Delivery state @@ -1182,6 +1197,110 @@ /*********************************************************************//** * @brief + * The checkDialysateConductivity function checks dialysate, acid, and + * bicarbonate concentrate conductivity against theoretical values. + * @details \b Inputs: filtered conductivity sensor readings, theoretical values + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED when + * dialysate conductivity is below theoretical minus 5% + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED when + * dialysate conductivity is above theoretical plus 5% + * @details \b Alarms: ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW when + * derived acid concentrate conductivity is below theoretical minus 5% + * @details \b Alarms: ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH when + * derived acid concentrate conductivity is above theoretical plus 5% + * @details \b Alarms: ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW when + * bicarbonate concentrate conductivity is below theoretical minus 5% + * @details \b Alarms: ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH when + * bicarbonate concentrate conductivity is above theoretical plus 5% + * @return none + *************************************************************************/ +static void checkDialysateConductivity( void ) +{ + F32 measuredBicarbConductivity = getFilteredConductivity( D17_COND ); + F32 measuredMixedDialysateCond = getFilteredConductivity( D27_COND ); + F32 measuredDialysateConductivity = getFilteredConductivity( D29_COND ); + F32 measuredAcidConductivity = measuredMixedDialysateCond - measuredBicarbConductivity; + F32 theoreticalBicarbConductivity = getBicarbConductivityPre(); + F32 theoreticalAcidConductivity = getAcidConducivityPost(); + F32 theoreticalDialysateConductivity = getTotalConductivity(); + F32 condPercentFactor = ( DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_PERCENT / 100.0F ); + F32 bicarbLowThreshold = theoreticalBicarbConductivity * ( 1.0F - condPercentFactor ); + F32 bicarbHighThreshold = theoreticalBicarbConductivity * ( 1.0F + condPercentFactor ); + F32 acidLowThreshold = theoreticalAcidConductivity * ( 1.0F - condPercentFactor ); + F32 acidHighThreshold = theoreticalAcidConductivity * ( 1.0F + condPercentFactor ); + F32 dialysateLowThreshold = theoreticalDialysateConductivity * ( 1.0F - condPercentFactor ); + F32 dialysateHighThreshold = theoreticalDialysateConductivity * ( 1.0F + condPercentFactor ); + BOOL isBicarbCondBelowTarget = ( measuredBicarbConductivity < bicarbLowThreshold ? TRUE : FALSE ); + BOOL isBicarbCondAboveTarget = ( measuredBicarbConductivity > bicarbHighThreshold ? TRUE : FALSE ); + BOOL isAcidCondBelowTarget = ( measuredAcidConductivity < acidLowThreshold ? TRUE : FALSE ); + BOOL isAcidCondAboveTarget = ( measuredAcidConductivity > acidHighThreshold ? TRUE : FALSE ); + BOOL isDialysateCondBelowTarget = ( measuredDialysateConductivity < dialysateLowThreshold ? TRUE : FALSE ); + BOOL isDialysateCondAboveTarget = ( measuredDialysateConductivity > dialysateHighThreshold ? TRUE : FALSE ); + + if ( ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_CONDUCTIVITY_ALARMS ) ) || + ( theoreticalBicarbConductivity <= 0.0F ) || + ( theoreticalAcidConductivity <= 0.0F ) || + ( theoreticalDialysateConductivity <= 0.0F ) ) + { + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + } + else if ( DD_GEND_DIALYSATE_DELIVERY_STATE == genDialysateState ) + { + if ( TRUE == isAlarmActive( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW ) ) + { + isBicarbCondBelowTarget = ( measuredBicarbConductivity >= bicarbLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, isBicarbCondBelowTarget, measuredBicarbConductivity, theoreticalBicarbConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH ) ) + { + isBicarbCondAboveTarget = ( measuredBicarbConductivity <= bicarbHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, isBicarbCondAboveTarget, measuredBicarbConductivity, theoreticalBicarbConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW ) ) + { + isAcidCondBelowTarget = ( measuredAcidConductivity >= acidLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, isAcidCondBelowTarget, measuredAcidConductivity, theoreticalAcidConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH ) ) + { + isAcidCondAboveTarget = ( measuredAcidConductivity <= acidHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, isAcidCondAboveTarget, measuredAcidConductivity, theoreticalAcidConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED ) ) + { + isDialysateCondBelowTarget = ( measuredDialysateConductivity >= dialysateLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, isDialysateCondBelowTarget, measuredDialysateConductivity, theoreticalDialysateConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED ) ) + { + isDialysateCondAboveTarget = ( measuredDialysateConductivity <= dialysateHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, isDialysateCondAboveTarget, measuredDialysateConductivity, theoreticalDialysateConductivity ); + } + else + { + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + } +} + +/*********************************************************************//** + * @brief * The publishGenDialysateModeData function broadcasts the generate dialysate * mode data at defined interval. * @details \b Inputs: genDialysateDataPublicationTimerCounter