JISA
is a library that I created, here in the Cavendish Laboratory, because I really (really really really) do not like LabView. Not to mention they named their language "G" as if it's somehow comparable to C. This hubris cannot and will not stand.
In essence then, the purpose of JISA
is to act as an alternative (and actually decent) means of creating experimental control systems. It comprises, largely, of three sections:
JISA
implements standard interfaces for each "type" of instrument, meaning that instruments are easily interchangeable. If we connect to a Keithley SMU and an Agilent SPA
// Connect to instruments
val keithley = K2600B(TCPIPAddress("192.168.0.5"))
val agilent = Agilent4155X(GPIBAddress(20))
then JISA
simply represents them as collections of SMU
channels
// Get first channel from both instruments
val smuK = keithley.getChannel(0)
val smuA = agilent.getChannel(0)
meaning that operating them is done exactly the same way in JISA regardless of which make/model of instsrument they are from
smuK.setIntegrationTime(0.1) // Set the integration time
smuK.useAutoRanges() // Use auto ranging on current and voltage
smuK.setVoltage(5.0) // Set to source 5.0 V
smuK.turnOn() // Enable output of channel
val currentK = smuK.getCurrent() // Measure current
smuK.turnOff() // Disable output of channel
smuA.setIntegrationTime(0.1) // Set the integration time
smuA.useAutoRanges() // Use auto ranging on current and voltage
smuA.setVoltage(5.0) // Set to source 5.0 V
smuA.turnOn() // Enable output of channel
val currentA = smuA.getCurrent() // Measure current
smuA.turnOff() // Disable output of channel
// Create results storage
val results = ResultList("Voltage", "Current", "Temperature")
// Take 10 readings
repeat(10) {
results.addData(smu.getVoltage(), smu.getCurrent(), tc.getTemperature())
}
// Easy output as CSV file
results.output("data.csv")
// Create user-input panel
val params = Fields("Parameters")
// Add input fields to it
val minV = params.addDoubleField("Min V [V]", 0.0)
val maxV = params.addDoubleField("Max V [V]", 60.0)
val numV = params.addIntegerField("No. Steps", 61)
// Create plot
val plot = Plot("Results", "Voltage", "Current")
// Add panel and plot to a grid
val grid = Grid("Main Window", params, plot)
// Add start button to toolbar
grid.addToolbarButton("Start Sweep") {
// Makes range starting at minV, ending at maxV in numV steps
val voltages = Range.linear(
minV.get(), // Start at
maxV.get(), // End at
numV.get() // No. steps
)
// Code to run sweep
}
// Show the grid in a window
grid.show()
JISA
is written in Java, but because Java is all about magic beans, you can actually use it in almost any language. More specifically, any language that can either be compiled to java byte-code or interpreted by a Java program (so basically anything) can use the library.
For example, here's the same program written in Java, Kotlin, Python and even gosh-darn MATLAB:
Java - Classic style, robust but verbose, like a northern grandparent.
public class Main {
public static void main(String[] args) throws Exception {
SMU smu = new K2450(new GPIBAddress(0, 20));
ResultTable results = new ResultList(new Col("Voltage", "V"), new Col("Current", "A"));
smu.setVoltage(0.0);
smu.turnOn();
for (double v : Range.linear(0, 60, 61)) {
smu.setVoltage(v);
Util.sleep(500);
results.addData(smu.getVoltage(), smu.getCurrent());
}
smu.turnOff();
results.output("data.csv");
}
}
Kotlin - Slick, simplified and concise without rocking the boat
fun main() {
val smu = K2450(GPIBAddress(0,20))
val results = ResultList(Col("Voltage", "V"), Col("Current", "A"))
smu.setVoltage(0.0)
smu.turnOn()
for (v in Range.linear(0.0, 60.0, 61)) {
smu.setVoltage(v)
Util.sleep(500)
results.addData(smu.getVoltage(), smu.getCurrent())
}
smu.turnOff()
results.output("data.csv")
}
Python (Jython) - "Screw your traditions, I'm a snake from the future"
To use in Python, take a look at PyJISA here.
def main():
smu = K2450(GPIBAddress(0,20))
results = ResultList([Col("Voltage", "V"), Col("Current", "A")])
smu.setVoltage(0.0)
smu.turnOn()
for v in Range.linear(0.0, 60.0, 61):
smu.setVoltage(v)
Util.sleep(500)
results.addData([smu.getVoltage(), smu.getCurrent()])
smu.turnOff()
results.output("data.csv")
main()
MATLAB - Why?
function main()
smu = jisa.devices.K2450(JISA.Addresses.GPIBAddress(0,20));
results = jisa.experiment.ResultList({'Voltage', 'Current'});
results.setUnits({'V', 'A'});
smu.setVoltage(0.0);
smu.turnOn();
for v=jisa.maths.Range.linear(0.0, 60.0, 61)
smu.setVoltage(v);
jisa.Util.sleep(500);
results.addData([smu.getVoltage(), smu.getCurrent()]);
end
smu.turnOff();
results.output('data.csv');
end
We can then extend this program easily, with only two lines, to display a plot of the results as they come in. Taking the example in Kotlin:
fun main() {
val smu = K2450(GPIBAddress(0,20))
val results = ResultList(Col("Voltage", "V"), Col("Current", "A"))
// Make a plot that watches our results
val plot = Plot("Results", results)
plot.show()
smu.setVoltage(0.0)
smu.turnOn()
for (v in Range.linear(0.0, 60.0, 61)) {
smu.setVoltage(v)
Util.sleep(500)
results.addData(smu.getVoltage(), smu.getCurrent())
}
smu.turnOff()
results.output("data.csv")
}
Resulting in:
Currently Implemented Devices:
Before being able to use JISA, you will need the Java Development Kit (JDK) 11 or newer installed.
Either you'll already have OpenJDK installed or you simply need to run something like:
sudo apt install openjdk-11-jdk
You can download pre-built OpenJDK packages (with installers) from the Adopt Open JDK website:
https://adoptopenjdk.net/?variant=openjdk11&jvmVariant=hotspot
You can use JISA in your project simply by including the JISA.jar file as a library. This will work so-long as your project uses Java 11 or newer.
If using IntelliJ IDEA, this means adding JISA.jar to your project directory and, inside IDEA, right-clicking on it then selecting "Add as Library..."