From 747231d1af8c53c0824e73152d82ed7c1b60cbab Mon Sep 17 00:00:00 2001 From: nroisin <nroisin@gmail.com> Date: Fri, 14 Mar 2025 12:35:23 +0100 Subject: [PATCH] example single_equipment --- .../__pycache__/dmm.cpython-311.pyc | Bin 0 -> 4072 bytes .../__pycache__/equipment.cpython-311.pyc | Bin 4445 -> 5116 bytes .../__pycache__/hp4145.cpython-311.pyc | Bin 6238 -> 12039 bytes .../__pycache__/k2450.cpython-311.pyc | Bin 0 -> 5380 bytes .../__pycache__/k24xx.cpython-311.pyc | Bin 0 -> 5526 bytes .../__pycache__/k4200.cpython-311.pyc | Bin 0 -> 9656 bytes equipment_control/cm110.py | 4 +- equipment_control/dmm.py | 92 +++++++--- equipment_control/equipment.py | 33 +++- .../example/single_equipment/dmm_script.py | 68 +++++++ .../example/single_equipment/hp4145_script.py | 52 ++++-- .../example/single_equipment/k2400_script.py | 71 ++++++++ .../example/single_equipment/k2450_script.py | 71 ++++++++ .../example/single_equipment/k4200_script.py | 79 +++++++++ .../example/single_equipment/temp.txt | 4 + equipment_control/hp4145.py | 167 +++++++++++++----- equipment_control/k2400.py | 112 ++++++++++++ equipment_control/k2450.py | 101 +++++++++++ equipment_control/k24xx.py | 86 --------- equipment_control/k4200.py | 149 +++++++++++----- equipment_control/kal100.py | 51 ++++++ 21 files changed, 903 insertions(+), 237 deletions(-) create mode 100644 equipment_control/__pycache__/dmm.cpython-311.pyc create mode 100644 equipment_control/__pycache__/k2450.cpython-311.pyc create mode 100644 equipment_control/__pycache__/k24xx.cpython-311.pyc create mode 100644 equipment_control/__pycache__/k4200.cpython-311.pyc create mode 100644 equipment_control/example/single_equipment/dmm_script.py create mode 100644 equipment_control/example/single_equipment/k2400_script.py create mode 100644 equipment_control/example/single_equipment/k2450_script.py create mode 100644 equipment_control/example/single_equipment/k4200_script.py create mode 100644 equipment_control/example/single_equipment/temp.txt create mode 100644 equipment_control/k2400.py create mode 100644 equipment_control/k2450.py delete mode 100644 equipment_control/k24xx.py create mode 100644 equipment_control/kal100.py diff --git a/equipment_control/__pycache__/dmm.cpython-311.pyc b/equipment_control/__pycache__/dmm.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84320a1ca1f6ef1565659367e52e192a271cd3f3 GIT binary patch literal 4072 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 PfAL>y@PF?xu|oJiX5odW literal 0 HcmV?d00001 diff --git a/equipment_control/__pycache__/equipment.cpython-311.pyc b/equipment_control/__pycache__/equipment.cpython-311.pyc index 656e109941a4e89daec1764462b956ead1dce9bd..83a47f5dd9896150bb92f4f2dfbbd2fe940651ea 100644 GIT binary patch delta 1367 zcmaJ>UuYaf7@ygHce^{gw`Vsr7n{vBx%1Mr7r`{rrZ%PYdKX#}DMloMNXTAIYI@bZ zO-qkG{6ilu<*;k!p{ZCrL2AL5hzcsc`XYk2WueExK|uPD7dcTM42sTfZlkHO-_87H z_V>;AeLv<KuGRlXO8!`q1VBubet6}W_^JFR1!a7Lib)Y&x&~hqb^1AQK>6$o>QAmG zJ3SZn&UTC^D^2DvcNzR0pJgo8h+;+PI~Xn~rswFG1$FKY1;8g{Zdo~Og^ZjPu2I<G zRZ0)xGr~C-#_tQmjK!HU{)vmxBNm72{N5OU2a;Gaw=4r*>Mip@?659ae2I8;A9o&w zpsJbCAP|5HJpNvY9Td#2e>h9n8KaA@`ZA54pahO1W~#&iu=5}UHY}tbnM&%UDw=!$ zT~HVCn)vvhTv@cl?Q(rVIZl@?$`bJq>SI#@8P+2f?b8LcpPdNkGx|f913}@#M@mvU zlHS=xQg2jzh?RVyXUoV!+d}sT#lu@dErbWr0Nv@O5C|poB1#5y_kV>}uaZQ_>pzZ% z<QWKbKwesOY7-7`{6(xu&lN8lhseb>;gu$wEwKafWKk$l$+=BPmVvn8HLAoWho3$z zY<TaZ#CZD>mn?eghUY#Y;isguU<`P9=%Q)hm!)1P;j)w-<u6^%8&`}4GvDOq^Rs&1 zXfpaN`GV)0%;G{JZ=CR=;6f8#C`x1-Cx*X~j!~y5{JWHVV_j6+faa4eMYU&Yw4)?k zB~dw9Ir(5Gu`Wj10P;E5K+=ue^_)F%d*0QayswSi(?%R^)YV4sYvcE{@h?qB%eY#` zQBON4>!NHOWgm!L_W9d$j@a*t{cS+;gN<(O1N0uM%}+bsLvHsF$t?}~U^5LRdNZ^V zT4h$JZ}GLnE!k00u9B+z<2MdOqSblZTrN}#6}BbHm8Ipe>X`ld_2ZS}+u~OBcb|1o z!bOQXN{~$pe=Yas8ELEy2-vW(N3~~H4%>$tYS+!&N^Uh<%iN8AlymkSa@4e|rtAJ# z?|3I_3v0~Uxz9uO<Pm4z5l21hsz>YoSnu3NW_hwYSs_3CmHe&D`dv5D<i@j8(|9>D z11Is1k!w9qu#dIDu7KZCVyDKuZn1@>i?3ZZ#>w6gJ&-+6Jb2y%<bn5(w;6us;w61) iF+Xm+Kt8?qQ+yk@l(Q!$AtZHn$De)v*Z=YQ+5ZMezEC9q delta 838 zcmeyPepiWaIWI340}v#r>`xEk+{o9!#K<$bpGlIJH-)=}F^W5dIha9{Z}V2Bzibl8 ztRR(8zzL+8f%vlw^W-y}Zj;5h<e6D(SSKs+i8HcIF5?PhWS@M3OD`yk9j2p(X&EB} z!)hRgfLgW^K^U8Xp@t1rHiaXb2_#!&ULuUFDur{h9j`R2LM=PQGIp*SrW$rhhRNr+ zWQ2MY^A@5SI(Y-PxL_X^BV+~H(L^~w1`B%Ea@267a6&CtgjmAO1G1!sBaI1S5lfFI zM1qsIh8ZF?`4_J$BiQ@me5gKQWaz1^VO_vAIgv|vvOGKg<N`i+Pkz5&jCwEs1Hmok z<l?d-9iSg?F(y_qs}^%rF{viM1O-zOC<LllRrSo$xL$(UEFg9jn`$wL{>8|p$vycb zpY9}nSw_yua{RhNjA=!-V3RU$F=iEm;%IUMzco`S<K(^ks`XEK1SUw%aK6Z+aD_*q zgYgCjXFq!v`vkVR99JYXuS@7&lF+><p?^g}|GI?5B?*fiA{Qm>u1MHj6tKU@;c$h+ z;R1)lQ$B&7j0q*3c|Ca@tWUZ5I!ZgOdaNcCcG-5=-W8RaVY)zYj>W|IDe)f|7<qNT z#01700)o@oC$Y=S;8>utpm2%$MG38o0@_yuv@d|s2WFts$=-rTxtYM>P^1fTx13NU zqx<9vp_UL)R-q3JIEW%1pxPn<5WxZ@G}((liL}TPNZex0E6pvaEV2O!aDxaw5CK-} kKRG~Hf-4Zn2ZeKS#pEJkZ&MpapgowxN08VTED~V50kikMw*UYD diff --git a/equipment_control/__pycache__/hp4145.cpython-311.pyc b/equipment_control/__pycache__/hp4145.cpython-311.pyc index 7427a598aa61f7d6a06b6b5568801b2db1caeeb2..dfc03a98e1bb6f4e1aab97330c3c072f6662cf7c 100644 GIT binary patch literal 12039 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 literal 6238 zcmcIoT}&I<6~5zt<1vg4AwURg0)&`9V<5j9NC;*ZlFbj0C4r=J9nSzJ#x^r!2(DT2 zu$5?)N@kU6oo-fQD>X}%KJZd0sw$Ozso3tzOf*ugkyeUS<$;Gv-e#*td1=ob|BXYU zMo7IgK6B4G_ndp~kLP}8zP4IR5R{>Yzf6C#523$fCRg;?%8M&d`5e)RCW2^=m?Vfy zT{EdsWZFrs^3+Z0HRwY`Yd%G^mLX<|oTG<YgdV{!Qzi{GF@~JF9n4<xXQj%+lx1Fw zL*;YCph<#8&<g=QXeM>Ec2ZC4z+O)qXrpqO9%yNE_9}Ux%StUEC2@VqL|Z>4CXICI zr)bhdmqEXjY?z7kxO<MqItGG1j&tx~hd&(R*>KP?bOkFM95WXH5gqmOVb<Xb`GQL^ zhLsH&wQRb;EOCM989sJ-hUX*PDVJ+;ak1leR@&hY&$;N^E+*sx_YBXuPIkIaw09mq z*?rW-G3-LX&$Q3^LQ!8(t?G!-Q?ING;UMpuW*poi!$fv;Fb%8*h*K-;#x8!`rO<AL z_DuikAAel`_g^>roH|9|X3e-cUQgDNvC(t9kL6_@$A=@BG7(ujeAVs84RZxI#cT88 zpRnGaqc{;q-kc7_HNfT9F|G#=hoh9Z4!HcP#<jrVcr!W!aJl`1;zr;Md7TM3V~#VU zIGW9^J6cyqmTLn0?jgkRC?5y$E;gDy*l2gz5VY>LGU9}WJ<P*DBv<(Txf()oJ*}_K zv%nb&TnyF&Bu144X1utcVh(19%sG39xiJ-6zth~9U$@~8<a&f?HFOD%y10!8{iJo- z{0{M0;%1tRfxFkAQ`#8pfnu)&y4&^+KCQ1?y@O3@@j84#&}GHzl$EGfCM%%|YxM>3 z<zD937T41Df|s~X%}r_EG!O4EqH^$BQsh;|?b&MucqNOxs<=IS-4{3Qag>#D<K8Ue zhCS?({d=&f+JjB?>o%d@2E^AE{&lluxq2gFTM5M1=XiwZn%Aw1c8jghvQT>n)kk@j zKocmWTSRxX6KIiucf1Dv3kM!(;XJI3EtWX4WiCuJr}7*YwmS|L9Z82yIf{74Vt}7< zz|rJ}bCP!Wqb$pWc*h*$<Dx7x2X)R74mo_mpo5=ba6>NdU)G!(khPvscT6`p;Bd3} zOkhhfv0{QJMAmo)WBUe%+-;8Lad$J&VN8K_@8IJgRy8oxL}O(Wt!R}8sJnOYTU*wQ zjm7liqacWB+8lBT9L<qnz!&l}G3)q1SDT}$qiYH%r<}4_)?JWcwnxS4hpsxBreb;z zet_$X5d6iiSmj5<nXsCNyPDgYhr2Q9X^z#q>Tf#61DtR8@*v9skT~Vw19MC`$~%}l zkpRok_*BPJE|-O(bGI1Q>!0z3LQIg8Ez0@tjrdsKoYT(Yx3gSY+=xA>2)Vhaw=gQ% zg!x+mA170R5YJ4rK0Xi*d6iyDXeQ`e^5P(5^GrBMXR2k9r3Hx6%Q9Rz%K8~uzsLr7 zM%ID@S?jw6(FB>$G(Y2|eY{WBv%b(YBO5YSvPCsQSs!7sk=`E+bBwbDAO{niQle+; zAX?Ue$$OaK;90!I*+ZB#0Fj9RhrvsBFT&&1G0&-+qu~G-2)R6Ae^l8{F8@q8!f-d4 z`Dh@5B`|yiz1_^fx{k<_ToMQc_<%1Mh%qr+R$LI_-NktTxvZeH9hL82)!j9xYFk!y zlIcLIx)DFC@_c0-sI95G4lF*HsyYO0S!%xn9;Inhz1f)}DT#DEB@aI#53lng*(Q-~ z0@+q1j*4WvM79fLdy#lSBs(OsLm)ezm6a#LPs*CavZm+tjlUb)Xx*HWT6!Pf-fouq zM#Yv<;i^~o>6CPJT69i}O*2x{j94F#>H`U#L^)Dag+w(zrCOd)EgL-|)hSV(0@e9U zB^FxGiPV5Z4G7f0^Xj_fCmTNTJ(pPBDOGo-5n-DkGBnYjs;H7Gjy$dCcv8_JxQ4gg z+auq0Z_f)Oqu+AE*j3@<adB*XyIpi$6DzJu71ssjR`;a}K^>VuwQRL+PfO><h0J~J zmf#Oa*Jg#xeS1MzT$XNsA}Dtnp|hF`8hCu9xvu#Ua}$`$KH4TVKOkhgfi*xu0aV@F z#+k=MTO)tIuw5!#yDkk)2=7mdt&<{kL!xd7)Q$g7)1p~8zIjq?JuOnb64fhEy+u79 z-#jI@_KH-WMD+<&pIRrhzAsXzCF-<5oi6fMSXg!QjiVyvmMFJCxz%E!bwH#%66Fyn z&&!wpG9ju`DyvT;joDcs-;*}MepDonN#rqsJf_~8B6&n2j|jOttp~%GFJGojsH%43 zlkFQq*#y2#6Pz9XO@A7G|NJrZw`0dIbZWnI5kUQUunuYr@0Apz3K9fJG0-dsGG&<v zpk+uh3dtf(WB@k{Dc`a-bf8G5&Fgfavli*}S)GP9EJHFfn@?0|V-~^_?00-V@jz%c zpRN>13uz0Q%_l9iNd=MAa`Ri{DrlyFVYQ7)SDYHtmWL4aqkQDcx}wPPvEwAIkTgxb zmg>NK>Hx$;lKyiIO-^Y}!&LL-xfuswPQ<mbT}cRS#c?j{X>!>BKO+DH^0qQV34(Qj zM^#d@Y>FGe2egk9nKrB$KyGPaE|$%qQf!lH1-{|UuGT{Q_+77*b)16kDs<T!K+pfO zp<cJ)3!S1_{Nh&%y$dR;=ZD9KQ?|s-0A!(8h_|p8RO`2U9*ZN$&T0vdPraN^)!G%e zh9rw#wiL|`m9tVmX<OWq@w^)<FOzX{{f&^2w(sh#ZQ05<6+FkSv=#4~!lV^j0Bkho zdd}=C;K=O%P9HZyOfbjG#=Grz8D;G;XMmk#jX}D+tZJd&U7N1B27qY!B^D2Mrwa)F zOwqN2F$1o3@8EUM;6uEI8IXwa;SOFD1-r30H{baW6j^i8BWo`Xx??8KWk6;C311Oy z&T{q$ZmVDp1y5;05dbscXo!{#fU^M9WFVCuzV(E;3}88oO&T%5vn1;j?4;*{@NtH1 z#$qQH>*u2kyCmy5z?Oi1rh;J~?<{3Iuugl)yCCZn<fOYa=er{t7QDd#$IE8GSQ&IC z>jNR0xg!&^vT?zi`DCMC@G=k>afx+dFJ|l@V`osR0S*J@0#w2^wi7ok5Bj1Z|BP1+ z!DBU95cCG!2Vlg}@XA?1&oGp!UDc+nWvjYpmNLoWSZ{h_X%;NaDO>rfXVsIk+9d0t z^}#1rr(kuyU6?i?lDc~mFpZ^2v@|_0-*@lCm**Y~uhY`uW1EZ8;WJx0>FgC@<eGH$ zx-jt*X(AxZMx=>(@$9_7F2JGA5d-*C_h`=JBc3BJ;Pd|AN0<Q$nv0rCSX6Nti-4|v z@Z45@uPWJ{<fZqzgqm*A)+5<^Am+;2RZqgET<%2qFNU92Rwo;h^!+1ibNA-f``5y& z!zp|D>R_t0Y_&gSKalMItaYt5RaKXaKCmW?sq(61#oDQ)|FgbCU#iBjZhz2{7)%U4 zgX+F@{;Qge{;z7Knhubt0M}bUkm|Vpo~pQ4lI&V5y;qtjeQw|PYk%_S`u_X98;w%S zsmI5pmUCjwIk9p;svHpQ9?9<68WHUuBnS-O@DRo7ZmGIEjr2A+*MR_Zt2-psbv>;+ z@ucp=<C?9Jt@&@p#FN8f-Fd0*d}27&(DwD2-=5j*78{OB4ad_+yALdZBrCsfbZ#8p zv~Aiq?SE(y8;?qjN0YkbNOFGNcArareBY8fP@DAqrYG5xsy&#Tzwb%*zf2pkeF?Hv zCipc=LZ70llkPP#VNOxDgnLbwAkyuqyf!nN=}tsdtXf{cW<!^pX4&NRhJ163*DIHJ zadr|7;yUT|&ckQXtj6f|(qTV{^*DVA%0`^$_(DsvHp&KBH+W)4f&3n^W4MlYKZ_46 zh2R$h_e&rv`RkePgrGZ-DzUE&rpU^b4^yUzm4Rn<?T<%<D<i_hq;ShG4AF3>ob8)e zw<@-;3iYG-o(Tx^tPuN|;EltbYB;jlzeS|=$Mutdns-r_aOo@3XgA4(i6e9x<paC& zmyWzdHs`Bs3m#BE5LplTUu22x#R6rRH*hUK^jD_SnR)DE@%LMdzqkb;X)QqzDdZB0 p?-a7GC|3$uR+KA+>_YBN>%s&9gLpGtosg`K9~9+}Z)u{$^<M!7d=&ry diff --git a/equipment_control/__pycache__/k2450.cpython-311.pyc b/equipment_control/__pycache__/k2450.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ada50c438bcb1a1c83e32da6e9062b025e7e93d GIT binary patch literal 5380 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 AbpQYW literal 0 HcmV?d00001 diff --git a/equipment_control/__pycache__/k24xx.cpython-311.pyc b/equipment_control/__pycache__/k24xx.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0615ce1d658c1ad7ba226efdc9ea220aa3ca7b2 GIT binary patch literal 5526 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 literal 0 HcmV?d00001 diff --git a/equipment_control/__pycache__/k4200.cpython-311.pyc b/equipment_control/__pycache__/k4200.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7bcbb2bba58af1122ba628d6589d291c2e97780 GIT binary patch literal 9656 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 S+XQXRALPbA9??bC>wf^%p@g~s literal 0 HcmV?d00001 diff --git a/equipment_control/cm110.py b/equipment_control/cm110.py index 8658953..3c10e61 100644 --- a/equipment_control/cm110.py +++ b/equipment_control/cm110.py @@ -7,11 +7,11 @@ class cm110(equipment.equipment): """Class to control CM110 monochromator""" model="CM110" company="Spectral Product" - link="https://www.spectralproducts.com/CM110" + url="https://www.spectralproducts.com/CM110" def __init__(self,port): self.serial_resource = serial.Serial( - port='COM5', + port=port, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, diff --git a/equipment_control/dmm.py b/equipment_control/dmm.py index 7444a6e..62256bd 100644 --- a/equipment_control/dmm.py +++ b/equipment_control/dmm.py @@ -1,4 +1,5 @@ import equipment_control.equipment as equipment +import time class dmm(equipment.equipment): @@ -7,45 +8,78 @@ class dmm(equipment.equipment): company="Keithley" url="https://www.tek.com/en/products/keithley/benchtop-digital-multimeter" - def initialize(self, mode, autozero=True, offset_compensation=True, nplc=1,timeout=10e3): + def initialize(self, mode, autozero=True, offset_compensation=True, nplc=1,timeout=10e3,digits=6,k2000=False,continuous_trigger=False,disp_enable=True): """ mode: - "voltage": voltage measurement - "current": current measurement - "resistance": resistance measurement - - "4 wires": 4 wires measurement + - "4 wires": 4wires measurement """ + self.continuous_trigger=continuous_trigger + self.k2000=k2000 self.pyvisa_resource.write("*RST") # self.set_connection_parameter_dic({"write_termination":'\r\n',"read_termination":'\r\n',"send_end":True}) - if mode=="voltage": - self.pyvisa_resource.write(":SENS:FUNC 'VOLT'") - elif mode=="current": - self.pyvisa_resource.write(":SENS:FUNC 'CURR'") - elif mode=="resistance": - self.pyvisa_resource.write(":SENS:FUNC 'RES'") - elif mode=="4 wires": - self.pyvisa_resource.write(":SENS:FUNC 'FRES'") - - - self.pyvisa_resource.write(":SENS:FRES:RANG:AUTO ON") # set automatic range - self.pyvisa_resource.write(":DISP:DIG MAX") # Query largest allowable display resolutio - self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. - self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering - - if offset_compensation: - self.pyvisa_resource.write(":SENS:FRES:OCOM ON") # enable offset compensation - else: - self.pyvisa_resource.write(":SENS:FRES:OCOM OFF") - - if autozero: - self.pyvisa_resource.write(":SENS:FRES:AZER ON") # enable auto-zero + mode_name={"voltage":"VOLT", "current":"CURR", "resistance":"RES", "4wires":"FRES", "4 wires":"FRES"} + + self.pyvisa_resource.write(":SENS:FUNC '%s'"%mode_name[mode]) + + self.pyvisa_resource.write(":SENS:%s:RANG:AUTO ON"%mode_name[mode]) # set automatic range + + + if k2000: + self.pyvisa_resource.write(":SENS:%s:DIG %d"%(mode_name[mode],digits)) + if disp_enable: + self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + else: + self.pyvisa_resource.write(":DISP:ENAB OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + + if continuous_trigger: + self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering + else: + self.pyvisa_resource.write("INIT:CONT OFF") # able continuous triggering + else: - self.pyvisa_resource.write(":SENS:FRES:AZER OFF") - - self.pyvisa_resource.write(":SENS:FRES:NPLC %d"%nplc) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec - + if disp_enable: + self.pyvisa_resource.write(":DISP:LIGHT:STAT ON100") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + else: + self.pyvisa_resource.write(":DISP:LIGHT:STAT OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + + self.pyvisa_resource.write(":DISP:%s:DIG %d"%(mode_name[mode],digits)) + self.pyvisa_resource.write(":SENS:%s:NPLC %d"%(mode_name[mode],nplc)) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + + # if mode_name[mode]=="RES" or mode_name[mode]=="FRES": + + # if offset_compensation: + # self.pyvisa_resource.write(":%s:OCOM ON"%mode_name[mode]) # enable offset compensation + # else: + # self.pyvisa_resource.write(":%s:OCOM OFF"%mode_name[mode]) + + if autozero: + self.pyvisa_resource.write(":%s:AZER ON"%mode_name[mode]) # enable auto-zero + else: + self.pyvisa_resource.write(":%s:AZER OFF"%mode_name[mode]) + + if continuous_trigger: + self.pyvisa_resource.write("TRIG:CONT REST") # able continuous triggering + else: + self.pyvisa_resource.write("TRIG:CONT OFF") def read_single(self): - data=self.pyvisa_resource.query("READ?") + if self.k2000: + if self.continuous_trigger: + data=self.pyvisa_resource.query("FETCH?") + else: + data=self.pyvisa_resource.query("READ?") + else: + if self.continuous_trigger: + self.pyvisa_resource.write("TRIG:CONT OFF") + time.sleep(0.1) + data=self.pyvisa_resource.query("MEAS?") + self.pyvisa_resource.write("TRIG:CONT REST") + else: + data=self.pyvisa_resource.query("MEAS?") + return float(data) + diff --git a/equipment_control/equipment.py b/equipment_control/equipment.py index 739c566..d275b92 100644 --- a/equipment_control/equipment.py +++ b/equipment_control/equipment.py @@ -51,25 +51,42 @@ class equipment(): def close_connection(self): self.pyvisa_resource.close() - def write_in_file(self,file_path,data,delimiter=",",extension="txt"): + def write_in_file(self,file_path,data,delimiter=",",extension="txt",overwrite=False,header=None,date=True): if file_path.split(".")[-1]=="csv": delimiter="," # Create file and header - f = open(file_path, "a") - f.write("%s\n"%(datetime.datetime.now().strftime("%c"))) + if overwrite: + f = open(file_path, "w") + else: + f = open(file_path, "a") + + if date: + f.write("# %s\n"%(datetime.datetime.now().strftime("%c"))) - shape=np.shape(data) + if isinstance(header, str): + for line in header.split("\n"): + f.write("# "+line+"\n") + - if len(shape)==1: + shape=np.shape(data) + if len(shape)==0: + f.write("%.6E\n"%(data)) + elif len(shape)==1: for i in range(shape[0]): - f.write("%.6f\n"%(data[i])) + if i==0: + f.write("%.6E"%(data[i])) + else: + f.write("%s%.6E"%(delimiter,data[i])) + + f.write("\n") + elif len(shape)==2: for i in range(shape[0]): for j in range(shape[1]): if j==0: - f.write("%.6f"%(data[i,j])) + f.write("%.6E"%(data[i,j])) else: - f.write("%s%.6f"%(delimiter,data[i,j])) + f.write("%s%.6E"%(delimiter,data[i,j])) f.write("\n") f.close() diff --git a/equipment_control/example/single_equipment/dmm_script.py b/equipment_control/example/single_equipment/dmm_script.py new file mode 100644 index 0000000..cf0643d --- /dev/null +++ b/equipment_control/example/single_equipment/dmm_script.py @@ -0,0 +1,68 @@ + + +# ============================================================================= +# 1. Import classes and modules +# ============================================================================= + +import sys +#sys.path.insert(1, '/path/to/application/app/folder') +sys.path.insert(1, 'D:/Roisin/Documents/chopes') + +import equipment_control.equipment as eq +import equipment_control.dmm as dmm +import time + +# ============================================================================= +# 2. List available connections (chopes use pyvisa package for communicate with most equipments) +# ============================================================================= +rm=eq.resource_manager() +list_connections= eq.available_connections() +print("Available connections: %s"%str(list_connections)) + +# ============================================================================= +# 3. Connection to the equipments +# ============================================================================= +mydmm=dmm.dmm('USB0::0x05E6::0x6500::04529651::INSTR',timeout=1e3) + +# ============================================================================= +# 4. Measurement parameters +# ============================================================================= +units={"voltage":"V", "current":"A", "resistance":"Ohms", "4wires":"Ohms"} + +mode="current" +autozero=True +offset_compensation=True +nplc=1 +digits=4 +continuous_trigger = False +disp_enable=True +k2000=False +file_path='temp.txt' +t_init=time.time() + +# ============================================================================= +# 5. Initialization of the equipments +# ============================================================================= +mydmm.initialize( mode=mode, autozero=autozero, offset_compensation=offset_compensation, + continuous_trigger=continuous_trigger, digits=digits,nplc=nplc,disp_enable=disp_enable + ,k2000=k2000) + +# ============================================================================= +# 6. Measurement script +# ============================================================================= +data=mydmm.read_single() +t_data=time.time()-t_init +print("%s measured: %E %s"%(mode,data,units[mode])) +# ============================================================================= +# 7. Close connection +# ============================================================================= +mydmm.close_connection() + + +# ============================================================================= +# 8. Save data +# ============================================================================= +data_to_write=[t_data,data] +header="Time (s), %s (%s)"%(mode,units[mode]) +mydmm.write_in_file(file_path,data_to_write,header=header,date=True,overwrite=True) +mydmm.write_in_file(file_path,data_to_write,header=None,date=False,overwrite=False) diff --git a/equipment_control/example/single_equipment/hp4145_script.py b/equipment_control/example/single_equipment/hp4145_script.py index 93848b6..5c50d64 100644 --- a/equipment_control/example/single_equipment/hp4145_script.py +++ b/equipment_control/example/single_equipment/hp4145_script.py @@ -6,47 +6,60 @@ import sys #sys.path.insert(1, '/path/to/application/app/folder') sys.path.insert(1, 'D:/Roisin/Documents/chopes') -import equipment_control.equipment as eq -import equipment_control.hp4145 as hp4145 - +import equipment_control.equipment as eq # Parent class that handle the connections with the equipments +import equipment_control.hp4145 as hp4145 # Child class that inherits from equipment parent class +import traceback # to write error message in try/except command +import datetime # ============================================================================= # 2. List available connections (chopes use pyvisa package for communicate with most equipments) # ============================================================================= -rm=eq.resource_manager() -list_connections= eq.available_connections() -print("Available connections: %s"%str(list_connections)) +rm=eq.resource_manager() # you can use the function from equipment class or directly the pyvisa command rm = pyvisa.ResourceManager() +list_connections= eq.available_connections(rm=rm) # you can use the function from equipment class or directly the pyvisa command rm.list_resources() +print("-------------------------------------------------\n Available connections: %s"%str(list_connections)) # ============================================================================= # 3. Connection to the equipments # ============================================================================= -myHP4145=hp4145.hp4145("GPIB0::1::INSTR") +myHP4145=hp4145.hp4145("GPIB0::1::INSTR",timeout=100e3) # ============================================================================= # 4. Measurement parameters # ============================================================================= file_path='temp.txt' -mode="voltage sweep" -number_channel=4 -smu_bias={"SMU2":0,"SMU3":0,"SMU4":0} +smu_type={"SMU1":"voltage","SMU2":"current","SMU3":"current","SMU4":"current"} +smu_used={"SMU1":"on","SMU2":"off","SMU3":"on","SMU4":"on"} +smu_master=1 +smu_bias={"SMU1":10,"SMU2":0,"SMU3":0,"SMU4":0} smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6} -sweep_param={"start":0,"stop":1,"step":0.1} +sweep_param={"start":0,"stop":1,"step":0.05} +sweep_type="linear" integration_mode="IT1" delay_time=0 hold_time=0 + # ============================================================================= # 5. Initialization of the equipments # ============================================================================= -myHP4145.initialize(mode=mode,number_channel=number_channel,smu_bias=smu_bias, - smu_compliance=smu_compliance,sweep_param=sweep_param, - integration_mode=integration_mode,delay_time=delay_time,hold_time=hold_time) +print("-------------------------------------------------\n Starting initialisation ...", end='') + +myHP4145.initialize(smu_type=smu_type,smu_used=smu_used,smu_master=smu_master,smu_bias=smu_bias, + smu_compliance=smu_compliance,sweep_param=sweep_param,sweep_type=sweep_type, + integration_mode=integration_mode,delay_time=delay_time,hold_time=hold_time) +print(" Done!") # ============================================================================= # 6. Measurement script # ============================================================================= -data=myHP4145.launch_measurements() +print("-------------------------------------------------\n Starting measurement ...", end='') +try: + data,data_header=myHP4145.launch_measurements() +except Exception: + traceback.print_exc() + myHP4145.close_connection() +print(" Done!") # ============================================================================= # 7. Close connection @@ -56,4 +69,11 @@ myHP4145.close_connection() # ============================================================================= # 8. Save data # ============================================================================= -myHP4145.write_in_file(file_path,data) +custom_header="IV results with HP4145\n" + +print("-------------------------------------------------\n Print in file %s"%file_path) +print(" - Header:") +print(" # %s"%(datetime.datetime.now().strftime("%c"))) +for line in (custom_header+data_header).split('\n'): + print(" # "+line) +myHP4145.write_in_file(file_path,data,overwrite=True,header=custom_header+data_header) diff --git a/equipment_control/example/single_equipment/k2400_script.py b/equipment_control/example/single_equipment/k2400_script.py new file mode 100644 index 0000000..b94598f --- /dev/null +++ b/equipment_control/example/single_equipment/k2400_script.py @@ -0,0 +1,71 @@ + + +# ============================================================================= +# 1. Import classes and modules +# ============================================================================= + +import sys +#sys.path.insert(1, '/path/to/application/app/folder') +sys.path.insert(1, 'D:/Roisin/Documents/chopes') + +import equipment_control.equipment as eq +import equipment_control.k2400 as k2400 +import time + +# ============================================================================= +# 2. List available connections (chopes use pyvisa package for communicate with most equipments) +# ============================================================================= +rm=eq.resource_manager() +list_connections= eq.available_connections() +print("Available connections: %s"%str(list_connections)) + +# ============================================================================= +# 3. Connection to the equipments +# ============================================================================= +myk2400=k2400.k2400("GPIB0::29::INSTR",timeout=1e3) + +# ============================================================================= +# 4. Measurement parameters +# ============================================================================= +units={"voltage":"V", "current":"A", "resistance":"Ohms"} + +source_mode = "current" +measurement_mode = "voltage" +compliance = 1 +autozero = True +offset_compensation = True +nplc = 1 +digits = 6 +continuous_trigger = False +disp_enable = True +bias_source = 1e-6 +file_path = 'temp.txt' +t_init=time.time() +# ============================================================================= +# 5. Initialization of the equipments +# ============================================================================= +myk2400.initialize(source_mode=source_mode, measurement_mode=measurement_mode, + compliance=compliance, autozero=autozero, offset_compensation=offset_compensation, + digits=digits,continuous_trigger=continuous_trigger,disp_enable=disp_enable, nplc=nplc) + +# ============================================================================= +# 6. Measurement script +# ============================================================================= +myk2400.set_source(bias_source) +myk2400.set_output("ON") +data=myk2400.read_single() +t_data=time.time()-t_init +print("%s measured: %E %s"%(measurement_mode,data,units[measurement_mode])) +# ============================================================================= +# 7. Close connection +# ============================================================================= +myk2400.close_connection() + + +# ============================================================================= +# 8. Save data +# ============================================================================= +data_to_write=[t_data,data] +header="Time (s), %s (%s)"%(measurement_mode,units[measurement_mode]) +myk2400.write_in_file(file_path,data_to_write,header=header,date=True,overwrite=True) +myk2400.write_in_file(file_path,data_to_write,header=None,date=False,overwrite=False) diff --git a/equipment_control/example/single_equipment/k2450_script.py b/equipment_control/example/single_equipment/k2450_script.py new file mode 100644 index 0000000..e3aad27 --- /dev/null +++ b/equipment_control/example/single_equipment/k2450_script.py @@ -0,0 +1,71 @@ + + +# ============================================================================= +# 1. Import classes and modules +# ============================================================================= + +import sys +#sys.path.insert(1, '/path/to/application/app/folder') +sys.path.insert(1, 'D:/Roisin/Documents/chopes') + +import equipment_control.equipment as eq +import equipment_control.k2450 as k2450 +import time + +# ============================================================================= +# 2. List available connections (chopes use pyvisa package for communicate with most equipments) +# ============================================================================= +rm=eq.resource_manager() +list_connections= eq.available_connections() +print("Available connections: %s"%str(list_connections)) + +# ============================================================================= +# 3. Connection to the equipments +# ============================================================================= +myk2450=k2450.k2450("GPIB0::29::INSTR",timeout=5e3) + +# ============================================================================= +# 4. Measurement parameters +# ============================================================================= +units={"voltage":"V", "current":"A", "resistance":"Ohms"} + +source_mode = "voltage" +measurement_mode = "current" +compliance = 1e-6 +autozero = True +offset_compensation = True +nplc = 1 +digits = 6 +continuous_trigger = True +disp_enable = True +bias_source = 1 +file_path = 'temp.txt' +t_init=time.time() +# ============================================================================= +# 5. Initialization of the equipments +# ============================================================================= +myk2450.initialize(source_mode=source_mode, measurement_mode=measurement_mode, + compliance=compliance, autozero=autozero, offset_compensation=offset_compensation, + digits=digits,continuous_trigger=continuous_trigger,disp_enable=disp_enable, nplc=nplc) + +# ============================================================================= +# 6. Measurement script +# ============================================================================= +myk2450.set_source(bias_source) +myk2450.set_output("ON") +data=myk2450.read_single() +t_data=time.time()-t_init +print("%s measured: %E %s"%(measurement_mode,data,units[measurement_mode])) +# ============================================================================= +# 7. Close connection +# ============================================================================= +myk2450.close_connection() + + +# ============================================================================= +# 8. Save data +# ============================================================================= +data_to_write=[t_data,data] +header="Time (s), %s (%s)"%(measurement_mode,units[measurement_mode]) +myk2450.write_in_file(file_path,data_to_write,header=header,date=True,overwrite=True) +myk2450.write_in_file(file_path,data_to_write,header=None,date=False,overwrite=False) diff --git a/equipment_control/example/single_equipment/k4200_script.py b/equipment_control/example/single_equipment/k4200_script.py new file mode 100644 index 0000000..557ae5c --- /dev/null +++ b/equipment_control/example/single_equipment/k4200_script.py @@ -0,0 +1,79 @@ +# ============================================================================= +# 1. Import classes and modules +# ============================================================================= + +import sys +#sys.path.insert(1, '/path/to/application/app/folder') +sys.path.insert(1, 'D:/Roisin/Documents/chopes') + +import equipment_control.equipment as eq # Parent class that handle the connections with the equipments +import equipment_control.k4200 as k4200 # Child class that inherits from equipment parent class +import traceback # to write error message in try/except command +import datetime + +# ============================================================================= +# 2. List available connections (chopes use pyvisa package for communicate with most equipments) +# ============================================================================= +rm=eq.resource_manager() # you can use the function from equipment class or directly the pyvisa command rm = pyvisa.ResourceManager() +list_connections= eq.available_connections(rm=rm) # you can use the function from equipment class or directly the pyvisa command rm.list_resources() +print("-------------------------------------------------\n Available connections: %s"%str(list_connections)) + +# ============================================================================= +# 3. Connection to the equipments +# ============================================================================= +myK4200=k4200.k4200("GPIB0::17::INSTR",timeout=10e3) + +# ============================================================================= +# 4. Measurement parameters +# ============================================================================= +file_path='temp.txt' + +smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"voltage","SMU4":"voltage"} +smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"} +smu_master=1 +smu_bias={"SMU1":10,"SMU2":0,"SMU3":0,"SMU4":0} +smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6} +sweep_param={"start":0,"stop":1,"step":0.05} +sweep_type="linear" +integration_mode="IT1" +delay_time=0 +hold_time=0 + + +# ============================================================================= +# 5. Initialization of the equipments +# ============================================================================= + +print("-------------------------------------------------\n Starting initialisation ...", end='') + +myK4200.initialize(smu_type=smu_type,smu_used=smu_used,smu_master=smu_master,smu_bias=smu_bias, + smu_compliance=smu_compliance,sweep_param=sweep_param,sweep_type=sweep_type, + integration_mode=integration_mode,delay_time=delay_time,hold_time=hold_time) +print(" Done!") +# ============================================================================= +# 6. Measurement script +# ============================================================================= +print("-------------------------------------------------\n Starting measurement ...", end='') +try: + data,data_header=myK4200.launch_measurements() +except Exception: + traceback.print_exc() + myK4200.close_connection() +print(" Done!") + +# ============================================================================= +# 7. Close connection +# ============================================================================= +myK4200.close_connection() + +# ============================================================================= +# 8. Save data +# ============================================================================= +custom_header="IV results with K4200\n" + +print("-------------------------------------------------\n Print in file %s"%file_path) +print(" - Header:") +print(" # %s"%(datetime.datetime.now().strftime("%c"))) +for line in (custom_header+data_header).split('\n'): + print(" # "+line) +myK4200.write_in_file(file_path,data,overwrite=True,header=custom_header+data_header) diff --git a/equipment_control/example/single_equipment/temp.txt b/equipment_control/example/single_equipment/temp.txt new file mode 100644 index 0000000..ff70473 --- /dev/null +++ b/equipment_control/example/single_equipment/temp.txt @@ -0,0 +1,4 @@ +# Mon Mar 10 17:02:23 2025 +# Time (s), current (A) +-1.114205E+00,1.364986E-12 +-1.114205E+00,1.364986E-12 diff --git a/equipment_control/hp4145.py b/equipment_control/hp4145.py index baab7d6..de71eef 100644 --- a/equipment_control/hp4145.py +++ b/equipment_control/hp4145.py @@ -10,8 +10,9 @@ class hp4145(equipment.equipment): company="Keysight" url="https://www.keysight.com/dk/en/assets/9018-07935/service-manuals/9018-07935.pdf" - def initialize(self, mode="voltage sweep",number_channel=4,smu_bias={"SMU2":0,"SMU3":0,"SMU4":0}, - smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0}, + def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, + smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, + smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0},sweep_type="linear", integration_mode="IT1",delay_time=0,hold_time=0): @@ -19,8 +20,10 @@ class hp4145(equipment.equipment): mode: - "voltage sweep": voltage sweep with SMU1 and current measurements on all the SMUs """ - self.mode=mode - self.number_channel=number_channel + self.smu_type=smu_type + self.sweep_type=sweep_type + self.smu_used=smu_used + self.smu_master=smu_master self.sweep_param=sweep_param self.smu_compliance=smu_compliance self.smu_bias=smu_bias @@ -28,36 +31,60 @@ class hp4145(equipment.equipment): self.delay_time=delay_time self.hold_time=hold_time - # self.set_connection_parameter_dic({write_termination":'\r\n',"read_termination":'\r\n',"send_end":True}) + index_measurement_type={"sweep":1, "constant":3} + index_smu_type={"voltage":1, "current":2, "common":3} try: self.pyvisa_resource.write("BC") # clear all buffer. self.pyvisa_resource.write("DR1") # This command enables or disables service request for data ready when communications is set to GPIB. self.pyvisa_resource.write("EC 1") # This command sets the condition to exit the test if compliance is reached. - if mode =="voltage sweep": - self.length_data=int(abs((sweep_param["stop"]-sweep_param["start"])/sweep_param["step"])) - self.pyvisa_resource.write("DE") # DE: Accesses SMU channel definition page. + self.pyvisa_resource.write("DE") # DE: Accesses SMU channel definition page. + + self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', %d, %d"%(smu_master,smu_master,smu_master,index_smu_type[smu_type["SMU%d"%smu_master]],index_measurement_type["sweep"])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant + + for smu_index in range(4): + if (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="off": + self.pyvisa_resource.write("CH%d"%(smu_index+1)) + elif (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="on": + self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', %d, %d"%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type["SMU%d"%(smu_index+1)]],index_measurement_type["constant"])) - self.pyvisa_resource.write("CH1, 'V1', 'I1', 1, 1") # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant - - for i in range(number_channel-1): - self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', 1, 3"%(i+2,i+2,i+2)) + self.pyvisa_resource.write("SS")# Accesses source setup page + if smu_type["SMU%d"%smu_master]=="voltage": + if sweep_type=="linear": + self.pyvisa_resource.write("VR1, %.6E, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],smu_compliance["SMU%d"%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif sweep_type=="log": + self.pyvisa_resource.write("VR2, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],smu_compliance["SMU%d"%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance + elif smu_type["SMU%d"%smu_master]=="current": + if sweep_type=="linear": + self.pyvisa_resource.write("IR1, %.6E, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],smu_compliance["SMU%d"%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif sweep_type=="log": + self.pyvisa_resource.write("IR2, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],smu_compliance["SMU%d"%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance + + for smu_index in range(4): + if (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="on": + if smu_type["SMU%d"%(smu_index+1)]=="voltage": + self.pyvisa_resource.write("VC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) + elif smu_type["SMU%d"%(smu_index+1)]=="current": + self.pyvisa_resource.write("IC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) + time.sleep(20) + self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep + self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep. + self.pyvisa_resource.write(integration_mode) # integration time, IT1/IT2/IT3 : short/medium/long - self.pyvisa_resource.write("SS")# Accesses source setup page - self.pyvisa_resource.write("VR1, %s, %s, %s, %s"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],sweep_param["compliance"])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance - self.pyvisa_resource.write("VC2, %.2f, %s"%(smu_bias[0],smu_compliance[0])) - self.pyvisa_resource.write("VC3, %.2f, %s"%(smu_bias[1],smu_compliance[1])) - self.pyvisa_resource.write("VC4, %.2f, %s"%(smu_bias[2],smu_compliance[2])) + self.pyvisa_resource.write("SM") + self.pyvisa_resource.write("DM2") - self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep - self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep. - self.pyvisa_resource.write(integration_mode) # integration time, IT1/IT2/IT3 : short/medium/long - - self.pyvisa_resource.write("SM") - self.pyvisa_resource.write("DM2") - self.pyvisa_resource.write("LI 'I1','I2','I3','I4'") + list_display="" + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + list_display+=",'%s%d'"%("I",smu_index+1) + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + list_display+=",'%s%d'"%("V",smu_index+1) + + self.pyvisa_resource.write("LI %s"%list_display[1:]) # self.pyvisa_resource.write("DM1") # self.pyvisa_resource.write("XN 'V1', 1, %.1f, %.1f"%(v_sweep_param["start"],v_sweep_param["stop"])) # self.pyvisa_resource.write("YA 'I1',2, 1E-15, 1E-12") @@ -65,12 +92,15 @@ class hp4145(equipment.equipment): print("/!\ VisaIOError : timeout expired") self.pyvisa_resource.close() - return {"mode":mode, "number_channels":number_channel, "sweep_param":sweep_param} + return 42 - def launch_measurements(self): + def launch_measurements(self,activate_segmentation=True): - N_v=self.length_data - data={} + number_channel=0 + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + number_channel+=1 + if self.integration_mode=="IT1": Nmax=50 @@ -80,39 +110,80 @@ class hp4145(equipment.equipment): Nmax=10 - if self.mode=="voltage sweep": - v_list=np.round(np.arange(self.sweep_param["start"],self.sweep_param["stop"]+self.sweep_param["step"],self.sweep_param["step"]),6) + sweep_list=np.round(np.arange(self.sweep_param["start"],self.sweep_param["stop"]+self.sweep_param["step"],self.sweep_param["step"]),6) + N_v=len(sweep_list) + data=np.zeros((N_v,number_channel+1)) + data[:,0]=sweep_list + j=0 - data=np.zeros((N_v,self.number_channel)) - data[:,0]=v_list - + if activate_segmentation: iteration=int(N_v/Nmax)+1 index=0 - j=0 while iteration>0: - v_start=v_list[index] + sweep_start=sweep_list[index] if index+Nmax>N_v: - v_end=v_list[-1] + sweep_end=sweep_list[-1] else: - v_end=v_list[index+Nmax-1] - + sweep_end=sweep_list[index+Nmax-1] + + if self.smu_type["SMU%d"%self.smu_master]=="voltage": + if self.sweep_type=="linear": + self.pyvisa_resource.write("VR1, %.6E, %.6E, %.6E, %.6E"%(sweep_start,sweep_end,self.sweep_param["step"],self.smu_compliance["SMU%d"%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif self.smu_type["SMU%d"%self.smu_master]=="current": + if self.sweep_type=="linear": + self.pyvisa_resource.write("IR1, %.6E, %.6E, %.6E, %.6E"%(sweep_start,sweep_end,self.sweep_param["step"],self.smu_compliance["SMU%d"%self.smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + + self.pyvisa_resource.write("SS") + if self.smu_type["SMU%d"%(self.smu_master)]=="voltage": + self.pyvisa_resource.write("VR1, %.6E, %.6E, %.6E, %.6E"%(sweep_start,sweep_end,self.sweep_param["step"],self.smu_compliance["SMU%d"%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif self.smu_type["SMU%d"%(self.smu_master)]=="current": + self.pyvisa_resource.write("IR1, %.6E, %.6E, %.6E, %.6E"%(sweep_start,sweep_end,self.sweep_param["step"],self.smu_compliance["SMU%d"%self.smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + self.pyvisa_resource.write("MD") # This command controls measurements. self.pyvisa_resource.write("ME1") # Run a single trigger test and store readings in a cleared buffer: 1 - time.sleep(10) - - N=int(abs((v_end-v_start)/self.sweep_param["step"]))+1 - for i in range(self.number_channel): - data_list=self.pyvisa_resource.query("DO 'I%d'"%(i+1))# Read measurements - for data_i in data_list.split(","): - data[j,i+1]=float(data_i[1:]) - if i==0: + i=0 + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + i+=1 + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + data_list=self.pyvisa_resource.query("DO 'I%d'"%(smu_index+1))# Read measurements + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + data_list=self.pyvisa_resource.query("DO 'V%d'"%(smu_index+1))# Read measurements + j=0 + for data_i in data_list.split(","): + data[index+j,i]=float(data_i[1:]) j+=1 index+=Nmax iteration-=1 - j+=1 + else: - return data + self.pyvisa_resource.write("MD") # This command controls measurements. + self.pyvisa_resource.write("ME1") # Run a single trigger test and store readings in a cleared buffer: 1 + time.sleep(10) + i=0 + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + i+=1 + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + data_list=self.pyvisa_resource.query("DO 'I%d'"%(smu_index+1))# Read measurements + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + data_list=self.pyvisa_resource.query("DO 'V%d'"%(smu_index+1))# Read measurements + + j=0 + for data_j in data_list.split(","): + data[j,i]=float(data_j[1:]) + j+=1 + + + header="%s%d"%(self.smu_type["SMU%d"%self.smu_master][0].upper(),self.smu_master) + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + header+=", %s%d"%("I",smu_index+1) + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + header+=", %s%d"%("V",smu_index+1) + return data, header diff --git a/equipment_control/k2400.py b/equipment_control/k2400.py new file mode 100644 index 0000000..72d8b99 --- /dev/null +++ b/equipment_control/k2400.py @@ -0,0 +1,112 @@ +import equipment_control.equipment as equipment +import time +class k2400(equipment.equipment): + + """Class to control K2400 or k2450 SMU""" + model="K2400 or K2450" + company="Keithley" + url="https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510" + + + def initialize(self, source_mode,measurement_mode, compliance, autozero=True, offset_compensation=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): + + """ + source_mode: + - "voltage": voltage source + - "current": current source + measurement_mode: + - "voltage": voltage measurement + - "current": current measurement + - "resistance": resistance measurement + """ + mode_name={"voltage":"VOLT", "current":"CURR", "resistance":"RES"} + self.output_state="OFF" + self.pyvisa_resource.write("*RST") + self.source_mode=source_mode + self.continuous_trigger=continuous_trigger + + if source_mode=="voltage": + self.pyvisa_resource.write(":SOUR:FUNC VOLT") + self.pyvisa_resource.write(":SENS:CURR:PROT %E"%compliance) # set automatic range + + if source_mode=="current": + self.pyvisa_resource.write(":SOUR:FUNC CURR") + self.pyvisa_resource.write(":SENS:VOLT:PROT %E"%compliance) # set automatic range + + + + if measurement_mode=="voltage": + self.pyvisa_resource.write(":SENS:FUNC 'VOLT'") + self.pyvisa_resource.write(":SENS:VOLT:RANG:AUTO ON") # set automatic range + + elif measurement_mode=="current": + self.pyvisa_resource.write(":SENS:FUNC 'CURR'") + self.pyvisa_resource.write(":SENS:CURR:RANG:AUTO ON") # set automatic range + + elif measurement_mode=="resistance": + self.pyvisa_resource.write(":SENS:FUNC 'RES'") + self.pyvisa_resource.write(":SENS:RES:RANG:AUTO ON") # set automatic range + + + self.pyvisa_resource.write(":DISP:DIG %d"%digits) # Query largest allowable display resolutio + if disp_enable: + self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + else: + self.pyvisa_resource.write(":DISP:ENAB OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + + # self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering + + # if offset_compensation: + # self.pyvisa_resource.write(":SENS:FRES:OCOM ON") # enable offset compensation + # else: + # self.pyvisa_resource.write(":SENS:FRES:OCOM OFF") + + if autozero: + self.pyvisa_resource.write(":SYST:AZER:STAT ON") # enable auto-zero + else: + self.pyvisa_resource.write(":SYST:AZER:STAT OFF") + + + self.pyvisa_resource.write(":SENS:%s:NPLC %d"%(mode_name[measurement_mode],nplc)) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + self.pyvisa_resource.write(":FORM:ELEM %s"%mode_name[measurement_mode]) + + if continuous_trigger: + self.pyvisa_resource.write(":ARM:SOUR TIMer") + self.pyvisa_resource.write(":ARM:TIMer 0.001") + self.pyvisa_resource.write(":ARM:COUNT INF") + else: + self.pyvisa_resource.write(":ARM:SOUR IMMediate") + + def read_single(self): + self.pyvisa_resource.write(":OUTP ON") + + if self.continuous_trigger: + self.pyvisa_resource.write(":ABORt") + self.pyvisa_resource.write(":ARM:COUNT 1") + data=self.pyvisa_resource.query(":READ?") + self.pyvisa_resource.write(":ARM:COUNT INF") + self.pyvisa_resource.write(":INIT") + + else: + data=self.pyvisa_resource.query("READ?") + self.pyvisa_resource.write(":OUTP %s"%self.output_state) + + + return float(data) + + def set_source(self,value): + if self.source_mode=="current": + self.pyvisa_resource.write(":SOUR:CURR %.2E"%value) #set output voltage + elif self.source_mode=="voltage": + self.pyvisa_resource.write(":SOUR:VOLT %.2E"%value) #set output voltage + + + def set_output(self,output_state="ON"): + self.output_state=output_state + + self.pyvisa_resource.write(":OUTP %s"%output_state) + if self.continuous_trigger: + self.pyvisa_resource.write(":INIT") + + + diff --git a/equipment_control/k2450.py b/equipment_control/k2450.py new file mode 100644 index 0000000..ab1dedf --- /dev/null +++ b/equipment_control/k2450.py @@ -0,0 +1,101 @@ +import equipment_control.equipment as equipment +import time +class k2450(equipment.equipment): + + """Class to control k2450 SMU""" + model="K2400 or K2450" + company="Keithley" + url="https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510" + + + def initialize(self, source_mode,measurement_mode, compliance, autozero=True, offset_compensation=True, nplc=1,digits=6,continuous_trigger=False,disp_enable=True): + + """ + source_mode: + - "voltage": voltage source + - "current": current source + measurement_mode: + - "voltage": voltage measurement + - "current": current measurement + - "resistance": resistance measurement + """ + mode_name={"voltage":"VOLT", "current":"CURR", "resistance":"RES"} + self.output_state="OFF" + self.pyvisa_resource.write("*RST") + self.source_mode=source_mode + self.continuous_trigger=continuous_trigger + + if source_mode=="voltage": + self.pyvisa_resource.write(":SOUR:FUNC VOLT") + self.pyvisa_resource.write(":SOUR:VOLT:ILIM %E"%compliance) # set automatic range + + if source_mode=="current": + self.pyvisa_resource.write(":SOUR:FUNC CURR") + self.pyvisa_resource.write(":SOUR:CURR:VLIM %E"%compliance) # set automatic range + + + if measurement_mode=="voltage": + self.pyvisa_resource.write(":SENS:FUNC 'VOLT'") + self.pyvisa_resource.write(":SENS:VOLT:RANG:AUTO ON") # set automatic range + + elif measurement_mode=="current": + self.pyvisa_resource.write(":SENS:FUNC 'CURR'") + self.pyvisa_resource.write(":SENS:CURR:RANG:AUTO ON") # set automatic range + + elif measurement_mode=="resistance": + self.pyvisa_resource.write(":SENS:FUNC 'RES'") + self.pyvisa_resource.write(":SENS:RES:RANG:AUTO ON") # set automatic range + + + self.pyvisa_resource.write(":DISP:%s:DIG %d"%(mode_name[measurement_mode],digits)) + self.pyvisa_resource.write(":SENS:%s:NPLC %d"%(mode_name[measurement_mode],nplc)) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec + + if disp_enable: + self.pyvisa_resource.write(":DISP:LIGHT:STAT ON100") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + else: + self.pyvisa_resource.write(":DISP:LIGHT:STAT OFF") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. + + if autozero: + self.pyvisa_resource.write(":SENS:%s:AZER ON"%mode_name[measurement_mode]) # enable auto-zero + else: + self.pyvisa_resource.write(":SENS:%s:AZER OFF"%mode_name[measurement_mode]) + + + + if continuous_trigger: + self.pyvisa_resource.write(":TRIG:LOAD 'LoopUntilEvent', DISP, 0") # able continuous triggering + + else: + self.pyvisa_resource.write("TRIG:CONT OFF") + + + + def read_single(self): + self.pyvisa_resource.write(":OUTP ON") + + if self.continuous_trigger: + self.pyvisa_resource.write(":ABORt") # able continuous triggering + data=self.pyvisa_resource.query("MEAS?") + self.pyvisa_resource.write(":TRIG:LOAD 'LoopUntilEvent', DISP, 0") # able continuous triggering + self.pyvisa_resource.write(":INIT") # able continuous triggering + else: + data=self.pyvisa_resource.query("MEAS?") + self.pyvisa_resource.write(":OUTP %s"%self.output_state) + + return float(data) + + def set_source(self,value): + if self.source_mode=="current": + self.pyvisa_resource.write(":SOUR:CURR %E"%value) #set output voltage + elif self.source_mode=="voltage": + self.pyvisa_resource.write(":SOUR:VOLT %E"%value) #set output voltage + + + def set_output(self,output_state="ON"): + self.output_state=output_state + self.pyvisa_resource.write(":OUTP %s"%output_state) + if self.continuous_trigger: + self.pyvisa_resource.write(":INIT") + + + diff --git a/equipment_control/k24xx.py b/equipment_control/k24xx.py deleted file mode 100644 index ce91ad4..0000000 --- a/equipment_control/k24xx.py +++ /dev/null @@ -1,86 +0,0 @@ -import equipment_control.equipment as equipment - -class k24XX(equipment.equipment): - - """Class to control K2400 or k2450 SMU""" - model="K2400 or K2450" - company="Keithley" - url="https://www.tek.com/en/products/keithley/digital-multimeter/dmm7510" - - - def initialize(self, source_mode,measurement_mode, compliance, autozero=True, offset_compensation=True, nplc=1): - - """ - source_mode: - - "voltage": voltage source - - "current": current source - measurement_mode: - - "voltage": voltage measurement - - "current": current measurement - - "resistance": resistance measurement - - "4 wires": 4 wires measurement - """ - - self.pyvisa_resource.write("*RST") - self.source_mode=source_mode - - if source_mode=="voltage": - self.pyvisa_resource.write(":SOUR:FUNC 'VOLT'") - self.pyvisa_resource.write(":SOUR:CURR:VLIM %f"%compliance) # set automatic range - - if source_mode=="current": - self.pyvisa_resource.write(":SOUR:FUNC 'CURR'") - self.pyvisa_resource.write(":SOUR:VOLT:CLIM %f"%compliance) # set automatic range - - - - if measurement_mode=="voltage": - self.pyvisa_resource.write(":SENS:FUNC 'VOLT'") - self.pyvisa_resource.write(":SENS:VOLT:RANG:AUTO ON") # set automatic range - - elif measurement_mode=="current": - self.pyvisa_resource.write(":SENS:FUNC 'CURR'") - self.pyvisa_resource.write(":SENS:CURR:RANG:AUTO ON") # set automatic range - - elif measurement_mode=="resistance": - self.pyvisa_resource.write(":SENS:FUNC 'RES'") - self.pyvisa_resource.write(":SENS:RES:RANG:AUTO ON") # set automatic range - - elif measurement_mode=="4 wires": - self.pyvisa_resource.write(":SENS:FUNC 'FRES'") - self.pyvisa_resource.write(":SENS:FRES:RANG:AUTO ON") # set automatic range - - - - self.pyvisa_resource.write(":DISP:DIG MAX") # Query largest allowable display resolutio - self.pyvisa_resource.write(":DISP:ENAB ON") # This command is used to enable and disable the front panel display circuitry. When disabled, the instrument operates at a higher speed. - self.pyvisa_resource.write("INIT:CONT ON") # able continuous triggering - - if offset_compensation: - self.pyvisa_resource.write(":SENS:FRES:OCOM ON") # enable offset compensation - else: - self.pyvisa_resource.write(":SENS:FRES:OCOM OFF") - - if autozero: - self.pyvisa_resource.write(":SENS:FRES:AZER ON") # enable auto-zero - else: - self.pyvisa_resource.write(":SENS:FRES:AZER OFF") - - self.pyvisa_resource.write(":SENS:FRES:NPLC %.1f"%nplc) # set NPLC. For a PLC of 1, the integration period would be 1/50 (for 50Hz line power) which is 20 msec - - - def read_single(self): - data=self.pyvisa_resource.query("READ?") - return float(data) - - def set_source(self,value): - if self.source_mode=="current": - self.pyvisa_resource.write(":SOUR:CURR %.2E"%value) #set output voltage - elif self.source_mode=="voltage": - self.pyvisa_resource.write(":SOUR:VOLT %.2E"%value) #set output voltage - - - def set_output(self,output_state="ON"): - self.pyvisa_resource.write(":OUTP %s"%output_state) - - diff --git a/equipment_control/k4200.py b/equipment_control/k4200.py index 72aaf7a..76c251c 100644 --- a/equipment_control/k4200.py +++ b/equipment_control/k4200.py @@ -10,8 +10,9 @@ class k4200(equipment.equipment): company="Keysight" url="https://www.tek.com/en/products/keithley/4200a-scs-parameter-analyzer" - def initialize(self, mode="voltage sweep",number_channel=4,smu_bias={"SMU2":0,"SMU3":0,"SMU4":0}, - smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0}, + def initialize(self, smu_type={"SMU1":"voltage","SMU2":"voltage","SMU3":"common","SMU4":"common"}, smu_used={"SMU1":"on","SMU2":"on","SMU3":"on","SMU4":"on"}, + smu_master=1,smu_bias={"SMU1":0,"SMU2":0,"SMU3":0,"SMU4":0}, + smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0},sweep_type="linear", integration_mode="IT1",delay_time=0,hold_time=0): @@ -19,8 +20,10 @@ class k4200(equipment.equipment): mode: - "voltage sweep": voltage sweep with SMU1 and current measurements on all the SMUs """ - self.mode=mode - self.number_channel=number_channel + self.smu_type=smu_type + self.sweep_type=sweep_type + self.smu_used=smu_used + self.smu_master=smu_master self.sweep_param=sweep_param self.smu_compliance=smu_compliance self.smu_bias=smu_bias @@ -28,69 +31,119 @@ class k4200(equipment.equipment): self.delay_time=delay_time self.hold_time=hold_time - self.set_connection_parameter_dic({"write_termination":'\r\n',"read_termination":'\r\n',"send_end":True}) + index_measurement_type={"sweep":1, "constant":3} + index_smu_type={"voltage":1, "current":2, "common":3} try: self.pyvisa_resource.write("BC") # clear all buffer. self.pyvisa_resource.write("DR1") # This command enables or disables service request for data ready when communications is set to GPIB. self.pyvisa_resource.write("EC 1") # This command sets the condition to exit the test if compliance is reached. - if mode =="voltage sweep": - self.length_data=int(abs((sweep_param["stop"]-sweep_param["start"])/sweep_param["step"])) - self.pyvisa_resource.write("DE") # DE: Accesses SMU channel definition page. - - self.pyvisa_resource.write("CH1, 'V1', 'I1', 1, 1") # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant - - for i in range(number_channel-1): - self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', 1, 3"%(i+2,i+2,i+2)) + self.pyvisa_resource.write("DE") # DE: Accesses SMU channel definition page. + + self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', %d, %d"%(smu_master,smu_master,smu_master,index_smu_type[smu_type["SMU%d"%smu_master]],index_measurement_type["sweep"])) # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant + + for smu_index in range(4): + if (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="off": + self.pyvisa_resource.write("CH%d"%(smu_index+1)) + elif (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="on": + self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', %d, %d"%(smu_index+1,smu_index+1,smu_index+1,index_smu_type[smu_type["SMU%d"%(smu_index+1)]],index_measurement_type["constant"])) - self.pyvisa_resource.write("SS")# Accesses source setup page - self.pyvisa_resource.write("VR1, %s, %s, %s, %s"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],sweep_param["compliance"])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance - self.pyvisa_resource.write("VC2, %.2f, %s"%(smu_bias[0],smu_compliance[0])) - self.pyvisa_resource.write("VC3, %.2f, %s"%(smu_bias[1],smu_compliance[1])) - self.pyvisa_resource.write("VC4, %.2f, %s"%(smu_bias[2],smu_compliance[2])) + self.pyvisa_resource.write("SS")# Accesses source setup page + if smu_type["SMU%d"%smu_master]=="voltage": + if sweep_type=="linear": + self.pyvisa_resource.write("VR1, %.6E, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],smu_compliance["SMU%d"%smu_master])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif sweep_type=="log": + self.pyvisa_resource.write("VR2, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],smu_compliance["SMU%d"%smu_master])) # VR2 for log sweep of VAR1 source function, vmin, vmax, compliance + elif smu_type["SMU%d"%smu_master]=="current": + if sweep_type=="linear": + self.pyvisa_resource.write("IR1, %.6E, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],smu_compliance["SMU%d"%smu_master])) # IR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance + elif sweep_type=="log": + self.pyvisa_resource.write("IR2, %.6E, %.6E, %.6E"%(sweep_param["start"],sweep_param["stop"],smu_compliance["SMU%d"%smu_master])) # IR2 for log sweep of VAR1 source function, vmin, vmax, compliance - self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep - self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep. - self.pyvisa_resource.write(integration_mode) # integration time, IT1/IT2/IT3 : short/medium/long + for smu_index in range(4): + if (smu_index+1!=smu_master) and smu_used["SMU%d"%(smu_index+1)]=="on": + if smu_type["SMU%d"%(smu_index+1)]=="voltage": + self.pyvisa_resource.write("VC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) + elif smu_type["SMU%d"%(smu_index+1)]=="current": + self.pyvisa_resource.write("IC%d, %.2f, %.6E"%(smu_index+1,smu_bias["SMU%d"%(smu_index+1)],smu_compliance["SMU%d"%(smu_index+1)])) - self.pyvisa_resource.write("RS 7") # This command sets the measurement resolution for all channels of a SM in number of bits - self.pyvisa_resource.write("RG 1, 10E-12") # This command sets the measurement resolution for all channels of a SM in number of bits - self.pyvisa_resource.write("RG 2, 10E-12") # This command sets the lowest current range of the SMU to be used when measuring. - - self.pyvisa_resource.write("SM") - self.pyvisa_resource.write("DM2") - self.pyvisa_resource.write("LI 'I1','I2','I3','I4'") + self.pyvisa_resource.write("RS 7") # This command sets the measurement resolution for all channels of a SM in number of bits + self.pyvisa_resource.write("RG 1, 10E-12") # This command sets the measurement resolution for all channels of a SM in number of bits + self.pyvisa_resource.write("RG 2, 10E-12") # This command sets the lowest current range of the SMU to be used when measuring. + +# ============================================================================= +# self.pyvisa_resource.write("SM") +# self.pyvisa_resource.write("DM1") +# self.pyvisa_resource.write("XN '%s%d', 1, %.1f, %.1f"%(smu_type["SMU%d"%smu_master][0].upper(),smu_master,sweep_param["start"],sweep_param["stop"])) +# +# list_display="" +# for smu_index in range(4): +# if self.smu_used["SMU%d"%(smu_index+1)]=="on": +# if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": +# self.pyvisa_resource.write("YA '%s%d', 3, 1e-15, 1e-6"%("I",smu_index+1)) +# elif self.smu_type["SMU%d"%(smu_index+1)]=="current": +# self.pyvisa_resource.write("YA '%s%d', 3, 1e-15, 1e-6"%("V",smu_index+1)) +# ============================================================================= + self.pyvisa_resource.write("SM") + self.pyvisa_resource.write("DM2") + list_display="" + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + list_display+=",'%s%d'"%("I",smu_index+1) + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + list_display+=",'%s%d'"%("V",smu_index+1) + + self.pyvisa_resource.write("LI %s"%list_display[1:]) except pyvisa.VisaIOError: print("/!\ VisaIOError : timeout expired") self.pyvisa_resource.close() - return {"mode":mode, "number_channels":number_channel, "sweep_param":sweep_param} + return 42 def launch_measurements(self): + number_channel=0 + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + number_channel+=1 + sweep_list=np.round(np.arange(self.sweep_param["start"],self.sweep_param["stop"]+self.sweep_param["step"],self.sweep_param["step"]),6) + N_sweep=len(sweep_list) + data=np.zeros((N_sweep,number_channel+1)) + data[:,0]=sweep_list + + self.pyvisa_resource.write("MD") # This command controls measurements. self.pyvisa_resource.write("ME1") # Run a single trigger test and store readings in a cleared buffer: 1 - time.sleep(10) - N=self.length_data - - if self.mode=="voltage sweep": - v_list=np.round(np.arange(self.sweep_param["start"],self.sweep_param["stop"]+self.sweep_param["step"],self.sweep_param["step"]),6) - - data=np.zeros((N,self.number_channel)) - data[:,0]=v_list - - count=0 - while (count<N): - data_ch1=np.float32(self.pyvisa_resource.query("RD 'I1', %d"%(count+1))) - if (data_ch1!=0.): - data[count,1]=data_ch1 - for i in range(self.number_channel-1): - data[count,i+2]=np.float32(self.pyvisa_resource.query("RD 'I%d', %d"%(i+2,count+1))) - count+=1 - time.sleep(0.1) - return data + time.sleep(1) + j=0 + while (j<N_sweep): + if self.smu_type["SMU%d"%(self.smu_master)]=="voltage": + data_master=np.float32(self.pyvisa_resource.query("RD 'I%d', %d"%(self.smu_master,j+1))) + elif self.smu_type["SMU%d"%(self.smu_master)]=="current": + data_master=np.float32(self.pyvisa_resource.query("RD 'V%d', %d"%(self.smu_master,j+1))) + if (data_master!=0.): + i=0 + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + i+=1 + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + data[j,i]=np.float32(self.pyvisa_resource.query("RD 'I%d', %d"%(smu_index+1,j+1)))# Read measurements + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + data[j,i]=np.float32(self.pyvisa_resource.query("RD 'V%d', %d"%(smu_index+1,j+1)))# Read measurements + + j+=1 + time.sleep(0.1) + header="%s%d"%(self.smu_type["SMU%d"%self.smu_master][0].upper(),self.smu_master) + for smu_index in range(4): + if self.smu_used["SMU%d"%(smu_index+1)]=="on": + if self.smu_type["SMU%d"%(smu_index+1)]=="voltage": + header+=", %s%d"%("I",smu_index+1) + elif self.smu_type["SMU%d"%(smu_index+1)]=="current": + header+=", %s%d"%("V",smu_index+1) + return data, header \ No newline at end of file diff --git a/equipment_control/kal100.py b/equipment_control/kal100.py new file mode 100644 index 0000000..d865a49 --- /dev/null +++ b/equipment_control/kal100.py @@ -0,0 +1,51 @@ +import equipment_control.equipment as equipment +import time +import serial + +class kal100(equipment.equipment): + + """Class to control KAL100 pressure system""" + model="KAL100" + company="halstrup-walcher" + url="https://www.halstrup-walcher.de/en/products/KAL100.php" + + units_dic={"kPa":0,"Pa":1,"hPa":0} + def __init__(self,port): + self.serial_resource = serial.Serial( + port=port, + baudrate=9600, + parity=serial.PARITY_NONE, + stopbits=serial.STOPBITS_ONE, + bytesize=serial.EIGHTBITS + ) + + def initialize(self,units="kPa",percentage=100, mode_operation="MS", mode_input="MI0"): + + self.serial_resource.write(">PD%d"%self.units_dic[units]) + time.sleep(1) + self.serial_resource.write(">PP%d"%percentage) # always 100% of the target + time.sleep(1) + + self.serial_resource.write("%s"%mode_input) # MI0: Positive P-input, MI1: Negative P-input, MI2: Differential pressure measurement + time.sleep(1) + + self.serial_resource.write("MZ") # mode zeroing + time.sleep(1) + self.serial_resource.write("%s"%mode_operation) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + time.sleep(1) + + if mode_operation=="MS": + self.serial_resource.write("PS%3.5f"%0) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + time.sleep(1) + + def set_pressure(self,pressure, units="kPa"): + self.serial_resource.write("MS") + time.sleep(1) + self.serial_resource.write(">PD%d"%self.units_dic[units]) + time.sleep(1) + self.serial_resource.write("PS%3.5f"%0) #MT: mode test, MZ: mode zeroing, MS: mode target value, MS: mode pressure measurement, + time.sleep(1) + + def close_connection(self): + self.serial_resource.close() + -- GitLab