/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Pst3202.java
* Written by Ajanta Chakraborty, Sun Microsystems.
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.simulation.test;
/**
* Low-level control of Instek PST 3202 power supply. You
* should instantiate {@link Pst3202Channel} instead of this class.
* That will allow easier switching between
* power supplies.
*/
class Pst3202 extends Equipment {
String s = new String("null");
/** Resolution of each channel in Volts */
private static final float[] VOLTAGE_RESOLUTION = { 0.01f, 0.01f, 0.002f };
/** Number of channels (value = 3) */
public static final int NUM_CHANNELS = 3;
/** Delay after each command, in seconds */
public static final float GPIB_DELAY = 0.2f;
/** Maximum number of errors to print out before stopping */
public static final int MAX_NUM_ERRORS = 20;
/**
* Creates a new instance of power suppy. Clears the error and other status
* registers.
*/
public Pst3202(String name) {
super(name);
logInit(" Initializing Pst3202 " + name);
try { Thread.sleep((int)(1000*GPIB_DELAY)); } catch (InterruptedException _) { }
writeAndWait(":*CLS");
// System.out.println("Error4: " + readError());
//System.out.println("Error5: " + readError());
testConnection();
}
/**
* Returns string indicating state of one of the channels
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public String getState(int channel) {
checkChannel(channel);
String result;
result = "Set " + getVoltageSetpoint(channel) + " V, "
+ getCurrentSetpoint(channel) + " A\n";
result += "Got " + readVoltage(channel) + " V, " + readCurrent(channel)
+ " A";
return result;
}
static void checkChannel(int channel) {
if (channel < 1 || channel > NUM_CHANNELS) {
throw new IllegalArgumentException("Channel " + channel
+ " outside allowed range 1.." + NUM_CHANNELS);
}
}
private void writeAndWait(String data) {
super.write(data);
try { Thread.sleep((int)(1000*GPIB_DELAY)); } catch (InterruptedException _) { }
}
public void write(String data) {
writeAndWait(data);
}
/**
* Returns voltage resolution of channel
*
* @param channel
* Supply channel number
* @return Voltage resoluton of channel
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public static float getVoltageResolution(int channel) {
checkChannel(channel);
return VOLTAGE_RESOLUTION[channel - 1];
}
void testConnection() {
writeAndWait("*idn?");
s = read(200).trim();
//s = s.substring(0,s.length()-1);
System.out.println("idn " + s);
} //end testConnection
String readError() {
write("SYST:ERR?");
s = read(200);
return s;
}
void handleError() {
if (isDisabled())
return;
String error;
for (int ind = 0; ind < MAX_NUM_ERRORS; ind++) {
error = readError();
if (error.length() <= 0) {
System.err
.println("Pst3202.handleError() no reply from supply");
}
System.err.println("PST 3202 reports error " + error);
if (error.equals("0, \"No error\""))
return;
}
Infrastructure.nonfatal("Printed " + MAX_NUM_ERRORS
+ " errors from PST 3202");
}
/**
* Measures the voltage on one of the 3 channels
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public float readVoltage(int channel) {
checkChannel(channel);
write(":CHAN" + channel + ":MEAS:VOLT ?");
s = read(200);
if (s.length() <= 0) {
handleError();
return -1.0f;
}
return Float.parseFloat(s);
}
/**
* Reads back the voltage setpoint from one of the 3 channels
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public float getVoltageSetpoint(int channel) {
checkChannel(channel);
logOther("Reading voltage setpoint on Pst3202 " + getName()
+ ", channel " + channel);
write(":CHAN" + channel + ":VOLT?");
s = read(200).trim();
if (s.length() <= 0) {
handleError();
return -1.0f;
}
return Float.parseFloat(s);
}
/**
* Changes the voltage setpoint on channel <code>channel</code> to
* <code>setVolts</code> Volts.
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public boolean setVoltage(int channel, float setVolts) {
checkChannel(channel);
writeAndWait(":CHAN" + channel + ":VOLT " + setVolts);
return true;
}
/**
* Changes the voltage setpoint on channel <code>channel</code> to
* <code>setVolts</code> Volts. Verifies that it the setpoint was changed
* successfully. Bonus points: the delay for verification ensures that a
* rapid sequence of invocations do not overwhelm the PST 3202's command
* buffer.
* <p>
* I don't expect anybody to actually use this method, I'm just keeping this
* code around in case we need it later.
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public boolean setVoltageCheck(int channel, float setVolts) {
checkChannel(channel);
write(":CHAN" + channel + ":VOLT " + setVolts + ";VOLT?");
s = read(200);
if (s.length() <= 0) {
handleError();
return false;
}
float volts = Float.parseFloat(s);
if (Math.abs(volts - setVolts) > 1.0001 * getVoltageResolution(channel)) {
Infrastructure
.nonfatal(this + ": requested voltage setpoint is"
+ setVolts + " V, but setpoint obtained is "
+ volts + " V");
return false;
}
return true;
}
/**
* Measures the current on one of the 3 channels
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public float readCurrent(int channel) {
checkChannel(channel);
write(":CHAN" + channel + ":MEAS:CURR ?");
String s = read(10);
if (s.length() <= 0) {
handleError();
return -1.0f;
}
return Float.parseFloat(s);
}
/**
* Reads back the current setpoint from one of the three channels
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public float getCurrentSetpoint(int channel) {
checkChannel(channel);
write(":CHAN" + channel + ":CURR ?");
String s = read(10);
if (s.length() <= 0) {
handleError();
return -1.0f;
}
return Float.parseFloat(s);
}
/**
* Clear internal or device functions of the device. Among other things,
* this should clear device GPIB error conditions and allow its use again.
* For some devices, it appears that the clear does not work if it is too
* soon after the error occurs.
*/
public void clear() {
super.clear();
try { Thread.sleep((int)(1000*GPIB_DELAY)); } catch (InterruptedException _) { }
}
/**
* Changes the current setpoint on channel <code>channel</code> to
* <code>setAmps</code> Amps.
*
* @throws IllegalArgumentException
* if channel not in range 1..3
*/
public void setCurrent(int channel, float setAmps) {
checkChannel(channel);
writeAndWait(":CHAN" + channel + ":CURR " + setAmps);
}
public void switchOnOff(int state) {
write(":OUTPUT:STATE " + state);
try { Thread.sleep((int)(1000*GPIB_DELAY)); } catch (InterruptedException _) { }
write(":OUTPUT:STATE?");
s = read(200).trim();
System.out.println("state " + s);
}
/**
* Unit test verifies that voltage setpoint resolution is 0.01 V. Should
* disconnect supply from any chips before running.
*/
public static void main(String args[]) {
Infrastructure.gpibControllers = new int[] { 1 };
Logger.setLogInits(true);
Pst3202 supply = new Pst3202("hPst3202");
//Infrastructure.readln("Hit return to clear device:");
supply.clear();
// Infrastructure.readln("Cleared");
System.out.println("Error1: " + supply.readError());
System.out.println("Error2: " + supply.readError());
System.out.println("Error3: " + supply.readError());
System.out.println("Error4: " + supply.readError());
System.out.println("Error5: " + supply.readError());
supply.testConnection();
float voltageSetpoint = supply.getVoltageSetpoint(1);
System.out.println(supply.getState(1));
if (voltageSetpoint < 0.2f) {
voltageSetpoint = 0.2f;
}
for (int chan = 1; chan <= 3; chan++) {
System.out.println("Chan " + chan + " resolution: "
+ Pst3202.getVoltageResolution(chan) + " V");
}
// Demonstrate that resolution is 0.01 V
for (float dv = 0.f; dv < 0.014; dv += 0.002) {
supply.setVoltage(1, voltageSetpoint - dv);
System.out.println((voltageSetpoint - dv) + ": "
+ supply.getState(1) + "\n");
}
// See if supply can tolerate rapid voltage setting
for (float volts = 1.8f; volts >= 1.60f; volts -= 0.01f) {
System.out.println(volts);
supply.setVoltage(1, volts);
supply.setVoltage(3, volts);
}
System.out.println("Error6: " + supply.readError());
System.out.println(supply.getState(1));
supply.setVoltage(1, voltageSetpoint);
supply.setVoltage(3, voltageSetpoint);
System.out.println("Error7: " + supply.readError());
System.out.println(supply.getState(1));
System.out.println("Error8: " + supply.readError());
}
} //end class