Index: firmware/App/Controllers/PistonPumpControl.c =================================================================== diff -u -r322747d530c1b8205be257557e53dcfe9caad50a -r5126b79e4970ffe2ed9db4cccea18a1216c78570 --- firmware/App/Controllers/PistonPumpControl.c (.../PistonPumpControl.c) (revision 322747d530c1b8205be257557e53dcfe9caad50a) +++ firmware/App/Controllers/PistonPumpControl.c (.../PistonPumpControl.c) (revision 5126b79e4970ffe2ed9db4cccea18a1216c78570) @@ -17,6 +17,7 @@ #include "ConcentratePumps.h" #include "FpgaDD.h" +#include "Level.h" #include "Messaging.h" #include "PistonPumpControl.h" #include "TaskGeneral.h" @@ -35,7 +36,8 @@ #define PISTON_PUMP_FILL_PERIOD ( 4000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the piston pump filling cycle time #define PISTON_PUMP_DISPENSE_PERIOD ( 4000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the piston pump dispense cycle time #define PISTON_PUMP_MIN_SPEED 3.0F ///< Piston pump minimum speed in ml/min. -#define PISTON_PUMP_MAX_SPEED 48.0F ///< Maximum speed for piston pump in mL/min +#define PISTON_PUMP_NOMINAL_SPEED 40.0F ///< Nominal piston pump speed in ml/min. +#define PISTON_PUMP_MAX_SPEED 48.0F ///< Maximum speed for piston pump in mL/min. /// Enumeration of piston pump states. typedef enum PistonPumpState @@ -63,12 +65,13 @@ static PISTON_PUMP_EXEC_STATE_T pistonPumpExecState[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump control executive state. static F32 pistonPumpSetSpeed[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump set speed. static F32 pistonPumpVolumeinMl[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump set volume to deliver. -static U32 pistonPumpFillPeriod; ///< Piston pump fill period -static U32 pistonPumpDispensePeriod; ///< Piston pump dispense period static U32 pistonPumpCycleCount[ NUM_OF_PISTON_PUMPS ]; ///< Number of piston pump (fill and dispense) cycle count -static U32 currentPistonPumpSwitchingCounter[ NUM_OF_PISTON_PUMPS ]; ///< Counter (in task interval) to monitor the piston pump fill/drain operation. -static U32 pistonPumpControlDataPublicationTimerCounter; ///< Used to schedule piston pump control data publication to CAN bus. static OVERRIDE_U32_T pistonPumpControlDataPublishInterval; ///< Piston Pump control data publish interval. +static OVERRIDE_U32_T pistonPumpFillAfterDispense; ///< Piston Pump fill after dispense on each cycle. +static U32 currentDosingTriggerStatus; ///< Read Current Dosing Trigger status +static U32 prevDosingTriggerStatus; ///< Previous Current Dosing status +static U32 pistonPumpControlDataPublicationTimerCounter; ///< Piston pump data publish timer counter +static BOOL readyToDose[ NUM_OF_PISTON_PUMPS ]; ///< Ready to dose status // ********** private function prototypes ********** @@ -80,6 +83,7 @@ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseCompleteState( PISTON_PUMPS_T pumpId ); static U32 getPistonPumpControlDataPublishInterval( void ); static void publishPistonPumpControlData( void ); +static U32 getPistonPumpFillafterDispenseControl( void ); /*********************************************************************//** * @brief @@ -94,24 +98,28 @@ pistonPumpExecState[ PISTONPUMPS_ACID ] = PISTON_PUMP_OFF_STATE; pistonPumpExecState[ PISTONPUMPS_BICARB ] = PISTON_PUMP_OFF_STATE; pistonPumpExecState[ PISTONPUMPS_UF ] = PISTON_PUMP_OFF_STATE; - currentPistonPumpSwitchingCounter[ PISTONPUMPS_ACID ] = 0; - currentPistonPumpSwitchingCounter[ PISTONPUMPS_BICARB ] = 0; - currentPistonPumpSwitchingCounter[ PISTONPUMPS_UF ] = 0; pistonPumpCycleCount[ PISTONPUMPS_ACID ] = 0; pistonPumpCycleCount[ PISTONPUMPS_BICARB ] = 0; pistonPumpCycleCount[ PISTONPUMPS_UF ] = 0; - pistonPumpVolumeinMl[ PISTONPUMPS_ACID ] = 0.0F; - pistonPumpVolumeinMl[ PISTONPUMPS_BICARB ] = 0.0F; + pistonPumpVolumeinMl[ PISTONPUMPS_ACID ] = DEFAULT_ACID_VOLUME_ML; + pistonPumpVolumeinMl[ PISTONPUMPS_BICARB ] = DEFAULT_BICARB_VOLUME_ML; pistonPumpVolumeinMl[ PISTONPUMPS_UF ] = 0.0F; - pistonPumpSetSpeed[ PISTONPUMPS_ACID ] = PISTON_PUMP_MIN_SPEED; - pistonPumpSetSpeed[ PISTONPUMPS_BICARB ] = PISTON_PUMP_MIN_SPEED; - pistonPumpSetSpeed[ PISTONPUMPS_UF ] = PISTON_PUMP_MIN_SPEED; + pistonPumpSetSpeed[ PISTONPUMPS_ACID ] = PISTON_PUMP_NOMINAL_SPEED; + pistonPumpSetSpeed[ PISTONPUMPS_BICARB ] = PISTON_PUMP_NOMINAL_SPEED; + pistonPumpSetSpeed[ PISTONPUMPS_UF ] = PISTON_PUMP_NOMINAL_SPEED; pistonPumpControlDataPublishInterval.data = PISTON_PUMP_CONTROL_DATA_PUBLISH_INTERVAL; pistonPumpControlDataPublishInterval.ovData = PISTON_PUMP_CONTROL_DATA_PUBLISH_INTERVAL; pistonPumpControlDataPublishInterval.ovInitData = 0; pistonPumpControlDataPublishInterval.override = OVERRIDE_RESET; - pistonPumpFillPeriod = PISTON_PUMP_FILL_PERIOD; - pistonPumpDispensePeriod = PISTON_PUMP_DISPENSE_PERIOD; + pistonPumpFillAfterDispense.data = TRUE; + pistonPumpFillAfterDispense.ovData = TRUE; + pistonPumpFillAfterDispense.ovInitData = 0; + pistonPumpFillAfterDispense.override = OVERRIDE_RESET; + currentDosingTriggerStatus = 0; + prevDosingTriggerStatus = 0; + readyToDose[ PISTONPUMPS_ACID ] = FALSE; + readyToDose[ PISTONPUMPS_BICARB ] = FALSE; + readyToDose[ PISTONPUMPS_UF ] = FALSE; pistonPumpControlDataPublicationTimerCounter = 0; } @@ -129,9 +137,6 @@ for ( pumpId = PISTONPUMPS_FIRST; pumpId < NUM_OF_PISTON_PUMPS; pumpId++ ) { - // Increment free running counter - currentPistonPumpSwitchingCounter [ pumpId ]++; - switch ( pistonPumpExecState[pumpId] ) { case PISTON_PUMP_OFF_STATE: @@ -210,6 +215,32 @@ /*********************************************************************//** * @brief + * The processPistonPumpDosingTrigger function sets the dosing trigger + * status for given pump. + * @details \b Inputs: Dosing pump trigger. + * @details \b Outputs: readyToDose. + * @return none. + *************************************************************************/ +void processPistonPumpDosingTrigger( void ) +{ + currentDosingTriggerStatus = getLevelStatus( PUMP_TRIG_LEVEL ); + + if ( currentDosingTriggerStatus != prevDosingTriggerStatus ) + { + // Trigger dosing only high to low transition + if ( ( LEVEL_STATE_HIGH == prevDosingTriggerStatus ) && ( LEVEL_STATE_LOW == currentDosingTriggerStatus ) ) + { + readyToDose[ PISTONPUMPS_ACID ] = TRUE; + readyToDose[ PISTONPUMPS_BICARB ] = TRUE; + readyToDose[ PISTONPUMPS_UF ] = TRUE; + } + + prevDosingTriggerStatus = currentDosingTriggerStatus; + } +} + +/*********************************************************************//** + * @brief * The startPistonPumpCycle function sets the given piston pump parameters * for dosing/UF operations. * @details \b Inputs: none @@ -227,7 +258,6 @@ pistonPumpCycleCount[ pumpId ] = cycleCount; pistonPumpVolumeinMl[ pumpId ] = targetVolume_ml; pistonPumpSetSpeed[ pumpId ] = speed; - pistonPumpExecState[ pumpId ] = PISTON_PUMP_OFF_STATE; } else { @@ -278,12 +308,17 @@ { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_OFF_STATE; - // Initiate piston pump control when cycle count is more than 1. + // Initiate piston pump control when cycle count is more than 1 or + // fill cycle to be completed for dispensing when asked. // Will redefine the off state later if required - if ( pistonPumpCycleCount[ pumpId ] > 0 ) + if ( ( pistonPumpCycleCount[ pumpId ] > 0 ) || + ( TRUE == (BOOL)getPistonPumpFillafterDispenseControl() ) ) { state = PISTON_PUMP_FILL_START_STATE; - pistonPumpCycleCount[ pumpId ]--; + if ( pistonPumpCycleCount[ pumpId ] > 0 ) + { + pistonPumpCycleCount[ pumpId ]--; + } } return state; @@ -300,8 +335,7 @@ *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillStartState( PISTON_PUMPS_T pumpId ) { - PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_FILL_START_STATE; - currentPistonPumpSwitchingCounter [ pumpId ] = 0; + PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_FILL_START_STATE; // Open Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_OPEN, VALVE_STATE_CLOSED ); @@ -320,19 +354,16 @@ * @brief * The handlePistonPumpFillCompleteState function check for the piston pump * fill complete and close the currently opened valve. - * @details \b Inputs: currentPistonPumpSwitchingCounter,pistonPumpFillPeriod - * @details \b Outputs: currentPistonPumpSwitchingCounter + * @details \b Inputs: None + * @details \b Outputs: None * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillCompleteState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_FILL_COMPLETE_STATE; - // TODO: The FPGA status register for step revolution count - downcounter to be monitered here - // to confirm the motor stop. Once FPGA status register issue is fixed, we can bring that here. - // Till then go with some guess timing for filling and dispensing. - if ( currentPistonPumpSwitchingCounter[ pumpId ] >= pistonPumpFillPeriod ) + if ( TRUE == isConcentratePumpDosingCompleted( (CONCENTRATE_PUMPS_T)pumpId ) ) { // Close Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_CLOSED ); @@ -360,39 +391,45 @@ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseStartState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_DISPENSE_START_STATE; - currentPistonPumpSwitchingCounter[ pumpId ] = 0; - F32 pumpSpeed = pistonPumpSetSpeed[ pumpId ] * -1.0 ; // This is to rotate motor in reverse direction - // Close Inlet and Open Outlet valve - pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_OPEN ); + // On regular piston pump cycle continue to dispense or when dosing trigger initiated + if ( ( FALSE == (BOOL)getPistonPumpFillafterDispenseControl() ) || + ( ( TRUE == (BOOL)getPistonPumpFillafterDispenseControl() && + ( TRUE == readyToDose[ pumpId ] ) ) ) ) + { + F32 pumpSpeed = pistonPumpSetSpeed[ pumpId ] * -1.0 ; // This is to rotate motor in reverse direction - // start stepper motor with the expected quantity - setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, pumpSpeed, pistonPumpVolumeinMl[ pumpId ] ); - requestConcentratePumpOn( (CONCENTRATE_PUMPS_T)pumpId ); + // Close Inlet and Open Outlet valve + pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_OPEN ); - //Move to next state - state = PISTON_PUMP_DISPENSE_COMPLETE_STATE; + // start stepper motor with the expected quantity + setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, pumpSpeed, pistonPumpVolumeinMl[ pumpId ] ); + requestConcentratePumpOn( (CONCENTRATE_PUMPS_T)pumpId ); + //Reset the dosing flag + readyToDose[ pumpId ] = FALSE; + + //Move to next state + state = PISTON_PUMP_DISPENSE_COMPLETE_STATE; + } + return state; } /*********************************************************************//** * @brief * The handlePistonPumpDispenseCompleteState function check for the piston pump * dispense complete and close the currently opened valve. - * @details \b Inputs: currentPistonPumpSwitchingCounter,pistonPumpDispensePeriod - * @details \b Outputs: currentPistonPumpSwitchingCounter + * @details \b Inputs: None + * @details \b Outputs: None * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseCompleteState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_DISPENSE_COMPLETE_STATE; - // TODO: The FPGA status register for step revolution count - downcounter to be monitered here - // to confirm the motor stop. Once FPGA status register issue is fixed, we can bring that here. - // Till then go with some guess timing for filling and dispensing. - if ( currentPistonPumpSwitchingCounter[ pumpId ] >= pistonPumpDispensePeriod ) + if ( TRUE == isConcentratePumpDosingCompleted( (CONCENTRATE_PUMPS_T)pumpId ) ) { // Close Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_CLOSED ); @@ -429,6 +466,26 @@ /*********************************************************************//** * @brief + * The getPistonPumpFillafterDispenseControl function gets the piston pump + * fill after dispense control. + * @details \b Inputs: pistonPumpFillAfterDispense + * @details \b Outputs: none + * @return the fill after dispense control status. + *************************************************************************/ +static U32 getPistonPumpFillafterDispenseControl( void ) +{ + U32 result = pistonPumpFillAfterDispense.data; + + if ( OVERRIDE_KEY == pistonPumpFillAfterDispense.override ) + { + result = pistonPumpFillAfterDispense.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The publishPistonPumpControlData function broadcasts the piston pump * control execution data at defined interval. * @details \b Inputs: pistonPumpControlDataPublicationTimerCounter @@ -446,9 +503,9 @@ data.acidPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_ACID ]; data.bicarbPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_BICARB ]; data.ufPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_UF ]; - data.acidPistonPumpSwCounter = currentPistonPumpSwitchingCounter[ PISTONPUMPS_ACID ]; - data.bicarbPistonPumpSwCounter = currentPistonPumpSwitchingCounter[ PISTONPUMPS_BICARB ]; - data.ufPistonPumpSwCounter = currentPistonPumpSwitchingCounter[ PISTONPUMPS_UF ]; + data.acidPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_ACID ]; + data.bicarbPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_BICARB ]; + data.ufPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_UF ]; data.acidPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_ACID ]; data.bicarbPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_BICARB ]; data.ufPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_UF ]; @@ -496,7 +553,7 @@ { BOOL result = FALSE; - // Verify tester has logged in with TD + // Verify tester has logged in with DD if ( TRUE == isTestingActivated() ) { // Verify payload length is valid @@ -511,8 +568,7 @@ // Handle start command if ( ( TRUE == payload.startStop ) && ( ( payload.speed >= PISTON_PUMP_MIN_SPEED ) && ( payload.speed <= PISTON_PUMP_MAX_SPEED ) ) && - ( payload.volume > 0.0 ) && - ( payload.cycleCount > 0 ) ) + ( payload.volume > 0.0 ) ) { startPistonPumpCycle( (PISTON_PUMPS_T)payload.pumpId, payload.cycleCount, payload.volume, payload.speed ); result = TRUE; @@ -531,6 +587,23 @@ return result; } +/*********************************************************************//** + * @brief + * The testDDPistonPumpFillAfterDispenseOverride function sets the override value + * of the piston pump fill after dispense control. + * @details Inputs: pistonPumpFillAfterDispense + * @details Outputs: pistonPumpFillAfterDispense + * @param message Override message from Dialin which includes the read + * counter value to override for the piston pump fill after dispense control. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDDPistonPumpFillAfterDispenseOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &pistonPumpFillAfterDispense, 0, 1 ); + + return result; +} + /**@}*/ #endif