Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keithley2400 driver #235

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions qcodes/instrument_drivers/tektronix/Keithley_2400.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from qcodes import VisaInstrument
from qcodes.utils.validators import Strings


class Keithley_2400(VisaInstrument):

def __init__(self, name, address, **kwargs):
super().__init__(name, address, terminator='\n', **kwargs)

self.add_parameter('rangev',
get_cmd='SENS:VOLT:RANG?',
get_parser=float,
set_cmd='SOUR:VOLT:RANG {:f}',
label='Voltage range')

self.add_parameter('rangei',
get_cmd='SENS:CURR:RANG?',
get_parser=float,
set_cmd='SOUR:CURR:RANG {:f}',
label='Current range')

self.add_parameter('compliancev',
get_cmd='SENS:VOLT:PROT?',
get_parser=float,
set_cmd='SENS:VOLT:PROT {:f}',
label='Voltage Compliance')

self.add_parameter('compliancei',
get_cmd='SENS:CURR:PROT?',
get_parser=float,
set_cmd='SENS:CURR:PROT {:f}',
label='Current Compliance')

self.add_parameter('volt',
get_cmd=':READ?',
get_parser=self._volt_parser,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

set_cmd=':SOUR:VOLT:LEV {:.8f}',
label='Voltage',
units='V')

self.add_parameter('curr',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

get_cmd=':READ?',
get_parser=self._curr_parser,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

set_cmd=':SOUR:CURR:LEV {:.8f}',
label='Current',
units='A')

self.add_parameter('mode',
vals=Strings(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing you know (or can figure out) what the options for'mode' really are, so you can describe them with validators.Enum instead of Strings(). Same for 'sense', but also all the numeric parameters should get explicit ranges with Numbers(min_value, max_value).

get_cmd=':SOUR:FUNC?',
set_cmd=self._set_mode_and_sense,
label='Mode')

self.add_parameter('sense',
vals=Strings(),
get_cmd=':SENS:FUNC?',
set_cmd=':SENS:FUNC "{:s}"',
label='Sense mode')

self.add_parameter('output',
get_parser=int,
set_cmd=':OUTP:STAT {:d}',
get_cmd=':OUTP:STAT?')

self.add_parameter('nplcv',
get_cmd='SENS:VOLT:NPLC?',
get_parser=float,
set_cmd='SENS:VOLT:NPLC {:f}',
label='Voltage integration time')

self.add_parameter('nplci',
get_cmd='SENS:CURR:NPLC?',
get_parser=float,
set_cmd='SENS:CURR:NPLC {:f}',
label='Current integration time')

self.add_parameter('resistance',
get_cmd=':READ?',
get_parser=self._resistance_parser,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

label='Voltage',
Copy link
Contributor

@MerlinSmiles MerlinSmiles Jun 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This label is probably not correct?
And the units neither?

units='V')

def _set_mode_and_sense(self, msg):
# This helps set the correct read out curr/volt
if msg == 'VOLT':
self.sense('CURR')
elif msg == 'CURR':
self.sense('VOLT')
else:
raise AttributeError('Mode does not exist')
self.write(':SOUR:FUNC {:s}'.format(msg))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Issue found: Trailing whitespace

def reset(self):
self.write(':*RST')

def _volt_parser(self, msg):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MerlinSmiler = [float(x) for x in msg.split(',')]
return MerlinSmiler[0]

def _curr_parser(self, msg):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MerlinSmilerIkke = [float(x) for x in msg.split(',')]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This made me LOL, but you'll need to use self explanatory variable names :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And to bring in a few more nice python patterns too:

v, i = map(float, msg.split(','))
return i

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @ThomasKanne was receiving 4 or 5 values here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see - I might still vote for this pattern though, as a way to document what all is in this READ? response, even if it generates some unused vars.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK and according to somebody: http://www.artima.com/weblogs/viewpost.jsp?thread=98196
map is less of a good python pattern than list comprehension, in the sense that is more readable for non experts. It can be faster but if and only if there are just built-ins functions.
What about this ?

volt, *_ = [float(x) for x in msg.split(',')]
return volt 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I don't care about map, list comprehension is probably clearer. I just don't like making this unknown list and pulling out a random element from it. We could also solve this with a comment describing what READ returns but it's nicer if the code is the comment.

return MerlinSmilerIkke[1]

def _resistance_parser(self, msg):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JohanSmiler = [float(x) for x in msg.split(',')]
return JohanSmiler[0]/JohanSmiler[1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThomasKanne what happens here if the current reading is zero?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MerlinSmiles what would be the science behaviour in this case?
Return Null ? None ? 0 ? 💩 emoji ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think NaN, ie float('nan'), would be the best. Shouldn't be 0, that's when voltage is 0. None is a possibility, but None will turn into NaN when you put it into a numpy float array (because NaN has type float) so we might as well start with that already.