#%TITLE% LAKESHORE#$)_ADDONDS.MAC - addtional functions for Lakeshore 340 temperature controller
#%UU% [percentage]
#%MDESC% Without argument, reads and prints the manual heater output value. With argument, sets the manual heater output to the specified value
def lsmout '{
local reply,heater,flag
flag = 0
if($# == 0){
# Display
reply = _ls_read_mout()
if(reply=="LSREADERROR"){
printf("Error reading lakeshore\n")
exit
}
printf("Manual heater output is %5.2f\n",reply)
flag = 1
}
if($# == 1){
# Set
if (($1<0) || ($1>100)) {
print "manual heater output can be in range 0 to 100 only."
exit
}
reply = _ls_set_mout("$1")
if(reply=="LSREADERROR"){
printf("Error reading lakeshore\n")
exit
}
comment "Lakeshore manual heater output set to %5.2f" reply
flag=1
}
if(flag==0){
printf("Syntax : lsmout [<range>]\n")
exit
}
}'
#%IU% ()
#%MDESC% Read and return the manual heater output.
def _ls_read_mout() '{
local rtn
rtn = _ls_read("MOUT? 1")
return rtn
}'
#%IU% (percentage)
#%MDESC% Set heater 1 to specified percentage.
def _ls_set_mout(percentage) '{
local rtn
rtn = _ls_send(sprintf("MOUT 1,%f",percentage))
if(rtn=="LSREADERROR")
return rtn
rtn = _ls_read_mout()
return rtn
}'
#%UU%
#%MDESC% Read and display the total heater output (PID + manual offset)
def lshtr '{
local reply, flag
flag = 0
if($# == 0){
# Display
reply = _ls_read_htr()
if(reply=="LSREADERROR"){
printf("Error reading lakeshore\n")
exit
}
printf("Total heater output is %5.2f\n",reply)
flag = 1
}
if(flag==0){
printf("Syntax : lshtr \n")
exit
}
}'
#%IU% ()
#%MDESC% Read and return the total heater output (PID+manual offset)
def _ls_read_htr() '{
local rtn
rtn = _ls_read("HTR?")
return rtn
}'
def lspower '{
local loopnr htrrange
if ($#==0) {loopnr=1}
else {loopnr=$1}
htrrange=_ls_read_heater()
printf("%.2f percent heater power (incl. %.2f percent manual) of heater range %d.\n",_ls_read_htr(), _ls_read_mout(),htrrange)
reply=_ls_read(sprintf("CDISP? %d",loopnr))
replyitems=split(reply,myparts,",")
storedR=__lsRvalue(myparts[1])
printf("Stored heater resistance is %d Ohm.\n",storedR)
reply=_ls_read(sprintf("CLIMIT? %d",loopnr))
replyitems=split(reply,myparts,",")
curval=myparts[3]*1
if (curval==1) {max_curr=0.25}
else if (curval==2) {max_curr=0.5}
else if (curval==3) {max_curr=1}
else if (curval==4) {max_curr=2}
else {
reply=_ls_read("CLIMI?")
max_curr=reply*1.0
}
printf("Maximal heater current is set to %.2f A (for heater range 5, less in the other ranges).\n",max_curr)
if (htrrange!=5) {
if (htrrange==4) {reducedmax=maxcurr/sqrt(10)}
else if (htrrange==4) {reducedmax=maxcurr/sqrt(10)}
else if (htrrange==3) {reducedmax=maxcurr/10}
else if (htrrange==2) {reducedmax=maxcurr/10/sqrt(10)}
else if (htrrange==1) {reducedmax=maxcurr/100}
printf("Now, with heater range %d, the maximum current is %.2f\n",htrrange,reducedmax)
}
else {reducedmax=max_curr}
max_power=reducedmax*reducedmax*storedR
curr_power=max_power*_ls_read_htr()/100.0
printf("Current power thus %f Watt. Maximum at 100 percent: %f Watt.\n",curr_power,max_power)
}'
def ls_cset '{
local reply, inputchan,unitdigit,powerstate,powerupenable,loopnr
local flag
flag=0
if ($#==0) {
flag=1
print "Loop 1:"
reply=_ls_read("CSET? 1")
print reply
print "Loop 2:"
reply=_ls_read("CSET? 2")
print reply
}
else if ($#==1) {
if (($1==1) || ($1==2)) {
print "Loop ",$1,":"
reply=_ls_read(sprintf("CSET? %d",$1))
print reply
flag=1
}
}
else if ($#==5){
flag=1
if (($1==1) || ($1==2)) {loopnr=$1}
else {flag=0}
if (($2=="B") || ($2=="A")) {inputchan="$2"}
else {flag=0}
if (($3>=1) && ($3<=3)) {unitdigit=$3}
else if ("$3"=="K") {unitdigit=1}
else if ("$3"=="C") {unitdigit=2}
else if ("$3"=="Ohm") {unitdigit=3}
else if ("$3"=="Sensor") {unitdigit=3}
else {flag=0}
if (("$4"=="on") || ("$4"=="ON")) {powerstate=1}
else if (("$4"=="off") || ("$4"=="OFF")) {powerstate=0}
else if (($4==0) || ($4==1)) {powerstate=$4}
else {flag=0}
if (("$5"=="on") || ("$5"=="ON")) {powerupenable=1}
else if (("$5"=="off") || ("$5"=="OFF")) {powerupenable=0}
else if (($5==0) || ($5==1)) {powerupenable=$5}
else {flag=0}
if (flag==1) {
cmdstr=sprintf("CSET %d,%s,%d,%d,%d",loopnr,inputchan,unitdigit,powerstate,powerupenable)
_ls_send(cmdstr)
print "Loop ",$1,":"
reply=_ls_read(sprintf("CSET? %d",$1))
print reply
}
}
if (flag==0) {
print "Usage is: ls_cset [control_loop] to query the control loop parameters."
print "or: ls_cset control_loop input_channel unit on/off power_up_enable"
}
}'
def __lsRvalue(rstr) '{
local ii startdigit
for (ii=1;ii<=3;ii++){
if (substr(rstr,ii,1)=="0") {
startdigit=ii+1
}
}
return 1.0*substr(rstr,startdigit)
}'
def ls_heaterresistance '{
local reply, replyitmes, myparts
flag=0
if ($#==0) {
flag=1
print "Loop 1:"
reply=_ls_read("CDISP? 1")
replyitems=split(reply,myparts,",")
print "Heater resistance is ",__lsRvalue(myparts[1])
print "Loop 2:"
reply=_ls_read("CDISP? 2")
replyitems=split(reply,myparts,",")
print "Heater resistance is ",__lsRvalue(myparts[1])
}
else if ($#==1) {
if (($1==1) || ($1==2)) {
print "Loop ",$1,":"
reply=_ls_read(sprintf("CDISP? %d",$1))
print reply
replyitems=split(reply,myparts,",")
print myparts
print myparts[1]
print "Heater resistance is ",__lsRvalue(myparts[1])
flag=1
}
}
else if ($#==2) {
if (($1==1) || ($1==2)) {
print "Loop ",$1,":"
reply=_ls_read(sprintf("CDISP? %d",$1))
replyitems=split(reply,myparts,",")
print "Current heater resistance is ",__lsRvalue(myparts[1])
if (($2>0) && ($2<9999)) {
myparts[1]=sprintf("%d",int($2+0.5))
answer=""
for (ii=0;ii<replyitems;ii++) {
answer=sprintf("%s,%s",answer,myparts[ii])
}
answer=sprintf("CDISP %d%s\n",$1,answer)
_ls_send(answer)
sleep(.1)
reply=_ls_read(sprintf("CDISP? %d",$1))
replyitems=split(reply,myparts,",")
print "Now heater resistance is ",__lsRvalue(myparts[1])
flag=1
}
}
}
# if (flag==0) {
# printf("Usage is: %s [loopnr [resistance in Ohm]]\n",$0)
# printf(" eg: %s 1 25 \n",$0)
# }
}'
#%IU%
#%MDESC% Switch from PID to open loop control, keeping the heater output constant. Old version, which does stays in PID mode, but with P=I=D=0. Obsolete.
def lsfreezeold '{
local heaterout manualout
global LSHTR LSMOUT LSP LSI LSD
heaterout=_ls_read_htr()
LSHTR=heaterout
printf("heater was at %5.2f percent power.\n",heaterout)
manualout=_ls_read_mout()
LSMOUT=manualout
printf("the manual output was at %5.2f percent power.\n",manualout)
print "change temporarily PID values to P=0, I=0, D=0, but remember the old ones."
reply=_ls_read_pid(LS_LOOP)
LSP=reply[0]
LSI=reply[1]
LSD=reply[2]
lspid 0 0 0
eval(sprintf("lsmout %f \n",heaterout))
printf("The manual output is set to %5.2f percent power \n.",heaterout)
print "LAkeshore is no more regulating, just delivering constant heater power."
print "Previuous heater outputs and PID values are stored in variables"
print "LSP, LSI, LSD, LSHTR and LSMOUT"
print "type \'lsunfreeze\' to recover regulation"
}'
#%IU%
#%MDESC% Switch back from open loop to PID control. Old version that recovers PID from above. Obsolete.
def lsunfreezeold '{
eval(sprintf("lsmout %f \n",LSMOUT))
lspid LSP LSI LSD
printf("PID values back to %d %d %d .\n",LSP,LSI,LSD)
printf("Manual output back to %5.2f percent.\n",LSMOUT)
}'
#UU% <counter_mne>
#%MDESC% Defines <counter_mne> as pseudo-counter for the heater output in Watts.
def ls_heaterctr_setup '{
if ($# != 1 ) {
print "Usage: ls_heaterctr_setup watt_ctr"
exit
}
watt_num = cnt_num("$1")
if (watt_num == -1) {
print "Check counter for power calculations. Must be defined in config"
exit
}
cdef("user_getcounts",sprintf("ls_heaterctr_getpos %d \n", watt_num), "$1", 0x22)
}'
#%IU%
#%MDESC% Macro that actually makes the calculation of the power
def ls_heaterctr_getpos '{
local htrrange maxcurr maxpower
htrrange=_ls_read_heater()
if (htrrange==0) {maxcurr=0}
if (htrrange==1) {maxcurr=0.0025}
if (htrrange==2) {maxcurr=0.0079}
if (htrrange==3) {maxcurr=0.025}
if (htrrange==4) {maxcurr=0.079}
if (htrrange==5) {maxcurr=0.25}
maxpower=maxcurr*maxcurr*83 #P=U*I and U+R*I makes P=R*I^2
S[$1] = _ls_read_htr()/100*maxpower
}'
#%UU%
#%MDESC% Switch from PID control to open loop, keeping the heater power constant. New version.
def lsfreeze '{
local heaterout manualout
global LSHTR LSMOUT LSRANGE
heaterout=_ls_read_htr()
LSHTR=heaterout
manualout=_ls_read_mout()
LSMOUT=manualout
LSRANGE=_ls_read_heater()
lsmode 3
eval(sprintf("lsmout %f \n",heaterout))
if (_ls_read_heater()==0) {eval(sprintf("lsheater %f \n",LSRANGE));print "reput heater range to " LSRANGE}
#printf("The manual output is set to %5.2f percent power in open loop\n.",heaterout)
}'
#%UU%
#%MDESC% Switch back from open loop to PID control. New version.
def lsunfreeze '{
if (_ls_read_heater()==0) {eval(sprintf("lsheater %f \n",LSRANGE));print "Occurance 5: reput heater range to " LSRANGE}
lsmode 1
eval(sprintf("lsmout %f \n",LSMOUT))
if (_ls_read_heater()==0) {eval(sprintf("lsheater %f \n",LSRANGE));print "Occurance 6: reput heater range to " LSRANGE}
#printf("Manual PID again with manual output back to %5.2f percent.\n",LSMOUT)
}'
#%UU% <target temperature> <error margin> <time window>
#%MDESC% Waits until the sample temperature is within <target_temperature> +/- <error margin> for <time window>.
def lswaitT '{
local actT finalT errormargin stabletime t0
if ($#!=3){
print" Usage is \'lswaitT finalT[K] errormargin[K] stabletime[sec]\' "
exit
}
if (($1>=4) && ($1<=350)) {finalT=$1}
else {
print" Usage is \'lswaitT finalT errormargin stabletime\' "
print" finalT must be in range 4 to 350."
exit
}
if (($2>=0.001) && ($2<=50)) {errormargin=$2}
else{
print" Usage is \'lswaitT finalT errormargin stabletime\' "
print" errormargin must be in range 0.001 to 50."
exit
}
if (($3>=1) && ($3<=3600)) {stabletime=$3}
else{
print" Usage is \'lswaitT finalT errormargin stabletime\' "
print" stabletimen must be in range 1 to 3600."
exit
}
t0 = -1;
while(1) {
actT=_ls_readsensor_k(0)
printf("Current T is %6.3f K. ",actT)
if (fabs(actT-finalT)>=errormargin){t0=-1; printf("error is %6.3f K. ",actT-finalT)}
else if (t0==-1) {t0=time()}
else if (time()-t0>stabletime) {break}
else {printf("Stable in between error for %4.1f seconds.",time()-t0)}
printf("\r");sleep(1);
}
printf("...temperature is stable. \n");
}'
#%UU%
#%MDESC% Reads a calibration curve from the controllers memory.
def lsreadcurve '{
local ii curve_num dummy header
if ($#!=1){
print "Usage is: lsreadcurve <curve number>"
exit
}
curve_num=$1
dummy=sprintf("CRVHDR? %d",curve_num)
header=_ls_read(dummy)
print header
if (split(ans, curve, ",") != 5) {
eprint "Funny answer from controller for curve", crv "."
}
for(ii=1;ii<=300;ii++){
dummy=sprintf("CRVPT? %d,%d",curve_num,ii);
printf("%3d: ",ii)
print _ls_read(dummy)
}
}'
#%UU%
#%MDESC% Communicates a calibration curve to the controller.This version is based on the lakeshore340.mac
#%version, but features some improvements. Especially, deleting the previously stored curve, which is important
#%At ID06, all curves should be stored in the /data/id06/inhouse/lakeshore directory.
#%if the new curve has less data points.
def lswritecurve '{
local i, j, ii, dummy, crv, fname
local curve[], textline, field[], ans
if ($# == 0) {
print "Use macro lslistallcurves to get a list of already stored curves!"
crv = getval("Number of curve to be written?",21)
print "At ID06, many curves are at /data/id06/inhouse/lakeshore ."
printf("Current directory is: ");unix("pwd")
fname = getval("Filename of temperature curve?","X12379.340")
}
else if ($# == 2) {
crv = $2
fname = "$1"
}
else {
print "Please give two or no args"
exit
}
if ( (crv < 21) || (crv > 60)) {
print "Curve number out of range."
print "Only curves 21 to 60 may be written by the user."
exit
}
if (!file_info(fname)) {
print "File: ",fname,"does not exist!"
exit
}
print "It seems better to delete previous curve now. Deleting curve ",crv
dummy=sprintf("CRVDEL %d",crv)
print _ls_send(dummy)
# this reads the existing entry
{
local ans
curve_units[1] = "mV/K"
curve_units[2] = "V/K"
curve_units[3] = "Ohm/K"
curve_units[4] = "log(Ohm)/K"
curve_units[5] = "log(Ohm)/log(K)"
curve_coeff[1] = "negative"
curve_coeff[2] = "positive"
fmt = "%2s %-15s %-10s %-10s %-10s %-10s\n"
print "Readings from actual curve", crv, "in LakeShore 340 :"
ans = _ls_read(sprintf("CRVHDR? %d",crv))
if(ans == "LSREADERROR"){
eprint "Error reading curve header", crv
exit
}
if (split(ans, curve, ",") != 5) {
eprint "Funny answer from controller for curve", crv "."
exit
}
printf(fmt, "", curve[0], curve[1], curve_units[curve[2]], \
curve[3], curve_coeff[curve[4]])
}
# scan in the informations from the head of the .340 file.
print "reading header of data file"
{
local stype, sernum, dfmt, sp_lim, coeff, npts
dfmt = sp_lim = coeff = npts = -1
open(fname)
i = 0
textline = getline(fname, 0)
while(1) {
if (split(textline, field, ":") == 1) break # no : stop!
# treat contents here, is that a new yacc :-)
if (field[0] == "Sensor Model") sscanf(field[1], "%s", stype)
if (field[0] == "Serial Number") sscanf(field[1], "%s", sernum)
if (field[0] == "Data Format") sscanf(field[1], "%d", dfmt)
if (field[0] == "SetPoint Limit") sscanf(field[1], "%f", sp_lim)
if (field[0] == "Temperature coefficient") sscanf(field[1], "%d", coeff)
if (field[0] == "Number of Breakpoints") sscanf(field[1], "%d", npts)
textline = getline(fname)
}
# Some input checking on Rudolfs request
if (stype == "") {
eprint "Data file", fname, "does not have expected line for \"Sensor Model\"!"
eprint "Aborted !"
exit
} else if (sernum == "") {
eprint "Data file", fname, "does not have expected line for \"Serial Number\"!"
eprint "Aborted !"
exit
} else if (dfmt == -1) {
eprint "Data file", fname, "does not have expected line for \"Data Format\"!"
eprint "Aborted !"
exit
} else if (sp_lim == -1) {
eprint "Data file", fname, "does not have expected line for \"SetPoint Limit\"!"
eprint "Aborted !"
exit
} else if (coeff == -1) {
eprint "Data file", fname, "does not have expected line for \"Temperature coefficient\"!"
eprint "Aborted !"
exit
}
dummy = sprintf("CRVHDR %d,%s,%s,%d,%f,%d\r\n", crv, stype,\
sernum, dfmt, sp_lim, coeff)
print "...sending command:", dummy
ans = _ls_send(dummy)
if(ans != "LSOK"){
eprint "Error listing curve number ", crv "."
exit
}
}
# Well now, to enable for Rudolf to add a header to a simple 2-column file, we have
# to juggle with sscanf.
{
local loop, ii, valunits, val_temp
loop = 1 # index of point, valid entries 1 - 200
while((textline = getline(fname)) != -1) {
if (sscanf(textline, "%d %g %g", ii, valunits, val_temp) == 3) {
if (ii == 0 && valunits == 0 && val_temp == 0)
continue
} else if (sscanf(textline, "%g %g", valunits, val_temp) == 2) {
if (valunits == 0 && val_temp == 0)
continue
} else {
continue # thats probably a text line. just forget
}
dummy = sprintf("CRVPT %d,%d,%1.5f,%3.3f\r\n", crv, loop, valunits, val_temp)
ans = _ls_send(dummy)
if(ans != "LSOK"){
eprint "Error listing curve number ", crv "."
exit
}
print dummy
printf(".")
loop ++
}
print
print "...sent ", loop-1, " data points"
}
close(fname)
print
print "Curve", crv, "was written to the LakeShore model 340 temperature controller."; print
# this reads the new entry
{
local ans
curve_units[1] = "mV/K"
curve_units[2] = "V/K"
curve_units[3] = "Ohm/K"
curve_units[4] = "log(Ohm)/K"
curve_units[5] = "log(Ohm)/log(K)"
curve_coeff[1] = "negative"
curve_coeff[2] = "positive"
fmt = "%2s %-15s %-10s %-10s %-10s %-10s\n"
print "Readings from actual curve", crv, " in LakeShore 340 :"
ans = _ls_read(sprintf("CRVHDR? %d",crv))
if(ans == "LSREADERROR"){
eprint "Error reading curve header", crv
exit
}
if (split(ans, curve, ",") != 5) {
eprint "Funny answer from controller for curve", crv "."
exit
}
printf(fmt, "", curve[0], curve[1], curve_units[curve[2]], \
curve[3], curve_coeff[curve[4]])
}
print "The curve will now be saved to the flash memory of the LakeShore 340."
print "To do so, I execute the command: _ls_send(\"CRVSAV\")"
ans = _ls_send("CRVSAV")
if (ans != "LSOK"){
print "Error saving curve number ", crv "."
exit
}
else {
print "Saved curve number ", crv "."
}
print "To make sure the curve was written correctly you might check it on the front panel"
}'
#%MACROS%
#%IMACROS%
#%AUTHOR: Thomas Roth, 17/07/2009%
|