Index: firmware/App/Controllers/ConcentratePumps.c =================================================================== diff -u -rd717fd8e877c00b205621ca5ef885c9a59c47376 -r3461c140ba07e74863dee1d4c51d0119076fecf8 --- firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision d717fd8e877c00b205621ca5ef885c9a59c47376) +++ firmware/App/Controllers/ConcentratePumps.c (.../ConcentratePumps.c) (revision 3461c140ba07e74863dee1d4c51d0119076fecf8) @@ -32,6 +32,9 @@ #define CONCENTRATE_PUMP_ON_CONTROL 0x1A ///< Configuration to turn on concentrate pump with 8 microsteps. #define CONCENTRATE_PUMP_OFF_CONTROL 0x3A ///< Configuration to turn off concentrate pump. +#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 8.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_MAX_SPEED 49.0 ///< Maximum speed for concentrate pump in mL per min. @@ -61,28 +64,39 @@ 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 +} CONCENTRATE_PUMP_T; + // ********** private data ********** -static CONCENTRATE_PUMP_STATE_T concentratePumpState; ///< Concentrate pump module current state. -static BOOL hasTurnOnPumpsBeenRequested; ///< Flag indicates a request to turn concentrate pumps on. -static U32 concentratePumpControlTimerCounter; ///< Timer counter to perform control on concentrate pump. static U32 concentratePumpMonitorTimerCounter; ///< Timer counter to perform monitor on concentrate pump. /// Concentrate pump data publish interval. static OVERRIDE_U32_T concentratePumpDataPublishInterval = { CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, CONCENTRATE_PUMP_DATA_PUBLISH_INTERVAL, 0, 0 }; -static F32 pumpTargetSpeed[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Target concentrate pumps' speed (mL/min). -static F32 currentPumpSpeed[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Current controlled concentrate pumps' speed (mL/min). -static OVERRIDE_F32_T measuredPumpSpeed[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Measured concentrate pump speed (mL/min). -static U16 togglePeriodCount[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Converted pump speed (mL/min) to toggle period counts (0.5 uS increment counts per step). +static CONCENTRATE_PUMP_T concentratePumps[ NUM_OF_CONCENTRATE_PUMPS ]; ///< Array of concentrate pumps' data structure. // ********** private function prototypes ********** -static void stopConcentratePump( void ); -static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( void ); +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( void ); +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOnState( CONCENTRATE_PUMPS_T pumpId ); static U32 getPublishConcentratePumpDataInterval( void ); static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ); @@ -97,13 +111,27 @@ *************************************************************************/ void initConcentratePump( void ) { - concentratePumpState = CONCENTRATE_PUMP_OFF_STATE; - hasTurnOnPumpsBeenRequested = FALSE; - concentratePumpControlTimerCounter = 0; + CONCENTRATE_PUMPS_T pumpId; + concentratePumpMonitorTimerCounter = 0; - stopConcentratePump(); + concentratePumps[ CONCENTRATEPUMPS_CP1 ].control = &setFPGACP1Control; + concentratePumps[ CONCENTRATEPUMPS_CP1 ].setStepSpeed = &setFPGACP1SetStepSpeed; + concentratePumps[ CONCENTRATEPUMPS_CP2 ].control = &setFPGACP2Control; + concentratePumps[ CONCENTRATEPUMPS_CP2 ].setStepSpeed = &setFPGACP2SetStepSpeed; + + for ( pumpId = CONCENTRATEPUMPS_CP1; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) + { + 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; + + stopConcentratePump( pumpId ); + } + initPersistentAlarm( PERSISTENT_ALARM_CP1_SPEED_CONTROL_ERROR, ALARM_ID_CP1_SPEED_CONTROL_ERROR, TRUE, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD, CONCENTRATE_PUMP_SPEED_CONTROL_PERSISTENCE_PERIOD ); initPersistentAlarm( PERSISTENT_ALARM_CP2_SPEED_CONTROL_ERROR, ALARM_ID_CP2_SPEED_CONTROL_ERROR, @@ -126,13 +154,13 @@ calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP1, getFPGACP1HallSensePulseWidth() ); calcMeasuredPumpsSpeed( CONCENTRATEPUMPS_CP2, getFPGACP2HallSensePulseWidth() ); - data.cp1TargetSpeed = pumpTargetSpeed[ CONCENTRATEPUMPS_CP1 ]; + data.cp1TargetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP1 ].pumpTargetSpeed; data.cp1MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1 ); - data.cp2TargetSpeed = pumpTargetSpeed[ CONCENTRATEPUMPS_CP2 ]; + data.cp2TargetSpeed = concentratePumps[ CONCENTRATEPUMPS_CP2 ].pumpTargetSpeed; data.cp2MeasuredSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2 ); - F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1 ) - currentPumpSpeed[ CONCENTRATEPUMPS_CP1 ] ) / currentPumpSpeed[ CONCENTRATEPUMPS_CP1 ]; - F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2 ) - currentPumpSpeed[ CONCENTRATEPUMPS_CP2 ] ) / currentPumpSpeed[ CONCENTRATEPUMPS_CP2 ]; + F32 const cp1Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1 ) - concentratePumps[ CONCENTRATEPUMPS_CP1 ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP1 ].currentPumpSpeed; + F32 const cp2Error = fabs( getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2 ) - concentratePumps[ CONCENTRATEPUMPS_CP2 ].currentPumpSpeed ) / concentratePumps[ CONCENTRATEPUMPS_CP2 ].currentPumpSpeed; checkPersistentAlarm( PERSISTENT_ALARM_CP1_SPEED_CONTROL_ERROR, cp1Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp1Error ); checkPersistentAlarm( PERSISTENT_ALARM_CP2_SPEED_CONTROL_ERROR, cp2Error > CONCENTRATE_PUMP_ERROR_TOLERANCE, cp2Error ); @@ -145,26 +173,31 @@ /*********************************************************************//** * @brief * The execConcentratePumpController function executes the concentrate pump controller. - * @details Inputs: concentratePumpState - * @details Outputs: concentratePumpState + * @details Inputs: execState + * @details Outputs: execState * @return none *************************************************************************/ void execConcentratePumpController( void ) { - switch ( concentratePumpState ) + CONCENTRATE_PUMPS_T pumpId; + + for ( pumpId = CONCENTRATEPUMPS_CP1; pumpId < NUM_OF_CONCENTRATE_PUMPS; ++pumpId ) { - case CONCENTRATE_PUMP_OFF_STATE: - concentratePumpState = handleConcentratePumpOffState(); - break; + switch ( concentratePumps[ pumpId ].execState ) + { + case CONCENTRATE_PUMP_OFF_STATE: + concentratePumps[ pumpId ].execState = handleConcentratePumpOffState( pumpId ); + break; - case CONCENTRATE_PUMP_ON_STATE: - concentratePumpState = handleConcentratePumpOnState(); - break; + case CONCENTRATE_PUMP_ON_STATE: + concentratePumps[ pumpId ].execState = handleConcentratePumpOnState( pumpId ); + break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, concentratePumpState ) - concentratePumpState = CONCENTRATE_PUMP_OFF_STATE; - break; + 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; + } } } @@ -174,11 +207,19 @@ * the concentrate pumps. * @details Inputs: none * @details Outputs: set flag isPumpOnRequested to TRUE + * @param pumpId concentrate pump id * @return none *************************************************************************/ -void requestConcentratePumpsOn( void ) +void requestConcentratePumpsOn( CONCENTRATE_PUMPS_T pumpId ) { - hasTurnOnPumpsBeenRequested = TRUE; + if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) + { + concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = TRUE; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } } /*********************************************************************//** @@ -187,13 +228,20 @@ * the concentrate pumps. * @details Inputs: none * @details Outputs: set flag isPumpOffRequested to TRUE + * @param pumpId concentrate pump id * @return none *************************************************************************/ -void requestConcentratePumpsOff( void ) +void requestConcentratePumpsOff( CONCENTRATE_PUMPS_T pumpId ) { - hasTurnOnPumpsBeenRequested = FALSE; - pumpTargetSpeed[ CONCENTRATEPUMPS_CP1 ] = 0.0; - pumpTargetSpeed[ CONCENTRATEPUMPS_CP2 ] = 0.0; + if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) + { + concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested = FALSE; + concentratePumps[ pumpId ].pumpTargetSpeed = 0.0; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, pumpId ); + } } /*********************************************************************//** @@ -210,9 +258,19 @@ { if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { + if ( targetSpeed_ml_min >= 0.0 ) + { + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_FORWARD_DIR; + } + else + { + concentratePumps[ pumpId ].direction = CONCENTRATE_PUMP_REVERSE_DIR; + targetSpeed_ml_min *= -1.0; + } + if ( ( CONCENTRATE_PUMP_MIN_SPEED <= targetSpeed_ml_min ) && ( targetSpeed_ml_min <= CONCENTRATE_PUMP_MAX_SPEED ) ) { - pumpTargetSpeed[ pumpId ] = targetSpeed_ml_min; + concentratePumps[ pumpId ].pumpTargetSpeed = targetSpeed_ml_min; } else { @@ -231,23 +289,16 @@ * and turns off concentrate pumps. * @details Inputs: none * @details Outputs: targetPumpSpeed[], currentPumpSpeed[], turn concentrate pumps off + * @param pumpId concentrate pump id * @return none *************************************************************************/ -static void stopConcentratePump( void ) +static void stopConcentratePump( CONCENTRATE_PUMPS_T pumpId ) { - U32 ii; + concentratePumps[ pumpId ].currentPumpSpeed = 0.0; + concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; - for ( ii = 0; ii < NUM_OF_CONCENTRATE_PUMPS; ii++ ) - { - pumpTargetSpeed[ ii ] = 0.0; - currentPumpSpeed[ ii ] = 0.0; - measuredPumpSpeed[ ii ].data = 0.0; - } - - setFPGACP1Control( CONCENTRATE_PUMP_OFF_CONTROL ); - setFPGACP2Control( CONCENTRATE_PUMP_OFF_CONTROL ); - setFPGACP1SetStepSpeed( currentPumpSpeed[ CONCENTRATEPUMPS_CP1 ] ); - setFPGACP2SetStepSpeed( currentPumpSpeed[ CONCENTRATEPUMPS_CP2 ] ); + concentratePumps[ pumpId ].control( CONCENTRATE_PUMP_OFF_CONTROL ); + concentratePumps[ pumpId ].setStepSpeed( CONCENTRATE_PUMP_ZERO_FLOW_RATE ); } /*********************************************************************//** @@ -256,17 +307,18 @@ * switch to on state upon request. * @details Inputs: none * @details Outputs: concentrate pumps turn on + * @param pumpId concentrate pump id * @return state *************************************************************************/ -static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( void ) +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOffState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_OFF_STATE; - if ( TRUE == hasTurnOnPumpsBeenRequested ) + if ( TRUE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { - setFPGACP1Control( CONCENTRATE_PUMP_ON_CONTROL ); - setFPGACP2Control( CONCENTRATE_PUMP_ON_CONTROL ); + U08 const controlValue = ( CONCENTRATE_PUMP_ON_CONTROL | concentratePumps[ pumpId ].direction ); + concentratePumps[ pumpId ].control( controlValue ); state = CONCENTRATE_PUMP_ON_STATE; } @@ -284,7 +336,7 @@ *************************************************************************/ static void stepConcentratePumpToTargetSpeed( CONCENTRATE_PUMPS_T pumpId ) { - F32 const currentToTargetDiff = fabs( pumpTargetSpeed[ pumpId ] - currentPumpSpeed[ pumpId ] ); + F32 const currentToTargetDiff = fabs( concentratePumps[ pumpId ].pumpTargetSpeed - concentratePumps[ pumpId ].currentPumpSpeed ); F32 speedIncrease; if ( currentToTargetDiff > NEARLY_ZERO ) @@ -299,23 +351,23 @@ } // Subtract current speed when target speed is smaller - if ( pumpTargetSpeed[ pumpId ] < currentPumpSpeed[ pumpId ] ) + if ( concentratePumps[ pumpId ].pumpTargetSpeed < concentratePumps[ pumpId ].currentPumpSpeed ) { speedIncrease *= -1.0; } - currentPumpSpeed[ pumpId ] += speedIncrease; + concentratePumps[ pumpId ].currentPumpSpeed += speedIncrease; } - if ( currentPumpSpeed[ pumpId ] > NEARLY_ZERO ) + if ( concentratePumps[ pumpId ].currentPumpSpeed > NEARLY_ZERO ) { - F32 const timePerStep = CONCENTRATE_PUMP_VOLUME_PER_REV / ( currentPumpSpeed[ pumpId ] * CONCENTRATE_PUMP_STEP_PER_REV ) ; + 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 ); - togglePeriodCount[ pumpId ] = (U16)( stepPeriodCounts + 0.5 ); + concentratePumps[ pumpId ].togglePeriodCount = (U16)( stepPeriodCounts + 0.5 ); } else { - togglePeriodCount[ pumpId ] = CONCENTRATE_PUMP_ZERO_FLOW_RATE; + concentratePumps[ pumpId ].togglePeriodCount = CONCENTRATE_PUMP_ZERO_FLOW_RATE; } } @@ -326,27 +378,25 @@ * 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( void ) +static CONCENTRATE_PUMP_STATE_T handleConcentratePumpOnState( CONCENTRATE_PUMPS_T pumpId ) { CONCENTRATE_PUMP_STATE_T state = CONCENTRATE_PUMP_ON_STATE; - if ( ++concentratePumpControlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) + if ( ++concentratePumps[ pumpId ].controlTimerCounter >= CONCENTRATE_PUMP_CONTROL_INTERVAL ) { - concentratePumpControlTimerCounter = 0; + concentratePumps[ pumpId ].controlTimerCounter = 0; - stepConcentratePumpToTargetSpeed( CONCENTRATEPUMPS_CP1 ); - stepConcentratePumpToTargetSpeed( CONCENTRATEPUMPS_CP2 ); - - setFPGACP1SetStepSpeed( togglePeriodCount[ CONCENTRATEPUMPS_CP1 ] ); - setFPGACP2SetStepSpeed( togglePeriodCount[ CONCENTRATEPUMPS_CP2 ] ); + stepConcentratePumpToTargetSpeed( pumpId ); + concentratePumps[ pumpId ].setStepSpeed( concentratePumps[ pumpId ].togglePeriodCount ); } - if ( FALSE == hasTurnOnPumpsBeenRequested ) + if ( FALSE == concentratePumps[ pumpId ].hasTurnOnPumpsBeenRequested ) { state = CONCENTRATE_PUMP_OFF_STATE; - stopConcentratePump(); + stopConcentratePump( pumpId ); } return state; @@ -385,11 +435,11 @@ static void calcMeasuredPumpsSpeed( CONCENTRATE_PUMPS_T pumpId, U16 pulseWidthCount ) { F32 const pulseWidthInSecond = (F32)( pulseWidthCount * CONCENTRATE_PUMP_HALL_SENSE_PERIOD_RESOLUTION ) / US_PER_SECOND; - measuredPumpSpeed[ pumpId ].data = ( 1 / pulseWidthInSecond ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; + concentratePumps[ pumpId ].measuredPumpSpeed.data = ( 1 / pulseWidthInSecond ) * CONCENTRATE_PUMP_VOLUME_PER_PULSE * SEC_PER_MIN; if ( CONCENTRATE_PUMP_ZERO_FLOW_RATE == pulseWidthCount ) { - measuredPumpSpeed[ pumpId ].data = 0.0; + concentratePumps[ pumpId ].measuredPumpSpeed.data = 0.0; } } @@ -407,11 +457,11 @@ if ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) { - result = measuredPumpSpeed[ pumpId ].data; + result = concentratePumps[ pumpId ].measuredPumpSpeed.data; - if ( OVERRIDE_KEY == measuredPumpSpeed[ pumpId ].override ) + if ( OVERRIDE_KEY == concentratePumps[ pumpId ].measuredPumpSpeed.override ) { - result = measuredPumpSpeed[ pumpId ].ovData; + result = concentratePumps[ pumpId ].measuredPumpSpeed.ovData; } } else @@ -491,7 +541,9 @@ if ( pumpId < NUM_OF_CONCENTRATE_PUMPS && isTestingActivated() ) { - if ( ( CONCENTRATE_PUMP_MIN_SPEED <= value ) && ( value <= CONCENTRATE_PUMP_MAX_SPEED ) ) + F32 const absSpeed = fabs( value ); + + if ( ( CONCENTRATE_PUMP_MIN_SPEED <= absSpeed ) && ( absSpeed <= CONCENTRATE_PUMP_MAX_SPEED ) ) { result = TRUE; setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, value ); @@ -518,8 +570,8 @@ if ( ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) && isTestingActivated() ) { result = TRUE; - measuredPumpSpeed[ pumpId ].ovData = value; - measuredPumpSpeed[ pumpId ].override = OVERRIDE_KEY; + concentratePumps[ pumpId ].measuredPumpSpeed.ovData = value; + concentratePumps[ pumpId ].measuredPumpSpeed.override = OVERRIDE_KEY; } return result; @@ -541,8 +593,8 @@ if ( ( pumpId < NUM_OF_CONCENTRATE_PUMPS ) && isTestingActivated() ) { result = TRUE; - measuredPumpSpeed[ pumpId ].ovData = 0.0; - measuredPumpSpeed[ pumpId ].override = OVERRIDE_RESET; + concentratePumps[ pumpId ].measuredPumpSpeed.ovData = 0.0; + concentratePumps[ pumpId ].measuredPumpSpeed.override = OVERRIDE_RESET; } return result;