Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r8b75fd11dd632fd4bccc6f28f1c757eae5b07c2b -ra4e044315bbfaaeff11cb9391485897458a48a5f --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 8b75fd11dd632fd4bccc6f28f1c757eae5b07c2b) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision a4e044315bbfaaeff11cb9391485897458a48a5f) @@ -7,8 +7,8 @@ * * @file DialOutFlow.c * -* @author (last) Dara Navaei -* @date (last) 15-Jun-2022 +* @author (last) Michael Garthwaite +* @date (last) 12-Oct-2022 * * @author (original) Sean * @date (original) 24-Jan-2020 @@ -27,6 +27,7 @@ #include "ModeTreatment.h" #include "NVDataMgmt.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "PIControllers.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" @@ -104,11 +105,16 @@ #define DOP_PWM_ZERO_OFFSET 0.1F ///< 10% PWM duty cycle = zero speed. /// Macro converts a flow rate to an estimated PWM duty cycle %. -#define DOP_PWM_FROM_ML_PER_MIN(rate) ( ( (rate) * 0.0009 ) + 0.0972 + DOP_PWM_ZERO_OFFSET ) +#define DOP_PWM_FROM_ML_PER_MIN(rate) ( ( ( rate ) * 0.0009F ) + 0.0972F + DOP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. -#define DOP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - DOP_PWM_ZERO_OFFSET) * 4000.0F ) +#define DOP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ( ( pwm ) - DOP_PWM_ZERO_OFFSET) * 4000.0F ) +/// 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 ) #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. +#define DOP_COMMUTATION_ERROR_MAX_CNT 3 ///< Maximum number of commutation errors within time window before alarm triggered. +#define DOP_COMMUTATION_ERROR_TIME_WIN_MS (15 * MS_PER_SECOND) ///< Time window for DPo commutation error. #define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. /// Enumeration of dialysate outlet pump controller states. @@ -240,6 +246,8 @@ ufMeasuredRate = 0.0; dopRateCorrectionOffset = 0.0; resetDialOutFlowMovingAverage(); + + initTimeWindowedCount( TIME_WINDOWED_COUNT_DOP_COMMUTATION_ERROR, DOP_COMMUTATION_ERROR_MAX_CNT, DOP_COMMUTATION_ERROR_TIME_WIN_MS ); } /*********************************************************************//** @@ -561,6 +569,10 @@ // Check for home position, zero/low speed checkDialOutPumpRotor(); } + else + { + lastDialOutPumpDirectionCount = getFPGADialOutPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; + } publishDialOutFlowData(); } @@ -931,24 +943,27 @@ { MOTOR_DIR_T dopMCDir, dopDir; U08 dirErrorCnt = getFPGADialOutPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; + F32 measMCSpeed = getMeasuredDialOutPumpMCSpeed(); + BOOL minDirSpeed = ( measMCSpeed >= DOP_MIN_DIR_CHECK_SPEED_RPM ? TRUE : FALSE ); + BOOL isHallSensorFailed = ( TRUE == minDirSpeed && lastDialOutPumpDirectionCount != dirErrorCnt ? TRUE : FALSE ); // Check pump direction error count + if ( ( TRUE == isHallSensorFailed ) && ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_DOP_COMMUTATION_ERROR ) ) ) + { #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif - { - if ( lastDialOutPumpDirectionCount != dirErrorCnt ) { - lastDialOutPumpDirectionCount = dirErrorCnt; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_DIALYSATE_OUTLET_PUMP ) } } + lastDialOutPumpDirectionCount = dirErrorCnt; dopMCDir = ( getMeasuredDialOutPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); dopDir = ( getMeasuredDialOutPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); // Check set direction vs. direction from hall sensors - if ( dialOutPumpDirectionSet != dopDir ) + if ( ( dialOutPumpDirectionSet != dopDir ) && ( TRUE == minDirSpeed ) ) { if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) { @@ -961,7 +976,7 @@ } } // Check set direction vs. direction from sign of motor controller speed - else if ( dialOutPumpDirectionSet != dopMCDir ) + else if ( ( dialOutPumpDirectionSet != dopMCDir ) && ( TRUE == minDirSpeed ) ) { if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) { @@ -1091,49 +1106,52 @@ { F32 dopCurr; - // DialOut pump should be off - if ( DIAL_OUT_PUMP_OFF_STATE == dialOutPumpState ) + if ( FALSE == isAlarmActive( ALARM_ID_HD_AC_POWER_LOST ) ) { - dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); - if ( dopCurr > DOP_MAX_CURR_WHEN_STOPPED_MA ) + // DialOut pump should be off + if ( DIAL_OUT_PUMP_OFF_STATE == dialOutPumpState ) { - dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) + dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); + if ( dopCurr > DOP_MAX_CURR_WHEN_STOPPED_MA ) { + dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; + if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) + { #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); + } } } + else + { + dopCurrErrorDurationCtr = 0; + } } + // DialOut pump should be running else { - dopCurrErrorDurationCtr = 0; - } - } - // DialOut pump should be running - else - { - dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); - if ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) - { - dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) + dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); + if ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) -#endif + dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; + if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); + #ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) + #endif + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); + } } } + else + { + dopCurrErrorDurationCtr = 0; + } } - else - { - dopCurrErrorDurationCtr = 0; - } } } @@ -1627,4 +1645,32 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetBloodPumpTargetDutyCycle function sets the duty cycle of the + * blood pump by calling setDialOutPumpTargetRate. + * @details Inputs: none + * @details Outputs: none + * @param value duty cycle of the dialysate outlet pump (as a percentage). + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testSetDialOutPumpTargetDutyCycle( F32 value ) +{ + BOOL result = FALSE; + F32 targetPWM = DOP_ML_PER_MIN_FROM_PWM(value) ; + + if ( TRUE == isTestingActivated() ) + { + // currently conversion can create negative values with values <= 10%. + if ( targetPWM < 0 ) + { + targetPWM = 0; + } + setDialOutPumpTargetRate( (U32)targetPWM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + result = TRUE; + } + + return result; +} + /**@}*/