GithubHelp home page GithubHelp logo

how to Write a New Driver? about jisa HOT 6 CLOSED

oe-fet avatar oe-fet commented on May 24, 2024
how to Write a New Driver?

from jisa.

Comments (6)

WuhrlWuhrd avatar WuhrlWuhrd commented on May 24, 2024

Hey! Thank you very much. It's largely just a project for within my research group at the moment but it's nice to know it's found interest outside it too!

Now, I'm not sure what sort of level of detail you're after here so I will continue by assuming you know and understand Java and it's implementation of object orientation.

I've had a quick look at the TSX3510P manual http://resources.aimtti.com/manuals/TSX-P_Instruction_Manual-Iss16.pdf and it seems to use fairly normal GPIB communications. Therefore, a place to start might be to create a class that extends VISADevice like so:

public class TSX3510P extends VISADevice {

    public TSX3510P(Address address) throws IOException, DeviceException {
        super(address);
    }

}

Because you are extending VISADevice you will be able to use functions like write(...), read() and query(...) to communicate with the device over whatever communication protocol was chosen with the Address object. You could put a check in the constructor to make sure the connected instrument is actually a TSX3510P and throw a DeviceException if it is not.

Since it is a DC power supply, it might be wise to make it so your class implements DCPower

public class TSX3510P extends VISADevice implements DCPower {

this will require it to provide a set of methods that JISA considers to be standard for all DC power supplies. For instance, it requires all DCPower classes to implement a function to turn the output on and one to turn it off called turnOn() and turnOff() respectively. In our case they would (or at least I think so after reading the manual) look something like this:

    public void turnOn() throws IOException {
        write("OP 1");
    }

    public void turnOff() throws IOException {
        write("OP 0");
    }

Now, you should be able to do all this in its own package/project by simply including JISA.jar in your classpath. Let me know if you have questions/none of this made sense and of course let me know how you get on with it!

from jisa.

uoiah avatar uoiah commented on May 24, 2024

Thank you very much!You responded so quickly.
I know Java well, but I'm not familiar with the GPIB.
I want to use the program to control the DC power supply, so that its current value being rising slowly to a certain value in a period of time.
Your advice is very helpful to me, I'll follow the step you mentioned above, and tell you the result whether it is successful or not.
Thanks again for your help.

from jisa.

WuhrlWuhrd avatar WuhrlWuhrd commented on May 24, 2024

You're welcome, and nice! Maybe then you would find some background leading up to the implementation of drivers and GPIB/other communication useful? I apologise if you already know any of this and/or find it obvious, but I'm planning on writing a wiki page about this so I'm sort of using it to get my thoughts in order.

So far with equipment we use in my lab I have encountered three different ways that instruments typically communicate. The first is via a series of text-based messages sent between the computer and instrument (by far the most common). This is typically dealt with via a library known as visa (which is where jisa gets its name) which unifies all the usual hardware protocols (like serial, GPIB, USB-TMC etc) under one interface. The only part where you need to be aware of how it's connected is when you establish the connection itself. When doing so you need to provide an address in the standardised visa format. For example, connected via GPIB at address 21 would be GPIB::21::INSTR. But then if we connected the instrument via TCP-IP instead with an IP address of 192.168.0.4 then it would change to TCPIP::192.168.0.4::INSTR. Basically, visa takes the address and figures out how to connect based on its value.

However, since the most complete implementation of visa is made by National Instruments, who are notoriously bad at writing software, it's often far from perfect (and sometimes doesn't even work at all if you're on anything other than Windows). For this reason jisa sometimes takes over and acts as visa itself, taking your address and figuring out which hardware driver to use directly (instead of just passing it on to visa).

The second is by use of an industry standard protocol called MODBUS which is typically only used on industrial equipment. It's understood best in hexadecimal, transmits as binary and is just kind of a pain to be honest. The only example of this here is the ET2408 driver which is for an industrial temperature controller.

The third is "black box" type communication where the manufacturer only provides a compiled library with methods to call that do the communication for you (ie you never get to see what is actually said between the computer and instrument, you just get to call something like read_temperature() and it spits back a number). An example of this is the USBTC08 driver which has to load in a native library to operate.

For this reason jisa has three base classes that you can choose from to extend your instrument class from. VISADevice, ModbusRTUDevice and NativeDevice.

Since we're talking about a visa-type instrument in your case we'll stick with VISADevice. To create a VISADevice object you, as you'd guess from how visa works, just need to provide it with an address. Instead of writing out the raw visa-style address, jisa works with Address objects. If I were to assume that your power supply was connected via GPIB and set to address 5 then I could open a connection to it by directly instantiating a VISADevice object like so:

VISADevice powerSupply = new VISADevice(new GPIBAddress(5));

Alternatively, if it were connected via TCP-IP:

VISADevice powerSupply = new VISADevice(new TCPIPAddress("192.168.0.5"));

However, you may find at this stage that you still can't communicate with your instrument. This is because the computer and instrument need to know how to tell that the other has finished talking. In more plain protocols like serial communications, this is done with a termination character like \n. In more complex protocols like GPIB they often have an in-built means of signalling this meaning you don't have to worry about it. However, sometimes manufacturers (for whatever reason) decide to ignore this.

Now, reading the manual, it tells us a couple of things. First, it tells us that all messages sent to the instrument should be terminated with \n, ^END or both. Picking the line-feed (\n), since it's the most standard, we can tell our VISADevice object to automatically append \n to the end of every message it sends by using setTerminator(...):

powerSuppply.setTerminator("\n");

As mentioned, GPIB has an in-built means of terminating messages called the EOI line. This is basically when it pulls the voltage of the EOI (end or identify) line to low so the controller/receiver knows that transmission has finished. However, some less standard and/or older equipment makes no use of this and instead sends a termination character, called the EOS (end of stream) character. In your case it looks like it's going to be awkward and not just fail to use EOI but also use a terminator that is more than one character long, specifically it will end all responses with \n^END. In visa, you're only allowed to set the termination sequence to be one character long so this will be awkward. (I may write a work-around for this at some point).

There is a way however. What we can do is make it use the \n part as the termination character then tell it to remove any instances of \n and ^END from any message it reads. Therefore, in all, we will need to:

  1. Disabled EOI usage
  2. Set the read termination character to \n
  3. Tell it to remove any instances of "^END" and "\n" from all messages it reads
powerSupply.setEOI(false);
powerSupply.setReadTerminationCharacter("\n");
powerSupply.addAutoRemove("\n");
powerSupply.addAutoRemove("^END");

Now, with any luck, you should be able to communicate! VISADevice has several I/O methods for you to use:

// Writes a string to the instrument
powerSupply.write("...message to send...");

// Reads a string from the instrument
String read = powerSupply.read();

// Reads a string from the instrument and converts it to an int
int read = powerSupply.readInt();

// Same but to a double instead
double read = powerSupply.readDouble();

// Writes then immediately reads the response
String response = powerSupply.query("...message to send...");
int    response = powerSupply.queryInt("...message to send...");
double response = powerSupply.queryDouble("...message to send...");

So, for instance, we could try asking it for what voltage value is currently set:

double voltage = powerSupply.queryDouble("V?");

(Make sure to use the query...() methods if you need to do a sequential write then read. It makes sure that the read() comes immediately after the write() so that another thread doesn't get in the way).

The next logical step then is to wrap this all up in its own class that extends VISADevice with methods that use these in-built read/write/query methods to perform actions like getVoltage(), turnOn(), turnOff() etc.

public class MyPowerSupply extends VISADevice {

    public MyPowerSupply(Address address) throws IOException, DeviceException {

        super(address);
        setTerminator("\n");
        setEOI(false);
        setReadTerminationCharacter(0xA);
        addAutoRemove("\n");
        addAutoRemove("^END");

    }

    public void setVoltage(double voltage) throws IOException {
        write("V %e", voltage);
    }

    public double getVoltage() throws IOException {
        return queryDouble("V?");
    }

    public void turnOn() throws IOException {
        write("OP 1");
    }

    public void turnOff() throws IOException {
        write("OP 0");
    }

}

As it happens, one of the goals of jisa is to standardise different instrument types and as such it provides a set of interfaces defining the standard methods that all instruments of a given type should have (including SMU, DCPower, LockIn, etc). In our case we want to implement DCPower:

public class MyPowerSupply extends VISADevice implements DCPower {
    ...
}

This will require you to implement the following methods:

/**
* Enables the output of the power supply
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
void turnOn() throws IOException, DeviceException;

/**
* Disables the output of the power supply
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
void turnOff() throws IOException, DeviceException;

/**
* Returns whether the output of the supply is enabled or not
*
* @return Is it enabled?
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
boolean isOn() throws IOException, DeviceException;

/**
* Sets the voltage output level of the supply
*
* @param voltage Voltage, in Volts
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
void setVoltage(double voltage) throws IOException, DeviceException;

/**
* Sets the current output level of the supply
*
* @param current Current, in Amps
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
void setCurrent(double current) throws IOException, DeviceException;

/**
* Returns the voltage output of the supply
*
* @return Output voltage, in Volts
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
double getVoltage() throws IOException, DeviceException;

/**
* Returns the current output of the supply
*
* @return Output current, in Amps
*
* @throws IOException     Upon communication error
* @throws DeviceException Upon device compatibility error
*/
double getCurrent() throws IOException, DeviceException;

So basically the idea would be to start with implementing these standard methods and go from there. This is what my IDE automatically generated by telling it to implement DCPower:

import jisa.addresses.Address;
import jisa.visa.VISADevice;

import java.io.IOException;

public class TSX3510P extends VISADevice implements DCPower {

    public TSX3510P(Address address) throws IOException, DeviceException {

        super(address);

        setTerminator("\n");
        setEOI(false);
        setReadTerminationCharacter(0xA);
        addAutoRemove("\n");
        addAutoRemove("^END");

    }

    @Override
    public void turnOn() throws IOException, DeviceException {

    }

    @Override
    public void turnOff() throws IOException, DeviceException {

    }

    @Override
    public boolean isOn() throws IOException, DeviceException {
        return false;
    }

    @Override
    public void setVoltage(double voltage) throws IOException, DeviceException {

    }

    @Override
    public void setCurrent(double current) throws IOException, DeviceException {

    }

    @Override
    public double getVoltage() throws IOException, DeviceException {
        return 0;
    }

    @Override
    public double getCurrent() throws IOException, DeviceException {
        return 0;
    }

}

Presumably, you could use this as a starting point for your code.

from jisa.

uoiah avatar uoiah commented on May 24, 2024

Hi William,
After I read TSX3510P's manual last night, I know something about the GPIB. I just tested the code as follows:
public class TSX3510P extends VISADevice implements DCPower {

public TSX3510P(Address address) throws IOException, DeviceException {
            super(address);
    }

@Override
public void turnOn() throws IOException, DeviceException {
	write("OP 1");
}

@Override
public void turnOff() throws IOException, DeviceException {
	write("OP 0");
}

@Override
public boolean isOn() throws IOException, DeviceException {
	return false;
}

@Override
public void setVoltage(double voltage) throws IOException, DeviceException {
	write("V %e", voltage);
}

@Override
public void setCurrent(double current) throws IOException, DeviceException {

}

@Override
public double getVoltage() throws IOException, DeviceException {
	return queryDouble("V?");
}

@Override
public double getCurrent() throws IOException, DeviceException {
	return 0;
}

    public static void main(String[] args) {
	try {
		TSX3510P tsx = new TSX3510P(new GPIBAddress(0, 11));
		String idn = tsx.getIDN();
		System.out.println(idn);
	} catch (IOException | DeviceException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

}

The program returned the corresponding information. Obviously, there is no problem with communication between programs and instruments. I think I made the right choice. Your API is wonderful.

but in the code you offered above:
public TSX3510P(Address address) throws IOException, DeviceException {
super(address);
setTerminator("\n");
setEOI(false);
setReadTerminationCharacter(0xA);
addAutoRemove("\n");
addAutoRemove("^END");
}
the method addAutoRemove() is shown undefined in my IDE, Maybe the JISA.jar is not the newest version?

from jisa.

WuhrlWuhrd avatar WuhrlWuhrd commented on May 24, 2024

from jisa.

uoiah avatar uoiah commented on May 24, 2024

Hi William,
It works well. thank you! You have helped a lot. The TSX3510P driver is just simple as follows:

`public class TSX3510P extends VISADevice implements DCPower {

private static TSX3510P tsx3510p = null;

private TSX3510P(Address address) throws IOException, DeviceException {
    super(address);
    setTerminator("\n");
    setEOI(false);
    setReadTerminationCharacter(0xA);
    addAutoRemove("\n");
    addAutoRemove("^END");
}

public static TSX3510P getTSXInstr() throws IOException, DeviceException {
	if(tsx3510p == null) {
		int board = Integer.parseInt(PropertiesUtil.get("Board"));
		int address = Integer.parseInt(PropertiesUtil.get("Address"));
		tsx3510p = new TSX3510P(new GPIBAddress(board, address));
	}
	return tsx3510p;	
}

@Override
public void turnOn() throws IOException, DeviceException {
	write("OP 1");
	
}

@Override
public void turnOff() throws IOException, DeviceException {
	write("OP 0");
	
}

@Override
public boolean isOn() throws IOException, DeviceException {
	// TODO Auto-generated method stub
	return false;
}

@Override
public void setVoltage(double voltage) throws IOException, DeviceException {
	write("V %e", voltage);
	
}

@Override
public void setCurrent(double current) throws IOException, DeviceException {
	write("I %e", current);
	
}

@Override
public double getVoltage() throws IOException, DeviceException {
	String res = this.query("V?");
	double v = Double.parseDouble(res.substring(2));
	return v;

// return queryDouble("V?");
}

@Override
public double getCurrent() throws IOException, DeviceException {
	String res = this.query("I?");
	double i = Double.parseDouble(res.substring(2));
	return i;

// return queryDouble("I?");
}

public void setOVP(double voltage) throws IOException, DeviceException{
	write("OVP %e", voltage);
}

public void setDeltaI(double current) throws IOException, DeviceException{
	write("DELTAI %e", current);
}

public void increaseI() throws IOException, DeviceException{
	write("INCI");
}

public void decreaseI() throws IOException, DeviceException{
	write("DECI");
}

}`

Best wishes,
Yf W

from jisa.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.