Skip to content

Making Your Program

William Wood edited this page Jan 11, 2019 · 1 revision

Making Your Program

This page serves as an illustrated example of how to go about building a comprehensive experiment control and data acquisition program using the simplified tools offered by JISA. This specific example shall be designed to control a set-up for making temperature-dependent FET output-curve measurements.

Basic Structure

When you being you will likely have the basic Java program structure given to you by your IDE:

public class Main {

    public static void main(String[] args) {
        // Code goes here
    }

}

The first two things we should start thinking about is that our code is liable to throw exceptions, and that we will be using GUI elements. As a result we need to tell Java that our main(...) method might throw an exception and make Main extend GUI so that it can set-up the GUI thread properly:

public class Main extends GUI {

    public static void main(String[] args) throws Exception {

    }

}

This is the simplest (but some might say most ineffective) way of dealing with exceptions. If an exception is indeed thrown by main(...), with it being the first method to be run thus having nothing above it to throw the exception up to, it will simply crash the program and output error text from the exception to the terminal. However, for our application this will do.

The next thing to think about is what variables/objects we want to store "globally". That is what will we want to be stored and accessible from all methods we write in our Main class? The obvious examples to start with are the instruments/devices to be used by the program. Since we're wanting to perform temperature-dependent output-curve measurements, we will be using:

  • 1 SMU or SMU channel for Source-Drain
  • 1 SMU or SMU channel for Source-Gate
  • 1 temperature controller

Therefore we can preemptively add these as static variables in Main:

public class Main extends GUI {

    private static SMU         sdSMU;
    private static SMU         sgSMU;
    private static TController tCont;

    public static main(String[] args) throws Exception {

    }

}

(I have made them private here because there's no need to be able to access them from outside our Main class. It doesn't matter that much, but generally it is best practice to make things private unless they need to be public. For example, main needs to be public because it gets called externally by Java itself when run)

You may have noticed that we have given these variables the more "generic" types of SMU and TController as opposed to something like K2450 and ITC503. This is because we do not know what specific models of SMU and temperature-controller we will be using. In-fact we will be making a part of the program to allow us to graphically select and configure which instruments we want to use instead of hard-coding them into the program.

We will also want some storage for results. For this, we can create a ResultList, then initialise it in main:

public class Main extends GUI {

    private static SMU         sdSMU;
    private static SMU         sgSMU;
    private static TController tCont;

    private static ResultList  results;

    public static main(String[] args) throws Exception {

        results = new ResultList(
            "Temperature"
            "SD Voltage",
            "SD Current",
            "SG Voltage",
            "SG Current"
        );

        results.setUnits("K", "V", "A", "V", "A");

    }

}

Finally, we will be wanting the user to input experimental parameters for us to use. These will be coming from a Fields object which gives us handles on the input-fields we create as Field objects. Therefore, it makes sense that we store those statically so that they can be accessed by all methods in Main:

public class Main extends GUI {

   // ... all that other stuff ...

    private static Field<Double>  minSD;    // Min SD Voltage
    private static Field<Double>  maxSD;    // Max SD Voltage
    private static Field<Integer> stepsSD;  // Number of steps in SD Voltage
    private static Field<Double>  minSG;    // Min SG Voltage
    private static Field<Double>  maxSG;    // Max SG Voltage
    private static Field<Integer> stepsSG;  // Number of steps in SG voltage

    private static Field<Double>  intTime;  // Integration time
    private static Field<Integer> delTime;  // Delay time
    private static Field<Double>  iLimit;   // Current limit/compliance
    private static Field<Integer> avCount;  // Averaging count

    // ... all that other stuff ...

}

So let's do a quick recap on what we've done:

  1. Allowed our main method to throw exceptions - a bit "hacky" but it's good enough for us
  2. Made static variables to hold onto our instruments (for when we add them)
  3. Created a static ResultList to store results
  4. Defined static Field<...>s to hold onto user-input fields for when we create them

Creating the measurement GUI

Now we can start "filling in" those static Field<...>s so that they're not just empty variables.

To start with we shall create two Fields objects. One for the experimental parameters and the other for the more "configuration" type parameters. We shall contain this code in a new method called createGUI().

private static void createGUI() {

    Fields params = new Fields("Experiment Parameters");
    Fields config = new Fields("Instrument Configuration");

    minSD  = params.addDoubleField("Min SD Voltage [V]");
    maxSD  = params.addDoubleField("Max SD Voltage [V]");
    stepSD = params.addIntegerField("No. Steps");
    
    params.addSeparator();

    minSG  = params.addDoubleField("Min SG Voltage [V]");
    maxSG  = params.addDoubleField("Max SG Voltage [V]");
    stepSG = params.addIntegerField("No. Steps");

    intTime = config.addDoubleField("Integration Time [s]");
    delTime = config.addIntegerField("Delay Time [ms]");
    iLimit  = config.addDoubleField("Current Limit [A]");
    avCount = config.addIntegerField("Averaging Count");

}

Measurement Method

We now have enough structure to begin writing the code to actually perform a measurement! Even though we haven't actually connected to any instruments or created an interface to allow the user to start the measurement, we do have enough written down to define what we want it to do.

Let's create a method to perform our measurements. Like with main we want this method to be able to throw exceptions.

public class Main {

    // ... all that stuff we wrote in the last section ...

    private static void runMeasurement() throws Exception {

    }

}
Clone this wiki locally