Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -48,11 +48,20 @@ #define BP_P_COEFFICIENT 0.00005 ///< P term for blood pump control #define BP_I_COEFFICIENT 0.00015 ///< I term for blood pump control -#define BP_HOME_RATE 50 ///< target pump speed (in estimate mL/min) for homing. +#define BP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define BP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). #define BP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the blood pump speed is calculated. #define BP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. +#define BP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN 50.0 ///< maximum difference between measured flow and flow implied by measured motor speed. +#define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. +#define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< maximum difference in speed between motor and rotor (in rotor RPM). +#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< maximum difference in speed between measured and commanded RPM. +#define BP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for flow vs. motor speed error condition. +#define BP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define BP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define BP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. + #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< motor controller current should not exceed this when pump should be stopped #define BP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< motor controller current should always exceed this when pump should be running #define BP_MAX_CURR_WHEN_RUNNING_MA 1000.0 ///< motor controller current should not exceed this when pump should be running @@ -139,6 +148,11 @@ static MOTOR_DIR_T bpMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count static U32 bpMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating blood pump motor speed from hall sensor count. +static U32 errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. +static U32 errorBloodMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. +static U32 errorBloodMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. +static U32 errorBloodRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. + static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< holds flow samples for a rolling average static U32 flowReadingsIdx = 0; ///< index for next sample in rolling average array static F32 flowReadingsTotal = 0.0; ///< rolling total - used to calc average @@ -352,18 +366,18 @@ // calculate blood pump motor speed/direction from hall sensor count updateBloodPumpSpeedAndDirectionFromHallSensors(); - // check pump speeds and flow - checkBloodPumpSpeeds(); - checkBloodPumpFlowAgainstSpeed(); - - // check for home position, zero/low speed - checkBloodPumpRotor(); - // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { + // check pump direction checkBloodPumpDirection(); + // check pump controller current checkBloodPumpMCCurrent(); + // check pump speeds and flow + checkBloodPumpSpeeds(); + checkBloodPumpFlowAgainstSpeed(); + // check for home position, zero/low speed + checkBloodPumpRotor(); } // publish blood flow data on interval @@ -990,24 +1004,139 @@ bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); if ( ( bloodPumpDirectionSet != bpMCDir ) || ( bloodPumpDirectionSet != bpMotorDirectionFromHallSensors ) ) { +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMotorDirectionFromHallSensors ) +#endif } } } +/*********************************************************************//** + * @brief + * The checkBloodPumpSpeeds function checks several aspects of the blood pump \n + * speed. \n + * 1. while pump is commanded off, measured motor speed should be < limit. \n + * 2. while pump is controlling, measured motor speed should be within allowed range of commanded speed. \n + * 3. measured motor speed should be within allowed range of measured rotor speed. \n + * All 3 checks have a persistence time that must be met before an alarm is triggered. + * @details + * Inputs : targetBloodFlowRate, bloodPumpSpeedRPM, bloodPumpRotorSpeedRPM + * Outputs : alarm(s) may be triggered + * @return none + *************************************************************************/ static void checkBloodPumpSpeeds( void ) { + F32 measMotorSpeed = getMeasuredBloodPumpSpeed(); + S32 cmdRate = getTargetBloodFlowRate(); + // check for pump running while commanded off + if ( 0 == cmdRate ) + { + if ( measMotorSpeed > BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) + { + if ( ++errorBloodMotorOffPersistTimerCtr >= BP_OFF_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); +#endif + } + } + else + { + errorBloodMotorOffPersistTimerCtr = 0; + } + } + else + { + errorBloodMotorOffPersistTimerCtr = 0; + } + + if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) + { + F32 cmdMotorSpeed = ( (F32)cmdRate / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; + F32 deltaMotorSpeed = FABS( measMotorSpeed - cmdMotorSpeed ); + F32 measRotorSpeed = getMeasuredBloodPumpRotorSpeed(); + F32 measMotorSpeedInRotorRPM = measMotorSpeed / BP_GEAR_RATIO; + F32 deltaRotorSpeed = FABS( measRotorSpeed - measMotorSpeedInRotorRPM ); + + // check measured motor speed vs. commanded motor speed while controlling to target + if ( deltaMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) + { + if ( ++errorBloodMotorSpeedPersistTimerCtr >= BP_MOTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, (F32)cmdRate, measMotorSpeed ); +#endif + } + } + else + { + errorBloodMotorSpeedPersistTimerCtr = 0; + } + + // check measured rotor speed vs. measured motor speed while controlling to target + if ( deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + { + if ( ++errorBloodRotorSpeedPersistTimerCtr >= BP_ROTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); +#endif + } + } + else + { + errorBloodRotorSpeedPersistTimerCtr = 0; + } + + } + else + { + errorBloodMotorSpeedPersistTimerCtr = 0; + errorBloodRotorSpeedPersistTimerCtr = 0; + } } +/*********************************************************************//** + * @brief + * The checkBloodPumpFlowAgainstSpeed function checks the measured blood flow \n + * against the implied flow of the measured pump speed when in treatment mode \n + * and controlling to target flow. If a sufficient difference persists, a \n + * flow vs. motor speed check error is triggered. + * @details + * Inputs : measuredBloodFlowRate, bloodPumpSpeedRPM, errorBloodFlowVsMotorSpeedPersistTimerCtr + * Outputs : alarm may be triggered + * @return none + *************************************************************************/ static void checkBloodPumpFlowAgainstSpeed( void ) { + // check only performed while in treatment mode and while we're in control to target state + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) + { + F32 flow = getMeasuredBloodFlowRate(); + F32 speed = getMeasuredBloodPumpSpeed(); + F32 impliedFlow = ( ( speed / BP_GEAR_RATIO ) / BP_REV_PER_LITER ) * (F32)ML_PER_LITER; + F32 delta = FABS( flow - impliedFlow ); + if ( delta > BP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN ) + { + if ( ++errorBloodFlowVsMotorSpeedPersistTimerCtr >= BP_FLOW_VS_SPEED_PERSIST ) + { +#ifndef DISABLE_PUMP_FLOW_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, impliedFlow ); +#endif + } + } + else + { + errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; + } + } + else + { + errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; + } } -//ALARM_ID_BLOOD_PUMP_OFF_CHECK = 7, ///< Blood pump failed motor controller off check. -//ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK = 9, ///< Blood pump failed rotor speed check. Mismatch with rotor and motor speeds. -//ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK = 51, ///< Blood pump failed flow vs. motor speed check. Mismatch with flow rate and rate implied by motor speed. -//ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK = 54, ///< Blood pump failed motor speed check. Measured vs. commanded. /*********************************************************************//** * @brief @@ -1031,7 +1160,7 @@ bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpMCCurrent() ); #endif } @@ -1050,7 +1179,7 @@ bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpMCCurrent() ); #endif } Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -49,11 +49,21 @@ #define DIP_P_COEFFICIENT 0.00005 ///> P term for dialIn pump control #define DIP_I_COEFFICIENT 0.00015 ///> I term for dialIn pump control -#define DIP_HOME_RATE 50 ///< target pump speed (in estimate mL/min) for homing. +#define DIP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DIP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). #define DIP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate inlet pump speed is calculated. #define DIP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. +#define DIP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN 50.0 ///< maximum difference between measured flow and flow implied by measured motor speed. +#define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. +#define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< maximum difference in speed between motor and rotor (in rotor RPM). +#define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< maximum difference in speed between measured and commanded RPM. +#define DIP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for flow vs. motor speed error condition. +#define DIP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define DIP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define DIP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. + + #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///> motor controller current should not exceed this when pump should be stopped #define DIP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///> motor controller current should always exceed this when pump should be running #define DIP_MAX_CURR_WHEN_RUNNING_MA 1000.0 ///> motor controller current should not exceed this when pump should be running @@ -140,6 +150,11 @@ static MOTOR_DIR_T dipMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count static U32 dipMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate inlet pump motor speed from hall sensor count. +static U32 errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. +static U32 errorDialInMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. +static U32 errorDialInMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. +static U32 errorDialInRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. + static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< holds flow samples for a rolling average static U32 flowReadingsIdx = 0; ///< index for next sample in rolling average array static F32 flowReadingsTotal = 0.0; ///< rolling total - used to calc average @@ -353,18 +368,18 @@ // calculate dialysate inlet pump motor speed/direction from hall sensor count updateDialInPumpSpeedAndDirectionFromHallSensors(); - // check pump speeds and flow - checkDialInPumpSpeeds(); - checkDialInPumpFlowAgainstSpeed(); - - // check for home position, zero/low speed - checkDialInPumpRotor(); - // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { + // check pump direction checkDialInPumpDirection(); + // check pump controller current checkDialInPumpMCCurrent(); + // check pump speeds and flow + checkDialInPumpSpeeds(); + checkDialInPumpFlowAgainstSpeed(); + // check for home position, zero/low speed + checkDialInPumpRotor(); } // publish dialIn flow data on interval @@ -911,19 +926,138 @@ dipMCDir = ( getMeasuredDialInPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); if ( ( dialInPumpDirectionSet != dipMCDir ) || ( dialInPumpDirectionSet != dipMotorDirectionFromHallSensors ) ) { +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK, (U32)dialInPumpDirectionSet, (U32)dipMotorDirectionFromHallSensors ) +#endif } } } +/*********************************************************************//** + * @brief + * The checkDialInPumpSpeeds function checks several aspects of the dialysate \n + * inlet pump speed. \n + * 1. while pump is commanded off, measured motor speed should be < limit. \n + * 2. while pump is controlling, measured motor speed should be within allowed range of commanded speed. \n + * 3. measured motor speed should be within allowed range of measured rotor speed. \n + * All 3 checks have a persistence time that must be met before an alarm is triggered. + * @details + * Inputs : targetDialInFlowRate, dialInPumpSpeedRPM, dialInPumpRotorSpeedRPM + * Outputs : alarm(s) may be triggered + * @return none + *************************************************************************/ static void checkDialInPumpSpeeds( void ) { + F32 measMotorSpeed = getMeasuredDialInPumpSpeed(); + S32 cmdRate = getTargetDialInFlowRate(); + // check for pump running while commanded off + if ( 0 == cmdRate ) + { + if ( measMotorSpeed > DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) + { + if ( ++errorDialInMotorOffPersistTimerCtr >= DIP_OFF_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_OFF_CHECK, measMotorSpeed ); +#endif + } + } + else + { + errorDialInMotorOffPersistTimerCtr = 0; + } + } + else + { + errorDialInMotorOffPersistTimerCtr = 0; + } + + if ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) + { + F32 cmdMotorSpeed = ( (F32)cmdRate / (F32)ML_PER_LITER ) * DIP_REV_PER_LITER * DIP_GEAR_RATIO; + F32 deltaMotorSpeed = FABS( measMotorSpeed - cmdMotorSpeed ); + F32 measRotorSpeed = getMeasuredDialInPumpRotorSpeed(); + F32 measMotorSpeedInRotorRPM = measMotorSpeed / DIP_GEAR_RATIO; + F32 deltaRotorSpeed = FABS( measRotorSpeed - measMotorSpeedInRotorRPM ); + + // check measured motor speed vs. commanded motor speed while controlling to target + if ( deltaMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) + { + if ( ++errorDialInMotorSpeedPersistTimerCtr >= DIP_MOTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MOTOR_SPEED_CHECK, (F32)cmdRate, measMotorSpeed ); +#endif + } + } + else + { + errorDialInMotorSpeedPersistTimerCtr = 0; + } + + // check measured rotor speed vs. measured motor speed while controlling to target + if ( deltaRotorSpeed > DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + { + if ( ++errorDialInRotorSpeedPersistTimerCtr >= DIP_ROTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); +#endif + } + } + else + { + errorDialInRotorSpeedPersistTimerCtr = 0; + } + + } + else + { + errorDialInMotorSpeedPersistTimerCtr = 0; + errorDialInRotorSpeedPersistTimerCtr = 0; + } } +/*********************************************************************//** + * @brief + * The checkDialInPumpFlowAgainstSpeed function checks the measured dialysate flow \n + * against the implied flow of the measured pump speed when in treatment mode \n + * and controlling to target flow. If a sufficient difference persists, a \n + * flow vs. motor speed check error is triggered. + * @details + * Inputs : measuredDialInFlowRate, dialInPumpSpeedRPM, errorDialInFlowVsMotorSpeedPersistTimerCtr + * Outputs : alarm may be triggered + * @return none + *************************************************************************/ static void checkDialInPumpFlowAgainstSpeed( void ) { + // check only performed while in treatment mode and while we're in control to target state + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) ) + { + F32 flow = getMeasuredDialInFlowRate(); + F32 speed = getMeasuredDialInPumpSpeed(); + F32 impliedFlow = ( ( speed / DIP_GEAR_RATIO ) / DIP_REV_PER_LITER ) * (F32)ML_PER_LITER; + F32 delta = FABS( flow - impliedFlow ); + if ( delta > DIP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN ) + { + if ( ++errorDialInFlowVsMotorSpeedPersistTimerCtr >= DIP_FLOW_VS_SPEED_PERSIST ) + { +#ifndef DISABLE_PUMP_FLOW_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, impliedFlow ); +#endif + } + } + else + { + errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; + } + } + else + { + errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; + } } /*********************************************************************//** @@ -948,7 +1082,7 @@ dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); #endif } @@ -967,7 +1101,7 @@ dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); #endif } Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -52,11 +52,18 @@ #define DOP_P_COEFFICIENT 0.0050 ///< P term for dialysate outlet pump control. #define DOP_I_COEFFICIENT 0.0001 ///< I term for dialysate outlet pump control. -#define DOP_HOME_RATE 50 ///< target pump speed (in estimate mL/min) for homing. +#define DOP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DOP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). #define DOP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate outlet pump speed is calculated. #define DOP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. +#define DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. +#define DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< maximum difference in speed between motor and rotor (in rotor RPM). +#define DOP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< maximum difference in speed between measured and commanded RPM. +#define DOP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define DOP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define DOP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. + #define DOP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. #define DOP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< Motor controller current should always exceed this when pump should be running. #define DOP_MAX_CURR_WHEN_RUNNING_MA 1000.0 ///< Motor controller current should not exceed this when pump should be running. @@ -142,6 +149,10 @@ static MOTOR_DIR_T dopMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count static U32 dopMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate outlet pump motor speed from hall sensor count. +static U32 errorDialOutMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. +static U32 errorDialOutMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. +static U32 errorDialOutRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. + static DIAL_OUT_PUMP_SELF_TEST_STATE_T dialOutPumpSelfTestState = DIAL_OUT_PUMP_SELF_TEST_STATE_START; ///< Current state of the dialysate outlet pump self test state machine. static U32 dialOutPumpSelfTestTimerCount = 0; ///< Timer counter for time reference during self test. @@ -166,7 +177,6 @@ static void checkDialOutPumpRotor( void ); static void checkDialOutPumpDirection( void ); static void checkDialOutPumpSpeeds( void ); -static void checkDialOutPumpFlowAgainstSpeed( void ); static void checkDialOutPumpMCCurrent( void ); static DATA_GET_PROTOTYPE( U32, getPublishDialOutDataInterval ); @@ -407,18 +417,17 @@ // calculate dialysate outlet pump motor speed/direction from hall sensor count updateDialOutPumpSpeedAndDirectionFromHallSensors(); - // check pump speeds and flow - checkDialOutPumpSpeeds(); - checkDialOutPumpFlowAgainstSpeed(); - - // check for home position, zero/low speed - checkDialOutPumpRotor(); - // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { + // check pump direction checkDialOutPumpDirection(); + // check pump controller current checkDialOutPumpMCCurrent(); + // check pump speeds + checkDialOutPumpSpeeds(); + // check for home position, zero/low speed + checkDialOutPumpRotor(); } publishDialOutFlowData(); @@ -810,19 +819,96 @@ dopMCDir = ( getMeasuredDialOutPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); if ( ( dialOutPumpDirectionSet != dopMCDir ) || ( dialOutPumpDirectionSet != dopMotorDirectionFromHallSensors ) ) { +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopMotorDirectionFromHallSensors ) +#endif } } } +/*********************************************************************//** + * @brief + * The checkDialOutPumpSpeeds function checks several aspects of the dialysate \n + * outlet pump speed. \n + * 1. while pump is commanded off, measured motor speed should be < limit. \n + * 2. while pump is controlling, measured motor speed should be within allowed range of measured motor controller speed. \n + * 3. measured motor speed should be within allowed range of measured rotor speed. \n + * All 3 checks have a persistence time that must be met before an alarm is triggered. + * @details + * Inputs : targetDialOutFlowRate, dialOutPumpSpeedRPM, dialOutPumpRotorSpeedRPM + * Outputs : alarm(s) may be triggered + * @return none + *************************************************************************/ static void checkDialOutPumpSpeeds( void ) { + F32 measMotorSpeed = getMeasuredDialOutPumpSpeed(); -} + // check for pump running while commanded off + if ( FALSE == isDialOutPumpOn ) + { + if ( measMotorSpeed > DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) + { + if ( ++errorDialOutMotorOffPersistTimerCtr >= DOP_OFF_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_OFF_CHECK, measMotorSpeed ); +#endif + } + } + else + { + errorDialOutMotorOffPersistTimerCtr = 0; + } + } + else + { + errorDialOutMotorOffPersistTimerCtr = 0; + } -static void checkDialOutPumpFlowAgainstSpeed( void ) -{ + if ( DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE == dialOutPumpState ) + { + F32 controllerMotorSpeed = getMeasuredDialOutPumpMCSpeed(); + F32 deltaMotorSpeed = FABS( measMotorSpeed - controllerMotorSpeed ); + F32 measRotorSpeed = getMeasuredDialOutPumpRotorSpeed(); + F32 measMotorSpeedInRotorRPM = measMotorSpeed / DOP_GEAR_RATIO; + F32 deltaRotorSpeed = FABS( measRotorSpeed - measMotorSpeedInRotorRPM ); + // check measured motor speed vs. commanded motor speed while controlling to target + if ( deltaMotorSpeed > DOP_MAX_MOTOR_SPEED_ERROR_RPM ) + { + if ( ++errorDialOutMotorSpeedPersistTimerCtr >= DOP_MOTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MOTOR_SPEED_CHECK, controllerMotorSpeed, measMotorSpeed ); +#endif + } + } + else + { + errorDialOutMotorSpeedPersistTimerCtr = 0; + } + + // check measured rotor speed vs. measured motor speed while controlling to target + if ( deltaRotorSpeed > DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + { + if ( ++errorDialOutRotorSpeedPersistTimerCtr >= DOP_ROTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); +#endif + } + } + else + { + errorDialOutRotorSpeedPersistTimerCtr = 0; + } + + } + else + { + errorDialOutMotorSpeedPersistTimerCtr = 0; + errorDialOutRotorSpeedPersistTimerCtr = 0; + } } /************************************************************************* @@ -847,7 +933,7 @@ dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); #endif } @@ -866,7 +952,7 @@ dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); #endif } Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r9d4666bf3064df18a6d935125d7a69e4e8234e84 -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 9d4666bf3064df18a6d935125d7a69e4e8234e84) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -256,6 +256,7 @@ F32 diOccl = getMeasuredDialInPumpOcclusion(); F32 doOccl = getMeasuredDialOutPumpOcclusion(); +#ifndef DISABLE_PRESSURE_CHECKS if ( bpOccl > bloodPumpOcclusionPressureThresholdmmHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) @@ -271,6 +272,7 @@ SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) // TODO - stop dialysate outlet pump immediately, ... } +#endif } /*********************************************************************//** Index: firmware/App/HDCommon.h =================================================================== diff -u -r8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -36,7 +36,11 @@ #define SKIP_POST 1 #define DISABLE_CRC_ERROR 1 #define DISABLE_ACK_ERRORS 1 - #define DISABLE_MOTOR_CURRENT_ERRORS 1 + #define DISABLE_MOTOR_CURRENT_CHECKS 1 + #define DISABLE_PUMP_FLOW_CHECKS 1 + #define DISABLE_PUMP_SPEED_CHECKS 1 + #define DISABLE_PUMP_DIRECTION_CHECKS 1 + #define DISABLE_PRESSURE_CHECKS 1 // #define SHOW_LOAD_CELL_IN_ROTOR_RPM 1 // #define SHOW_RAW_FLOW_VALUES 1 Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -ra19a676d1e67bb3e1aca9e9bba49727f9d5f8b38 -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision a19a676d1e67bb3e1aca9e9bba49727f9d5f8b38) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -56,6 +56,9 @@ void transitionToStandbyMode( void ) { // temporary test code - TODO - remove later + homeBloodPump(); + homeDialInPump(); + homeDialOutPump(); #ifndef UF_TEST_ENABLED setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 8377b4e6ed494cbfc5dfc2bd9ad3c89b85b333cd) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -110,6 +110,7 @@ { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE, TRUE , TRUE, TRUE, TRUE, TRUE, TRUE, FALSE }, // ALARM_ID_TEMPERATURE_SENSORS_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE, TRUE , TRUE, TRUE, TRUE, TRUE, TRUE, FALSE }, // ALARM_ID_TEMPERATURE_SENSORS_INCONSISTENT { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_HD_COMM_TIMEOUT + { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE, TRUE , TRUE, TRUE, TRUE, TRUE, TRUE, FALSE }, // ALARM_ID_VALVE_CONTROL_FAILURE { ALARM_PRIORITY_HIGH, ALM_ESC_4_MIN, ALARM_ID_BLOOD_SITTING_WARNING, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK { ALARM_PRIORITY_HIGH, ALM_ESC_4_MIN, ALARM_ID_BLOOD_SITTING_WARNING, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_IN_PUMP_FLOW_VS_MOTOR_SPEED_CHECK { ALARM_PRIORITY_HIGH, ALM_ESC_4_MIN, ALARM_ID_BLOOD_SITTING_WARNING, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_OUT_PUMP_FLOW_VS_MOTOR_SPEED_CHECK Index: firmware/App/Services/CommBuffers.c =================================================================== diff -u -r5bec978fa9cce89bbf8c559f0844b7528a10c0d1 -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision 5bec978fa9cce89bbf8c559f0844b7528a10c0d1) +++ firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -124,7 +124,7 @@ // release thread protection bufferGetLock[ buffer ] = FALSE; _enable_IRQ(); - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, len ) +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, len ) } } else // invalid buffer given Index: firmware/App/Services/Interrupts.c =================================================================== diff -u -r4ebc1f7e1aeb3a332e91fcdd1bbbe1a01873d93a -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 4ebc1f7e1aeb3a332e91fcdd1bbbe1a01873d93a) +++ firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -329,11 +329,13 @@ break; case HET1_EDGE_DPI_ROTOR_HALL_SENSOR: - signalDialInPumpRotorHallSensor(); + //signalDialInPumpRotorHallSensor(); + signalDialOutPumpRotorHallSensor(); break; case HET1_EDGE_DPO_ROTOR_HALL_SENSOR: - signalDialOutPumpRotorHallSensor(); + //signalDialOutPumpRotorHallSensor(); + signalDialInPumpRotorHallSensor(); break; default: Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r9b262ba08e3180f121c3cf19d8d25e565183f87d -r93a439cf9d1b347e23b84d1156417380ee01efaa --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 9b262ba08e3180f121c3cf19d8d25e565183f87d) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 93a439cf9d1b347e23b84d1156417380ee01efaa) @@ -60,24 +60,12 @@ if ( TRUE == uiCommunicated() ) #endif { -#ifndef CAN_TEST // monitor pressure/occlusion sensors execPresOccl(); -#endif // run operation mode state machine execOperationModes(); -#ifdef CAN_TEST - { - static U32 canTestCtr = 0; - if ( ++canTestCtr >= 2 ) - { - broadcastCANTest1LargeFrequentMessage(); - canTestCtr = 0; - } - } -#else // control blood pump execBloodFlowController(); @@ -95,7 +83,6 @@ // control alarm lamp execAlarmLamp(); -#endif #ifdef RM46_EVAL_BOARD_TARGET if ( getUserButtonState() == PIN_SIGNAL_LOW )