Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r2b7580660f89067dd78f91701dbd1a5b71bbdbba -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 2b7580660f89067dd78f91701dbd1a5b71bbdbba) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -8,7 +8,7 @@ * @file BloodFlow.c * * @author (last) Sean Nash -* @date (last) 08-Mar-2023 +* @date (last) 28-Mar-2023 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -90,7 +90,7 @@ #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. #define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. -#define BP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. +#define BP_MAX_CURR_ERROR_DURATION_MS 5000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define BLOODPUMP_ADC_FULL_SCALE_V 3.0F ///< BP analog signals are 0-3V (while int. ADC ref may be different). #define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -re84a4b77954afb6f0c656bcf605d56c9861e77fc -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision e84a4b77954afb6f0c656bcf605d56c9861e77fc) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -43,16 +43,19 @@ #define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. -#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 2.0F ///< Dialysate temperature out of target tolerance C. -#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. -#define DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C 46.0F ///< Dialysate high safety temperature limit in C. -#define DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature high safety timeout in milliseconds. -#define DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C 42.0F ///< Dialysate low safety temperature limit in C. -#define DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature low safety timeout in milliseconds. -#define DG_DATA_FRESHNESS_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< DG data freshness timeout (in ms). -#define DG_TRIMMER_HTR_CHECK_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL + 2 ) ///< DG trimmer heater check interval in general task execution time counts. +#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 ( 300 * 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_UPPER_SAFETY_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature upper bound timeout in milliseconds. +#define DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C 33.0F ///< Dialysate lower bound safety temperature limit in C. +#define DIALYSATE_TEMP_LOWER_SAFETY_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature lower bound timeout in milliseconds. +#define DIALYSATE_TEMP_CLEAR_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Dialysate temperature clear persistence timeout. +#define DG_DATA_FRESHNESS_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< DG data freshness timeout (in ms). +#define DG_TRIMMER_HTR_CHECK_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL + 2 ) ///< DG trimmer heater check interval in general task execution time counts. - // ********** private data ********** // DG status @@ -177,11 +180,12 @@ lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0F; lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0F; - initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_HIGH_SAFETY_RANGE, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_LOW_SAFETY_RANGE, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_UPPER_SAFETY_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_LOW_SAFETY_RANGE, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_LOWER_SAFETY_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_NEW_DIALYSATE_TEMPERATURE_DATA_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); @@ -458,14 +462,14 @@ /*********************************************************************//** * @brief - * The getDialysateTemperature function gets the latest dialysate temperature. - * @details Inputs: dgDialysateTemp + * The getDGDisinfectsStates function returns the DG disinfects readings. + * @details Inputs: none * @details Outputs: none - * @return the current dialysate temperature + * @return the current DG disinfects readings *************************************************************************/ -F32 getDialysateTemperature( void ) +DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) { - return dgDialysateTemp; + return disinfectsStatus; } /*********************************************************************//** @@ -499,11 +503,11 @@ * The getDGDisinfectsStates function returns the DG disinfects readings. * @details Inputs: none * @details Outputs: none - * @return the current DG disinfects readings + * @return the current dialysate temperature *************************************************************************/ -DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +F32 getDialysateTemperature( void ) { - return disinfectsStatus; + return dgDialysateTemp; } /*********************************************************************//** @@ -1174,23 +1178,51 @@ *************************************************************************/ void checkDialysateTemperature( void ) { - BOOL isTDiTempAboveHighSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ? TRUE : FALSE ); - BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDiTempAboveHighSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDITempBelowLowSafety = ( dgDialysateTemp <= DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ? TRUE : FALSE ); F32 TDiHigh = dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; - BOOL isTDiTempAboveDialysateTarget = ( TDiHigh >= dgDialysateTemp ? TRUE : FALSE ); + BOOL isTDiTempAboveDialysateTarget = ( dgDialysateTemp >= TDiHigh ? TRUE : FALSE ); F32 TDiLow = dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; - BOOL isTDiTempBelowDialysateTarget = ( TDiLow >= dgDialysateTemp ? TRUE : FALSE ); + BOOL isTDiTempBelowDialysateTarget = ( dgDialysateTemp <= TDiLow ? TRUE : FALSE ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - // Per PRS 377, PRS 124 - checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, isTDiTempAboveHighSafety, dgDialysateTemp, DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ); - checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, isTDiTempAboveLowSafety, dgDialysateTemp, DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ); + // Per PRS 866 + if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_HIGH_SAFETY_RANGE ) ) + { + isTDiTempAboveHighSafety = ( dgDialysateTemp <= ( dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_HIGH_SAFETY_RANGE, isTDiTempAboveHighSafety, dgDialysateTemp, DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C ); - checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTDiTempAboveDialysateTarget, dgDialysateTemp, TDiHigh ); - checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTDiTempBelowDialysateTarget, dgDialysateTemp, TDiLow ); + // Per PRS 377 + if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ) ) + { + isTDiTempAboveDialysateTarget = ( dgDialysateTemp <= ( dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTDiTempAboveDialysateTarget, dgDialysateTemp, TDiHigh ); + + if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_LOW_SAFETY_RANGE ) ) + { + isTDiTempAboveLowSafety = ( dgDialysateTemp <= ( dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_LOW_SAFETY_RANGE, isTDiTempAboveLowSafety, dgDialysateTemp, DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ); + + // Per PRS 124 + if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ) ) + { + isTDiTempBelowDialysateTarget = ( dgDialysateTemp >= ( dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTDiTempBelowDialysateTarget, dgDialysateTemp, TDiLow ); + + if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_LOW_SAFETY_RANGE ) ) + { + isTDITempBelowLowSafety = ( dgDialysateTemp >= ( dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_LOW_SAFETY_RANGE, isTDITempBelowLowSafety, dgDialysateTemp, DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ); + } } Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r8036381b5c41ab87146c929eeeb9ba073efd4541 -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 8036381b5c41ab87146c929eeeb9ba073efd4541) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -121,6 +121,7 @@ F32 getHeatDisinfectTemperatureSensorValue( void ); BOOL getTrimmerHeaterCommandedOn( void ); DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ); +F32 getDialysateTemperature( void ); DG_MIXING_RATIOS_T getDGMixingRatios( void ); void getHDVersionDGServiceAndUsageData( DG_SERVICE_AND_USAGE_DATA_T* data ); Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r3a230bfa79e1f80038e8c243499f8ef7ea11ff60 -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 3a230bfa79e1f80038e8c243499f8ef7ea11ff60) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -8,7 +8,7 @@ * @file DialInFlow.c * * @author (last) Sean Nash -* @date (last) 08-Mar-2023 +* @date (last) 28-Mar-2023 * * @author (original) Sean * @date (original) 16-Dec-2019 @@ -90,7 +90,7 @@ #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. #define DIP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. -#define DIP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. +#define DIP_MAX_CURR_ERROR_DURATION_MS 5000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define DIAL_IN_PUMP_ADC_FULL_SCALE_V 3.0F ///< BP analog signals are 0-3V (while int. ADC ref V may be different). #define DIAL_IN_PUMP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. @@ -1550,15 +1550,10 @@ **************************************************************************/ static BOOL setDialInPumpToFixedPWM( F32 pwm ) { - MOTOR_DIR_T dir = MOTOR_DIR_FORWARD; + MOTOR_DIR_T dir = ( pwm < 0.0F ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); BOOL result = FALSE; F32 pwmFabs = fabs(pwm); - if ( pwm < 0 ) - { - dir = MOTOR_DIR_REVERSE; - } - // Direction change while pump is running is not allowed unless we are turning off if ( ( FALSE == isDialInPumpOn ) && ( dir != dialInPumpDirectionSet ) ) { @@ -1942,14 +1937,12 @@ BOOL result = FALSE; F32 absolutePWM = fabs( pwmPct ); - if ( TRUE == isTestingActivated() ) + // check for max of pump pwm for acceptance. *** Function used in dialyzer re-prime, so no Dialin login required *** + if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) { - // check for max of pump pwm for acceptance. - if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) - { - result = setDialInPumpToFixedPWM( pwmPct ); - } + result = setDialInPumpToFixedPWM( pwmPct ); } + return result; } Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r2b7580660f89067dd78f91701dbd1a5b71bbdbba -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 2b7580660f89067dd78f91701dbd1a5b71bbdbba) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -8,7 +8,7 @@ * @file DialOutFlow.c * * @author (last) Sean Nash -* @date (last) 18-Jan-2023 +* @date (last) 23-Mar-2023 * * @author (original) Sean * @date (original) 24-Jan-2020 @@ -53,7 +53,7 @@ #define MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE 0.0133F ///< Maximum duty cycle change when ramping up ~ 200 mL/min/s. #define MAX_DIAL_OUT_PUMP_PWM_STEP_DN_CHANGE 0.02F ///< Maximum duty cycle change when ramping down ~ 300 mL/min/s. -#define MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.89F ///< Controller will error if PWM duty cycle > 90%, so set max to 89%. +#define MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.90F ///< Controller will error if PWM duty cycle > 90%, so set max to 89%. #define MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.10F ///< Controller will error if PWM duty cycle < 10%, so set min to 10%. #define MAX_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL 0.4F ///< Maximum PWM offset (added to DPi PWM duty cycle). #define MIN_DIAL_OUT_PUMP_PWM_OFFSET_CONTROL -0.4F ///< Minimum PWM offset (added to DPi PWM duty cycle). @@ -89,7 +89,7 @@ #define DOP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. #define DOP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. -#define DOP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. +#define DOP_MAX_CURR_ERROR_DURATION_MS 5000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define DOP_ADC_FULL_SCALE_V 3.0F ///< DPo analog signals are 0-3V (while int. ADC ref V may be different). #define DOP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. @@ -113,6 +113,8 @@ #define DOP_MOTOR_SPEED_RPM_TO_PWM(rpm) ( ( (F32)(rpm) / DOP_100_PCT_PWM_RPM_RANGE ) + DOP_PWM_ZERO_OFFSET ) /// Macro converts a PWM to an estimated flow rate. #define DOP_ML_PER_MIN_FROM_PWM(pwm) ( ( ( pwm - DOP_PWM_ZERO_OFFSET ) - 0.0972F ) / 0.0009F ) +/// Macro converts a PWM to an estimated flow rate (basic version). +#define DOP_ML_PER_MIN_FROM_PWM_BASIC(pwm) ( ( ( ( pwm ) - DOP_PWM_ZERO_OFFSET ) * DOP_100_PCT_PWM_RPM_RANGE ) * 0.2 ) #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. #define DOP_MIN_DIR_CHECK_SPEED_RPM 10.0F ///< Minimum motor speed before we check pump direction. @@ -221,6 +223,7 @@ static void resetDialOutFlowMovingAverage( void ); static void filterDialOutFlowReadings( F64 flow ); +static BOOL setDialOutPumpToFixedPWM( F32 pwm ); /*********************************************************************//** * @brief @@ -1194,6 +1197,73 @@ /*********************************************************************//** * @brief + * The setDialOutPumpToFixedPWM function sets a new pwm value and pump direction. + * @details Inputs: isDialOutPumpOn, dialOutPumpPWMDutyCyclePct, dialOutPumpDirectionSet, + * dialOutPumpState + * @details Outputs: dialOutPumpControlMode, dialOutPumpDirection, dialOutPumpPWMDutyCyclePct + * @param pwm the new pwm value + * @return TRUE if new flow rate & dir are set, FALSE if not + **************************************************************************/ +static BOOL setDialOutPumpToFixedPWM( F32 pwm ) +{ + MOTOR_DIR_T dir = ( pwm < 0.0F ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); + BOOL result = FALSE; + F32 pwmFabs = fabs(pwm); + + // Direction change while pump is running is not allowed unless we are turning off + if ( ( FALSE == isDialOutPumpOn ) && ( dir != dialOutPumpDirectionSet ) ) + { + dialOutPumpDirection = dir; + } + + // Direction change while pump is running is not allowed + if ( ( ( FALSE == isDialOutPumpOn ) || ( dir == dialOutPumpDirectionSet ) ) || ( pwmFabs <= MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ) ) + { + // Don't interrupt pump control unless rate is changing + if ( ( pwmFabs != dialOutPumpPWMDutyCyclePct ) ) + { + resetDialOutFlowMovingAverage(); + dialOutPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; + dialOutPumpPWMDutyCyclePct = RANGE( pwmFabs, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); + lastGivenRate = DOP_ML_PER_MIN_FROM_PWM_BASIC( pwmFabs ); + + switch ( dialOutPumpState ) + { + case DIAL_OUT_PUMP_RAMPING_UP_STATE: // See if we need to reverse direction of ramp + if ( dialOutPumpPWMDutyCyclePct < dialOutPumpPWMDutyCyclePctSet ) + { + dialOutPumpState = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; + } + break; + case DIAL_OUT_PUMP_RAMPING_DOWN_STATE: // See if we need to reverse direction of ramp + if ( dialOutPumpPWMDutyCyclePct > dialOutPumpPWMDutyCyclePctSet ) + { + dialOutPumpState = DIAL_OUT_PUMP_RAMPING_UP_STATE; + } + break; + case DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE: // Start ramp to new target in appropriate direction + if ( dialOutPumpPWMDutyCyclePctSet > dialOutPumpPWMDutyCyclePct ) + { + dialOutPumpState = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; + } + else + { + dialOutPumpState = DIAL_OUT_PUMP_RAMPING_UP_STATE; + } + break; + default: + // Ok - not all states need to be handled here + break; + } + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief * The getTotalTargetDialOutUFVolumeInMl function gets the target UF volume. * @details Inputs: referenceUFVolumeInMl * @details Outputs: none @@ -1688,17 +1758,12 @@ BOOL testSetDialOutPumpTargetDutyCycle( F32 value ) { BOOL result = FALSE; - F32 targetRate = DOP_ML_PER_MIN_FROM_PWM( value ); + F32 absolutePWM = fabs( value ); - if ( TRUE == isTestingActivated() ) + // check for max of pump pwm for acceptance. *** Function used in dialyzer re-prime, so no Dialin login required *** + if ( absolutePWM < MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ) { - // currently conversion can create negative values with values <= 10%. - if ( targetRate < 0 ) - { - targetRate = 0; - } - setDialOutPumpTargetRate( (U32)targetRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - result = TRUE; + result = setDialOutPumpToFixedPWM( value ); } return result; Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r43b49f38bc7fec96c04a71fd1a1ef7adeebf8fc4 -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 43b49f38bc7fec96c04a71fd1a1ef7adeebf8fc4) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -8,7 +8,7 @@ * @file PresOccl.c * * @author (last) Sean Nash -* @date (last) 03-Mar-2023 +* @date (last) 28-Mar-2023 * * @author (original) Sean * @date (original) 15-Jan-2020 @@ -63,17 +63,17 @@ #define ARTERIAL_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum arterial pressure reading (in mmHg) for range check. #define ARTERIAL_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum arterial pressure reading (in mmHg) for range check. -#define ARTERIAL_PRESSURE_ND_MIN_MMHG ( -250.0F ) ///< Minimum arterial pressure reading (in mmHg) when not dialyzing. #define VENOUS_PRESSURE_SELF_TEST_MIN ( -100.0F ) ///< Minimum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum venous pressure reading (in mmHg) for range check. -#define VENOUS_PRESSURE_ND_MAX_MMHG ( 300.0F ) ///< Maximum venous pressure reading (in mmHg) when not dialyzing. #define VENOUS_PRESSURE_OCCL_OFFSET_MMHG ( 50.0F ) ///< Venous pressure occlusion threshold offset from max alarm limit (in mmHg). +#define VENOUS_PRESSURE_LIMIT_DELAY_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Venous pressure limit delay period following dialysis start/resume (use wider limits during this period). #define PSI_TO_MMHG ( 51.7149F ) ///< Conversion factor for converting PSI to mmHg. +// The new arterial pressure sensor is the same as the venous pressure sensor #define VENOUS_PRESSURE_NORMAL_OP 0 ///< Venous pressure status bits indicate normal operation. #define VENOUS_PRESSURE_CMD_MODE 1 ///< Venous pressure status bits indicate sensor in command mode. #define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). @@ -165,6 +165,7 @@ static U32 venPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. static F32 venPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. static U32 venPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. +static U32 venPressureLimitDelayStart; ///< Time stamp for last time dialysis started/resumed. static PRESSURE_SELF_TEST_STATE_T presOcclPostState; ///< Pressure self test post state. static HD_PRESSURE_SENSORS_CAL_RECORD_T pressureSensorsCalRecord; ///< Pressure sensors calibration record. static HD_OCCLUSION_SENSORS_CAL_RECORD_T occlusionSensorsCalRecord; ///< Occlusion sensors calibration record. @@ -208,13 +209,14 @@ initFPGAPersistentAlarm( FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, ALARM_ID_HD_VENOUS_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); - longFilteredArterialPressure = 0.0F; - shortFilteredArterialPressure = 0.0F; - shortFilteredVenousPressure = 0.0F; - presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - presOcclState = PRESSURE_WAIT_FOR_POST_STATE; - presOcclPostState = PRESSURE_SELF_TEST_STATE_START; + longFilteredArterialPressure = 0.0F; + shortFilteredArterialPressure = 0.0F; + shortFilteredVenousPressure = 0.0F; + presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + presOcclState = PRESSURE_WAIT_FOR_POST_STATE; + presOcclPostState = PRESSURE_SELF_TEST_STATE_START; bloodPumpOcclusionAfterCartridgeInstall = 0; + venPressureLimitDelayStart = 0; } /*********************************************************************//** @@ -302,6 +304,20 @@ } } +/*********************************************************************//** + * @brief + * The signalStartDialysisStartOrResume function signals that dialysis has + * just been started or resumed which begins a brief time window where + * venous pressure limits are relaxed while treatment reaches stability. + * @details Inputs: none + * @details Outputs: venPressureLimitDelayStart + * @return none + *************************************************************************/ +void signalStartDialysisStartOrResume( void ) +{ + venPressureLimitDelayStart = getMSTimerCount(); +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. @@ -470,12 +486,12 @@ // Check arterial pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || - ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || - ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( DIALYSIS_UF_STATE == getDialysisState() ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + BOOL artPresLow, artPresHigh; // If BP is ramping up, extend range to outer limits as pressure may not yet have reached expected range. if ( isBloodPumpRampComplete() != TRUE ) @@ -484,24 +500,36 @@ artHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); } + artPresLow = ( artPres < artLowLimit ? TRUE : FALSE ); + artPresHigh = ( artPres > artHighLimit ? TRUE : FALSE ); + // Check arterial pressure is within user set alarm limits - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); } } else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if above { - // Check arterial pressure is within non-treatment alarm limits - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < ARTERIAL_PRESSURE_ND_MIN_MMHG ) ) + F32 artLowLimit = (F32)getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + F32 artHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + BOOL artPresLow = ( artPres < artLowLimit ? TRUE : FALSE ); + BOOL artPresHigh = ( artPres > artHighLimit ? TRUE : FALSE ); + + // Check arterial pressure is within max selectable range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPresLow ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, ARTERIAL_PRESSURE_ND_MIN_MMHG ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPresHigh ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); + } } else { // Reset persistence if alarm is out of scope @@ -537,12 +565,12 @@ // Check venous pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || - ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || - ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( DIALYSIS_UF_STATE == getDialysisState() ) && ( TRUE == didTimeout( venPressureLimitDelayStart, VENOUS_PRESSURE_LIMIT_DELAY_MS ) ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + BOOL venPresLow, venPresHigh; // If BP is ramping up, extend range to outer limits as pressure may not yet have reached expected range. if ( isBloodPumpRampComplete() != TRUE ) @@ -551,10 +579,13 @@ venHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); } + venPresLow = ( venPres < venLowLimit ? TRUE : FALSE ); + venPresHigh = ( venPres > venHighLimit ? TRUE : FALSE ); + // Cannot monitor for low venous pressure while venting air trap if ( getValveAirTrapStatus() != STATE_OPEN ) { - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); } @@ -564,19 +595,27 @@ isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } } else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if statement above { - // Check venous pressure is less than non-treatment alarm limit - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > VENOUS_PRESSURE_ND_MAX_MMHG ) ) + F32 venLowLimit = (F32)getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + F32 venHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + BOOL venPresLow = ( venPres < venLowLimit ? TRUE : FALSE ); + BOOL venPresHigh = ( venPres > venHighLimit ? TRUE : FALSE ); + + // Check venous pressure is within max selectable range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPresHigh ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, VENOUS_PRESSURE_ND_MAX_MMHG ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } - isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPresLow ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + } } else { // Reset persistence if alarm is out of scope @@ -637,7 +676,6 @@ } } } - // Check for occlusion in Treatment modes where pumps are moving else if ( MODE_TREA == getCurrentOperationMode() ) { Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r9d9654c846b21b8e09b0840097e5bf39d58e300f -ra6d1ff9f7223af8efaa54f47c217d44391740405 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 9d9654c846b21b8e09b0840097e5bf39d58e300f) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision a6d1ff9f7223af8efaa54f47c217d44391740405) @@ -48,11 +48,11 @@ #define PRE_TREATMENT_FLUSH_FILL_TARGET_TEMP_C 45.0F ///< Pre treatment flush fill target temperature in C. #define PRE_TREATMENT_NORMAL_FILL_TARGET_TEMP_C ( 37.0F + 2.0F ) ///< Pre treatment normal fill target temperature in C. -#define PRE_TREATMENT_MIN_FILL_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume minimum to prep volume during development. -#define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume (in mL) to flush filter and lines. -#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. -#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 600 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. -#define PRE_TREATMENT_FULL_RESERVOIR_VOLUME_ML 1500 ///< Fill reservoir to this volume minimum to prep volume during development. +#define PRE_TREATMENT_MIN_FILL_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume minimum to prep volume during development. +#define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume (in mL) to flush filter and lines. +#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 750 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FULL_RESERVOIR_VOLUME_ML 1500 ///< Fill reservoir to this volume minimum to prep volume during development. #define PRE_TREATMENT_FLUSH_COUNT 2 ///< Number of flush cycles for each reservoir.