Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r5f929b475f0143cd3597547e3c20a77a5abb6d9c -r37a9fd8f15e413db5337371a7d1a1cb65567af7c --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 5f929b475f0143cd3597547e3c20a77a5abb6d9c) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 37a9fd8f15e413db5337371a7d1a1cb65567af7c) @@ -7,8 +7,8 @@ * * @file DialInFlow.c * -* @author (last) Sean Nash -* @date (last) 15-Nov-2021 +* @author (last) Darren Cox +* @date (last) 10-Mar-2022 * * @author (original) Sean * @date (original) 16-Dec-2019 @@ -104,7 +104,7 @@ /// Macro converts flow rate to motor RPM. #define DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DIP_REV_PER_LITER / ML_PER_LITER ) #define DIP_GEAR_RATIO 32.0 ///< DialIn pump motor to dialIn pump gear ratio. -#define DIP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. +#define DIP_PWM_ZERO_OFFSET 0.1F ///< 10% PWM duty cycle = zero speed. /// Macro converts flow rate to estimate PWM needed to achieve it. #define DIP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO * DIP_MOTOR_RPM_TO_PWM_DC_FACTOR + DIP_PWM_ZERO_OFFSET ) @@ -116,6 +116,8 @@ #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. +#define DATA_PUBLISH_COUNTER_START_COUNT 30 ///< Data publish counter start count. + /// Enumeration of dialysate inlet pump states. typedef enum DialInPump_States { @@ -147,7 +149,7 @@ // ********** private data ********** static DIAL_IN_PUMP_STATE_T dialInPumpState = DIAL_IN_PUMP_OFF_STATE; ///< Current state of dialIn flow controller state machine -static U32 dialInFlowDataPublicationTimerCounter = 5; ///< Used to schedule dialIn flow data publication to CAN bus +static U32 dialInFlowDataPublicationTimerCounter; ///< Used to schedule dialIn flow data publication to CAN bus static BOOL isDialInPumpOn = FALSE; ///< DialIn pump is currently running static F32 dialInPumpPWMDutyCyclePct = 0.0; ///< Initial dialIn pump PWM duty cycle static F32 dialInPumpPWMDutyCyclePctSet = 0.0; ///< Currently set dialIn pump PWM duty cycle @@ -189,7 +191,8 @@ static F64 flowReadingsTotal = 0.0; ///< Rolling total - used to calc average. static U32 flowReadingsCount = 0; ///< Number of samples in flow rolling average buffer. -static U32 dipCurrErrorDurationCtr = 0; ///< Used for tracking persistence of dip current errors. +static U32 dipCurrErrorDurationCtr = 0; ///< Used for tracking persistence of dip current errors. +static HD_PUMPS_CAL_RECORD_T dialInPumpCalRecord; ///< Dialysate inlet calibration record. // ********** private function prototypes ********** @@ -221,6 +224,8 @@ void initDialInFlow( void ) { U32 i; + + dialInFlowDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; signalDialInPumpHardStop(); setDialInPumpDirection( MOTOR_DIR_FORWARD ); @@ -232,7 +237,7 @@ dipMotorSpeedCalcIdx = 0; for ( i = 0; i < DIP_SPEED_CALC_BUFFER_LEN; i++ ) { - dipLastMotorHallSensorCounts[ i ] = 0; + dipLastMotorHallSensorCounts[ i ] = getFPGADialInPumpHallSensorCount(); } // Initialize dialysate inlet flow PI controller @@ -267,10 +272,17 @@ // Don't interrupt pump control unless rate or mode is changing if ( ( dirFlowRate != targetDialInFlowRate ) || ( mode != dialInPumpControlMode ) ) { -#ifndef NO_PUMP_FLOW_LIMITS + BOOL byPassFlowLimit = FALSE; + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMPS_FLOW_LIMITS ) ) + { + byPassFlowLimit = TRUE; + } +#endif + // Verify flow rate - if ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) -#endif + if ( ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) || ( TRUE == byPassFlowLimit ) ) { resetDialInFlowMovingAverage(); targetDialInFlowRate = dirFlowRate; @@ -309,12 +321,17 @@ } result = TRUE; } -#ifndef NO_PUMP_FLOW_LIMITS + else // Requested flow rate too high - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_IN_FLOW_SET_TOO_HIGH, flowRate ) - } + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMPS_FLOW_LIMITS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_IN_FLOW_SET_TOO_HIGH, flowRate ) + } + } + } } @@ -398,6 +415,21 @@ return isDialInPumpOn; } +/*********************************************************************//** + * @brief + * The isDialInPumpRampComplete function returns whether the dialysate inlet pump has + * completed its ramp up and entered control state (closed or open loop). + * @details Inputs: dialInPumpState + * @details Outputs: none + * @return TRUE if pump is in control state, FALSE if not + *************************************************************************/ +BOOL isDialInPumpRampComplete( void ) +{ + BOOL result = ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ? TRUE : FALSE ); + + return result; +} + /*********************************************************************//** * @brief * The execDialInFlowMonitor function executes the dialIn flow monitor. @@ -417,18 +449,22 @@ { dipFlow = getDGDialysateFlowRateLMin() * (F64)ML_PER_LITER; // convert rate to mL/min filterDialInFlowReadings( dipFlow ); // process the fresh dialysate flow data - dialysateFlowDataFreshStatusCounter = 0; // reset counter + dialysateFlowDataFreshStatusCounter = 0; } else { // Alarm if not receiving new dialysate flow readings in timely manner - if ( ++dialysateFlowDataFreshStatusCounter > DIP_DIALYSATE_FLOW_DATA_ALARM_THRESHOLD ) + if ( TRUE == isDGCommunicating() ) { - filterDialInFlowReadings( 0.0 ); - if ( TRUE == isDGCommunicating() ) + if ( ++dialysateFlowDataFreshStatusCounter > DIP_DIALYSATE_FLOW_DATA_ALARM_THRESHOLD ) { + filterDialInFlowReadings( 0.0 ); activateAlarmNoData( ALARM_ID_HD_DIALYSATE_FLOW_DATA_NOT_RECEIVE ); } } + else + { + dialysateFlowDataFreshStatusCounter = 0; + } } // Get latest pump speed and current from motor controller @@ -916,7 +952,7 @@ U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCounts[ nextIdx ] ? \ dipMotorHallSensorCount - dipLastMotorHallSensorCounts[ nextIdx ] : \ ( HEX_64_K - dipLastMotorHallSensorCounts[ nextIdx ] ) + dipMotorHallSensorCount ); - U16 decDelta = HEX_64_K - incDelta; + U16 decDelta = ( 0 == incDelta ? 0xFFFF : HEX_64_K - incDelta ); U16 delta; // Determine dialysate inlet pump speed/direction from delta hall sensor count since last interval @@ -979,36 +1015,33 @@ MOTOR_DIR_T dipMCDir, dipDir; U08 dirErrorCnt = getFPGADialInPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; -#ifndef DISABLE_PUMP_DIRECTION_CHECKS // Check pump direction error count - if ( lastDialInPumpDirectionCount != dirErrorCnt ) + if ( ( lastDialInPumpDirectionCount != dirErrorCnt ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { lastDialInPumpDirectionCount = dirErrorCnt; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_DIALYSATE_INLET_PUMP ) } -#endif dipMCDir = ( getMeasuredDialInPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); dipDir = ( getMeasuredDialInPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); // Check set direction vs. direction from hall sensors if ( dialInPumpDirectionSet != dipDir ) { - if ( ++errorDialInPumpDirectionPersistTimerCtr >= DIP_DIRECTION_ERROR_PERSIST ) + if ( ( ++errorDialInPumpDirectionPersistTimerCtr >= DIP_DIRECTION_ERROR_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK, (U32)dialInPumpDirectionSet, (U32)dipDir ) -#endif } } // Check set direction vs. direction from sign of motor controller speed else if ( dialInPumpDirectionSet != dipMCDir ) { - if ( ++errorDialInPumpDirectionPersistTimerCtr >= DIP_DIRECTION_ERROR_PERSIST ) + if ( ( ++errorDialInPumpDirectionPersistTimerCtr >= DIP_DIRECTION_ERROR_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK, (U32)dialInPumpDirectionSet, (U32)dipMCDir ) -#endif } } else @@ -1044,12 +1077,11 @@ { if ( measMotorSpeed > DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) { - if ( ++errorDialInMotorOffPersistTimerCtr >= DIP_OFF_ERROR_PERSIST ) + if ( ( ++errorDialInMotorOffPersistTimerCtr >= DIP_OFF_ERROR_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_OFF_CHECK, measMotorSpeed ); activateSafetyShutdown(); -#endif } } else @@ -1075,11 +1107,10 @@ // Check measured motor speed vs. commanded motor speed while controlling to target if ( ( deltaMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) ) { - if ( ++errorDialInMotorSpeedPersistTimerCtr >= DIP_MOTOR_SPEED_ERROR_PERSIST ) + if ( ( ++errorDialInMotorSpeedPersistTimerCtr >= DIP_MOTOR_SPEED_ERROR_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MOTOR_SPEED_CHECK, cmdMotorSpeed, measMotorSpeed ); -#endif } } else @@ -1090,11 +1121,10 @@ // 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 ) + if ( ( ++errorDialInRotorSpeedPersistTimerCtr >= DIP_ROTOR_SPEED_ERROR_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); -#endif } } else @@ -1123,12 +1153,11 @@ F32 flow = getMeasuredDialInFlowRate(); // Range check on measure DPi flow rate. -#ifndef DISABLE_PUMP_FLOW_CHECKS - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DIAL_IN_FLOW_OUT_OF_RANGE, ( flow > DIP_MAX_FLOW_RATE ) || ( flow < DIP_MIN_FLOW_RATE ) ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DIAL_IN_FLOW_OUT_OF_RANGE, ( flow > DIP_MAX_FLOW_RATE ) || ( flow < DIP_MIN_FLOW_RATE ) ) ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_FLOW_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_DIAL_IN_FLOW_OUT_OF_RANGE, flow ); } -#endif // Check only performed while in treatment mode and while we are in control to target state if ( ( MODE_TREA == getCurrentOperationMode() ) && ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) ) @@ -1140,11 +1169,10 @@ if ( delta > DIP_MAX_FLOW_VS_SPEED_DIFF_RPM ) { - if ( ++errorDialInFlowVsMotorSpeedPersistTimerCtr >= DIP_FLOW_VS_SPEED_PERSIST ) + if ( ( ++errorDialInFlowVsMotorSpeedPersistTimerCtr >= DIP_FLOW_VS_SPEED_PERSIST ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_FLOW_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_PUMP_FLOW_CHECKS SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); -#endif } } else @@ -1177,11 +1205,10 @@ if ( dipCurr > DIP_MAX_CURR_WHEN_STOPPED_MA ) { dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) + if ( ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); -#endif } } else @@ -1196,11 +1223,10 @@ if ( dipCurr > DIP_MAX_CURR_WHEN_RUNNING_MA ) { dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) + if ( ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { -#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); -#endif } } else @@ -1215,13 +1241,25 @@ * The execDialInFlowTest function executes the state machine for the * DialInFlow self-test. * @details Inputs: none - * @details Outputs: none + * @details Outputs: dialInPumpCalRecord * @return the current state of the DialInFlow self-test. *************************************************************************/ SELF_TEST_STATUS_T execDialInFlowTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + BOOL calStatus = getNVRecord2Driver( GET_CAL_PUMPS, (U08*)&dialInPumpCalRecord, sizeof( HD_PUMPS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_HD_PUMPS, ALARM_ID_NO_ALARM ); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + return result; }