12-07-2016 12:50 PM
Hi, I'm trying to ask a Keithley 2440 to loop through relatively fast sets of 4 wire measurements, report the data, and repeat. I have tried RS232 serial communications with pyserial, which worked alright but was not able to communicate quickly and therefore had a low duty cycle of time collecting data vs. not, so I switched to GPIB (NI GPIB-USB-HS with PyVISA in Python 2.7). Now I have managed to get the Keithley set up for the right current for the 4 wire measurement, but often have errors of the output not turning off after a given period of time and the Keithley has not successfully reported any values back to my computer with my recent attempts at these controls. I got most of the SCPI commands from a coworker who was using a LabVIEW program to control his Keithley a couple of years ago. Current code looks like this:
import visa
import numpy as np
from pylab import *
import matplotlib.pyplot as plt
import time
number_loops = 20
count = 10
DIVoutput = np.zeros((count*number_loops,5)) # make sure this is at least larger than loops*trig count!!!!
NPLC = 6
COUNT = 10
rm = visa.ResourceManager()
rm.list_resources()
('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::24::INSTR')
inst = rm.open_resource('GPIB0::24::INSTR')
inst.timeout = 25000 # in milliseconds
time.sleep(0.001)
print(inst.query("*IDN?"))
print(inst.query(':ROUT:TERM?'))
inst.write(':ROUT:TERM FRON')
print(inst.query(':ROUT:TERM?'))
inst.write('*RST')
inst.write(':FORM:ELEM VOLT,CURR,TIME;DATA SREAL;BORD NORM')
inst.write(':SENSE:AVER:TCON MOV OFF')
inst.write(':SYSTEM:AZERO:STAT OFF')
inst.write(':TRIG:DEL 0.0')
inst.write(':SOURCE:DELAY 0.0')
inst.write(':SYST:AZERO OFF')
inst.write(':DISP:ENAB OFF')
inst.write(':SYST:BEEP:STAT OFF')
inst.write(':AVER OFF')
inst.write(':SYST:RSEN ON')
inst.write(':SYST:AZERO ONCE')
for i in range(number_loops):
#START OF LOOP
inst.write(':CURR:NPLC '+str(NPLC)+';')
inst.write(':SOUR:FUNC CURR')
inst.write(':SOUR:CURR 1e-3')
inst.write(":SENS:FUNC 'VOLT:DC'")
inst.write(':VOLT:PROT 5')
inst.write(':OUTP ON')
inst.write(':ARM:COUN 1;:TRIG:COUN '+str(count)+';:SOUR:CURR:MODE FIX;')
inst.write(':ARM:SOUR IMM;:ARM:TIME 0.01;:TRIG:SOUR IMM;:TRIG:DEL 0')
inst.write(':TRIG:CLE;:INIT')
inst.write(':OUTP OFF')
b=inst.query_ascii_values('FETC?')
a=(inst.read())
inst.close()
I get errors like "UnicodeDecodeError: 'ascii' codec can't decode byte 0xb3 in position 3: ordinal not in range(128)" when I do this.
Does anyone have an example of code that effectively gets 4 wire measurements out of a Keithley at faster than 1 Hz? I'd be happy with anything that pretty much works and has a higher than 50% "up" time of actually taking measurements.
Thanks in advance for any help.
12-08-2016 05:08 PM
I'm not as familiar with Python, but still wanted to provide some online documentation that might be of some help! Most specifically with the error you are receiving.
How to fix: “UnicodeDecodeError: 'ascii' codec can't decode byte”
Pragmatic Unicode
http://nedbatchelder.com/text/unipain.html
PyVISA Keithley Example
http://pyvisa.readthedocs.io/en/stable/example.html
Let me know if this gets you in a good enough spot to move forward!
Best,
Chris D. | Applications Engineer | National Instruments
12-09-2016 09:04 AM
This line is the culprite - I think:
inst.write(':FORM:ELEM VOLT,CURR,TIME;DATA SREAL;BORD NORM')
"data sreal" is putting the data into binary format when you do a fetc?. Need to set 'data asc' instead. Then you will return ascii data.
Binary data is more effcient transfer from the instrument but you have to assemble the raw bytes in to doubles (or char). No idea how to do that in Python. C or C# yes.
12-09-2016 11:25 AM
Great, thanks! I'll try that later today. I've tried serial and GPIB communications with this tool and, while I can occasionally get some data out of the tool, it has not been fast enough (waits entire length of timeout in serial communications) or enough data (only got 30 points back on GPIB) to meet my needs. I'll look through this change and Chris's advice and see if I can get it to work. Thank you for your help!!!
12-10-2016 02:36 PM
Not quite sure what you are getting at but this line controls how many readings you will get.
inst.write(':ARM:COUN 1;:TRIG:COUN '+str(count)+';OUR:CURR:MODE FIX;')
arm count = 1 is the outer loop of the trigger model
trig count is the number of readings to take. So what ever 'count' is.