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