Example: I(V) curve

A common measure in a laboratory is the mesurement of the current vs voltage response of a sample. This examples shows an example of code written in Python which takes an I(V) curve using Pyrame modules. Configuration strings for the Agilent 34401A and Keithley 6487 multimeters and for the power supply within the Keithley 6487, are given. Obviously, only two of the three should be used for an I(V) curve (one for power supply and one for multimeter).

The use of a helper function like sendcmd allows to reduce the amount of boilerplate code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# 
# Copyright 2012-2017 Frédéric Magniette, Miguel Rubio-Roy
# This file is part of Pyrame.
# 
# Pyrame is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Pyrame 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 Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrame.  If not, see <http://www.gnu.org/licenses/>

import sys,os,time
import bindpyrame

######################################################

# Connectivity parameters to power supply (ps) and multimeter/picoammeter (mm)
conf_string_ps="ki_6487(bus=gpib(bus=tcp(host=10.220.0.73),dst_addr=22))"
conf_string_mm="mm_ki_6487(bus=gpib(bus=tcp(host=10.220.0.73),dst_addr=22))"
#conf_string_mm="ag_34401a(bus=gpib(bus=tcp(host=10.220.0.72),dst_addr=22))"

# IdV parameters (base units of the SI)
v_start=0 # v_start must be < than v_end
v_end=350
v_step=10
stabilization_time=0.5
current_limit=25e-6
Irange=2e-4

######################################################
# disable stdout buffering
sys.stdout=os.fdopen(sys.stdout.fileno(),"w",0)
######################################################

# Helper function
def sendcmd(*params):
    retcode,res=bindpyrame.sendcmd("localhost",*params)
    if retcode==0:
        print(res)
        sys.exit(1)
    return res

# Get ports
ps_port=bindpyrame.get_port("PS_PORT")
mm_port=bindpyrame.get_port("MULTIMETER_PORT")

# Initialization of module PS and MULTIMETER
ps_id=sendcmd(ps_port,"init_ps",conf_string_ps)
mm_id=sendcmd(mm_port,"init_multimeter",conf_string_mm)

# Configure modules
sendcmd(ps_port,"config_ps",ps_id)
sendcmd(mm_port,"config_multimeter",mm_id)

# Set current limit on PS
sendcmd(ps_port,"set_current_limit_ps",ps_id,str(current_limit))

# Set starting voltage on PS
sendcmd(ps_port,"set_voltage_ps",ps_id,str(v_start))
time.sleep(2*stabilization_time)

# Power on PS
sendcmd(ps_port,"power_on_ps",ps_id)

# Main loop
print("# voltage(V)   current(A)")
for v in range(int(v_start/v_step),int(v_end/v_step)+1):
    v=v*v_step
    sendcmd(ps_port,"set_voltage_ps",ps_id,str(v))
    time.sleep(stabilization_time)
    res=sendcmd(ps_port,"get_voltage_ps",ps_id)
    v="%.6e"%(float(res))
    res=sendcmd(mm_port,"get_dc_current_multimeter",mm_id,str(Irange),"max")
    i="%.6e"%(float(res))
    print("%s %s"%(v,i))

# Power off PS
sendcmd(ps_port,"power_off_ps",ps_id)

# Deinitialize modules
sendcmd(ps_port,"deinit_ps",ps_id)
sendcmd(mm_port,"deinit_multimeter",mm_id)