Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r5f929b475f0143cd3597547e3c20a77a5abb6d9c -r37a9fd8f15e413db5337371a7d1a1cb65567af7c --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 5f929b475f0143cd3597547e3c20a77a5abb6d9c) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 37a9fd8f15e413db5337371a7d1a1cb65567af7c) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file DialOutFlow.c * -* @author (last) Sean Nash -* @date (last) 12-Nov-2021 +* @author (last) Darren Cox +* @date (last) 10-Mar-2022 * * @author (original) Sean * @date (original) 24-Jan-2020 @@ -25,6 +25,7 @@ #include "FPGA.h" #include "InternalADC.h" #include "ModeTreatment.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PIControllers.h" #include "SafetyShutdown.h" @@ -100,14 +101,15 @@ #define DOP_REV_PER_LITER 146.84 ///< Rotor revolutions per liter. #define DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DOP_REV_PER_LITER / ML_PER_LITER ) ///< Conversion factor from mL/min to pump motor RPM. #define DOP_GEAR_RATIO 32.0 ///< Pump motor to pump gear ratio. -#define DOP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. +#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) * DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DOP_GEAR_RATIO * DOP_MOTOR_RPM_TO_PWM_DC_FACTOR + 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.0 ) #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. +#define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. /// Enumeration of dialysate outlet pump controller states. typedef enum DialOutPump_States @@ -139,7 +141,7 @@ // ********** private data ********** static DIAL_OUT_PUMP_STATE_T dialOutPumpState = DIAL_OUT_PUMP_OFF_STATE; ///< Current state of the dialysate outlet pump controller state machine. -static U32 dialOutFlowDataPublicationTimerCounter = 6; ///< Timer counter controlling when to publish dialysate outlet data. Set non-zero to phase data publication to CAN bus. +static U32 dialOutFlowDataPublicationTimerCounter; ///< Timer counter controlling when to publish dialysate outlet data. Set non-zero to phase data publication to CAN bus. static BOOL isDialOutPumpOn = FALSE; ///< Flag set to TRUE when dialysate outlet pump is running. static U32 lastGivenRate = 0; ///< Remembers the last given set point rate for the dialysate outlet pump. static F32 dialOutPumpPWMDutyCyclePct = 0.0; ///< Requested PWM duty cycle for dialysate outlet pump (based on given rate). @@ -185,7 +187,8 @@ static U32 errorDialOutRotorSpeedPersistTimerCtr = 0; ///< Persistence timer counter for rotor speed error condition. static U32 errorDialOutPumpDirectionPersistTimerCtr = 0; ///< Persistence timer counter for pump direction error condition. -static U08 lastDialOutPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA +static U08 lastDialOutPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. +static HD_PUMPS_CAL_RECORD_T dialOutPumpCalRecord; ///< Dialysate outlet calibration record. // ********** private function prototypes ********** @@ -214,21 +217,23 @@ * @brief * The initDialOutFlow function initializes the DialOutFlow module. * @details Inputs: none - * @details Outputs: DialOutFlow module initialized. + * @details Outputs: dialOutFlowDataPublicationTimerCounter * @return none *************************************************************************/ void initDialOutFlow( void ) { U32 i; + dialOutFlowDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + signalDialOutPumpHardStop(); setDialOutPumpDirection( MOTOR_DIR_FORWARD ); // Zero motor hall sensors counts buffer dopMotorSpeedCalcIdx = 0; for ( i = 0; i < DOP_SPEED_CALC_BUFFER__LEN; i++ ) { - dopLastMotorHallSensorCounts[ i ] = 0; + dopLastMotorHallSensorCounts[ i ] = getFPGADialOutPumpHallSensorCount(); } dopMeasuredRate = 0.0; @@ -260,10 +265,17 @@ // Don't interrupt pump control unless rate or mode is changing if ( ( fabs( pwmDC - dialOutPumpPWMDutyCyclePct ) > NEARLY_ZERO ) || ( mode != dialOutPumpControlMode ) ) { -#ifndef NO_PUMP_FLOW_LIMITS - // Verify flow rate - if ( flowRate <= MAX_DIAL_OUT_FLOW_RATE ) + 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_OUT_FLOW_RATE ) || ( TRUE == byPassFlowLimit ) ) { resetDialOutFlowMovingAverage(); dopControlSignal = FALSE; @@ -272,7 +284,6 @@ dialOutPumpControlMode = mode; // Set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we will control to flow when ramp completed dialOutPumpPWMDutyCyclePct = pwmDC; - dialOutPumpPWMDutyCyclePct = MIN( dialOutPumpPWMDutyCyclePct, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); switch ( dialOutPumpState ) { @@ -304,12 +315,15 @@ } 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_OUT_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_OUT_FLOW_SET_TOO_HIGH, flowRate ) + } + } } } @@ -461,6 +475,48 @@ /*********************************************************************//** * @brief + * The isDialOutPumpRampComplete function returns whether the dialysate outlet pump has + * completed its ramp up and entered control state (closed or open loop). + * @details Inputs: dialOutPumpState + * @details Outputs: none + * @return TRUE if pump is in control state, FALSE if not + *************************************************************************/ +BOOL isDialOutPumpRampComplete( void ) +{ + BOOL result = ( DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE == dialOutPumpState ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief + * The execDialOutFlowTest function executes the state machine for the + * DialOutFlow self-test. + * @details Inputs: none + * @details Outputs: dialOutPumpCalRecord + * @return the current state of the DialOutFlow self-test. + *************************************************************************/ +SELF_TEST_STATUS_T execDialOutFlowTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + + BOOL calStatus = getNVRecord2Driver( GET_CAL_PUMPS, (U08*)&dialOutPumpCalRecord, 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; +} + +/*********************************************************************//** + * @brief * The execDialOutFlowMonitor function executes the dialysate outlet pump * and load cell sensor monitor. Checks are performed. Data is published * at appropriate interval. @@ -809,7 +865,7 @@ U16 incDelta = ( dopMotorHallSensorCount >= dopLastMotorHallSensorCounts[ nextIdx ] ? \ dopMotorHallSensorCount - dopLastMotorHallSensorCounts[ nextIdx ] : \ ( HEX_64_K - dopLastMotorHallSensorCounts[ nextIdx ] ) + dopMotorHallSensorCount ); - U16 decDelta = HEX_64_K - incDelta; + U16 decDelta = ( 0 == incDelta ? 0xFFFF : HEX_64_K - incDelta ); U16 delta; // Determine dialysate outlet pump speed/direction from delta hall sensor count since last interval @@ -885,21 +941,19 @@ // Check set direction vs. direction from hall sensors if ( dialOutPumpDirectionSet != dopDir ) { - if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) + if ( ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_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_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopDir ) -#endif } } // Check set direction vs. direction from sign of motor controller speed else if ( dialOutPumpDirectionSet != dopMCDir ) { - if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) + if ( ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_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_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopMCDir ) -#endif } } else @@ -935,12 +989,11 @@ { if ( measMotorSpeed > DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) { - if ( ++errorDialOutMotorOffPersistTimerCtr >= DOP_OFF_ERROR_PERSIST ) + if ( ( ++errorDialOutMotorOffPersistTimerCtr >= DOP_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_OUT_PUMP_OFF_CHECK, measMotorSpeed ); activateSafetyShutdown(); -#endif } } else @@ -965,11 +1018,10 @@ // Check measured motor speed vs. commanded motor speed while controlling to target if ( ( deltaMotorSpeed > DOP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > DOP_MAX_MOTOR_SPEED_ERROR_RPM ) ) { - if ( ++errorDialOutMotorSpeedPersistTimerCtr >= DOP_MOTOR_SPEED_ERROR_PERSIST ) + if ( ( ++errorDialOutMotorSpeedPersistTimerCtr >= DOP_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_OUT_PUMP_MOTOR_SPEED_CHECK, cmdMotorSpeed, measMotorSpeed ); -#endif } } else @@ -980,11 +1032,10 @@ // 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 ) + if ( ( ++errorDialOutRotorSpeedPersistTimerCtr >= DOP_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_OUT_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); -#endif } } else @@ -1018,11 +1069,10 @@ if ( dopCurr > DOP_MAX_CURR_WHEN_STOPPED_MA ) { dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) + if ( ( dopCurrErrorDurationCtr > DOP_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_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); -#endif } } else @@ -1037,11 +1087,10 @@ if ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) { dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) + if ( ( dopCurrErrorDurationCtr > DOP_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_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); -#endif } } else