The ca_matlab package provides an easy to use Channel Access library for Matlab. It is cross platform and runs on all major operating systems - Linux, Windows, Mac OS X.
The latest release of this package can be downloaded here.
The prerequisites for this package is Matlab2015a or later. There are no other dependencies (just include the Jar as described below).
There are two options to use the library, a dynamic and a static one. With the dynamic option you will bundle the library with your Matlab code whereas with the static option you will set the library one time globally for your Matlab instance.
We strongly suggest to use the dynamic approach!
Reasons why are discussed here.
To get started with the library:
- Copy the downloaded jar into the folder holding your Matlab code file.
- At the top of your .m file add following line (remember to change the version to the actual one).
In scripts that get executed several times in the same workspace:
- Use following construct to get rid of the Matlab warnings regarding re-adding to the classpath.
if not(exist('java_classpath_set')) javaaddpath('ca_matlab-1.0.0.jar') java_classpath_set = 1; end
In more complex Matlab projects you might want to have the library in a sub/parent-folder. In this case use relative paths to refer to the library.
For Windows users, keep in mind to use backslashes ( __ ) !
Include the full qualified path of the jar in the javaclasspath.txt within the Matlab home folder (ideally also copy the jar into this directory). For example:
After creating/altering the file javaclasspath.txt you need to restart Matlab.
After loading the required jar, channels can be created and be read/written as follows:
import ch.psi.jcae.* context = Context(); channel = Channels.create(context, ChannelDescriptor('double', 'ARIDI-PCT:CURRENT')); channel.get() channel.put(10.1); channel.close(); context.close();
A context is necessary to create channels. Ideally, there should be one context per Matlab application only.
import ch.psi.jcae.* context = Context();
It is also possible to configure the context via properties (i.e. to set the EPICS_CA_ADDR_LIST or EPICS_CA_MAX_ARRAY_BYTES).
import ch.psi.jcae.* properties = java.util.Properties(); properties.setProperty('EPICS_CA_ADDR_LIST', '10.0.0.255'); context = Context(properties);
Currently following properties are supported:
|EPICS_CA_ADDR_LIST||Address list to search channel on|
|EPICS_CA_AUTO_ADDR_LIST||Automatically create address list|
|EPICS_CA_SERVER_PORT||Port of the channel access server|
|EPICS_CA_MAX_ARRAY_BYTES||Maximum number of bytes for an array/waveform|
Note: For Paul Scherrer Institute users there is a list of example configurations for accessing the different facilities in Environments.md.
To set e.g. the EPICS_CA_ADDR_LIST to the same value as the environment variable of the machine running the script you can use:
The context needs to be closed at the end of the application via
To create a channel use the create function of the Channels utility class. The function's argument is a so called ChannelDescriptor which describes the desired channel, i.e. name, type, monitored (whether the channel object should be constantly monitoring the channel) as well as size (in case of array).
Here are some examples on how to create channels:
% Create double channel channel = Channels.create(context, ChannelDescriptor('double', 'ARIDI-PCT:CURRENT')); % Create monitored double channel channel = Channels.create(context, ChannelDescriptor('double', 'ARIDI-PCT:CURRENT', true)); % Create a channel for a double waveform/array - the size will be determined by the channel channel = Channels.create(context, ChannelDescriptor('double', 'ARIDI-PCT:CURRENT', true)); % Create a channel for a double waveform/array of specific size 10 % If the actual channel array is bigger you specify you would only retrieve the first 10 elements channel = Channels.create(context, ChannelDescriptor('double', 'ARIDI-PCT:CURRENT', true, java.lang.Integer(10)));
Supported types are:
string and the respective array forms
After creating a channel you are able to get and put values via the
Note: If you created a channel with the monitored flag set to true,
get() does not access the network to get the latest value of the channel but returns the latest update by a channel monitor.
If you require to explicitly fetch the value over the network use
get(true) (this should be rarely used as most of the time its enough to get the cached value)
Note: A polling loop within your Matlab application on a channel created with the monitored flag set to true is perfectly fine as it does not induce any load on the network.
To put a value in a fire and forget style use
putNoWait(value). This method will put the change request on the network but does not wait for any kind of acknowledgement.
value = channel.get(); channel.put(10.0); channel.putNoWait(10.0);
Beside the synchronous (i.e. blocking until the operation is done) versions of
put(value) there are also asynchronous calls. They are named
putAsync(value). Both functions immediately return with a handle for the operation, i.e. a so called Future. This Future can be used to wait at any location in the script for the completion of the operation and retrieve the final value of the channel.
Example asynchronous get:
future = channel.getAsync(); future_2 = channel_2.getAsync(); % do something different ... do_something(); % ... or simply sleep ... pause(10); % ... or simply do nothing ... value_channel = future.get(); value_channel_2 = future_2.get();
Example asynchronous put:
future = channel.putAsync(value_1); % this could, for example start some move of a motor ... future_2 = channel_2.putAsync(value_2); % do something different ... do_something(); % ... or simply sleep ... pause(10); % ... or simply do nothing ... future.get(); future_2.get();
To specify a timeout for the get/put operation following code can be used:
f = channel.getAsync(); f.get(10, java.util.concurrent.TimeUnit.SECONDS); f = channel.putAsync(value); f.get(10, java.util.concurrent.TimeUnit.SECONDS);
In both examples the operation would time out after 10 seconds. The function returns a
TimeoutException if the operation times out.
Waiting for channels to reach a certain value can be done as follows:
// Wait without timeout (i.e. forever) Channels.waitForValue(channel, 'world'); // Wait with timeout f = Channels.waitForValueAsync(channel, 'world'); f.get(10, java.util.concurrent.TimeUnit.SECONDS);
If you want to do stuff while waiting you can implement a busy loop like this:
future = Channels.waitForValueAsync(channel, 'world'); while not(future.isDone()) % do something end
After you are done working with a channel close the channel via
Examples can be found in the examples folder within this repository.
Issues / Feedback
We very much appreciate your feedback! Please drop an issue for any bug or improvement you see for this library!
In case of problems with your application:
- Upgrade to latest version
- Check whether the problem persists
- If yes, open an issue
- Provide code snippet causing the problem
- Provide the library version used!
ca_matlab - Development
This package is currently based on the jcae library developed at PSI. Basically it is a repackaging of the library together with its dependencies.
Building this package is currently only possible within PSI.
To build the package use: