Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -rdcd360fb4dc37db2dcbeb7fb14fb327fe68235f4 -ra89d6b091874136d75a9bfbdbbc1ff00f42467b3 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision dcd360fb4dc37db2dcbeb7fb14fb327fe68235f4) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision a89d6b091874136d75a9bfbdbbc1ff00f42467b3) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2021 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 ConcentratePumps.c * * @author (last) Dara Navaei -* @date (last) 30-Sep-2021 +* @date (last) 04-Aug-2022 * * @author (original) Quang Nguyen * @date (original) 22-Oct-2020 @@ -36,49 +36,77 @@ #define CONCENTRATE_PUMP_FORWARD_DIR 0x1 ///< Concentrate pump forward direction configuration. #define CONCENTRATE_PUMP_REVERSE_DIR 0x0 ///< Concentrate pump reverse direction configuration. -#define CONCENTRATE_PUMP_SPEED_INCREMENT 2.0 ///< Speed increase (mL/min) when controlling concentrate pump to target step speed. -#define CONCENTRATE_PUMP_MIN_SPEED 3.0 ///< Minimum speed for concentrate pump in mL per min. -#define CONCENTRATE_PUMP_ERROR_TOLERANCE 0.02 ///< Measured speed needs to be within 2% of commanded speed. +#define CONCENTRATE_PUMP_SPEED_INCREMENT 2.0F ///< Speed increase (mL/min) when controlling concentrate pump to target step speed. +#define CONCENTRATE_PUMP_MIN_SPEED 3.0F ///< Minimum speed for concentrate pump in mL per min. +#define CONCENTRATE_PUMP_ERROR_TOLERANCE 0.02F ///< Measured speed needs to be within 2% of commanded speed. #define CONCENTRATE_PUMP_ZERO_FLOW_RATE 0xFFFF ///< Pulse width value when zero flow rate or pump is off. -#define CONCENTRATE_PUMP_VOLUME_PER_REV 0.1 ///< Volume output every revolution (mL). -#define CONCENTRATE_PUMP_PULSE_PER_REV 2.0 ///< Number of pulses generate for every revolution. -#define CONCENTRATE_PUMP_STEP_PER_REV 200.0 ///< Number of steps for every revolution. -#define CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION 100.0 ///< Hall sense period resolution in microseconds. +#define CONCENTRATE_PUMP_VOLUME_PER_REV 0.1F ///< Volume output every revolution (mL). +#define CONCENTRATE_PUMP_PULSE_PER_REV 2.0F ///< Number of pulses generate for every revolution. +#define CONCENTRATE_PUMP_STEP_PER_REV 200.0F ///< Number of steps for every revolution. +#define CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION 100.0F ///< Hall sense period resolution in microseconds. +#define CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT 1000 ///< Hall sensors minimum allowed value. +#define CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS ( 5 * MS_PER_SECOND ) ///< Hall sensors out of range time in milliseconds. -#define CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP 8.0 ///< Number of micro-steps ( fractions of step) per step. -#define CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION ( 0.5 / ( US_PER_SECOND * SEC_PER_MIN ) ) ///< Convert step period resolution (0.5 us) to minute. +#define CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP 8.0F ///< Number of micro-steps ( fractions of step) per step. +#define CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION ( 0.5F / ( US_PER_SECOND * SEC_PER_MIN ) ) ///< Convert step period resolution (0.5 us) to minute. /// Volume output per pulse. #define CONCENTRATE_PUMP_VOLUME_PER_PULSE ( CONCENTRATE_PUMP_VOLUME_PER_REV / CONCENTRATE_PUMP_PULSE_PER_REV ) #define CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is monitored. -#define CONCENTRATE_PUMP_CONTROL_INTERVAL ( 50 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is controlled. +#define CONCENTRATE_PUMP_CONTROL_INTERVAL ( 1 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is controlled. #define CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for concentrate pump speed control error. +#define NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK 1 ///< Number of acid and bicarb non-volatile data to check. + +#define DATA_PUBLISH_COUNTER_START_COUNT 0 ///< Data publish counter start count. + +/*************************DVT Definitions********************************************/ + +#define CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP 0x07 ///< Concentrate pump control 1/8th step. +#define CONCENTRATE_PUMP_CONTROL_REVERSE_DIR 0x08 ///< Concentrate pump control reverse direction. +#define CONCENTRATE_PUMP_CONTROL_FORWARD_DIR 0x00 ///< Concentrate pump control forward direction. +#define CONCENTRATE_PUMP_CONTROL_ENABLE 0x00 ///< Concentrate pump control enable pump. +#define CONCENTRATE_PUMP_CONTROL_NOT_RESET 0x20 ///< Concentrate pump control not reset. +#define CONCENTRATE_PUMP_CONTROL_SLEEP_OFF 0x40 ///< Concentrate pump control sleep off. + +static const U32 CONCENTRATE_PUMP_CONTROL_FORWARD = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | + CONCENTRATE_PUMP_CONTROL_NOT_RESET | + CONCENTRATE_PUMP_CONTROL_ENABLE | + CONCENTRATE_PUMP_CONTROL_FORWARD_DIR | + CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control forward. + +static const U32 CONCENTRATE_PUMP_CONTROL_REVERSE = CONCENTRATE_PUMP_CONTROL_SLEEP_OFF | + CONCENTRATE_PUMP_CONTROL_NOT_RESET | + CONCENTRATE_PUMP_CONTROL_ENABLE | + CONCENTRATE_PUMP_CONTROL_REVERSE_DIR | + CONCENTRATE_PUMP_CONTROL_EIGHTH_STEP; ///< Concentrate pump control reverse. + +/*************************DVT Definitions********************************************/ + /// Enumeration of concentrate pump states. typedef enum ConcentratePumpState { - CONCENTRATE_PUMP_OFF_STATE = 0, ///< Concentrate pump off state - CONCENTRATE_PUMP_ON_STATE, ///< Concentrate pump on state - NUM_OF_CONCENTRATE_PUMP_STATES ///< Number of concentrate pump states + CONCENTRATE_PUMP_OFF_STATE = 0, ///< Concentrate pump off state. + CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE, ///< Concentrate pump ramp to target state. + CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE, ///< Concentrate pump on state. + NUM_OF_CONCENTRATE_PUMP_STATES ///< Number of concentrate pump states. } CONCENTRATE_PUMP_STATE_T; /// Concentrate pump data structure typedef struct { - U32 controlTimerCounter; ///< Timer counter to perform control on concentrate pump - CONCENTRATE_PUMP_STATE_T execState; ///< Concentrate pump execute current state - BOOL hasTurnOnPumpsBeenRequested; ///< Flag indicates a request to turn concentrate pumps on - - F32 pumpTargetSpeed; ///< Target concentrate pumps' speed (mL/min) - F32 currentPumpSpeed; ///< Current controlled concentrate pumps' speed (mL/min) - OVERRIDE_F32_T measuredPumpSpeed; ///< Measured concentrate pump speed (mL/min) - U16 togglePeriodCount; ///< Converted pump speed (mL/min) to toggle period counts (0.5 uS increment counts per step) - - U08 direction; ///< Concentrate pump motor direction - void ( *control )( U08 ); ///< Concentrate pump FPGA control function pointer - void ( *setStepSpeed )( U16 ); ///< Concentrate pump FPGA set step speed function pointer + U32 controlTimerCounter; ///< Timer counter to perform control on concentrate pump. + CONCENTRATE_PUMP_STATE_T execState; ///< Concentrate pump execute current state. + BOOL hasTurnOnPumpsBeenRequested; ///< Flag indicates a request to turn concentrate pumps on. + F32 pumpTargetSpeed; ///< Target concentrate pumps' speed (mL/min). + F32 currentPumpSpeed; ///< Current controlled concentrate pumps' speed (mL/min). + OVERRIDE_F32_T measuredPumpSpeed; ///< Measured concentrate pump speed (mL/min). + U16 togglePeriodCount; ///< Converted pump speed (mL/min) to toggle period counts (0.5 uS increment counts per step). + U08 direction; ///< Concentrate pump motor direction. + U08 controlSet; ///< Concentrate pump control set. (Used in DVT) + F32 pulseWidthUS; ///< Concentrate pump pulse width in microseconds. } CONCENTRATE_PUMP_T; // ********** private data ********** @@ -91,17 +119,17 @@ static CONCENTRATE_PUMP_T concentratePumps[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Array of concentrate pumps' data structure. static DG_ACID_CONCENTRATES_RECORD_T acidConcentrateCalRecord; ///< Acid concentrate calibration record. static DG_BICARB_CONCENTRATES_RECORD_T bicarbConcentrateCalRecord; ///< Bicarb concentrate calibration record. +static DG_CONC_PUMPS_CAL_RECORD_T concentratePumpsCalRecord; ///< Concentrate pumps calibration record. // ********** private function prototypes ********** static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ); static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( CONCENTRATE_PUMPS_T pumpId ); - -static void stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ); -static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOnState( CONCENTRATE_PUMPS_T pumpId ); - +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpRampToTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ); +static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ); static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ); -static BOOL processCalibrationData( void ); +static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ); /*********************************************************************//** * @brief @@ -114,27 +142,23 @@ { CONCENTRATE_PUMPS_T pumpId; - concentratePumpMonitorTimerCounter = 0; + concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].control = &setFPGACP1Control; - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].setStepSpeed = &setFPGACP1SetStepSpeed; - - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].control = &setFPGACP2Control; - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].setStepSpeed = &setFPGACP2SetStepSpeed; - for ( pumpId = CONCENTRATEPUMPS_CP1_ACID; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { - concentratePumps[ pumpId ].controlTimerCounter = 0; - concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; + concentratePumps[ pumpId ].controlTimerCounter = 0; + concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; - concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; - + concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT stopConcentratePump( pumpId ); } initPersistentAlarm( ALARM_ID_CP1_SPEED_CONTROL_ERROR, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_CP2_SPEED_CONTROL_ERROR, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS, + CONCENTRATE_PUMP_HALL_SENSORS_OUT_OF_RANGE_TIME_MS ); } /*********************************************************************//** @@ -149,47 +173,52 @@ // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) { - // Get the new calibration data and check its validity - processCalibrationData(); + // Get the calibration values of acid and bicarb + getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( acidConcentrateCalRecord ), + NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); + getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( bicarbConcentrateCalRecord ), + NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); } if ( ++concentratePumpMonitorTimerCounter >= getU32OverrideValue( &concentratePumpDataPublishInterval ) ) { CONCENTRATE_PUMP_DATA_T data; - U08 const fpgaConcentratePumpsFault = getFPGAConcentratePumpsFault(); + U08 fpgaConcentratePumpsFault = getFPGAConcentratePumpsFault(); if ( 0 != fpgaConcentratePumpsFault ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONCENTRATE_PUMP_FAULT, fpgaConcentratePumpsFault ); } - calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); + calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1_ACID, getFPGACP1HallSensePulseWidth() ); calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2_BICARB, getFPGACP2HallSensePulseWidth() ); - // Get CP1 specifications - U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; - F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; - F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + U08 cp1Direction = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].direction; + F32 cp1SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; + F32 cp1Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; + F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; + F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - // Get CP2 specifications - U08 cp2Direction = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].direction; - F32 cp2SetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; - F32 cp2Speed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - + // Use the above values to prepare the broadcast data data.cp1CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1SetSpeed * -1.0 : cp1SetSpeed ); - data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); + data.cp1MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp1Direction ? cp1Speed * -1.0 : cp1Speed ); data.cp2CurrentSetSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2SetSpeed * -1.0 : cp2SetSpeed ); - data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); + data.cp2MeasuredSpeed = ( CONCENTRATE_PUMP_REVERSE_DIR == cp2Direction ? cp2Speed * -1.0 : cp2Speed ); + data.cp1State = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].execState; + data.cp2State = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].execState; + data.cp1PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].pulseWidthUS; + data.cp2PulseUS = concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].pulseWidthUS; -#ifndef DISABLE_DIALYSATE_CHECK - F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) - concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1_ACID ].currentPumpSpeed; - F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) - concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2_BICARB ].currentPumpSpeed; - - checkPersistentAlarm( ALARM_ID_CP1_SPEED_CONTROL_ERROR, cp1Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp1Error, CONCENTRATE_PUMP_ERROR_TOLERANCE ); - checkPersistentAlarm( ALARM_ID_CP2_SPEED_CONTROL_ERROR, cp2Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp2Error, CONCENTRATE_PUMP_ERROR_TOLERANCE ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS_SPEED_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + monitorPumpSpeed( CONCENTRATEPUMPS_CP1_ACID, ALARM_ID_CP1_SPEED_CONTROL_ERROR ); + monitorPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB, ALARM_ID_CP2_SPEED_CONTROL_ERROR ); + } - concentratePumpMonitorTimerCounter = 0U; + concentratePumpMonitorTimerCounter = 0; broadcastData( MSG_ID_DG_CONCENTRATE_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( CONCENTRATE_PUMP_DATA_T ) ); } } @@ -213,14 +242,21 @@ concentratePumps[ pumpId ].execState = handleConcentratePumpOffState( pumpId ); break; - case CONCENTRATE_PUMP_ON_STATE: - concentratePumps[ pumpId ].execState = handleConcentratePumpOnState( pumpId ); + case CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE: + concentratePumps[ pumpId ].execState = handleConcentratePumpRampToTargetSpeedState( pumpId ); break; + case CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE: + concentratePumps[ pumpId ].execState = handleConcentratePumpControlTargetSpeedState( pumpId ); + break; + +#ifndef _VECTORCAST_ + // The switch case is in a for loop so the default case cannot be covered in VectorCAST default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, pumpId ) concentratePumps[ pumpId ].execState = CONCENTRATE_PUMP_OFF_STATE; break; +#endif } } } @@ -236,18 +272,19 @@ SELF_TEST_STATUS_T execConcenratePumpsSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + BOOL calStatus = FALSE; - BOOL calStatus = processCalibrationData(); + calStatus |= getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( DG_ACID_CONCENTRATES_RECORD_T ), + NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } + calStatus |= getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( DG_BICARB_CONCENTRATES_RECORD_T ), + NUMBER_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); + calStatus |= getNVRecord2Driver( GET_CAL_CONCENTRATE_PUMPS_RECORD, (U08*)&concentratePumpsCalRecord, sizeof( DG_CONC_PUMPS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_DG_CONC_PUMPS, ALARM_ID_NO_ALARM ); + + result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); + return result; } @@ -264,7 +301,12 @@ { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { - concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CONC_PUMPS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; + } } else { @@ -286,7 +328,7 @@ if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; - concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; + concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } else { @@ -310,12 +352,14 @@ { if ( targetSpeed_ml_min >= 0.0 ) { - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_FORWARD; // For DVT } else { - concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; - targetSpeed_ml_min *= -1.0; + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; // For V3 + concentratePumps[ pumpId ].controlSet = CONCENTRATE_PUMP_CONTROL_REVERSE; // For DV + targetSpeed_ml_min *= -1.0; } if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) @@ -326,9 +370,9 @@ { concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; } - else + else if ( targetSpeed_ml_min > CONCENTRATE_PUMP_MAX_SPEED ) { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE, targetSpeed_ml_min ) + concentratePumps[ pumpId ].pumpTargetSpeed = CONCENTRATE_PUMP_MAX_SPEED; } } else @@ -339,6 +383,31 @@ /*********************************************************************//** * @brief + * The getConcentratePumpTargetFlowMLPM function returns the concentrate pump's + * flow rate in mL/min. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId concentrate pump id to get its target flow + * @return the current concentrate pump flow rate (in mL/min). + *************************************************************************/ +F32 getConcentratePumpTargetFlowMLPM( CONCENTRATE_PUMPS_T pumpId ) +{ + F32 flow = 0.0; + + if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) + { + flow = concentratePumps[ pumpId ].pumpTargetSpeed; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return flow; +} + +/*********************************************************************//** + * @brief * The getMeasuredPumpSpeed function gets the measured concentrate pump flow rate. * @details Inputs: measuredPumpSpeed * @details Outputs: none @@ -347,23 +416,18 @@ *************************************************************************/ F32 getMeasuredPumpSpeed( CONCENTRATE_PUMPS_T pumpId ) { - F32 result = 0.0; + F32 speed = 0.0; if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { - result = concentratePumps[ pumpId ].measuredPumpSpeed.data; - - if ( OVERRIDE_KEY == concentratePumps[ pumpId ].measuredPumpSpeed.override ) - { - result = concentratePumps[ pumpId ].measuredPumpSpeed.ovData; - } + speed = getF32OverrideValue( &concentratePumps[ pumpId ].measuredPumpSpeed ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); } - return result; + return speed; } /*********************************************************************//** @@ -404,11 +468,31 @@ *************************************************************************/ static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ) { - concentratePumps[ pumpId ].currentPumpSpeed = 0.0; + concentratePumps[ pumpId ].currentPumpSpeed = 0.0; concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; - concentratePumps[ pumpId ].control( CONCENTRATE_PUMP_OFF_CONTROL ); - concentratePumps[ pumpId ].setStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) + { + setFPGAV3AcidPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); + } + else + { + setFPGAV3BicarbPumpControl( CONCENTRATE_PUMP_OFF_CONTROL ); + } + } +#endif + + if ( CONCENTRATEPUMPS_CP1_ACID == pumpId ) + { + setFPGAAcidPumpSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); + } + else + { + setFPGABicarbSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); + } } /*********************************************************************//** @@ -426,28 +510,91 @@ if ( TRUE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { - U08 const controlValue = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); + U08 controlSet = 0; +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + controlSet = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAV3AcidPumpControl( controlSet ) : setFPGAV3BicarbPumpControl( controlSet ); + } + else +#endif + { + controlSet = concentratePumps[ pumpId ].controlSet; + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpControl( controlSet ) : setFPGABicarbPumpControl( controlSet ); + } - concentratePumps[ pumpId ].control( controlValue ); - state = CONCENTRATE_PUMP_ON_STATE; + state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; } return state; } /*********************************************************************//** * @brief + * The handleConcentratePumpRampToTargetSpeedState function executes the + * concentrate pump ramp up to target speed state. Once the speed is close + * to target the state is transitioned to control target state. + * @details Inputs: none + * @details Outputs: none + * @param pumpId concentrate pump id + * @return next state of the state machine + *************************************************************************/ +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpRampToTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ) +{ + CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_RAMP_TO_TARGET_SPEED_STATE; + + if ( TRUE == stepConcentratePumpToTargetSpeed( pumpId ) ) + { + state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleConcentratePumpControlTargetSpeedState function turns off concentrate + * pumps switch to off state upon request. While in on state, the function + * controls concentrate pumps to a target step speed. + * @details Inputs: currentPumpSpeed[] + * @details Outputs: control concentrate pumps to target step speed + * @param pumpId concentrate pump id + * @return state + *************************************************************************/ +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpControlTargetSpeedState( CONCENTRATE_PUMPS_T pumpId ) +{ + CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_CONTROL_TARGET_SPEED_STATE; + + if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) + { + concentratePumps[ pumpId ].controlTimerCounter = 0; + stepConcentratePumpToTargetSpeed( pumpId ); + } + + if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) + { + state = CONCENTRATE_PUMP_OFF_STATE; + stopConcentratePump( pumpId ); + } + + return state; +} + +/*********************************************************************//** + * @brief * The stepConcentratePumpToTargetSpeed function steps current step speed * toward target speed with predefined step increase. * @details Inputs: none * @details Outputs: currentPumpSpeed[] * @param pumpId concentrate pump id to increase current step speed - * @return none + * @return TRUE if the pump has reached to target otherwise, FALSE *************************************************************************/ -static void stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ) +static BOOL stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ) { - F32 const currentToTargetDiff = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); F32 speedIncrease; + BOOL hasTgtBeenReached = FALSE; + F32 currentToTargetDiff = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); if ( currentToTargetDiff > NEARLY_ZERO ) { @@ -457,7 +604,8 @@ } else { - speedIncrease = currentToTargetDiff; + speedIncrease = currentToTargetDiff; + hasTgtBeenReached = TRUE; } // Subtract current speed when target speed is smaller @@ -471,45 +619,19 @@ if ( concentratePumps[ pumpId ].currentPumpSpeed > NEARLY_ZERO ) { - F32 const timePerStep = CONCENTRATE_PUMP_VOLUME_PER_REV / ( concentratePumps[ pumpId ].currentPumpSpeed * CONCENTRATE_PUMP_STEP_PER_REV ) ; - F32 const stepPeriodCounts = timePerStep / ( CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION * CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ); - concentratePumps[ pumpId ].togglePeriodCount = (U16)( stepPeriodCounts + 0.5 ); + F32 timePerStep = CONCENTRATE_PUMP_VOLUME_PER_REV / ( concentratePumps[ pumpId ].currentPumpSpeed * CONCENTRATE_PUMP_STEP_PER_REV ); + F32 stepPeriodCounts = timePerStep / ( CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION * CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ); + concentratePumps[ pumpId ].togglePeriodCount = (U16)( stepPeriodCounts + FLOAT_TO_INT_ROUNDUP_OFFSET ); } else { concentratePumps[ pumpId ].togglePeriodCount = CONCENTRATE_PUMP_ZERO_FLOW_RATE; } -} -/*********************************************************************//** - * @brief - * The handleConcentratePumpOnState function turns off concentrate pumps switch - * to off state upon request. While in on state, the function controls concentrate - * pumps to a target step speed. - * @details Inputs: currentPumpSpeed[] - * @details Outputs: control concentrate pumps to target step speed - * @param pumpId concentrate pump id - * @return state - *************************************************************************/ -static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOnState( CONCENTRATE_PUMPS_T pumpId ) -{ - CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_ON_STATE; + CONCENTRATEPUMPS_CP1_ACID == pumpId ? setFPGAAcidPumpSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ) : + setFPGABicarbSetStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); - if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) - { - concentratePumps[ pumpId ].controlTimerCounter = 0; - - stepConcentratePumpToTargetSpeed( pumpId ); - concentratePumps[ pumpId ].setStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); - } - - if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) - { - state = CONCENTRATE_PUMP_OFF_STATE; - stopConcentratePump( pumpId ); - } - - return state; + return hasTgtBeenReached; } /*********************************************************************//** @@ -524,73 +646,50 @@ *************************************************************************/ static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ) { - F32 const pulseWidthInSecond = (F32)( pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION ) / US_PER_SECOND; - concentratePumps[ pumpId ].measuredPumpSpeed.data = ( 1 / pulseWidthInSecond ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; + F32 pulseWidthInMicroSeconds = (F32)pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION; + BOOL isPulseWidthOut = ( pulseWidthInMicroSeconds <= (F32)CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ? TRUE : FALSE ); - if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) + concentratePumps[ pumpId ].pulseWidthUS = pulseWidthInMicroSeconds; + + checkPersistentAlarm( ALARM_ID_DG_CONC_PUMP_HALL_SENSOR_OUT_OF_RANGE, isPulseWidthOut, pulseWidthInMicroSeconds, + CONCENTRATE_PUMP_MIN_ALLOWED_HALL_SENSOR_COUNT ); + + if ( FALSE == isPulseWidthOut ) { + concentratePumps[ pumpId ].measuredPumpSpeed.data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; + } + else if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) + { concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; } } /*********************************************************************//** * @brief - * The processCalibrationData function gets the calibration data and makes - * sure it is valid by checking the calibration date. The calibration date - * should not be 0. - * @details Inputs: none - * @details Outputs: acidConcentrateCalRecord, bicarbConcentrateCalRecord - * @return TRUE if the calibration record is valid, otherwise FALSE + * The monitorPumpSpeed function monitors the concentrate pumps speed and + * triggers the alarms if they are out of range. + * @details Inputs: concentratePumps + * @details Outputs: none + * @param pumpId pump id to set step speed + * @param alarm which the corresponding alarm of the concentrate pump + * @return none *************************************************************************/ -static BOOL processCalibrationData( void ) +static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ) { - BOOL status = TRUE; + F32 cpTargetSpeed = concentratePumps[ pumpId ].pumpTargetSpeed; + F32 cpError = fabs( getMeasuredPumpSpeed( pumpId ) - cpTargetSpeed ); + BOOL isCpSpeedOut = FALSE; - // Get the calibration record from NVDataMgmt - DG_ACID_CONCENTRATES_RECORD_T acidCalRecord = getDGAcidConcentratesRecord(); - DG_BICARB_CONCENTRATES_RECORD_T bicarbCalRecord = getDGBicarbConcentratesRecord(); - - // Check if the calibration data that was received from NVDataMgmt is legitimate - // The calibration date item should not be zero. If the calibration date is 0, - // then the data is not stored in the NV memory or it was corrupted. - if ( 0 == acidCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].calibrationTime ) + if ( concentratePumps[ pumpId ].execState != CONCENTRATE_PUMP_OFF_STATE ) { -#ifndef SKIP_CAL_CHECK - activateAlarmNoData( ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); - status = FALSE; -#endif + // Check if the pump is not in the off state and if it is not, divide the error + // to target speed. If the pump is off the target speed is 0 + cpError = cpError / cpTargetSpeed; } - // NOTE: Right now only acid concentrate 1 is used, therefore there is no for loop - acidConcentrateCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].startVolume = - acidCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].startVolume; + isCpSpeedOut = ( cpError > CONCENTRATE_PUMP_ERROR_TOLERANCE ? TRUE : FALSE ); - acidConcentrateCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio = - acidCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; - - acidConcentrateCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].reserverdSpace = - acidCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].reserverdSpace; - - // Check the validity of the bicarb concentrate values - if ( 0 == bicarbCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].calibrationTime ) - { -#ifndef SKIP_CAL_CHECK - activateAlarmNoData( ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); - status = FALSE; -#endif - } - - // NOTE: Right now only bicarb concentrate 1 is used, therefore there is no for loop - bicarbConcentrateCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].startVolume = - bicarbCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].startVolume; - - bicarbConcentrateCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio = - bicarbCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; - - bicarbConcentrateCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].reservedSpace = - bicarbCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].reservedSpace; - - return status; + checkPersistentAlarm( alarm, isCpSpeedOut, cpError, CONCENTRATE_PUMP_ERROR_TOLERANCE ); }