PEARL Procedures
Igor procedures for the analysis of PEARL data
pearl-anneal.ipf
Go to the documentation of this file.
1 #pragma rtGlobals=3// Use modern global access method and strict wave access.
2 #pragma version = 0.1
3 #pragma IgorVersion = 6.2
4 #pragma ModuleName = PearlAnneal
5 #include "pearl-epics"
6 
86 
92 
93 static const string package_name = "pearl_anneal";
94 static const string package_path = "root:packages:pearl_anneal:";
95 // semicolon-separated list of persistent variable, string, and wave names
96 static const string prefs_objects = "";
97 
98 static variable AfterCompiledHook(){
99  // initializes package data once when the procedure is first loaded
100 
101  dfref savedf = GetDataFolderDFR()
102  variable do_init = 1
103  if (DataFolderExists(package_path))
104  setdatafolder $(package_path)
105  nvar /z init_done
106  if (nvar_exists(init_done))
107  if (init_done)
108  do_init = 0
109  endif
110  endif
111  endif
112 
113  if (do_init)
114  init_package()
115  load_prefs()
116  setdatafolder $(package_path)
117  variable /g init_done = 1
118  endif
119 
120  setdatafolder savedf
121  return 0
122 };
123 
128 static variable init_package(){
129  dfref savedf = getdatafolderdfr()
130  setdatafolder root:
131  newdatafolder /o/s packages
132  newdatafolder /o/s $package_name
133 
134  // configuration (persistent)
135  string /g graphname = "graph_anneal_tracker"
136  string /g dataname = "anneal"
137 
138  // recently used (persistent)
139 
140  // recently used (volatile)
141 
142  // run-time variables (volatile)
143  string /g controls, monitors
144  variable /g psu_connected = 0
145  variable /g ls_connected = 0
146  variable /g pyro_connected = 0
147  variable /g vac_connected = 0
148 
149  // channel ID
150  variable /g chidSetVolts = 0
151  variable /g chidGetVolts = 0
152  variable /g chidSetAmps = 0
153  variable /g chidGetAmps = 0
154  variable /g chidGetWatts = 0
155  variable /g chidSetOnOff = 0
156  variable /g chidGetOnOff = 0
157  variable /g chidStatCC = 0
158  variable /g chidStatCV = 0
159  variable /g chidGetRemote = 0
160 
161  variable /g chidGetTempA = 0
162  variable /g chidGetTempB = 0
163  variable /g chidGetPyro1 = 0
164  variable /g chidGetPyroQ = 0
165 
166  variable /g chidGetPressure = 0
167 
168  // current PV values
169  variable /g curGetVolts = 0
170  variable /g curSetVolts = 0
171  variable /g curGetAmps = 0
172  variable /g curSetAmps = 0
173  variable /g curGetWatts = 0
174  variable /g curSetWatts = 0
175  variable /g curGetOnOff = 0
176  variable /g curStatCC = 0
177  variable /g curStatCV = 0
178 
179  variable /g curGetTempA = 0
180  variable /g curGetTempB = 0
181  variable /g curGetPyro1 = 0
182  variable /g curGetPyroQ = 0
183 
184  variable /g curGetPressure = 0
185 
186  // current phase indicators
187  variable /g curTargetWatts = nan
188  variable /g curTargetTempA = nan
189  variable /g curTargetTempB = nan
190  variable /g curTargetTempPy = nan
191  variable /g curTripTempA = nan
192  variable /g curTripTempB = nan
193  variable /g curTripTempPy = nan
194  variable /g curLimitPressure = nan
195  variable /g curTripPressure = nan
196  variable /g curPhaseMinutes = 0
197 
198  // chart control and data
199  make /n=500 /o recVolts, recAmps, recWatts, recTemp, recPressure, recMinutes
200  variable /g recPoint
201  variable /g recMinutesStart
202  recPoint = 0
203  recMinutesStart = datetime / 60
204 
205  // ramp status: 1 = running, 0.5 = paused, 0 = off
206  variable /g ramp_status
207  // index of the current ramp phase
208  variable /g ramp_phase
209  // ramping direction +1 = up, -1 = down
210  variable /g ramp_dir
211  // system time in minutes at the start of the current phase
212  variable /g minutes_start
213  // system time in minutes at the time of the previous step
214  variable /g minutes_previous
215  // status message for user
216  string /g ramp_message
217 
218  ann_new_ramp_table(edit_table=0)
219 
220  setdatafolder savedf
221 };
222 
223 static variable save_prefs(){
224  // saves persistent package data to the preferences file
225  dfref saveDF = GetDataFolderDFR()
226 
227  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
228  fullPath += package_name
229  NewPath/O/C/Q tempPackagePrefsPath, fullPath
230  fullPath += ":preferences.pxp"
231 
232  SetDataFolder root:packages
233  SetDataFolder $package_name
234  SaveData /O /Q /J=prefs_objects fullPath
235 
236  KillPath/Z tempPackagePrefsPath
237 
238  SetDataFolder saveDF
239 };
240 
241 static variable load_prefs(){
242  // loads persistent package data from the preferences file
243  // the preferences file is an Igor packed experiment file in a special preferences folder
244  dfref saveDF = GetDataFolderDFR()
245 
246  variable result = -1
247  setdatafolder root:
248  NewDataFolder /O/S packages
249  NewDataFolder /O/S $package_name
250  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
251  fullPath += package_name
252 
253  GetFileFolderInfo /Q /Z fullPath
254  if (V_Flag == 0)// Disk directory exists?
255  fullPath += ":preferences.pxp"
256  GetFileFolderInfo /Q /Z fullPath
257  if (V_Flag == 0)// Preference file exist?
258  LoadData /O /R /Q fullPath
259  result = 0
260  endif
261  endif
262 
263  SetDataFolder saveDF
264  return result
265 };
266 
270 static variable save_ramp(){
271  dfref saveDF = GetDataFolderDFR()
272 
273  SetDataFolder root:packages
274  SetDataFolder $package_name
275 
276  wave minutes
277  wave target_watts
278  wave target_tempA
279  wave target_tempB
280  wave target_tempPy
281  wave trip_tempA
282  wave trip_tempB
283  wave trip_tempPy
284  wave limit_pressure
285  wave trip_pressure
286 
287  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"
288 
289  SetDataFolder saveDF
290 };
291 
293 static variable IgorQuitHook(string app){
294  string app
296 };
297 
303 static variable epics_connect(){
304  dfref savedf = getdatafolderdfr()
305  setdatafolder $(package_path)
306 
307  nvar psu_connected
308  nvar ls_connected
309  nvar vac_connected
310  nvar pyro_connected
311 
312  if (!psu_connected)
314  endif
315  if (!ls_connected)
317  endif
318  if (!vac_connected)
320  endif
321  if (!pyro_connected)
323  endif
324 
325  setdatafolder saveDF
326  return !(psu_connected && ls_connected && vac_connected && pyro_connected)
327 };
328 
338 static variable epics_connect_psu(){
339  dfref savedf = getdatafolderdfr()
340  setdatafolder $(package_path)
341 
342  // create variables and waves
343  nvar connected = psu_connected
344  svar ramp_message
345 
346  // channel ID variables
347  nvar chidSetVolts
348  nvar chidGetVolts
349  nvar chidSetAmps
350  nvar chidGetAmps
351  nvar chidGetWatts
352  nvar chidSetOnOff
353  nvar chidGetOnOff
354  nvar chidStatCC
355  nvar chidStatCV
356  nvar chidGetRemote
357 
358  nvar curGetVolts
359  nvar curGetAmps
360  nvar curGetWatts
361  nvar curGetOnOff
362  nvar curStatCC
363  nvar curStatCV
364 
365  string psu_name = "X03DA-PSU-XP:"
366  variable timeout = 5// seconds
367 
368  #if exists("pvWait")
369  // EPICS.XOP version 0.3.0 or later
370  pvOpen /Q chidSetVolts, psu_name + "SETVOLTS"
371  pvOpen /Q chidGetVolts, psu_name + "GETVOLTS"
372  pvOpen /Q chidSetAmps, psu_name + "SETCUR"
373  pvOpen /Q chidGetAmps, psu_name + "GETCUR"
374  pvOpen /Q chidGetWatts, psu_name + "CALCPWR"
375  pvOpen /Q chidSetOnOff, psu_name + "SETONOFF"
376  pvOpen /Q chidGetOnOff, psu_name + "GETONOFF"
377  pvOpen /Q chidGetRemote, psu_name + "COMGETRMT"// string
378  pvOpen /Q chidStatCC, psu_name + "STAT-CC"
379  pvOpen /Q chidStatCV, psu_name + "STAT-CV"
380 
381  pvWait timeout
382  #endif
383 
384  if (GetRTError(1))
385  connected = 0
386  ramp_message = "PSU: no connection"
387  else
388  connected = 1
389  endif
390 
391  #if exists("pvMonitor")
392  if (connected)
393  pvMonitor chidGetVolts, curGetVolts
394  pvMonitor chidSetVolts, curSetVolts
395  pvMonitor chidGetAmps, curGetAmps
396  pvMonitor chidSetAmps, curSetAmps
397  pvMonitor chidGetWatts, curGetWatts
398  pvMonitor chidGetOnOff, curGetOnOff
399  pvMonitor chidStatCC, curStatCC
400  pvMonitor chidStatCV, curStatCV
401  endif
402  #endif
403 
404  setdatafolder saveDF
405  return !connected
406 };
407 
417 static variable epics_connect_ls(){
418  dfref savedf = getdatafolderdfr()
419  setdatafolder $(package_path)
420 
421  nvar connected = ls_connected
422  svar ramp_message
423 
424  nvar chidGetTempA
425  nvar chidGetTempB
426 
427  nvar curGetTempA
428  nvar curGetTempB
429 
430  string base_name = "X03DA-PC-LAKESHOREXP:"
431  variable timeout = 5// seconds
432 
433  #if exists("pvWait")
434  // EPICS.XOP version 0.3.0 or later
435  pvOpen /Q chidGetTempA, base_name + "A-TEMP_RBV"
436  pvOpen /Q chidGetTempB, base_name + "B-TEMP_RBV"
437 
438  pvWait timeout
439  #endif
440 
441  if (GetRTError(1))
442  connected = 0
443  ramp_message = "Lakeshore: no connection"
444  else
445  connected = 1
446  endif
447 
448  #if exists("pvMonitor")
449  if (connected)
450  pvMonitor /F=ann_callback_ls chidGetTempA, curGetTempA
451  pvMonitor /F=ann_callback_ls chidGetTempB, curGetTempB
452  endif
453  #endif
454 
455  setdatafolder saveDF
456  return !connected
457 };
458 
468 static variable epics_connect_vac(){
469  dfref savedf = getdatafolderdfr()
470  setdatafolder $(package_path)
471 
472  nvar connected = vac_connected
473  svar ramp_message
474 
475  nvar chidGetPressure
476 
477  nvar curGetPressure
478 
479  string base_name = "X03DA-PVC-XP:"
480  variable timeout = 5// seconds
481 
482  #if exists("pvWait")
483  // EPICS.XOP version 0.3.0 or later
484  pvOpen /Q chidGetPressure, base_name + "IG-PRESSURE"
485 
486  pvWait timeout
487  #endif
488 
489  if (GetRTError(1))
490  connected = 0
491  ramp_message = "vacuum gauge: no connection"
492  else
493  connected = 1
494  endif
495 
496  #if exists("pvMonitor")
497  if (connected)
498  pvMonitor /F=ann_callback_pvc chidGetPressure, curGetPressure
499  endif
500  #endif
501 
502  setdatafolder saveDF
503  return !connected
504 };
505 
519 static variable epics_connect_pyro(){
520  dfref savedf = getdatafolderdfr()
521  setdatafolder $(package_path)
522 
523  nvar connected = pyro_connected
524  svar ramp_message
525 
526  nvar chidGetPyro1
527  nvar chidGetPyroQ
528 
529  nvar curGetPyro1
530  nvar curGetPyroQ
531 
532  string base_name = "X03DA-LV-MAURER:"
533  variable timeout = 5// seconds
534 
535  #if exists("pvWait")
536  // EPICS.XOP version 0.3.0 or later
537  pvOpen /Q chidGetPyro1, base_name + "TEMP-1"
538  pvOpen /Q chidGetPyroQ, base_name + "TEMP-Q"
539 
540  pvWait timeout
541  #endif
542 
543  if (GetRTError(1))
544  connected = 0
545  ramp_message = "pyrometer: no connection"
546  else
547  connected = 1
548  endif
549 
550  #if exists("pvMonitor")
551  if (connected)
552  pvMonitor /F=ann_callback_ls chidGetPyro1, curGetPyro1
553  pvMonitor /F=ann_callback_ls chidGetPyroQ, curGetPyroQ
554  endif
555  #endif
556 
557  setdatafolder saveDF
558  return !connected
559 };
560 
561 static variable epics_disconnect_chid(string chid_var_name){
562  string chid_var_name
563 
564  #if exists("pvClose")
565  nvar /z chid = $chid_var_name
566  if (nvar_exists(chid))
567  if (chid != 0)
568  pvClose chid
569  endif
570  chid = 0
571  endif
572  #endif
573 };
574 
577 static variable epics_disconnect(){
578  dfref savedf = GetDataFolderDFR()
579  setdatafolder $(package_path)
580 
585 
586  setdatafolder savedf
587 };
588 
591 static variable epics_disconnect_psu(){
592  dfref savedf = GetDataFolderDFR()
593  setdatafolder $(package_path)
594 
595  nvar connected = psu_connected
596  if (connected)
597  connected = 0
598  epics_disconnect_chid("chidSetVolts")
599  epics_disconnect_chid("chidGetVolts")
600  epics_disconnect_chid("chidSetAmps")
601  epics_disconnect_chid("chidGetAmps")
602  epics_disconnect_chid("chidGetWatts")
603  epics_disconnect_chid("chidSetOnOff")
604  epics_disconnect_chid("chidGetOnOff")
605  epics_disconnect_chid("chidGetRemote")
606  epics_disconnect_chid("chidStatCC")
607  epics_disconnect_chid("chidStatCV")
608  endif
609 
610  setdatafolder savedf
611 };
612 
615 static variable epics_disconnect_ls(){
616  dfref savedf = GetDataFolderDFR()
617  setdatafolder $(package_path)
618 
619  nvar connected = ls_connected
620  if (connected)
621  connected = 0
622 
623  epics_disconnect_chid("chidGetTempA")
624  epics_disconnect_chid("chidGetTempB")
625  endif
626 
627  setdatafolder savedf
628 };
629 
632 static variable epics_disconnect_vac(){
633  dfref savedf = GetDataFolderDFR()
634  setdatafolder $(package_path)
635 
636  nvar connected = vac_connected
637  if (connected)
638  connected = 0
639 
640  epics_disconnect_chid("chidGetPressure")
641  endif
642 
643  setdatafolder savedf
644 };
645 
648 static variable epics_disconnect_pyro(){
649  dfref savedf = GetDataFolderDFR()
650  setdatafolder $(package_path)
651 
652  nvar connected = pyro_connected
653  if (connected)
654  connected = 0
655 
656  epics_disconnect_chid("chidGetPyro1")
657  epics_disconnect_chid("chidGetPyroQ")
658  endif
659 
660  setdatafolder savedf
661 };
662 
668 variable ann_new_ramp_table(variable edit_table = defaultValue){
669  variable edit_table
670 
671  if (ParamIsDefault(edit_table))
672  edit_table = 1
673  endif
674 
675  dfref savedf = GetDataFolderDFR()
676 
677  make /n=3 /o minutes,cum_minutes,target_watts
678  make /n=3 /o target_tempA, target_tempB, target_tempPy
679  make /n=3 /o limit_pressure
680  make /n=3 /o trip_tempA, trip_tempB, trip_tempPy
681  make /n=3 /o trip_pressure
682  make /n=3 /o est_temp
683 
684  minutes = 1
685  cum_minutes = nan
686  target_watts[0] = {0, 5, 0}
687  target_tempA = nan
688  target_tempB = nan
689  target_tempPy = nan
690  limit_pressure = 1e-8
691  trip_tempA = nan
692  trip_tempB = 450
693  trip_tempPy = nan
694  trip_pressure = 5e-8
695  est_temp = nan
696 
697  if (edit_table)
698  edit /k=1 minutes, target_watts
699  appendtotable target_tempA, trip_tempA
700  appendtotable target_tempB, trip_tempB
701  appendtotable target_tempPy, trip_tempPy
702  appendtotable limit_pressure,trip_pressure
703  endif
704 
705  setdatafolder savedf
706 };
707 
712 variable ann_init_bg(){
713  dfref savedf = GetDataFolderDFR()
714  setdatafolder $(package_path)
715 
716  CtrlNamedBackground ann_ramp, period = 60, proc = PearlAnneal#ann_ramp_bg
717  CtrlNamedBackground ann_record, period = 600, proc = PearlAnneal#ann_record_bg
718 
719  setdatafolder savedf
720 };
721 
723 static variable ann_record_bg(WMBackgroundStruct* s){
724  STRUCT WMBackgroundStruct &s
725 
726  dfref savedf = GetDataFolderDFR()
727  setdatafolder $(package_path)
728 
729  nvar curGetVolts
730  nvar curGetAmps
731  nvar curGetWatts
732  nvar curGetOnOff
733  nvar curStatCC
734  nvar curStatCV
735 
736  nvar curGetTempA
737  nvar curGetTempB
738  nvar curGetPyro1
739  nvar curGetPyroQ
740 
741  nvar curGetPressure
742 
743  nvar recPoint
744  nvar recMinutesStart
745 
746  wave recMinutes
747  wave recVolts
748  wave recAmps
749  wave recWatts
750  wave recTemp
751  wave recPressure
752 
753  variable nshift = 12
754  variable plo
755  variable phi
756 
757  if (recPoint >= numpnts(recWatts))
758  plo = 0
759  phi = numpnts(recWatts) - nshift - 1
760  recMinutes[plo, phi] = recMinutes[p + nshift]
761  recVolts[plo, phi] = recVolts[p + nshift]
762  recAmps[plo, phi] = recAmps[p + nshift]
763  recWatts[plo, phi] = recWatts[p + nshift]
764  recTemp[plo, phi] = recTemp[p + nshift]
765  recPressure[plo, phi] = recPressure[p + nshift]
766 
767  plo = numpnts(recWatts) - nshift
768  phi = numpnts(recWatts) - 1
769  recMinutes[plo, phi] = nan
770  recVolts[plo, phi] = nan
771  recAmps[plo, phi] = nan
772  recWatts[plo, phi] = nan
773  recTemp[plo, phi] = nan
774  recPressure[plo, phi] = nan
775 
776  recPoint = plo
777  endif
778 
779  variable temp = curGetTempA
780  if (curGetPyroQ >= 625)
781  temp = max(temp, curGetPyroQ)
782  else if (curGetPyro1 >= 625)
783  temp = max(temp, curGetPyro1)
784  endif
785 
786  recMinutes[recPoint] = datetime / 60 - recMinutesStart
787  recVolts[recPoint] = curGetVolts
788  recAmps[recPoint] = curGetAmps
789  recWatts[recPoint] = curGetWatts
790  recTemp[recPoint] = temp
791  recPressure[recPoint] = curGetPressure
792 
793  recPoint += 1
794 
795  setdatafolder savedf
796  return 0
797 };
798 
800 static variable ann_ramp_bg(WMBackgroundStruct* s){
801  STRUCT WMBackgroundStruct &s
802 
803  dfref savedf = GetDataFolderDFR()
804  setdatafolder $(package_path)
805 
806  ann_ramp_step()
807 
808  setdatafolder savedf
809  return 0
810 };
811 
816 variable ann_ramp_step(){
817  dfref savedf = GetDataFolderDFR()
818  setdatafolder $(package_path)
819 
820  nvar minutes_start
821  nvar minutes_previous
822  nvar ramp_phase
823  svar ramp_message
824 
825  wave minutes
826  wave target_watts
827 
828  variable minutes_now = datetime / 60
829  variable minutes_phase = minutes_now - minutes_start
830  variable minutes_step = minutes_now - minutes_previous
831 
832  variable trip
833  variable hold
834  variable phase_complete
835 
836  ann_ramp_update(ramp_phase)
837  // check trip conditions
838  trip = ann_ramp_trip(ramp_phase)
839  if (!trip)
840  // check hold conditions
841  hold = ann_ramp_hold(ramp_phase)
842  if (!hold)
843  // check targets
844  phase_complete = ann_ramp_target(ramp_phase)
845  if (!phase_complete)
846  // execute step
847  phase_complete = ann_ramp_step_exec(minutes_now)
848  ramp_message = ""
849  endif
850  if (phase_complete)
851  ramp_phase += 1
852  minutes_start = minutes_now
853  // check end of ramp
854  if ((ramp_phase >= numpnts(minutes)) || (ramp_phase >= numpnts(target_watts)) || numtype(minutes[ramp_phase]) || numtype(target_watts[ramp_phase]))
855  ann_ramp_stop(0)
856  endif
857  endif
858  endif
859  endif
860 
861  minutes_previous = minutes_now
862 
863  setdatafolder savedf
864  return 0
865 };
866 
868 static variable ann_ramp_update(variable phase){
869  variable phase
870 
871  dfref savedf = GetDataFolderDFR()
872  setdatafolder $(package_path)
873 
874  wave minutes
875  wave target_watts
876  wave target_tempA
877  wave target_tempB
878  wave target_tempPy
879  wave trip_tempA
880  wave trip_tempB
881  wave trip_tempPy
882  wave limit_pressure
883  wave trip_pressure
884 
885  nvar curTargetWatts
886  nvar curTargetTempA
887  nvar curTargetTempB
888  nvar curTargetTempPy
889  nvar curTripTempA
890  nvar curTripTempB
891  nvar curTripTempPy
892  nvar curLimitPressure
893  nvar curTripPressure
894  nvar curPhaseMinutes
895 
896  curPhaseMinutes = minutes[phase]
897  curTargetWatts = target_watts[phase]
898  curTargetTempA = target_tempA[phase]
899  curTargetTempB = target_tempB[phase]
900  curTargetTempPy = target_tempPy[phase]
901  curTripTempA = trip_tempA[phase]
902  curTripTempB = trip_tempB[phase]
903  curTripTempPy = trip_tempPy[phase]
904  curLimitPressure = limit_pressure[phase]
905  curTripPressure = trip_pressure[phase]
906 
907  setdatafolder savedf
908 };
909 
916 static variable ann_ramp_step_exec(variable minutes_now){
917  variable minutes_now
918 
919  dfref savedf = GetDataFolderDFR()
920  setdatafolder $(package_path)
921 
922  nvar chidSetVolts
923  nvar chidSetAmps
924 
925  nvar curGetVolts
926  nvar curGetAmps
927  nvar curGetWatts
928  nvar curSetVolts
929  nvar curSetAmps
930  nvar curSetWatts
931 
932  nvar minutes_start
933  nvar minutes_previous
934  nvar ramp_phase
935  nvar ramp_dir
936 
937  variable p2 = ramp_phase
938  variable p1 = p2 - 1
939 
940  variable minutes_phase = minutes_now - minutes_start
941  variable minutes_step = minutes_now - minutes_previous
942 
943  wave minutes
944  wave target_watts
945 
946  variable step_watts
947  variable next_volts
948  variable next_amps
949  variable next_watts
950  variable resistance
951 
952  variable max_step_volts = 0.5
953  variable max_step_amps = 0.1
954  variable max_test_volts = 5.0
955  variable max_test_amps = 0.5
956 
957  variable watts_complete
958 
959  // calculate power step
960  step_watts = (target_watts[p2] - target_watts[p1]) / minutes[p2] * minutes_step
961  next_watts = curSetWatts + step_watts
962 
963  // check end of ramp phase
964  if (step_watts > 0.0001)
965  watts_complete = next_watts > target_watts[p2]
966  else if (step_watts < -0.0001)
967  watts_complete = next_watts < target_watts[p2]
968  else
969  watts_complete = minutes_phase >= minutes[p2]
970  endif
971 
972  // limit power
973  if (watts_complete)
974  next_watts = curSetWatts
975  else
976  next_watts = limit(next_watts, 0, max(target_watts[p1], target_watts[p2]))
977  endif
978 
979  // calculate voltage and current
980  if (next_watts >= 0.1)
981  curSetWatts = next_watts
982  if ((curGetVolts > 0.1) && (curGetAmps > 0.1))
983  resistance = curGetVolts / curGetAmps
984  next_volts = limit(sqrt(next_watts * resistance), 0, curGetVolts + max_step_volts)
985  next_amps = limit(sqrt(next_watts / resistance), 0, curGetAmps + max_step_amps)
986  else
987  // apply small voltage to measure the resistance
988  next_volts = min(curSetVolts + 0.5, max_test_volts)
989  next_amps = min(curSetAmps + 0.1, max_test_amps)
990  endif
991  else
992  curSetWatts = next_watts
993  next_volts = 0
994  next_amps = 0
995  endif
996 
997  // change setpoints
998  pvPutNumber /Q chidSetVolts, next_volts
999  pvPutNumber /Q chidSetAmps, next_amps
1000  pvWait 5
1001 
1002  setdatafolder savedf
1003  return watts_complete
1004 };
1005 
1011 static variable ann_ramp_trip(variable phase){
1012  variable phase
1013 
1014  dfref savedf = GetDataFolderDFR()
1015  setdatafolder $(package_path)
1016 
1017  variable trip = 0
1018 
1019  wave trip_tempA
1020  wave trip_tempB
1021  wave trip_tempPy
1022  wave trip_pressure
1023 
1024  nvar curGetTempA
1025  nvar curGetTempB
1026  nvar curGetTempPyro1
1027  nvar curGetTempPyroQ
1028  nvar curGetPressure
1029  svar ramp_message
1030 
1031  if ((phase < numpnts(trip_tempA)) && (numtype(trip_tempA[phase]) == 0) && (curGetTempA >= trip_tempA[phase]))
1032  ramp_message = "temperature A trip"
1033  trip = 1
1034  endif
1035  if ((phase < numpnts(trip_tempB)) && (numtype(trip_tempB[phase]) == 0) && (curGetTempB >= trip_tempB[phase]))
1036  ramp_message = "temperature B trip"
1037  trip = 2
1038  endif
1039  if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyro1 >= trip_tempPy[phase]))
1040  ramp_message = "pyrometer trip (1)"
1041  trip = 3
1042  endif
1043  if ((phase < numpnts(trip_tempPy)) && (numtype(trip_tempPy[phase]) == 0) && (curGetTempPyroQ >= trip_tempPy[phase]))
1044  ramp_message = "pyrometer trip (Q)"
1045  trip = 4
1046  endif
1047  if ((phase < numpnts(trip_pressure)) && (numtype(trip_pressure[phase]) == 0) && (curGetPressure >= trip_pressure[phase]))
1048  ramp_message = "pressure trip"
1049  trip = 5
1050  endif
1051 
1052  if (trip)
1053  ann_ramp_stop(1)
1054  endif
1055 
1056  setdatafolder savedf
1057  return trip
1058 };
1059 
1064 static variable ann_ramp_hold(variable phase){
1065  variable phase
1066 
1067  dfref savedf = GetDataFolderDFR()
1068  setdatafolder $(package_path)
1069 
1070  nvar curGetPressure
1071 
1072  variable hold = 0
1073 
1074  wave limit_pressure
1075 
1076  if ((phase < numpnts(limit_pressure)) && (numtype(limit_pressure[phase]) == 0) && (curGetPressure >= limit_pressure[phase]))
1077  hold = 5
1078  endif
1079 
1080  setdatafolder savedf
1081  return hold
1082 };
1083 
1087 static variable ann_ramp_target(variable phase){
1088  variable phase
1089 
1090  if (phase < 1)
1091  return 0
1092  endif
1093 
1094  dfref savedf = GetDataFolderDFR()
1095  setdatafolder $(package_path)
1096 
1097  variable target = 0
1098 
1099  wave target_watts
1100  wave target_tempA
1101  wave target_tempB
1102  wave target_tempPy
1103 
1104  variable direction_up = target_watts[phase] >= target_watts[phase - 1]
1105 
1106  nvar curGetTempA
1107  nvar curGetTempB
1108  nvar curGetTempPyro1
1109  nvar curGetTempPyroQ
1110  svar ramp_message
1111 
1112  if ((phase < numpnts(target_tempA)) && (numtype(target_tempA[phase]) == 0))
1113  if (direction_up)
1114  if (curGetTempA >= target_tempA[phase])
1115  target = 1
1116  endif
1117  else
1118  if (curGetTempA <= target_tempA[phase])
1119  target = 1
1120  endif
1121  endif
1122  endif
1123 
1124  if ((phase < numpnts(target_tempB)) && (numtype(target_tempB[phase]) == 0))
1125  if (direction_up)
1126  if (curGetTempB >= target_tempB[phase])
1127  target = 2
1128  endif
1129  else
1130  if (curGetTempB <= target_tempB[phase])
1131  target = 2
1132  endif
1133  endif
1134  endif
1135 
1136  if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0))
1137  if (direction_up)
1138  if (curGetTempPyro1 >= target_tempPy[phase])
1139  target = 3
1140  endif
1141  else
1142  if (curGetTempPyro1 <= target_tempPy[phase])
1143  target = 3
1144  endif
1145  endif
1146  endif
1147 
1148  if ((phase < numpnts(target_tempPy)) && (numtype(target_tempPy[phase]) == 0))
1149  if (direction_up)
1150  if (curGetTempPyroQ >= target_tempPy[phase])
1151  target = 4
1152  endif
1153  else
1154  if (curGetTempPyroQ <= target_tempPy[phase])
1155  target = 4
1156  endif
1157  endif
1158  endif
1159 
1160  switch(target)
1161  case 1:
1162  ramp_message = "temperature A target reached"
1163  break
1164  case 2:
1165  ramp_message = "temperature B target reached"
1166  break
1167  case 3:
1168  ramp_message = "pyrometer 1 target reached"
1169  break
1170  case 4:
1171  ramp_message = "pyrometer Q target reached"
1172  break
1173  endswitch
1174 
1175  setdatafolder savedf
1176  return target
1177 };
1178 
1180 variable ann_ramp_start(){
1181  dfref savedf = GetDataFolderDFR()
1182  setdatafolder $(package_path)
1183 
1184  epics_connect()
1185 
1186  nvar recPoint
1187  nvar recMinutesStart
1188  recPoint = 0
1189  recMinutesStart = datetime / 60
1190 
1191  wave recMinutes
1192  wave recVolts
1193  wave recAmps
1194  wave recWatts
1195  wave recTemp
1196  wave recPressure
1197 
1198  recMinutes = nan
1199  recVolts = nan
1200  recAmps = nan
1201  recWatts = nan
1202  recTemp = nan
1203  recPressure = nan
1204 
1205  nvar minutes_start
1206  minutes_start = datetime / 60
1207  nvar minutes_previous
1208  minutes_previous = minutes_start
1209  nvar ramp_phase
1210  ramp_phase = 1
1211  nvar ramp_status
1212  ramp_status = 1
1213 
1214  nvar chidSetVolts
1215  nvar chidSetAmps
1216  nvar chidSetOnOff
1217 
1218  wave target_watts
1219 
1220  pvPutNumber /Q chidSetVolts, 0.5
1221  pvPutNumber /Q chidSetAmps, 0.5
1222  pvPutNumber /Q chidSetOnOff, 0
1223  pvWait 5
1224 
1225  nvar curSetWatts
1226  curSetWatts = target_watts[0]
1227 
1228  ann_init_bg()
1229  CtrlNamedBackground ann_ramp, start
1230  CtrlNamedBackground ann_record, start
1231 
1232  setdatafolder savedf
1233  return 0
1234 };
1235 
1236 variable ann_ramp_pause(){
1237  dfref savedf = GetDataFolderDFR()
1238  setdatafolder $(package_path)
1239 
1240  CtrlNamedBackground ann_ramp, stop
1241 
1242  nvar ramp_status
1243  ramp_status = 0.5
1244 
1245  setdatafolder savedf
1246  return 0
1247 };
1248 
1249 variable ann_ramp_resume(){
1250  dfref savedf = GetDataFolderDFR()
1251  setdatafolder $(package_path)
1252 
1253  CtrlNamedBackground ann_ramp, start
1254 
1255  nvar ramp_status
1256  ramp_status = 1
1257 
1258  setdatafolder savedf
1259  return 0
1260 };
1261 
1266 variable ann_ramp_stop(variable reset_psu){
1267  variable reset_psu
1268 
1269  dfref savedf = GetDataFolderDFR()
1270  setdatafolder $(package_path)
1271 
1272  CtrlNamedBackground ann_ramp, stop
1273  CtrlNamedBackground ann_record, stop
1274 
1275  nvar ramp_phase
1276  ramp_phase = 0
1277  nvar ramp_status
1278  ramp_status = 0
1279  nvar curTargetWatts
1280 
1281  if (reset_psu || (curTargetWatts < 1))
1282  nvar chidSetVolts
1283  nvar chidSetAmps
1284  nvar chidSetOnOff
1285  pvPutNumber /Q chidSetVolts, 0
1286  pvPutNumber /Q chidSetAmps, 0
1287  pvPutNumber /Q chidSetOnOff, 1
1288  pvWait 5
1289  endif
1290 
1291  setdatafolder savedf
1292  return 0
1293 };
1294 
1295 variable ann_display_ramp(){
1296  dfref savedf = GetDataFolderDFR()
1297  setdatafolder $(package_path)
1298 
1299  wave recMinutes
1300  wave recVolts
1301  wave recAmps
1302  wave recWatts
1303  wave recTemp
1304  wave recPressure
1305 
1306  display recWatts vs recMinutes
1307  appendtograph /r recVolts vs recMinutes
1308  appendtograph /r recAmps vs recMinutes
1309 };
1310 
1312  PauseUpdate; Silent 1// building window...
1313  NewPanel /K=1 /W=(441,64,887,702) as "ramp generator"
1314  ValDisplay valdisp0,pos={11,178},size={233,42},bodyWidth=200,title="pyro 1"
1315  ValDisplay valdisp0,limits={0,1500,625},barmisc={10,50}
1316  ValDisplay valdisp0,value= #"root:packages:pearl_anneal:curGetPyro1"
1317  ValDisplay valdisp1,pos={11,233},size={233,42},bodyWidth=200,title="pyro q"
1318  ValDisplay valdisp1,limits={0,1500,625},barmisc={10,50}
1319  ValDisplay valdisp1,value= #"root:packages:pearl_anneal:curGetPyroQ"
1320  ValDisplay valdisp2,pos={11,73},size={234,42},bodyWidth=200,title="lake A"
1321  ValDisplay valdisp2,limits={0,1500,300},barmisc={10,50}
1322  ValDisplay valdisp2,value= #"root:packages:pearl_anneal:curGetTempA"
1323  ValDisplay valdisp3,pos={10,128},size={234,42},bodyWidth=200,title="lake B"
1324  ValDisplay valdisp3,limits={0,1500,300},barmisc={10,50}
1325  ValDisplay valdisp3,value= #"root:packages:pearl_anneal:curGetTempB"
1326  ValDisplay valdisp4,pos={16,23},size={229,42},bodyWidth=200,title="watts"
1327  ValDisplay valdisp4,limits={0,90,0},barmisc={10,50}
1328  ValDisplay valdisp4,value= #"root:packages:pearl_anneal:curGetWatts"
1329  ValDisplay valdisp5,pos={6,5},size={60,14},title="phase"
1330  ValDisplay valdisp5,limits={0,0,0},barmisc={0,1000}
1331  ValDisplay valdisp5,value= #"root:packages:pearl_anneal:ramp_phase"
1332  ValDisplay valdisp6,pos={0,282},size={244,42},bodyWidth=200,title="pressure"
1333  ValDisplay valdisp6,format="%.1e",limits={1e-09,1e-08,0},barmisc={10,80}
1334  ValDisplay valdisp6,value= #"root:packages:pearl_anneal:curGetPressure"
1335  ValDisplay valdisp7,pos={335,90},size={47,14},bodyWidth=14,title="power"
1336  ValDisplay valdisp7,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (60928,60928,60928),lowColor= (0,52224,0),zeroColor= (61440,61440,61440)
1337  ValDisplay valdisp7,value= #"root:packages:pearl_anneal:curGetOnOff"
1338  ValDisplay valdisp16,pos={262,168},size={114,14},bodyWidth=34,title="target temp pyro"
1339  ValDisplay valdisp16,limits={0,0,0},barmisc={0,1000},mode= 2,highColor= (60928,60928,60928),lowColor= (65280,0,0),zeroColor= (0,52224,0)
1340  ValDisplay valdisp16,value= #"root:packages:pearl_anneal:curTargetTempPy"
1341  ValDisplay valdisp17,pos={300,4},size={80,14},bodyWidth=14,title="power supply"
1342  ValDisplay valdisp17,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
1343  ValDisplay valdisp17,value= #"root:packages:pearl_anneal:psu_connected"
1344  ValDisplay valdisp18,pos={317,21},size={64,14},bodyWidth=14,title="lakeshore"
1345  ValDisplay valdisp18,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
1346  ValDisplay valdisp18,value= #"root:packages:pearl_anneal:ls_connected"
1347  ValDisplay valdisp19,pos={318,38},size={64,14},bodyWidth=14,title="pyrometer"
1348  ValDisplay valdisp19,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
1349  ValDisplay valdisp19,value= #"root:packages:pearl_anneal:pyro_connected"
1350  ValDisplay valdisp20,pos={293,52},size={91,14},bodyWidth=14,title="vacuum system"
1351  ValDisplay valdisp20,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (65280,0,0),zeroColor= (61440,61440,61440)
1352  ValDisplay valdisp20,value= #"root:packages:pearl_anneal:vac_connected"
1353  ValDisplay valdisp21,pos={341,76},size={41,14},bodyWidth=14,title="ramp"
1354  ValDisplay valdisp21,limits={0,1,0.5},barmisc={0,0},mode= 2,highColor= (0,52224,0),lowColor= (61440,61440,61440),zeroColor= (0,34816,52224)
1355  ValDisplay valdisp21,value= #"root:packages:pearl_anneal:ramp_status"
1356  ValDisplay valdisp8,pos={278,120},size={100,14},title="target watts"
1357  ValDisplay valdisp8,limits={0,0,0},barmisc={0,1000}
1358  ValDisplay valdisp8,value= #"root:packages:pearl_anneal:curTargetWatts"
1359  ValDisplay valdisp9,pos={278,137},size={100,14},title="target temp A"
1360  ValDisplay valdisp9,limits={0,0,0},barmisc={0,1000}
1361  ValDisplay valdisp9,value= #"root:packages:pearl_anneal:curTargetTempA"
1362  ValDisplay valdisp10,pos={278,152},size={100,14},title="target temp B"
1363  ValDisplay valdisp10,limits={0,0,0},barmisc={0,1000}
1364  ValDisplay valdisp10,value= #"root:packages:pearl_anneal:curTargetTempB"
1365  ValDisplay valdisp11,pos={271,266},size={100,14},title="limit pressure"
1366  ValDisplay valdisp11,limits={0,0,0},barmisc={0,1000}
1367  ValDisplay valdisp11,value= #"root:packages:pearl_anneal:curLimitPressure"
1368  ValDisplay valdisp12,pos={261,205},size={100,14},title="trip temp A"
1369  ValDisplay valdisp12,limits={0,0,0},barmisc={0,1000}
1370  ValDisplay valdisp12,value= #"root:packages:pearl_anneal:curTripTempA"
1371  ValDisplay valdisp13,pos={262,224},size={100,14},title="trip temp B"
1372  ValDisplay valdisp13,limits={0,0,0},barmisc={0,1000}
1373  ValDisplay valdisp13,value= #"root:packages:pearl_anneal:curTripTempB"
1374  ValDisplay valdisp14,pos={276,242},size={100,14},title="trip pyro"
1375  ValDisplay valdisp14,limits={0,0,0},barmisc={0,1000}
1376  ValDisplay valdisp14,value= #"root:packages:pearl_anneal:curTripTempPy"
1377  ValDisplay valdisp15,pos={273,309},size={100,14},title="ramp interval"
1378  ValDisplay valdisp15,limits={0,0,0},barmisc={0,1000}
1379  ValDisplay valdisp15,value= #"root:packages:pearl_anneal:curPhaseMinutes"
1380  Button b_start,pos={15,362},size={50,20},proc=PearlAnneal#bp_ramp_start,title="start"
1381  Button b_start,fColor=(0,52224,0)
1382  Button b_pause,pos={75,362},size={50,20},proc=PearlAnneal#bp_ramp_pause,title="pause"
1383  Button b_stop,pos={135,362},size={50,20},proc=PearlAnneal#bp_ramp_stop,title="stop"
1384  Button b_stop,fColor=(52224,0,0)
1385  Button b_edit,pos={195,362},size={50,20},proc=PearlAnneal#bp_ramp_edit,title="edit"
1386  ValDisplay valdisp11_1,pos={274,282},size={100,14},title="trip pressure"
1387  ValDisplay valdisp11_1,limits={0,0,0},barmisc={0,1000}
1388  ValDisplay valdisp11_1,value= #"root:packages:pearl_anneal:curTripPressure"
1389  TitleBox title0,pos={16,334},size={400,20}
1390  TitleBox title0,variable= root:packages:pearl_anneal:ramp_message,fixedSize=1
1391  DefineGuide UGH0={FT,390}
1392  String fldrSav0= GetDataFolder(1)
1393  SetDataFolder root:packages:pearl_anneal:
1394  Display/W=(82,153,246,462)/FG=(FL,UGH0,FR,FB)/HOST=# recTemp vs recMinutes
1395  AppendToGraph/R recPressure vs recMinutes
1396  AppendToGraph/L=power recWatts vs recMinutes
1397  NewFreeAxis/O/L power
1398  SetDataFolder fldrSav0
1399  ModifyGraph margin(left)=80
1400  ModifyGraph rgb(recPressure)=(0,0,65280),rgb(recWatts)=(0,39168,0)
1401  ModifyGraph log(right)=1
1402  ModifyGraph mirror(bottom)=2
1403  ModifyGraph nticks=3
1404  ModifyGraph minor=1
1405  ModifyGraph axThick=0.5
1406  ModifyGraph axRGB(left)=(65280,0,0),axRGB(right)=(0,0,65280),axRGB(power)=(0,39168,0)
1407  ModifyGraph tlblRGB(left)=(65280,0,0),tlblRGB(right)=(0,0,65280),tlblRGB(power)=(0,39168,0)
1408  ModifyGraph alblRGB(left)=(65280,0,0),alblRGB(right)=(0,0,65280),alblRGB(power)=(0,39168,0)
1409  ModifyGraph lblPos(left)=42,lblPos(power)=35
1410  ModifyGraph lblLatPos(left)=1
1411  ModifyGraph btLen=4
1412  ModifyGraph freePos(power)=48
1413  Label left "temperature (K)"
1414  Label bottom "time (minutes)"
1415  Label right "pressure (mbar)"
1416  Label power "power (W)"
1417  SetAxis/E=1 power 0,80
1418  RenameWindow #,G0
1419  SetActiveSubwindow ##
1420 };
1421 
1422 static variable bp_ramp_start(WMButtonAction* ba){
1423  struct WMButtonAction &ba
1424 
1425  switch( ba.eventCode )
1426  case 2:// mouse up
1427  dfref ann_df = $(package_path)
1428  nvar /sdfr=ann_df ramp_status
1429  if (ramp_status < 0.4)
1430  ann_ramp_start()
1431  endif
1432  break
1433  case -1:// control being killed
1434  break
1435  endswitch
1436 
1437  return 0
1438 };
1439 
1440 static variable bp_ramp_pause(WMButtonAction* ba){
1441  struct WMButtonAction &ba
1442 
1443  switch( ba.eventCode )
1444  case 2:// mouse up
1445  dfref ann_df = $(package_path)
1446  nvar /sdfr=ann_df ramp_status
1447  if (ramp_status > 0.6)
1448  ann_ramp_pause()
1449  Button b_pause, win=$(ba.win), title="resume"
1450  else
1451  ann_ramp_resume()
1452  Button b_pause, win=$(ba.win), title="pause"
1453  endif
1454  break
1455  case -1:// control being killed
1456  break
1457  endswitch
1458 
1459  return 0
1460 };
1461 
1462 static variable bp_ramp_stop(WMButtonAction* ba){
1463  struct WMButtonAction &ba
1464 
1465  switch( ba.eventCode )
1466  case 2:// mouse up
1467  ann_ramp_stop(1)
1468  break
1469  case -1:// control being killed
1470  break
1471  endswitch
1472 
1473  return 0
1474 };
1475 
1476 static variable bp_ramp_edit(WMButtonAction* ba){
1477  struct WMButtonAction &ba
1478 
1479  dfref savedf = GetDataFolderDFR()
1480  switch( ba.eventCode )
1481  case 2:// mouse up
1482  setdatafolder $(package_path)
1483 
1484  wave minutes
1485  wave target_watts
1486  wave target_tempA
1487  wave target_tempB
1488  wave target_tempPy
1489  wave trip_tempA
1490  wave trip_tempB
1491  wave trip_tempPy
1492  wave limit_pressure
1493  wave trip_pressure
1494 
1495  edit /k=1 minutes, target_watts
1496  appendtotable target_tempA, trip_tempA
1497  appendtotable target_tempB, trip_tempB
1498  appendtotable target_tempPy, trip_tempPy
1499  appendtotable limit_pressure,trip_pressure
1500 
1501  break
1502  case -1:// control being killed
1503  break
1504  endswitch
1505 
1506  setdatafolder savedf
1507  return 0
1508 };
1509 
static variable ann_record_bg(WMBackgroundStruct *s)
background task of the recorder
static const string prefs_objects
static variable load_prefs()
variable ann_init_bg()
initialize the background tasks
void panel_ramp_gen()
static variable ann_ramp_bg(WMBackgroundStruct *s)
background task of the ramp
static variable save_ramp()
save current ramp table
static variable epics_disconnect()
disconnect from all EPICS devices.
static const string package_path
variable ann_new_ramp_table(variable edit_table=defaultValue)
create a new ramp table and open it in a table window.
static variable ann_ramp_target(variable phase)
check target conditions
static variable ann_ramp_hold(variable phase)
check hold conditions
static variable ann_ramp_update(variable phase)
update control panel variables
variable ann_ramp_pause()
static variable epics_connect_vac()
connect to the vacuum gauge
static variable epics_disconnect_psu()
disconnect from the power supply unit
static variable epics_connect_psu()
connect to the power supply unit
variable ann_display_ramp()
static variable epics_connect_ls()
connect to the lakeshore temperature controller
static variable epics_connect_pyro()
connect to the pyrometer
static variable epics_disconnect_vac()
disconnect from the vacuum gauge
variable ann_ramp_step()
prepare and execute the next ramp step
ramp generator for sample annealing
static const string package_name
static variable AfterCompiledHook()
static variable save_prefs()
static variable init_package()
initialize the package data folder
static variable bp_ramp_start(WMButtonAction *ba)
variable ann_ramp_start()
start an annealing ramp
static variable ann_ramp_step_exec(variable minutes_now)
execute the next ramp step
static variable bp_ramp_pause(WMButtonAction *ba)
static variable epics_disconnect_ls()
disconnect from the lakeshore controller
static variable ann_ramp_trip(variable phase)
check trip conditions
static variable epics_connect()
connect to all required EPICS devices.
static variable bp_ramp_stop(WMButtonAction *ba)
static variable IgorQuitHook(string app)
Igor sometimes crashes if the PVs are not disconnected when it quits.
variable ann_ramp_resume()
static variable epics_disconnect_pyro()
disconnect from the pyrometer
variable ann_ramp_stop(variable reset_psu)
stop a running annealing ramp
static variable epics_disconnect_chid(string chid_var_name)
static variable bp_ramp_edit(WMButtonAction *ba)