Skip to content

Connectors

William Wood edited this page Jul 6, 2021 · 9 revisions

Connections and Connectors

JISA has the means to provide and store user-configurable connections for instruments by use of Connection and Connector objects.

Connection objects represent a configurable connection to a given type of instrument. For instance a Connection<SMU> object represents a connection to an SMU - where the exact make/model/driver and address are configurable.

Connector objects are GUI elements that visually represent a Connection object. These let the user graphically configure a connection to an instrument. For instance, a Connector<SMU> object is a GUI representation of a Connection<SMU> allowing the user to select which SMU driver class to use as well as which address to use.

These are important concepts in JISA as they are what allow for the polymorphic behaviour of its standardised instrument interfaces to be exploited (i.e. to let the user swap-and-change instrument makes/models without needing to edit the code).

Connection Objects

JISA has a class called Connection to represent a configurable connection to an instrument of a given type. Generally, speaking you won't be creating these directly - but by creating Connector GUI elements (more on that in the next section). However, when you have a Connection object, you can define the connection parameters, connect to the instrument and extract its object representation like so:

Connection<VMeter> connection = new Connection<>("Voltmeter", VMeter.class);

connection.setDriver(K2181.class);
connection.setAddress(new GPIBAddress(24));
connection.connect();

VMeter voltmeter = connection.getInstrument();

In Kotlin, you'd instantiate a Connection object like so:

val connection = Connection<>("Voltmeter", VMeter::class.java)

You can save/load/link connections to a ConfigFile by using writeToConfig(...), loadFromConfig(...) and/or linkToConfig(...) respectively and passing the desired ConfigBlock to save it into as the argument:

ConfigFile  file             = new ConfigFile("UniqueNameForProgram");
ConfigBlock instrumentConfig = file.subBlock("UniqueNameForConnection");

// Write current configuration to config once
connection.writeToConfig(instrumentConfig);

// Load configuration from file
connection.loadFromConfig(instrumentConfig);

// Load from file, and automatically write when program exits
connection.linkToConfig(instrumentConfig);

The writeToConfig(...) and loadFromConfig(...) methods will perform a one-time write/load whereas linkToConfig(...) will first load from the given block followed by an automatic write when the program exits.

Connector Elements

To allow the user to define a Connection themselves graphically, we use Connector objects. These are JISA GUI elements that, in short, visually represent a Connection object. To create one, simply instantiate a Connector object and provide it a name for the connection and the target class (i.e. what kind of instrument should it be connecting to). For instance, if we wanted a connection to a Voltmeter (i.e. a VMeter) we could write:

Java

Connector<VMeter> connector = new Connector<>("Voltmeter", VMeter.class);

Kotlin

val connector = Connector<>("Voltmeter Connector", VMeter::class.java)

Then by making it show itself:

connector.show();

we get:

In the "Driver" drop-down menu the user gets to choose from all available Instrument driver classes that qualify as being a VMeter. When the user has selected a driver, entered the address and pressed "Apply" - the connect() method is called on the underlying Connection. You can extract the underlying Connection object, and thus the Instrument (i.e. the VMeter) object representing the connected instrument itself like so:

Connection<VMeter> connection = connector.getConnection();
VMeter             voltmeter  = connection.getInstrument();

If the Connection object is not connected to anything it will return null instead. Alternatively, you can check if it's connected or not using isConnected() like so:

if (connection.isConnected()) {
    VMeter voltmeter = connection.getInstrument();
    // Do stuff with the voltmeter
} else {
    GUI.errorAlert("Voltmeter is not connected!");
}

Similarly to Connection objects, you can call writeToConfig(...), loadFromConfig(...) and linkToConfig(...) on any Connector object. This basically just calls the same method on the underlying Connection object anyway.

Each Connector object will visually display the status of the connection with an icon. There's four statuses that it can have:

  1. Not connected (grey dots)
  2. Connecting (yellow hour-glass)
  3. Connected (green tick)
  4. Error (red exclamation mark)

If there was an error connecting, the error will be displayed in a red box at the top of the connector (until the connection is re-attempted or the error is clicked-on):

Connector Grids

If you have need of letting the user configure any arbitrary number of instruments - which they can define - then you will want to use a ConnectorGrid. To create one, instantiate a ConnectorGrid object, giving it a title and the number of columns you want it to display Connectors in like so:

Java

ConnectorGrid grid = new ConnectorGrid("Instrument Connections", 3);

Kotlin

val grid = ConnectorGrid("Instrument Connections", 3)

When shown using grid.show() the user will be presented with an empty grid into which they can add as many user-configurable instrument connections as they like:

By clicking "Add" the user can select what type of instrument connection they wish to define:

For instance, they could add SMU, VMeter and LockIn connections like so:

(in the above example, the first two connections worked where the third one encountered an error).

You can then use the writeToConfig(...), loadFromConfig(...) and linkToConfig(...) methods to save/load/link the whole thing to a configuration file. For instance:

grid.linkToConfig(configBlock);

will mean that whatever we add this time will be loaded back up next time we start the program after exiting.

Clone this wiki locally