Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -r573a26b2a0273a4983b1de1cbff5bed63e01dce0 -rd210786d6c7d75bb0b4d9e18efc40a01d85123fe --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 573a26b2a0273a4983b1de1cbff5bed63e01dce0) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision d210786d6c7d75bb0b4d9e18efc40a01d85123fe) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 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) Vinayakam Mani -* @date (last) 18-Sep-2024 +* @author (last) Sameer Kalliadan Poyil +* @date (last) 03-Feb-2026 * * @author (original) Vinayakam Mani -* @date (original) 18-Sep-2024 +* @date (original) 19-Sep-2024 * ***************************************************************************/ #include @@ -37,19 +37,13 @@ #define CONCENTRATE_PUMP_RAMP_SPEED_INCREMENT 10.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_SPD_OUT_OF_RANGE_TOL_WHEN_ON_PCT 0.02F ///< Concentrate pump speed out of range tolerance when on in percentage. +#define CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_ON_PCT 0.01F ///< Concentrate pump speed out of range tolerance when on in percentage. +#define CONCENTRATE_PUMP_CLEANING_SPD_OUT_OF_RANGE_TOL_PCT 0.05F ///< Concentrate pump cleaning mode speed out of range tolerance when on in percentage. #define CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_SLOW_MLPM 1.0F ///< Concentrate pump speed out of range tolerance when slow in mL/min. #define CONCENTRATE_PUMP_LOW_SPEED_THRESHOLD_MLPM 10.0F ///< Concentrate pump low speed threshold in mL/min. #define CONCENTRATE_PUMP_ZERO_FLOW_RATE 0xFFFF ///< Pulse width value when zero flow rate or pump is off. - -#ifdef __DIENER_CONC_PUMP__ -#define CONCENTRATE_PUMP_VOLUME_PER_REV 0.4F ///< Volume output every revolution (mL). -#elif __PUMPTEST__ -#define PISTON_PUMP_STEPS_PER_ML 342.0F ///< Revolution count for 1ml volume delivery. -#define CONCENTRATE_PUMP_VOLUME_PER_REV ( CONCENTRATE_PUMP_STEP_PER_REV / PISTON_PUMP_STEPS_PER_ML ) ///< Volume output every revolution (mL). -#else +#define CONCENTRATE_PUMP_VOLUME_PER_REV_DIENER 0.4F ///< Volume output every revolution (mL). #define CONCENTRATE_PUMP_VOLUME_PER_REV 0.1F ///< Volume output every revolution (mL). -#endif #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. @@ -58,27 +52,21 @@ #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.0F ///< Number of micro-steps ( fractions of step) per step. -#define CONCENTRATE_PUMP_VOLUME_TO_REVOLUTION ( ( 1.0F / CONCENTRATE_PUMP_VOLUME_PER_REV ) * \ +#define CONCENTRATE_PUMP_VOLUME_TO_REVOLUTION_DIENER ( ( 1.0F / CONCENTRATE_PUMP_VOLUME_PER_REV_DIENER ) * \ ( CONCENTRATE_PUMP_STEP_PER_REV * \ CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ) ) ///< Convert volume in to number of revolutions needed. -#ifdef __PUMPTEST__ -#define PISTON_PUMP_VOLUME_TO_REVOLUTION ( PISTON_PUMP_STEPS_PER_ML * CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ) ///< Convert volume in to number of revolutions needed. -#endif #define CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION ( 0.50F / ( US_PER_SECOND * SEC_PER_MIN ) ) ///< Convert step period resolution (0.50 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_VOLUME_PER_PULSE_DIENER ( CONCENTRATE_PUMP_VOLUME_PER_REV_DIENER / CONCENTRATE_PUMP_PULSE_PER_REV ) #define CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is monitored. #define CONCENTRATE_PUMP_CONTROL_INTERVAL ( 100 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the concentrate pump is controlled. #define CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Concentrate pumps speed out of range timeout in milliseconds. #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. - #define ZERO_REVOLUTION_COUNT 0 ///< Revolution count reached to Zero. - #define CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD 500 ///< Concentrate pump fault persistence period in milliseconds. #define CONCENTRATE_PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD_MLPM 20.0F ///< Concentrate pump transition to ramp to target speed threshold in mL/min. @@ -140,10 +128,9 @@ static U32 concentratePumpMonitorTimerCounter; ///< Timer counter to perform monitor on concentrate pump. static BOOL acidConcentratePumpParkPersistenceClear; ///< Boolean acid park persistence clearing. static BOOL bicarbConcentratePumpParkPersistenceClear; ///< Boolean for bicarb park persistence clearing. +static BOOL ufPumpParkPersistenceClear; ///< Boolean for UF pump park persistence clearing. +static OVERRIDE_U32_T concentratePumpDataPublishInterval; ///< Concentrate pump data publish interval. -/// Concentrate pump data publish interval. -static OVERRIDE_U32_T concentratePumpDataPublishInterval = { CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, 0, 0 }; - static CONCENTRATE_PUMP_T concentratePumps[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Array of concentrate pumps' data structure. static OVERRIDE_U32_T hasParkBeenRequested[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Flag indicates a request to park the pump. static OVERRIDE_F32_T pumpTargetSpeed[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Target concentrate pumps' speed (mL/min). @@ -186,6 +173,7 @@ concentratePumpMonitorTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; acidConcentratePumpParkPersistenceClear = FALSE; bicarbConcentratePumpParkPersistenceClear = FALSE; + ufPumpParkPersistenceClear = FALSE; for ( pumpId = CONCENTRATEPUMPS_FIRST; pumpId < NUM_OF_CONCENTRATE_PUMPS; pumpId++ ) { @@ -227,9 +215,14 @@ isDosingCompleted[ pumpId ] = FALSE; } + concentratePumpDataPublishInterval.data = CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL; + concentratePumpDataPublishInterval.ovInitData = CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL; + concentratePumpDataPublishInterval.ovData = 0; + concentratePumpDataPublishInterval.override = OVERRIDE_RESET; + initPersistentAlarm( ALARM_ID_DD_D11_PUMP_SPEED_CONTROL_ERROR, 0, CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_D10_PUMP_SPEED_CONTROL_ERROR, 0, CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ); - //TODO: UF pump park bits to be defined in HDD and then will handle UF pump alarm later + initPersistentAlarm( ALARM_ID_DD_D76_PUMP_SPEED_CONTROL_ERROR, 0, CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_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 ); initPersistentAlarm( ALARM_ID_DD_CONCENTRATE_PUMP_FAULT, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD ); } @@ -248,6 +241,9 @@ U08 fpgaConcPumpsFault = getFPGAConcentratePumpsFault(); BOOL isConcPumpFault = ( fpgaConcPumpsFault > 0 ? TRUE : FALSE ); + //Update UF pump speed fault + fpgaConcPumpsFault |= getFPGAUFPumpFault(); + // Check if a new calibration is available // if ( TRUE == isNewCalibrationRecordAvailable() ) // { @@ -272,6 +268,7 @@ //Monitor Pump Speed monitorPumpSpeed( D11_PUMP, ALARM_ID_DD_D11_PUMP_SPEED_CONTROL_ERROR ); monitorPumpSpeed( D10_PUMP, ALARM_ID_DD_D10_PUMP_SPEED_CONTROL_ERROR ); + monitorPumpSpeed( D76_PUMP, ALARM_ID_DD_D76_PUMP_SPEED_CONTROL_ERROR ); checkPersistentAlarm( ALARM_ID_DD_CONCENTRATE_PUMP_FAULT, isConcPumpFault, fpgaConcPumpsFault, CONCENTRATE_PUMP_FAULT_PERSISTENCE_PERIOD ); @@ -285,16 +282,17 @@ * and associated fault handling. * @details \b Inputs: Park status * @details \b Outputs: isConcPumpParkInProgress,acidConcentratePumpParkPersistenceClear - * bicarbConcentratePumpParkPersistenceClear + * bicarbConcentratePumpParkPersistenceClear,ufPumpParkPersistenceClear * @return none *************************************************************************/ static void monitorPumpParkStatus( void ) { parked[ D11_PUMP ].data = (U32)getFPGAD11PumpIsParked(); parked[ D10_PUMP ].data = (U32)getFPGAD10PumpIsParked(); + parked[ D76_PUMP ].data = (U32)getFPGAD76PumpIsParked(); parkFaulted[ D11_PUMP ].data = (U32)getFPGAD11PumpParkFault(); parkFaulted[ D10_PUMP ].data = (U32)getFPGAD10PumpParkFault(); - // TODO : Handle UF Pump Park alarms once HDD updated with the details. + parkFaulted[ D76_PUMP ].data = (U32)getFPGAD76PumpParkFault(); if ( ( TRUE == getConcPumpIsParked( D11_PUMP ) ) || ( TRUE == getConcPumpParkIsFaulted( D11_PUMP ) ) ) { @@ -305,6 +303,10 @@ { concentratePumps[ D10_PUMP ].isConcPumpParkInProgress = FALSE; } + if ( ( TRUE == getConcPumpIsParked( D76_PUMP ) ) || ( TRUE == getConcPumpParkIsFaulted( D76_PUMP ) ) ) + { + concentratePumps[ D76_PUMP ].isConcPumpParkInProgress = FALSE; + } // Don't monitor persistence for cp speed alarms if we are parked. if ( TRUE == acidConcentratePumpParkPersistenceClear ) @@ -332,6 +334,19 @@ resetPersistentAlarmTimer( ALARM_ID_DD_D10_PUMP_SPEED_CONTROL_ERROR ); } } + + if ( TRUE == ufPumpParkPersistenceClear ) + { + // Clear flag and resume persistence checking once park bit is set. + if ( TRUE == getConcPumpIsParked( D76_PUMP ) ) + { + ufPumpParkPersistenceClear = FALSE; + } + else + { + resetPersistentAlarmTimer( ALARM_ID_DD_D76_PUMP_SPEED_CONTROL_ERROR ); + } + } } /*********************************************************************//** @@ -404,7 +419,7 @@ * the concentrate pumps. * @details \b Inputs: none * @details \b Outputs: concentratePumps[],acidConcentratePumpParkPersistenceClear, - * bicarbConcentratePumpParkPersistenceClear + * bicarbConcentratePumpParkPersistenceClear, ufPumpParkPersistenceClear * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. * @param pumpId concentrate pump id * @return none @@ -416,6 +431,7 @@ concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; acidConcentratePumpParkPersistenceClear = FALSE; bicarbConcentratePumpParkPersistenceClear = FALSE; + ufPumpParkPersistenceClear = FALSE; } else { @@ -534,18 +550,15 @@ //Update target revolution count if ( targetVolume_ml > 0.0 ) { -#ifndef __PUMPTEST__ if ( DOSING_CONT_VOLUME == targetVolume_ml ) { pumpTargetRevCnt[ pumpId ].data = DOSING_CONT_VOLUME; } else { - pumpTargetRevCnt[ pumpId ].data = (U32)( targetVolume_ml * CONCENTRATE_PUMP_VOLUME_TO_REVOLUTION ); + pumpTargetRevCnt[ pumpId ].data = (U32)( targetVolume_ml * CONCENTRATE_PUMP_VOLUME_TO_REVOLUTION_DIENER ); } -#else - pumpTargetRevCnt[ pumpId ].data = (U32)( targetVolume_ml * PISTON_PUMP_VOLUME_TO_REVOLUTION ); -#endif + if ( D11_PUMP == pumpId ) { setFPGAD11PumpRevolutionCount( getConcPumpTargetRevolutionCount( pumpId ) ); @@ -563,9 +576,9 @@ } /* - * If 3.0 <= speed <= 48 set it + * If 3.0 <= speed <= 60 set it * If speed < 3.0 set to 0 - * else speed > 48 set to 48 + * else speed > 60 set to 60 */ if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) { @@ -577,7 +590,7 @@ } else { - pumpTargetSpeed[ pumpId ].data = CONCENTRATE_PUMP_MAX_SPEED; + pumpTargetSpeed[ pumpId ].data = DOSING_CONCENTRATE_PUMP_SPEED; } } else @@ -859,7 +872,7 @@ { setFPGAD76PumpSetStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); } -#ifndef __PUMPTEST__ + // Park concentrate pump too if requested if ( TRUE == parkPump ) { @@ -875,12 +888,11 @@ } else { - //TODO: Need to evaluate park support in the new pump. setFPGAD76PumpParkCmd(); + ufPumpParkPersistenceClear = TRUE; } concentratePumps[ pumpId ].isConcPumpParkInProgress = TRUE; } -#endif } /*********************************************************************//** @@ -1040,9 +1052,11 @@ if ( concentratePumps[ pumpId ].currentPumpSpeed > NEARLY_ZERO ) { - 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 ); + F32 timePerStep; + F32 stepPeriodCounts; + timePerStep = CONCENTRATE_PUMP_VOLUME_PER_REV_DIENER / ( concentratePumps[ pumpId ].currentPumpSpeed * CONCENTRATE_PUMP_STEP_PER_REV ); + stepPeriodCounts = timePerStep / ( CONCENTRATE_PUMP_STEP_PERIOD_RESOLUTION * CONCENTRATE_PUMP_MICRO_STEPS_PER_STEP ); concentratePumps[ pumpId ].togglePeriodCount = (U16)( stepPeriodCounts + FLOAT_TO_INT_ROUNDUP_OFFSET ); } else @@ -1116,7 +1130,7 @@ } else if ( FALSE == isPumpPulseWidthOut ) { - measuredPumpSpeed[ pumpId ].data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; + measuredPumpSpeed[ pumpId ].data = ( US_PER_SECOND / pulseWidthInMicroSeconds ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE_DIENER * SEC_PER_MIN; } // If pulse width is out of range capture pump out of range, pumpId and pulse width @@ -1142,23 +1156,33 @@ * between requested and measured is not in range. * @details \b Alarm: ALARM_ID_DD_D10_PUMP_SPEED_CONTROL_ERROR when the speed difference * between requested and measured is not in range. + * @details \b Alarm: ALARM_ID_DD_D76_PUMP_SPEED_CONTROL_ERROR when the speed difference + * between requested and measured is not in range. * @param pumpId pump id to check the difference between requested and measured speed * @param alarm which the corresponding alarm of the concentrate pump * @return none *************************************************************************/ static void monitorPumpSpeed( CONCENTRATE_PUMPS_T pumpId, ALARM_ID_T alarm ) { - F32 cpTargetSpeed = concentratePumps[ pumpId ].currentPumpSpeed; - F32 cpError = fabs( fabs( getMeasuredPumpSpeedMLPM( pumpId ) ) - cpTargetSpeed ); - BOOL isCpSpeedOut = FALSE; - F32 tolerance = CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_SLOW_MLPM; + F32 cpTargetSpeed = fabs( concentratePumps[ pumpId ].currentPumpSpeed ); + F32 cpMeasSpeed = fabs( getMeasuredPumpSpeedMLPM( pumpId ) ); + F32 cpError = fabs( cpMeasSpeed - cpTargetSpeed ); + BOOL isCpSpeedOut = FALSE; + F32 tolerance = CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_SLOW_MLPM; + DD_OP_MODE_T opMode = getCurrentOperationMode(); if ( cpTargetSpeed > CONCENTRATE_PUMP_LOW_SPEED_THRESHOLD_MLPM ) { // Check if the pump is not in the off state and if it is not and greater than the minimum threshold, divide the error // to target speed. If the pump is off the target speed is 0 so the speed check is done differently + // The speed tolerance is looser in heat disinfect and flush than the rest of the modes that the concentrate pump are running. cpError = cpError / cpTargetSpeed; tolerance = CONCENTRATE_PUMP_SPD_OUT_OF_RANGE_TOL_WHEN_ON_PCT; + + if ( DD_MODE_HEAT == opMode ) + { + tolerance = CONCENTRATE_PUMP_CLEANING_SPD_OUT_OF_RANGE_TOL_PCT; + } } isCpSpeedOut = ( cpError > tolerance ? TRUE : FALSE ); @@ -1403,9 +1427,7 @@ { // Handle start command if ( ( TRUE == payload.startStop ) && -#ifndef __PUMPTEST__ - ( ( payload.speed >= CONCENTRATE_PUMP_MIN_SPEED ) && ( payload.speed <= CONCENTRATE_PUMP_MAX_SPEED ) ) && -#endif + ( ( payload.speed >= CONCENTRATE_PUMP_MIN_SPEED ) && ( payload.speed <= DOSING_CONCENTRATE_PUMP_SPEED ) ) && ( payload.volume > 0.0 ) ) { setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)payload.pumpID, payload.speed, payload.volume );