Introduction
General
This pump library defines a common pump control interface for a range of different pump types such as e.g. syringe pumps, dilutors, peristaltic pumps, or diaphragm pumps.
In general a pump consists of an actuator (like a linear drive for a syringe pump, a servo drive for a peristaltic pump or a simple DC/EC drive for a diaphragm pump) and a container for the transport of the fluid (like a syringe for a syringe pump/dilutor, a tube for a peristaltic pump or a pump head for the diaphragm pump). With some pumps like syringe pumps and peristaltic pumps the container is exchangeable by the application engineer or even by the user of the laboratory device. That means a user may mount different kind of syringes on a syringe pump or may use different tube sizes on a peristaltic pump. With other pumps (i.e. diaphragm pumps) the container and the actuator are fixed to each other and build up one single unit. The pump parameters (e.g. volume, flow or pressure) may be limited by the actuator and/or by the container.
Actuator limits
On a syringe pump the flow is limited by the speed of the actuator (the velocity of the linear drive) and the volume is limited by the length/maximum position of the linear drive. On a peristaltic pump or diaphragm pump the volume is not limited by the actuator but the maximum flow is limited by the actuator speed - the maximum rotation speed of the peristaltic pump drive or the speed of the DC/EC diaphragm pump drive.
Container limits
Container limits are only important for devices where it is possible to change the container. On every change of the container the calculation of the flow and volume values changes and therefore the parameters maximum volume and maximum flow may also change. That means each container has its own container limits. The maximum volume of a syringe pump is limited by the stroke of the syringe piston and the inner syringe diameter. The maximum flow is limited by the inner diameter of the syringe. The tube dimensions do not limit the maximum volume of a peristaltic pump but the maximum flow is limited by the inner diameter of the tube.
Including
The way how you include the library functions in your own windows program, depends on the compiler and on the programming language you use. In order to access the pump API, you have to include the library labbCAN_Pump_API.dll to your programming environment. You have to copy this file to the working directory of your system or to the application directory that contains your application EXE file. Use the calling convention LCP_CALL for this library. This convention is managing how the parameters are put on the stack and who is responsible to clean the stack after the function execution.
The interface of the library, constant definitions and declarations of the library functions, is defined in the header file interface/labbCAN_Pump_API.h
Initialization
Step 1 - Retrieve device handle
To work with a pump, you need a valid device handle. A device handle is simply an opaque pointer to the internal device object created by the labbCAN environment. So the first thing you need do to is obtaining a valid device handle.
You can get a valid pump handle with the functions LCP_LookupPumpByName() or LCP_GetPumpHandle():
- Note
- You can get the pump names from the device configuration files (see Device Configuration Files)
Step 2 - Enable devices
If you have valid device handle, you can start to bring your devices into a properly enabled and initialized state. To do this, you need to:
- clear all faults (LCP_ClearFault())
- enable all pump drives (LCP_Enable())
Step 3 - Initialize Position Sensing System
Each pump drive tracks the actual position value (volume value) by an internal position counter. If a positioning sensing system needs to get initialized depends on the type of used position sensor. Newer pumps, such as the Nemesys 4 pumps Nemesys S and Nemesys M have absolute encoders. These encoders keep their position value even when the pump is switched off. For such devices an initialization of the position sensing system is not required.
Other pumps, such as the older Nemesys Low Presssure Pumps or the Nemesys XL pumps use incremental encoders. If these pumps are switched off, the actual value of the position counter gets lost and is initialized to zero at next start. So right after power on, you don't know anything about the actual position of the pump drive units. For pumps like peristaltic pumps this does not matter but for pumps like syringe pumps this is very important because the position defines the actual fill level. For such devices an initialization of the position sensing system is required.
To find out, if an initialization is required, simply call the function LCP_IsPositionSensingInitialized(). This function always returns 1 for devices with an absolute encoder. For other devices, the returned value is 0 if the position value has not been initialized yet.
To properly initialize the internal position counter you either need to execute a reference move via LCP_SyringePumpCalibrate() or you need to restore a previously saved position counter value via LCP_RestoreDrivePosCnt(). Because a safe reference move is possible only if there is now syringe mounted on the device, the recommended way is using LCP_RestoreDrivePosCnt(). That means, right before you shut down your system, you need to query the actual position counter value of each pump via LCP_GetDrivePosCnt(). Then you need to store this value into a file. The next time you start up your devices, you load the saved position values, and write it back into the devices vial LCP_RestoreDrivePosCnt().
- Warning
- If you have a pump without absolute encoder and if you manually change the position of the pusher of this pump while it is switched off, the saved position counter value is not valid anymore and you need to execute a calibration move via LCP_SyringePumpCalibrate().
Step 4 - Ensure, that force monitoring is enabled
The newer Nemesys 4 devices (Nemesys S and Nemesys M) have internal force monitoring. The execution of dosing commands is only possible if the force monitoring is active. Force monitoring can be enabled / disabled via the function LCP_EnableForceMonitoring().
Initialization Example
The following example code snippet shows a valid valid pump initialization procedure:
InitializationReference
See the Pump API Initialisation module and the Pump Configuration module for a detailed reference of all pump initialization and configuration functions.
Dosing
For almost all dosing tasks the functions from the Pump Control module and from the Pump Status module are required. Using the pump API you can choose from a number of different dosing modes:
- LCP_Aspirate() for the aspiration of a certain volume with a certain flow
- LCP_Dispense() for dispension of a certain volume
- LCP_PumpVolume() for aspiration or dispension depending on the sign of the flow rate parameter (negativ = aspiration, positive = dispension)
- LCP_SetFillLevel() aspirates or dispenses until a certain syringe fill level is reached
- LCP_GenerateFlow() generates a constant flow - dosing continues until it gets stopped manually or until pusher reached one of its limits.
- Note
- All dosing functions are non blocking. That means each function returns Immediately after the dosing process has been started and you need to poll the LCP_IsPumping() function to detect if dosing has been finished.
With the status functions you can always query the actual state of the pumps you are working with:
- LCP_GetDosedVolume() returns the dosed volume since start of last dosage
- LCP_GetFillLevel()returns the actual fill level of the pump container (eg.syringe)
- LCP_GetFlowIs() always returns the actual flow rate of the pump
- LCP_IsPumping() returns true (1) as long as dosing is active.
Dosing Example
The following example code snippet shows how to empty a syringe completely and then aspirate a certain volume with a certain flow rate.
Dosing Reference
See the Pump Control module and the Pump Status module for a detailed reference of all pump dosing and status functions.
Force Monitoring
Overview of the force monitoring functionality
The newer Nemesys 4 pumps, such as Nemesys S and Nemesys M, have an internal force sensor for force monitoring and safety stop in case of too high forces (pressures). To find out if a pump supports force monitoring you can use the function LCP_HasForceMonitoring(). Only if this function returns 1 the force monitoring functions are supported. Each pump has an internal hardware specific maximum force. To find out the maximum force, simply call LCP_GetMaxDeviceForce(). If the force of the device raises above this maximum force, the pump drive is stopped immediately.
- Note
- If you would like to know the SI unit that is used for all force values, call LCP_GetForceUnit()
It is possible to reduce the force limit below the maximum device force by setting a custom force limit if this is required by your application. You can do this by calling the function LCP_WriteForceLimit().
If you would like to know the current force limit, simply call LCP_GetForceLimit(). The force limit defines the threshold for triggering the safety stop. If a safety stop is triggered, the pump drive is stopped and the safety stop input of the pump is set. To find out, if you are in a force overload situation, that means if the safety stop is active, you can read the state of the safety stop input via LCP_IsForceSafetyStopActive(). If this function returns 1 then you know, that the pump has been stopped because of an force overload.
How to resolve a force overload situation
If the safety stop is active, it is no longer possible to carry out any dosing with the pump. To resolve this force overload situation, you need to reduce the force below the force limit threshold. There are different ways to reduce the pressure:
- by using some kind of overpressure valve
- by waiting until the pressure is released
- by pulling back the syringe plunger (aspirating)
Pulling the syringe plunger is not possible as long as the safety stop input is active. To reduce the pressure by pulling the syringe plunger, you first need to disable the force monitoring by calling LCP_EnableForceMonitoring() function. This will clear the safety stop input.
- Note
- Moving the syringe plunger when force monitoring is disabled is only possible in a force overload situation. If you disable force monitoring if the force is in the allowed range, then dosing is not possible.
If force monitoring is disabled, you can pull the syringe plunger by executing a flow command with a negative flow rate (aspirating). The following example shows how to do this:
Now the syringe plunger will be pulled slowly out of the syringe and the pressure (force) will decrease. If the force falls below the force limit, then the safety stop input will be set and the pump will be stopped. To detect this event, you just need to monitor the safety stop input via LCP_IsForceSafetyStopActive().
Now you can enable force monitoring again using LCP_EnableForceMonitoring() and the force overload situation is resolved.
- Note
- The force monitoring functionality has a hysteresis. In case of a force overload situation you need to lower the force ca. 0.1 kN to clear the safety stop input. If this is not possible, you can lower the force less (for example 0.02 kN) and then call the function LCP_ClearForceSafetyStop() to clear the safety stop input.
Reading the force sensor
If you would like to monitor or log the force sensor value, you can read the current force using the function LCP_ReadForceSensor(). This will return the current force value in the SI unit returned by LCP_GetForceUnit().
Force Monitoring API Reference
See the Force Monitoring module for a detailed description and reference of all force monitoring functions.
Continuous Flow
Introduction into continuous flow functionality
A disadvantage of syringe pumps is that the maximum dosable volume is limited by the syringe. If the syringe is empty, the syringe must be refilled. During the refill cycle the dosing is interrupted. To solve this problem and enable uninterrupted, continuous dosing, the SDK offers Continuous Flow functionality.
To generate a continuous flow, two syringe pumps are connected by software to form a virtual continuous flow pump. The continuous flow algorithm then controls the alternating filling and emptying of the syringe, thus creating a continuous flow. The creation of the virtual continuous flow pump can be done during runtime via library functions or by declaring the continuous flow pump in the device configuration file.
Declare a continuous flow pump in device configuration file
The CETONI SDK requires a device configuration (a set of XML files) to control the supported devices. So the first step is to create a device configuration in the QmixElements software with at least 2 neMESYS syringe pumps. The device configuration folder now contains several XML files. Open the file nemesys.xml with an editor thats supports syntax highlighting (such as Notepad++).
- Note
- Make a backup of your device configuration before you start editing files manually.
Now scroll to the end of the <Plugin><labbCAN><DeviceList>
section to insert a new device declaration. The following example shows the declaration of a continuous flow pump at the end of the <DeviceList>
section:
The following things are declared in the example:
- line 1: the device is declared and a unique name
ContiFlowPump_1
is given - line 2: the device type is declared - this is always
Lcl::CContiFlowPump
for a continuous flow pump - line 3: the syringe pump
neMESYS_Low_Pressure_1_Pump
is assigned as the first pump channel. The syringe pump with the given name must exist in the device list above - line 4: the first valve
neMESYS_Low_Pressure_1_Valve
is assigned to the first syringe pump channel. For the valve the switching positions are configured for aspirating, dispensing and closed state. A value of -1 indicates that this position is not used and will not be switched.
In the following lines the second pump and the valve for the second pump are declared.
- Note
- All devices (valves and pumps) that are assigned to the continuous flow pump must exist in the device list above.
If you now load this device configuration into the CETONI SDK, then you can easily access the continues flow pump from source code:
Create a continuous flow pump in source code
As an alternative to creating the pump via the configuration file, the pump can also be created in source code at runtime. The first step is to obtain the device handles for all devices that should be combined into a continuous flow pump. Any error checking code has been removed to keep the example simple.
If you have all required device handles, you can start to create the pump device:
First the continuoues flow pump is created by assigning the two syringe pumps. The device handle is returned in the ContiFlowPump
variable. Then the first valve for the first pump channel is configured and the the first valve for the second pump channel. After these steps, the continuous flow pump has the same configuration like the pump created via the device configuration file above.
Parameterize the continuous flow
If you have a valid continuous flow pump handle, you can start to parameterize the continuous flow. This is the same procedure like you know if from the continuous flow wizard in the QmixElements software. At the moment, the continus flow pump supports only cross flow switching. This means, the cross flow algorithm provides a soft transition and a constant flow rate when switching from one dosing unit to the other. This mode is most suitable if your application uses a low system pressure and you don’t have pressure sensors.
The first thing you need to configure is the switching mode for the continuous flow. At the moment only the cross flow is supported but pressure controlled switching will come soon.
Then you need to configure the maximum refill flow rate that is allowed in your application. If you would like to know the maximum possible refill flow, then you can query it like this:
Then you can limit the maximum flow rate like this:
The next parameter that you can configure is the cross flow duration. This is the time to cross-fade the flows of both syringe pumps. The smaller this value, the steeper the flow rate curve and the less time is required for the cross-flow operation to be completed. A value of 1 second is a good initial default value. If you do not want to cross fade, then use a value of 0.
An optional parameter that you can configure is the overlap duration. This is the period of time by which the flow curves of both pumps overlap. It is a simple way of compensating for pressure drops during switching, because the second pump starts earlier to pressurize. The larger the value, the longer both pumps keep dosing simultaneously
If you have configured all parameters, you can no query the maximum continuous flow rate. Because of the times for switching, cross flow and overlap, the maximum flow rate of the continuous flow pump is lower than the maximum flow rate of the single syringe pumps.
Continuous flow initialization
To start the continuous flow, the pump needs to be initialized properly. This means that at least one of the two syringe pumps should contain enough liquid for dosing so that the other pump can be filled during dosing.
The first step is to clear all potential errors of the pump. Then you need to bring the pump into enable state - that means, both syringe pumps should be enabled. If the positioning system of both syringe pumps has not been initialized, then you need to excute a reference move via LCP_SyringePumpCalibrate function.
The last step will start the initialization procedure that will fill one syringe with the configured refill flow rate. See capi_nemesys_test.cpp for more details.
Continuous Flow Usage
If you have properly configured and initialized your continuous flow pump, you can use it like any other pump. That means, you can use the normal pump control and pump status functions.
- Note
- The continuous flow mode is meant for dispensing volumes or generating flows and works only in one direction. That means using negative flow rates or negative volumes for aspiration is not possible.
Programming Interface - API
See the labbCAN Pump API module for a detailed reference of the pump library application programming interface