pearl-anneal.ipf
Go to the documentation of this file.
#pragma rtGlobals=3// Use modern global access method and strict wave access.
#pragma version = 0.1
#pragma IgorVersion = 6.2
#pragma ModuleName = PearlAnneal
#include "pearl-epics"
static const string package_name = "pearl_anneal";
static const string package_path = "root:packages:pearl_anneal:";
// semicolon-separated list of persistent variable, string, and wave names
static const string prefs_objects = "";
static variable AfterCompiledHook(){
// initializes package data once when the procedure is first loaded
dfref savedf = GetDataFolderDFR()
variable do_init = 1
if (DataFolderExists(package_path))
setdatafolder $(package_path)
nvar /z init_done
if (nvar_exists(init_done))
if (init_done)
do_init = 0
endif
endif
endif
if (do_init)
init_package()
load_prefs()
setdatafolder $(package_path)
variable /g init_done = 1
endif
setdatafolder savedf
return 0
};
static variable init_package(){
dfref savedf = getdatafolderdfr()
setdatafolder root:
newdatafolder /o/s packages
newdatafolder /o/s $package_name
// configuration (persistent)
string /g graphname = "graph_anneal_tracker"
string /g dataname = "anneal"
// recently used (persistent)
// recently used (volatile)
// run-time variables (volatile)
string /g controls, monitors
variable /g psu_connected = 0
variable /g ls_connected = 0
variable /g pyro_connected = 0
variable /g vac_connected = 0
// channel ID
variable /g chidSetVolts = 0
variable /g chidGetVolts = 0
variable /g chidSetAmps = 0
variable /g chidGetAmps = 0
variable /g chidGetWatts = 0
variable /g chidSetOnOff = 0
variable /g chidGetOnOff = 0
variable /g chidStatCC = 0
variable /g chidStatCV = 0
variable /g chidGetRemote = 0
variable /g chidGetTempA = 0
variable /g chidGetTempB = 0
variable /g chidGetPyro1 = 0
variable /g chidGetPyroQ = 0
variable /g chidGetPressure = 0
// current PV values
variable /g curGetVolts = 0
variable /g curSetVolts = 0
variable /g curGetAmps = 0
variable /g curSetAmps = 0
variable /g curGetWatts = 0
variable /g curSetWatts = 0
variable /g curGetOnOff = 0
variable /g curStatCC = 0
variable /g curStatCV = 0
variable /g curGetTempA = 0
variable /g curGetTempB = 0
variable /g curGetPyro1 = 0
variable /g curGetPyroQ = 0
variable /g curGetPressure = 0
// current phase indicators
variable /g curTargetWatts = nan
variable /g curTargetTempA = nan
variable /g curTargetTempB = nan
variable /g curTargetTempPy = nan
variable /g curTripTempA = nan
variable /g curTripTempB = nan
variable /g curTripTempPy = nan
variable /g curLimitPressure = nan
variable /g curTripPressure = nan
variable /g curPhaseMinutes = 0
// chart control and data
make /n=500 /o recVolts, recAmps, recWatts, recTemp, recPressure, recMinutes
variable /g recPoint
variable /g recMinutesStart
recPoint = 0
recMinutesStart = datetime / 60
// ramp status: 1 = running, 0.5 = paused, 0 = off
variable /g ramp_status
// index of the current ramp phase
variable /g ramp_phase
// ramping direction +1 = up, -1 = down
variable /g ramp_dir
// system time in minutes at the start of the current phase
variable /g minutes_start
// system time in minutes at the time of the previous step
variable /g minutes_previous
// status message for user
string /g ramp_message
ann_new_ramp_table(edit_table=0)
setdatafolder savedf
};
static variable save_prefs(){
// saves persistent package data to the preferences file
dfref saveDF = GetDataFolderDFR()
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
fullPath += package_name
NewPath/O/C/Q tempPackagePrefsPath, fullPath
fullPath += ":preferences.pxp"
SetDataFolder root:packages
SetDataFolder $package_name
SaveData /O /Q /J=prefs_objects fullPath
KillPath/Z tempPackagePrefsPath
SetDataFolder saveDF
};
static variable load_prefs(){
// loads persistent package data from the preferences file
// the preferences file is an Igor packed experiment file in a special preferences folder
dfref saveDF = GetDataFolderDFR()
variable result = -1
setdatafolder root:
NewDataFolder /O/S packages
NewDataFolder /O/S $package_name
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
fullPath += package_name
GetFileFolderInfo /Q /Z fullPath
if (V_Flag == 0)// Disk directory exists?
fullPath += ":preferences.pxp"
GetFileFolderInfo /Q /Z fullPath
if (V_Flag == 0)// Preference file exist?
LoadData /O /R /Q fullPath
result = 0
endif
endif
SetDataFolder saveDF
return result
};
static variable save_ramp(){
dfref saveDF = GetDataFolderDFR()
SetDataFolder root:packages
SetDataFolder $package_name
wave minutes
wave target_watts
wave target_tempA
wave target_tempB
wave target_tempPy
wave trip_tempA
wave trip_tempB
wave trip_tempPy
wave limit_pressure
wave trip_pressure
Save /T /M="\r\n" /I minutes,target_watts,target_tempPy,target_tempB,target_tempA,limit_pressure,trip_tempPy,trip_tempB,trip_tempA,trip_pressure as "anneal-ramp.itx"
SetDataFolder saveDF
};
static variable IgorQuitHook(string app){
string app
epics_disconnect()
};
static variable epics_connect(){
dfref savedf = getdatafolderdfr()
setdatafolder $(package_path)
nvar psu_connected
nvar ls_connected
nvar vac_connected
nvar pyro_connected
if (!psu_connected)
epics_connect_psu()
endif
if (!ls_connected)
epics_connect_ls()
endif
if (!vac_connected)
epics_connect_vac()
endif
if (!pyro_connected)
epics_connect_pyro()
endif
setdatafolder saveDF
return !(psu_connected && ls_connected && vac_connected && pyro_connected)
};
static variable epics_connect_psu(){
dfref savedf = getdatafolderdfr()
setdatafolder $(package_path)
// create variables and waves
nvar connected = psu_connected
svar ramp_message
// channel ID variables
nvar chidSetVolts
nvar chidGetVolts
nvar chidSetAmps
nvar chidGetAmps
nvar chidGetWatts
nvar chidSetOnOff
nvar chidGetOnOff
nvar chidStatCC
nvar chidStatCV
nvar chidGetRemote
nvar curGetVolts
nvar curGetAmps
nvar curGetWatts
nvar curGetOnOff
nvar curStatCC
nvar curStatCV
string psu_name = "X03DA-PSU-XP:"
variable timeout = 5// seconds
#if exists("pvWait")
// EPICS.XOP version 0.3.0 or later
pvOpen /Q chidSetVolts, psu_name + "SETVOLTS"
pvOpen /Q chidGetVolts, psu_name + "GETVOLTS"
pvOpen /Q chidSetAmps, psu_name + "SETCUR"
pvOpen /Q chidGetAmps, psu_name + "GETCUR"
pvOpen /Q chidGetWatts, psu_name + "CALCPWR"
pvOpen /Q chidSetOnOff, psu_name + "SETONOFF"
pvOpen /Q chidGetOnOff, psu_name + "GETONOFF"
pvOpen /Q chidGetRemote, psu_name + "COMGETRMT"// string
pvOpen /Q chidStatCC, psu_name + "STAT-CC"
pvOpen /Q chidStatCV, psu_name + "STAT-CV"
pvWait timeout
#endif
if (GetRTError(1))
connected = 0
ramp_message = "PSU: no connection"
else
connected = 1
endif
#if exists("pvMonitor")
if (connected)
pvMonitor chidGetVolts, curGetVolts
pvMonitor chidSetVolts, curSetVolts
pvMonitor chidGetAmps, curGetAmps
pvMonitor chidSetAmps, curSetAmps
pvMonitor chidGetWatts, curGetWatts
pvMonitor chidGetOnOff, curGetOnOff
pvMonitor chidStatCC, curStatCC
pvMonitor chidStatCV, curStatCV
endif
#endif
setdatafolder saveDF
return !connected
};
static variable epics_connect_ls(){
dfref savedf = getdatafolderdfr()
setdatafolder $(package_path)
nvar connected = ls_connected
svar ramp_message
nvar chidGetTempA
nvar chidGetTempB
nvar curGetTempA
nvar curGetTempB
string base_name = "X03DA-PC-LAKESHOREXP:"
variable timeout = 5// seconds
#if exists("pvWait")
// EPICS.XOP version 0.3.0 or later
pvOpen /Q chidGetTempA, base_name + "A-TEMP_RBV"
pvOpen /Q chidGetTempB, base_name + "B-TEMP_RBV"
pvWait timeout
#endif
if (GetRTError(1))
connected = 0
ramp_message = "Lakeshore: no connection"
else
connected = 1
endif
#if exists("pvMonitor")
if (connected)
pvMonitor /F=ann_callback_ls chidGetTempA, curGetTempA
pvMonitor /F=ann_callback_ls chidGetTempB, curGetTempB
endif
#endif
setdatafolder saveDF
return !connected
};
static variable epics_connect_vac(){
dfref savedf = getdatafolderdfr()
setdatafolder $(package_path)
nvar connected = vac_connected
svar ramp_message
nvar chidGetPressure
nvar curGetPressure
string base_name = "X03DA-PVC-XP:"
variable timeout = 5// seconds
#if exists("pvWait")
// EPICS.XOP version 0.3.0 or later
pvOpen /Q chidGetPressure, base_name + "IG-PRESSURE"
pvWait timeout
#endif
if (GetRTError(1))
connected = 0
ramp_message = "vacuum gauge: no connection"
else
connected = 1
endif
#if exists("pvMonitor")
if (connected)
pvMonitor /F=ann_callback_pvc chidGetPressure, curGetPressure
endif
#endif
setdatafolder saveDF
return !connected
};
static variable epics_connect_pyro(){
dfref savedf = getdatafolderdfr()
setdatafolder $(package_path)
nvar connected = pyro_connected
svar ramp_message
nvar chidGetPyro1
nvar chidGetPyroQ
nvar curGetPyro1
nvar curGetPyroQ
string base_name = "X03DA-LV-MAURER:"
variable timeout = 5// seconds
#if exists("pvWait")
// EPICS.XOP version 0.3.0 or later
pvOpen /Q chidGetPyro1, base_name + "TEMP-1"
pvOpen /Q chidGetPyroQ, base_name + "TEMP-Q"
pvWait timeout
#endif
if (GetRTError(1))
connected = 0
ramp_message = "pyrometer: no connection"
else
connected = 1
endif
#if exists("pvMonitor")
if (connected)
pvMonitor /F=ann_callback_ls chidGetPyro1, curGetPyro1
pvMonitor /F=ann_callback_ls chidGetPyroQ, curGetPyroQ
endif
#endif
setdatafolder saveDF
return !connected
};
static variable epics_disconnect_chid(string chid_var_name){
string chid_var_name
#if exists("pvClose")
nvar /z chid = $chid_var_name
if (nvar_exists(chid))
if (chid != 0)
pvClose chid
endif
chid = 0
endif
#endif
};
static variable epics_disconnect(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
epics_disconnect_psu()
epics_disconnect_ls()
epics_disconnect_vac()
epics_disconnect_pyro()
setdatafolder savedf
};
static variable epics_disconnect_psu(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar connected = psu_connected
if (connected)
connected = 0
epics_disconnect_chid("chidSetVolts")
epics_disconnect_chid("chidGetVolts")
epics_disconnect_chid("chidSetAmps")
epics_disconnect_chid("chidGetAmps")
epics_disconnect_chid("chidGetWatts")
epics_disconnect_chid("chidSetOnOff")
epics_disconnect_chid("chidGetOnOff")
epics_disconnect_chid("chidGetRemote")
epics_disconnect_chid("chidStatCC")
epics_disconnect_chid("chidStatCV")
endif
setdatafolder savedf
};
static variable epics_disconnect_ls(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar connected = ls_connected
if (connected)
connected = 0
epics_disconnect_chid("chidGetTempA")
epics_disconnect_chid("chidGetTempB")
endif
setdatafolder savedf
};
static variable epics_disconnect_vac(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar connected = vac_connected
if (connected)
connected = 0
epics_disconnect_chid("chidGetPressure")
endif
setdatafolder savedf
};
static variable epics_disconnect_pyro(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar connected = pyro_connected
if (connected)
connected = 0
epics_disconnect_chid("chidGetPyro1")
epics_disconnect_chid("chidGetPyroQ")
endif
setdatafolder savedf
};
variable ann_new_ramp_table(variable edit_table = defaultValue){
variable edit_table
if (ParamIsDefault(edit_table))
edit_table = 1
endif
dfref savedf = GetDataFolderDFR()
make /n=3 /o minutes,cum_minutes,target_watts
make /n=3 /o target_tempA, target_tempB, target_tempPy
make /n=3 /o limit_pressure
make /n=3 /o trip_tempA, trip_tempB, trip_tempPy
make /n=3 /o trip_pressure
make /n=3 /o est_temp
minutes = 1
cum_minutes = nan
target_watts[0] = {0, 5, 0}
target_tempA = nan
target_tempB = nan
target_tempPy = nan
limit_pressure = 1e-8
trip_tempA = nan
trip_tempB = 450
trip_tempPy = nan
trip_pressure = 5e-8
est_temp = nan
if (edit_table)
edit /k=1 minutes, target_watts
appendtotable target_tempA, trip_tempA
appendtotable target_tempB, trip_tempB
appendtotable target_tempPy, trip_tempPy
appendtotable limit_pressure,trip_pressure
endif
setdatafolder savedf
};
variable ann_init_bg(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
CtrlNamedBackground ann_ramp, period = 60, proc = PearlAnneal#ann_ramp_bg
CtrlNamedBackground ann_record, period = 600, proc = PearlAnneal#ann_record_bg
setdatafolder savedf
};
static variable ann_record_bg(WMBackgroundStruct* s){
STRUCT WMBackgroundStruct &s
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar curGetVolts
nvar curGetAmps
nvar curGetWatts
nvar curGetOnOff
nvar curStatCC
nvar curStatCV
nvar curGetTempA
nvar curGetTempB
nvar curGetPyro1
nvar curGetPyroQ
nvar curGetPressure
nvar recPoint
nvar recMinutesStart
wave recMinutes
wave recVolts
wave recAmps
wave recWatts
wave recTemp
wave recPressure
variable nshift = 12
variable plo
variable phi
if (recPoint >= numpnts(recWatts))
plo = 0
phi = numpnts(recWatts) - nshift - 1
recMinutes[plo, phi] = recMinutes[p + nshift]
recVolts[plo, phi] = recVolts[p + nshift]
recAmps[plo, phi] = recAmps[p + nshift]
recWatts[plo, phi] = recWatts[p + nshift]
recTemp[plo, phi] = recTemp[p + nshift]
recPressure[plo, phi] = recPressure[p + nshift]
plo = numpnts(recWatts) - nshift
phi = numpnts(recWatts) - 1
recMinutes[plo, phi] = nan
recVolts[plo, phi] = nan
recAmps[plo, phi] = nan
recWatts[plo, phi] = nan
recTemp[plo, phi] = nan
recPressure[plo, phi] = nan
recPoint = plo
endif
variable temp = curGetTempA
if (curGetPyroQ >= 625)
temp = max(temp, curGetPyroQ)
else if (curGetPyro1 >= 625)
temp = max(temp, curGetPyro1)
endif
recMinutes[recPoint] = datetime / 60 - recMinutesStart
recVolts[recPoint] = curGetVolts
recAmps[recPoint] = curGetAmps
recWatts[recPoint] = curGetWatts
recTemp[recPoint] = temp
recPressure[recPoint] = curGetPressure
recPoint += 1
setdatafolder savedf
return 0
};
static variable ann_ramp_bg(WMBackgroundStruct* s){
STRUCT WMBackgroundStruct &s
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
ann_ramp_step()
setdatafolder savedf
return 0
};
variable ann_ramp_step(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar minutes_start
nvar minutes_previous
nvar ramp_phase
svar ramp_message
wave minutes
wave target_watts
variable minutes_now = datetime / 60
variable minutes_phase = minutes_now - minutes_start
variable minutes_step = minutes_now - minutes_previous
variable trip
variable hold
variable phase_complete
ann_ramp_update(ramp_phase)
// check trip conditions
trip = ann_ramp_trip(ramp_phase)
if (!trip)
// check hold conditions
hold = ann_ramp_hold(ramp_phase)
if (!hold)
// check targets
phase_complete = ann_ramp_target(ramp_phase)
if (!phase_complete)
// execute step
phase_complete = ann_ramp_step_exec(minutes_now)
ramp_message = ""
endif
if (phase_complete)
ramp_phase += 1
minutes_start = minutes_now
// check end of ramp
if ((ramp_phase >= numpnts(minutes)) || (ramp_phase >= numpnts(target_watts)) || numtype(minutes[ramp_phase]) || numtype(target_watts[ramp_phase]))
ann_ramp_stop(0)
endif
endif
endif
endif
minutes_previous = minutes_now
setdatafolder savedf
return 0
};
static variable ann_ramp_update(variable phase){
variable phase
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
wave minutes
wave target_watts
wave target_tempA
wave target_tempB
wave target_tempPy
wave trip_tempA
wave trip_tempB
wave trip_tempPy
wave limit_pressure
wave trip_pressure
nvar curTargetWatts
nvar curTargetTempA
nvar curTargetTempB
nvar curTargetTempPy
nvar curTripTempA
nvar curTripTempB
nvar curTripTempPy
nvar curLimitPressure
nvar curTripPressure
nvar curPhaseMinutes
curPhaseMinutes = minutes[phase]
curTargetWatts = target_watts[phase]
curTargetTempA = target_tempA[phase]
curTargetTempB = target_tempB[phase]
curTargetTempPy = target_tempPy[phase]
curTripTempA = trip_tempA[phase]
curTripTempB = trip_tempB[phase]
curTripTempPy = trip_tempPy[phase]
curLimitPressure = limit_pressure[phase]
curTripPressure = trip_pressure[phase]
setdatafolder savedf
};
static variable ann_ramp_step_exec(variable minutes_now){
variable minutes_now
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar chidSetVolts
nvar chidSetAmps
nvar curGetVolts
nvar curGetAmps
nvar curGetWatts
nvar curSetVolts
nvar curSetAmps
nvar curSetWatts
nvar minutes_start
nvar minutes_previous
nvar ramp_phase
nvar ramp_dir
variable p2 = ramp_phase
variable p1 = p2 - 1
variable minutes_phase = minutes_now - minutes_start
variable minutes_step = minutes_now - minutes_previous
wave minutes
wave target_watts
variable step_watts
variable next_volts
variable next_amps
variable next_watts
variable resistance
variable max_step_volts = 0.5
variable max_step_amps = 0.1
variable max_test_volts = 5.0
variable max_test_amps = 0.5
variable watts_complete
// calculate power step
step_watts = (target_watts[p2] - target_watts[p1]) / minutes[p2] * minutes_step
next_watts = curSetWatts + step_watts
// check end of ramp phase
if (step_watts > 0.0001)
watts_complete = next_watts > target_watts[p2]
else if (step_watts < -0.0001)
watts_complete = next_watts < target_watts[p2]
else
watts_complete = minutes_phase >= minutes[p2]
endif
// limit power
if (watts_complete)
next_watts = curSetWatts
else
next_watts = limit(next_watts, 0, max(target_watts[p1], target_watts[p2]))
endif
// calculate voltage and current
if (next_watts >= 0.1)
curSetWatts = next_watts
if ((curGetVolts > 0.1) && (curGetAmps > 0.1))
resistance = curGetVolts / curGetAmps
next_volts = limit(sqrt(next_watts * resistance), 0, curGetVolts + max_step_volts)
next_amps = limit(sqrt(next_watts / resistance), 0, curGetAmps + max_step_amps)
else
// apply small voltage to measure the resistance
next_volts = min(curSetVolts + 0.5, max_test_volts)
next_amps = min(curSetAmps + 0.1, max_test_amps)
endif
else
curSetWatts = next_watts
next_volts = 0
next_amps = 0
endif
// change setpoints
pvPutNumber /Q chidSetVolts, next_volts
pvPutNumber /Q chidSetAmps, next_amps
pvWait 5
setdatafolder savedf
return watts_complete
};
static variable ann_ramp_trip(variable phase){
variable phase
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
variable trip = 0
wave trip_tempA
wave trip_tempB
wave trip_tempPy
wave trip_pressure
nvar curGetTempA
nvar curGetTempB
nvar curGetTempPyro1
nvar curGetTempPyroQ
nvar curGetPressure
svar ramp_message
if ((phase < numpnts(trip_tempA)) && (numtype(trip_tempA[phase]) == 0) && (curGetTempA >= trip_tempA[phase]))
ramp_message = "temperature A trip"
trip = 1
endif
if ((phase < numpnts(trip_tempB)) && (numtype(trip_tempB[phase]) == 0) && (curGetTempB >= trip_tempB[phase]))
ramp_message = "temperature B trip"
trip = 2
endif
if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyro1 >= trip_tempPy[phase]))
ramp_message = "pyrometer trip (1)"
trip = 3
endif
if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyroQ >= trip_tempPy[phase]))
ramp_message = "pyrometer trip (Q)"
trip = 4
endif
if ((phase < numpnts(trip_pressure)) && (numtype(trip_pressure[phase]) == 0) && (curGetPressure >= trip_pressure[phase]))
ramp_message = "pressure trip"
trip = 5
endif
if (trip)
ann_ramp_stop(1)
endif
setdatafolder savedf
return trip
};
static variable ann_ramp_hold(variable phase){
variable phase
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
nvar curGetPressure
variable hold = 0
wave limit_pressure
if ((phase < numpnts(limit_pressure)) && (numtype(limit_pressure[phase]) == 0) && (curGetPressure >= limit_pressure[phase]))
hold = 5
endif
setdatafolder savedf
return hold
};
static variable ann_ramp_target(variable phase){
variable phase
if (phase < 1)
return 0
endif
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
variable target = 0
wave target_watts
wave target_tempA
wave target_tempB
wave target_tempPy
variable direction_up = target_watts[phase] >= target_watts[phase - 1]
nvar curGetTempA
nvar curGetTempB
nvar curGetTempPyro1
nvar curGetTempPyroQ
svar ramp_message
if ((phase < numpnts(target_tempA)) && (numtype(target_tempA[phase]) == 0))
if (direction_up)
if (curGetTempA >= target_tempA[phase])
target = 1
endif
else
if (curGetTempA <= target_tempA[phase])
target = 1
endif
endif
endif
if ((phase < numpnts(target_tempB)) && (numtype(target_tempB[phase]) == 0))
if (direction_up)
if (curGetTempB >= target_tempB[phase])
target = 2
endif
else
if (curGetTempB <= target_tempB[phase])
target = 2
endif
endif
endif
if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0))
if (direction_up)
if (curGetTempPyro1 >= target_tempPy[phase])
target = 3
endif
else
if (curGetTempPyro1 <= target_tempPy[phase])
target = 3
endif
endif
endif
if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0))
if (direction_up)
if (curGetTempPyroQ >= target_tempPy[phase])
target = 4
endif
else
if (curGetTempPyroQ <= target_tempPy[phase])
target = 4
endif
endif
endif
switch(target)
case 1:
ramp_message = "temperature A target reached"
break
case 2:
ramp_message = "temperature B target reached"
break
case 3:
ramp_message = "pyrometer 1 target reached"
break
case 4:
ramp_message = "pyrometer Q target reached"
break
endswitch
setdatafolder savedf
return target
};
variable ann_ramp_start(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
epics_connect()
nvar recPoint
nvar recMinutesStart
recPoint = 0
recMinutesStart = datetime / 60
wave recMinutes
wave recVolts
wave recAmps
wave recWatts
wave recTemp
wave recPressure
recMinutes = nan
recVolts = nan
recAmps = nan
recWatts = nan
recTemp = nan
recPressure = nan
nvar minutes_start
minutes_start = datetime / 60
nvar minutes_previous
minutes_previous = minutes_start
nvar ramp_phase
ramp_phase = 1
nvar ramp_status
ramp_status = 1
nvar chidSetVolts
nvar chidSetAmps
nvar chidSetOnOff
wave target_watts
pvPutNumber /Q chidSetVolts, 0.5
pvPutNumber /Q chidSetAmps, 0.5
pvPutNumber /Q chidSetOnOff, 0
pvWait 5
nvar curSetWatts
curSetWatts = target_watts[0]
ann_init_bg()
CtrlNamedBackground ann_ramp, start
CtrlNamedBackground ann_record, start
setdatafolder savedf
return 0
};
variable ann_ramp_pause(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
CtrlNamedBackground ann_ramp, stop
nvar ramp_status
ramp_status = 0.5
setdatafolder savedf
return 0
};
variable ann_ramp_resume(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
CtrlNamedBackground ann_ramp, start
nvar ramp_status
ramp_status = 1
setdatafolder savedf
return 0
};
variable ann_ramp_stop(variable reset_psu){
variable reset_psu
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
CtrlNamedBackground ann_ramp, stop
CtrlNamedBackground ann_record, stop
nvar ramp_phase
ramp_phase = 0
nvar ramp_status
ramp_status = 0
nvar curTargetWatts
if (reset_psu || (curTargetWatts < 1))
nvar chidSetVolts
nvar chidSetAmps
nvar chidSetOnOff
pvPutNumber /Q chidSetVolts, 0
pvPutNumber /Q chidSetAmps, 0
pvPutNumber /Q chidSetOnOff, 1
pvWait 5
endif
setdatafolder savedf
return 0
};
variable ann_display_ramp(){
dfref savedf = GetDataFolderDFR()
setdatafolder $(package_path)
wave recMinutes
wave recVolts
wave recAmps
wave recWatts
wave recTemp
wave recPressure
display recWatts vs recMinutes
appendtograph /r recVolts vs recMinutes
appendtograph /r recAmps vs recMinutes
};
void panel_ramp_gen(){
PauseUpdate; Silent 1// building window...
NewPanel /K=1 /W=(441,64,887,702) as "ramp generator"
ValDisplay valdisp0,pos={11,178},size={233,42},bodyWidth=200,title="pyro 1"
ValDisplay valdisp0,limits={0,1500,625},barmisc={10,50}
ValDisplay valdisp0,value= #"root:packages:pearl_anneal:curGetPyro1"
ValDisplay valdisp1,pos={11,233},size={233,42},bodyWidth=200,title="pyro q"
ValDisplay valdisp1,limits={0,1500,625},barmisc={10,50}
ValDisplay valdisp1,value= #"root:packages:pearl_anneal:curGetPyroQ"
ValDisplay valdisp2,pos={11,73},size={234,42},bodyWidth=200,title="lake A"
ValDisplay valdisp2,limits={0,1500,300},barmisc={10,50}
ValDisplay valdisp2,value= #"root:packages:pearl_anneal:curGetTempA"
ValDisplay valdisp3,pos={10,128},size={234,42},bodyWidth=200,title="lake B"
ValDisplay valdisp3,limits={0,1500,300},barmisc={10,50}
ValDisplay valdisp3,value= #"root:packages:pearl_anneal:curGetTempB"
ValDisplay valdisp4,pos={16,23},size={229,42},bodyWidth=200,title="watts"
ValDisplay valdisp4,limits={0,90,0},barmisc={10,50}
ValDisplay valdisp4,value= #"root:packages:pearl_anneal:curGetWatts"
ValDisplay valdisp5,pos={6,5},size={60,14},title="phase"
ValDisplay valdisp5,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp5,value= #"root:packages:pearl_anneal:ramp_phase"
ValDisplay valdisp6,pos={0,282},size={244,42},bodyWidth=200,title="pressure"
ValDisplay valdisp6,format="%.1e",limits={1e-09,1e-08,0},barmisc={10,80}
ValDisplay valdisp6,value= #"root:packages:pearl_anneal:curGetPressure"
ValDisplay valdisp7,pos={335,90},size={47,14},bodyWidth=14,title="power"
ValDisplay valdisp7,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (60928,60928,60928),lowColor= (0,52224,0),zeroColor= (61440,61440,61440)
ValDisplay valdisp7,value= #"root:packages:pearl_anneal:curGetOnOff"
ValDisplay valdisp16,pos={262,168},size={114,14},bodyWidth=34,title="target temp pyro"
ValDisplay valdisp16,limits={0,0,0},barmisc={0,1000},mode= 2,highColor= (60928,60928,60928),lowColor= (65280,0,0),zeroColor= (0,52224,0)
ValDisplay valdisp16,value= #"root:packages:pearl_anneal:curTargetTempPy"
ValDisplay valdisp17,pos={300,4},size={80,14},bodyWidth=14,title="power supply"
ValDisplay valdisp17,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
ValDisplay valdisp17,value= #"root:packages:pearl_anneal:psu_connected"
ValDisplay valdisp18,pos={317,21},size={64,14},bodyWidth=14,title="lakeshore"
ValDisplay valdisp18,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
ValDisplay valdisp18,value= #"root:packages:pearl_anneal:ls_connected"
ValDisplay valdisp19,pos={318,38},size={64,14},bodyWidth=14,title="pyrometer"
ValDisplay valdisp19,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
ValDisplay valdisp19,value= #"root:packages:pearl_anneal:pyro_connected"
ValDisplay valdisp20,pos={293,52},size={91,14},bodyWidth=14,title="vacuum system"
ValDisplay valdisp20,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
ValDisplay valdisp20,value= #"root:packages:pearl_anneal:vac_connected"
ValDisplay valdisp21,pos={341,76},size={41,14},bodyWidth=14,title="ramp"
ValDisplay valdisp21,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (61440,61440,61440),zeroColor= (0,34816,52224)
ValDisplay valdisp21,value= #"root:packages:pearl_anneal:ramp_status"
ValDisplay valdisp8,pos={278,120},size={100,14},title="target watts"
ValDisplay valdisp8,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp8,value= #"root:packages:pearl_anneal:curTargetWatts"
ValDisplay valdisp9,pos={278,137},size={100,14},title="target temp A"
ValDisplay valdisp9,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp9,value= #"root:packages:pearl_anneal:curTargetTempA"
ValDisplay valdisp10,pos={278,152},size={100,14},title="target temp B"
ValDisplay valdisp10,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp10,value= #"root:packages:pearl_anneal:curTargetTempB"
ValDisplay valdisp11,pos={271,266},size={100,14},title="limit pressure"
ValDisplay valdisp11,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp11,value= #"root:packages:pearl_anneal:curLimitPressure"
ValDisplay valdisp12,pos={261,205},size={100,14},title="trip temp A"
ValDisplay valdisp12,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp12,value= #"root:packages:pearl_anneal:curTripTempA"
ValDisplay valdisp13,pos={262,224},size={100,14},title="trip temp B"
ValDisplay valdisp13,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp13,value= #"root:packages:pearl_anneal:curTripTempB"
ValDisplay valdisp14,pos={276,242},size={100,14},title="trip pyro"
ValDisplay valdisp14,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp14,value= #"root:packages:pearl_anneal:curTripTempPy"
ValDisplay valdisp15,pos={273,309},size={100,14},title="ramp interval"
ValDisplay valdisp15,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp15,value= #"root:packages:pearl_anneal:curPhaseMinutes"
Button b_start,pos={15,362},size={50,20},proc=PearlAnneal#bp_ramp_start,title="start"
Button b_start,fColor=(0,52224,0)
Button b_pause,pos={75,362},size={50,20},proc=PearlAnneal#bp_ramp_pause,title="pause"
Button b_stop,pos={135,362},size={50,20},proc=PearlAnneal#bp_ramp_stop,title="stop"
Button b_stop,fColor=(52224,0,0)
Button b_edit,pos={195,362},size={50,20},proc=PearlAnneal#bp_ramp_edit,title="edit"
ValDisplay valdisp11_1,pos={274,282},size={100,14},title="trip pressure"
ValDisplay valdisp11_1,limits={0,0,0},barmisc={0,1000}
ValDisplay valdisp11_1,value= #"root:packages:pearl_anneal:curTripPressure"
TitleBox title0,pos={16,334},size={400,20}
TitleBox title0,variable= root:packages:pearl_anneal:ramp_message,fixedSize=1
DefineGuide UGH0={FT,390}
String fldrSav0= GetDataFolder(1)
SetDataFolder root:packages:pearl_anneal:
Display/W=(82,153,246,462)/FG=(FL,UGH0,FR,FB)/HOST=# recTemp vs recMinutes
AppendToGraph/R recPressure vs recMinutes
AppendToGraph/L=power recWatts vs recMinutes
NewFreeAxis/O/L power
SetDataFolder fldrSav0
ModifyGraph margin(left)=80
ModifyGraph rgb(recPressure)=(0,0,65280),rgb(recWatts)=(0,39168,0)
ModifyGraph log(right)=1
ModifyGraph mirror(bottom)=2
ModifyGraph nticks=3
ModifyGraph minor=1
ModifyGraph axThick=0.5
ModifyGraph axRGB(left)=(65280,0,0),axRGB(right)=(0,0,65280),axRGB(power)=(0,39168,0)
ModifyGraph tlblRGB(left)=(65280,0,0),tlblRGB(right)=(0,0,65280),tlblRGB(power)=(0,39168,0)
ModifyGraph alblRGB(left)=(65280,0,0),alblRGB(right)=(0,0,65280),alblRGB(power)=(0,39168,0)
ModifyGraph lblPos(left)=42,lblPos(power)=35
ModifyGraph lblLatPos(left)=1
ModifyGraph btLen=4
ModifyGraph freePos(power)=48
Label left "temperature (K)"
Label bottom "time (minutes)"
Label right "pressure (mbar)"
Label power "power (W)"
SetAxis/E=1 power 0,80
RenameWindow #,G0
SetActiveSubwindow ##
};
static variable bp_ramp_start(WMButtonAction* ba){
struct WMButtonAction &ba
switch( ba.eventCode )
case 2:// mouse up
dfref ann_df = $(package_path)
nvar /sdfr=ann_df ramp_status
if (ramp_status < 0.4)
ann_ramp_start()
endif
break
case -1:// control being killed
break
endswitch
return 0
};
static variable bp_ramp_pause(WMButtonAction* ba){
struct WMButtonAction &ba
switch( ba.eventCode )
case 2:// mouse up
dfref ann_df = $(package_path)
nvar /sdfr=ann_df ramp_status
if (ramp_status > 0.6)
ann_ramp_pause()
Button b_pause, win=$(ba.win), title="resume"
else
ann_ramp_resume()
Button b_pause, win=$(ba.win), title="pause"
endif
break
case -1:// control being killed
break
endswitch
return 0
};
static variable bp_ramp_stop(WMButtonAction* ba){
struct WMButtonAction &ba
switch( ba.eventCode )
case 2:// mouse up
ann_ramp_stop(1)
break
case -1:// control being killed
break
endswitch
return 0
};
static variable bp_ramp_edit(WMButtonAction* ba){
struct WMButtonAction &ba
dfref savedf = GetDataFolderDFR()
switch( ba.eventCode )
case 2:// mouse up
setdatafolder $(package_path)
wave minutes
wave target_watts
wave target_tempA
wave target_tempB
wave target_tempPy
wave trip_tempA
wave trip_tempB
wave trip_tempPy
wave limit_pressure
wave trip_pressure
edit /k=1 minutes, target_watts
appendtotable target_tempA, trip_tempA
appendtotable target_tempB, trip_tempB
appendtotable target_tempPy, trip_tempPy
appendtotable limit_pressure,trip_pressure
break
case -1:// control being killed
break
endswitch
setdatafolder savedf
return 0
};
ann_record_bg
static variable ann_record_bg(WMBackgroundStruct *s)
background task of the recorder
Definition: pearl-anneal.ipf:723
prefs_objects
static const string prefs_objects
Definition: pearl-anneal.ipf:96
load_prefs
static variable load_prefs()
Definition: pearl-anneal.ipf:241
ann_init_bg
variable ann_init_bg()
initialize the background tasks
Definition: pearl-anneal.ipf:712
panel_ramp_gen
void panel_ramp_gen()
Definition: pearl-anneal.ipf:1311
ann_ramp_bg
static variable ann_ramp_bg(WMBackgroundStruct *s)
background task of the ramp
Definition: pearl-anneal.ipf:800
save_ramp
static variable save_ramp()
save current ramp table
Definition: pearl-anneal.ipf:270
epics_disconnect
static variable epics_disconnect()
disconnect from all EPICS devices.
Definition: pearl-anneal.ipf:577
package_path
static const string package_path
Definition: pearl-anneal.ipf:94
ann_new_ramp_table
variable ann_new_ramp_table(variable edit_table=defaultValue)
create a new ramp table and open it in a table window.
Definition: pearl-anneal.ipf:668
ann_ramp_target
static variable ann_ramp_target(variable phase)
check target conditions
Definition: pearl-anneal.ipf:1087
ann_ramp_hold
static variable ann_ramp_hold(variable phase)
check hold conditions
Definition: pearl-anneal.ipf:1064
ann_ramp_update
static variable ann_ramp_update(variable phase)
update control panel variables
Definition: pearl-anneal.ipf:868
ann_ramp_pause
variable ann_ramp_pause()
Definition: pearl-anneal.ipf:1236
epics_connect_vac
static variable epics_connect_vac()
connect to the vacuum gauge
Definition: pearl-anneal.ipf:468
epics_disconnect_psu
static variable epics_disconnect_psu()
disconnect from the power supply unit
Definition: pearl-anneal.ipf:591
epics_connect_psu
static variable epics_connect_psu()
connect to the power supply unit
Definition: pearl-anneal.ipf:338
ann_display_ramp
variable ann_display_ramp()
Definition: pearl-anneal.ipf:1295
epics_connect_ls
static variable epics_connect_ls()
connect to the lakeshore temperature controller
Definition: pearl-anneal.ipf:417
epics_connect_pyro
static variable epics_connect_pyro()
connect to the pyrometer
Definition: pearl-anneal.ipf:519
epics_disconnect_vac
static variable epics_disconnect_vac()
disconnect from the vacuum gauge
Definition: pearl-anneal.ipf:632
ann_ramp_step
variable ann_ramp_step()
prepare and execute the next ramp step
Definition: pearl-anneal.ipf:816
PearlAnneal
ramp generator for sample annealing
package_name
static const string package_name
Definition: pearl-anneal.ipf:93
AfterCompiledHook
static variable AfterCompiledHook()
Definition: pearl-anneal.ipf:98
save_prefs
static variable save_prefs()
Definition: pearl-anneal.ipf:223
init_package
static variable init_package()
initialize the package data folder
Definition: pearl-anneal.ipf:128
bp_ramp_start
static variable bp_ramp_start(WMButtonAction *ba)
Definition: pearl-anneal.ipf:1422
ann_ramp_start
variable ann_ramp_start()
start an annealing ramp
Definition: pearl-anneal.ipf:1180
ann_ramp_step_exec
static variable ann_ramp_step_exec(variable minutes_now)
execute the next ramp step
Definition: pearl-anneal.ipf:916
bp_ramp_pause
static variable bp_ramp_pause(WMButtonAction *ba)
Definition: pearl-anneal.ipf:1440
epics_disconnect_ls
static variable epics_disconnect_ls()
disconnect from the lakeshore controller
Definition: pearl-anneal.ipf:615
ann_ramp_trip
static variable ann_ramp_trip(variable phase)
check trip conditions
Definition: pearl-anneal.ipf:1011
epics_connect
static variable epics_connect()
connect to all required EPICS devices.
Definition: pearl-anneal.ipf:303
bp_ramp_stop
static variable bp_ramp_stop(WMButtonAction *ba)
Definition: pearl-anneal.ipf:1462
IgorQuitHook
static variable IgorQuitHook(string app)
Igor sometimes crashes if the PVs are not disconnected when it quits.
Definition: pearl-anneal.ipf:293
ann_ramp_resume
variable ann_ramp_resume()
Definition: pearl-anneal.ipf:1249
epics_disconnect_pyro
static variable epics_disconnect_pyro()
disconnect from the pyrometer
Definition: pearl-anneal.ipf:648
ann_ramp_stop
variable ann_ramp_stop(variable reset_psu)
stop a running annealing ramp
Definition: pearl-anneal.ipf:1266
epics_disconnect_chid
static variable epics_disconnect_chid(string chid_var_name)
Definition: pearl-anneal.ipf:561
bp_ramp_edit
static variable bp_ramp_edit(WMButtonAction *ba)
Definition: pearl-anneal.ipf:1476