source: trunk/FACT++/scripts/Main.js@ 15054

Last change on this file since 15054 was 15030, checked in by tbretz, 12 years ago
Also reset the rate control state after the single-pe run.
File size: 27.9 KB
Line 
1/**
2 * @fileOverview This file has functions related to documenting JavaScript.
3 * @author <a href="mailto:thomas.bretz@epfl.ch">Thomas Bretz</a>
4 */
5'use strict';
6
7//this is just the class implementation of 'Observation'
8include('scripts/Observation_class.js');
9
10dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
11
12
13// error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
14// clases: http://www.phpied.com/3-ways-to-define-a-javascript-class/
15//
16// Arguments: TakeFirstDrsCalib
17// To be determined: How to stop the script without foreceful interruption?
18
19// adapt states of drivectrl
20
21//
22// SCRIPTS:
23//
24// - Startup, e.g. do not open LID
25//
26// - Bring telescop to state 'operational', e.g. open lid,
27// when first run != START is detected in the loop
28//
29// - Take data
30//
31// - Shutdown
32//
33// ----> Does smartfact display alarm messages already?
34// ----> How to display errors in smartfact? Is that necessary at all?
35// (red output? maybe just <red>...</red>?
36//
37// ----------------------------------------------------------------
38
39function currentEst(source)
40{
41 var moon = new Moon();
42 if (!moon.isUp)
43 return 7.7;
44
45 var dist = Sky.dist(moon, source);
46
47 var alt = 90-moon.toLocal().zd;
48
49 var lc = dist*alt*pow(Moon.disk(), 6)/360/360;
50
51 var cur = 7.7+4942*lc;
52
53 return cur;
54}
55
56function thresholdEst(source) // relative threshold (ratio)
57{
58 // Assumption:
59 // atmosphere is 70km, shower taks place after 60km, earth radius 6400km
60 // just using the cosine law
61 // This fits very well with MC results: See Roger Firpo, p.45
62 // "Study of the MAGIC telescope sensitivity for Large Zenith Angle observations"
63
64 var c = Math.cos(Math.Pi-source.zd);
65 var ratio = (10*sqrt(409600*c*c+9009) + 6400*c - 60)/10;
66
67 // assumption: Energy threshold increases linearily with current
68 // assumption: Energy threshold increases linearily with distance
69
70 return ratio*currentEst(source)/7.7;
71}
72
73// Ratio in rate would be (estimate, not precise calculation)
74// pow(ratio, -0.7)
75
76// ----------------------------------------------------------------
77
78//DN: the name of the Subscription object 'service_con' is not really
79// telling that its a subscription to FAD_CONTROL/CONNECTIONS
80// fad_connections sound ok for be, since
81// fad_connections.onchange() is pretty clear
82// fad_connections.reconnect() is not really good, but at least it has FAD in it.
83var service_con = new Subscription("FAD_CONTROL/CONNECTIONS");
84/**
85 * call-back function of FAD_CONTROL/CONNECTIONS
86 * store IDs of problematic FADs
87 *
88 */
89service_con.onchange = function(evt)
90{
91 // This happens, but why?
92 if (!evt.obj['status'])
93 return;
94
95 this.reset = [ ];
96
97 for (var x=0; x<40; x++)
98 if (evt.obj['status'][x]!=66 && evt.obj['status'][x]!=67)
99 this.reset.push(x);
100
101 if (this.reset.length==0)
102 return;
103
104 dim.alarm("FAD board loss detected...");
105 dim.send("MCP/RESET");
106 dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
107}
108
109/**
110 * reconnect to problematic FADs
111 *
112 * Dis- and Reconnects to FADs, found to be problematic by call-back function
113 * onchange() to have a different CONNECTION value than 66 or 67.
114 *
115 * @returns
116 * a boolean is returned.
117 * reconnect returns true if:
118 * * nothing needed to be reset --> no problems found by onchange()
119 * * the reconnection went fine.
120 *
121 * reconnect *never returns false* so far.
122 *
123 * @example
124 * if (!service_con.reconnect())
125 * exit();
126 */
127service_con.reconnect = function()
128{
129 // this.reset is a list containing the IDs of FADs,
130 // which have neither CONNECTION==66 nor ==67, whatever this means :-)
131 if (this.reset.length==0)
132 return true;
133
134 console.out(" Reconnect: start ["+this.reset.length+"]");
135
136 for (var i=0; i<this.reset.length; i++)
137 dim.send("FAD_CONTROL/DISCONNECT", this.reset[i]);
138
139 v8.sleep(3000);
140
141 while (this.reset.length)
142 dim.send("FAD_CONTROL/CONNECT", this.reset.pop());
143
144 v8.sleep(1000);
145 dim.wait("FAD_CONTROL", "Connected", 3000);
146
147 console.out(" Reconnect: end");
148
149 return true;
150}
151
152function takeRun(type, count, time)
153{
154 if (!count)
155 count = -1;
156 if (!time)
157 time = -1;
158
159 console.out(" Take run N="+count+" T="+time+"s ["+type+"]");
160 // change rats for cal runs1!!!
161
162 dim.send("MCP/START", time?time:-1, count?count:-1, type);
163
164
165
166 // What could be a reasonable timeout here?
167 // FIXME: Replace by callback?
168 //
169 // DN: I believe instead of waiting for 'TakingData' one could split this
170 // up into two checks with an extra condition:
171 // if type == 'data':
172 // wait until ThresholdCalibration starts:
173 // --> this time should be pretty identical for each run
174 // if this takes longer than say 3s:
175 // there might be a problem with one/more FADs
176 //
177 // wait until "TakingData":
178 // --> this seems to take even some minutes sometimes...
179 // (might be optimized rather soon, but still in the moment...)
180 // if this takes way too long:
181 // there might be something broken,
182 // so maybe a very high time limit is ok here.
183 // I think there is not much that can go wrong,
184 // when the Thr-Calib has already started. Still it might be nice
185 // If in the future RateControl is written so to find out that
186 // in case the threshold finding algorithm does
187 // *not converge as usual*
188 // it can complain, and in this way give a hint, that the weather
189 // might be a little bit too bad.
190 // else:
191 // wait until "TakingData":
192 // --> in a non-data run this time should be pretty short again
193 // if this takes longer than say 3s:
194 // there might be a problem with one/more FADs
195 //
196
197 if (!dim.wait("MCP", "TakingData", -300000) )
198 {
199 console.out("MCP took longer than 5 minutes to start TakingData");
200 console.out("maybe this idicates a problem with one of the FADs?");
201 dimctrl.setState(37);
202 dim.wait("MCP", "TakingData", 500);
203 }
204 dim.wait("MCP", "Idle");
205
206 console.out(" Take run: end");
207
208 // DN: currently reconnect() never returns false
209 // .. but it can fail of course.
210 if (!service_con.reconnect())
211 exit();
212
213 return true;//service_con.reconnect();
214}
215
216// ----------------------------------------------------------------
217
218function doDrsCalibration()
219{
220 console.out(" DRS cal: start");
221 service_feedback.voltageOff();
222
223 while (1)
224 {
225 dim.send("FAD_CONTROL/START_DRS_CALIBRATION");
226 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
227 continue;
228 if (!takeRun("drs-gain", 1000)) // 40 / 20s (50Hz)
229 continue;
230 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
231 continue;
232
233 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
234 if (!takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
235 continue;
236 if (!takeRun("drs-time", 1000)) // 40 / 20s (50Hz)
237 continue;
238
239 dim.send("FAD_CONTROL/RESET_SECONDARY_DRS_BASELINE");
240 if (!takeRun("pedestal", 1000)) // 40 / 10s (80Hz)
241 continue;
242
243 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
244 if (!takeRun("pedestal", 1000)) // 40 / 10s (80Hz)
245 continue;
246 // -----------
247 // 4'40 / 2'00
248
249 break;
250 }
251
252 dim.send("RATE_CONTROL/STOP"); // get out of GlobalThresholdSet
253 dim.wait("RATE_CONTROL", "Connected", 3000);
254
255 console.out(" DRS cal: end");
256}
257
258// ----------------------------------------------------------------
259
260function OpenLid()
261{
262 var horizon_parameter = "nautical";
263 while (Sun.horizon( horizon_parameter ).isUp)
264 {
265 var minutes_until_sunset = (Sun.horizon( horizon_parameter ).set - new Date())/60000;
266 console.out("Open Lid - Info: ");
267 console.out(" Sun is above FACT-horizon, lid cannot be opened.");
268 console.out(" sleeping " + minutes_until_sunset + "minutes ...");
269 v8.sleep(60000);
270 }
271
272 console.out("Open lid: start");
273
274 // Wait for lid to be open
275 if (dim.state("LID_CONTROL").name=="Closed")
276 dim.send("LID_CONTROL/OPEN");
277 dim.wait("LID_CONTROL", "Open", 30000);
278 console.out("Open lid: done");
279}
280
281function CloseLid()
282{
283 console.out("Close lid: start");
284
285 // Wait for lid to be open
286 if (dim.state("LID_CONTROL").name=="Open")
287 dim.send("LID_CONTROL/CLOSE");
288 dim.wait("LID_CONTROL", "Closed", 30000);
289
290 console.out("Close lid: end");
291}
292
293// ----------------------------------------------------------------
294
295var service_feedback = new Subscription("FEEDBACK/DEVIATION");
296
297// DN: Why is voltageOff() implemented as
298// a method of a Subscription to a specific Service
299// I naively would think of voltageOff() as an unbound function.
300// I seems to me it has to be a method of a Subscription object, in order
301// to use the update counting method. But does it have to be
302// a Subscription to FEEDBACK/DEVIATION, or could it work with other services as well?
303service_feedback.voltageOff = function()
304{
305 console.out(" Voltage off: start");
306
307 var isOn = dim.state("BIAS_CONTROL").name=="VoltageOn";
308
309 if (isOn)
310 {
311 console.out(" Voltage on: switch off");
312 dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
313 }
314
315 dim.wait("BIAS_CONTROL", "VoltageOff", 5000);
316
317 // FEEDBACK stays in CurrentCtrl when Voltage is off but output enabled
318 // dim.wait("FEEDBACK", "CurrentCtrlIdle", 1000);
319
320 console.out(" Voltage off: end");
321}
322
323// DN: The name of the method voltageOn() in the context of the method
324// voltageOff() is a little bit misleading, since when voltageOff() returns
325// the caller can be sure the voltage is off, but when voltageOn() return
326// this is not the case, in the sense, that the caller can now take data.
327// instead the caller of voltageOn() *must* call waitForVoltageOn() afterwards
328// in order to safely take good-quality data.
329// This could lead to nasty bugs in the sense, that the second call might
330// be forgotten by somebody
331//
332// so I suggest to rename voltageOn() --> prepareVoltageOn()
333// waitForVoltageOn() stays as it is
334// and one creates a third method called:voltageOn() like this
335/* service_feedback.voltageOn = function()
336 * {
337 * this.prepareVoltageOn();
338 * this.waitForVoltageOn();
339 * }
340 *
341 * */
342// For convenience.
343
344service_feedback.voltageOn = function()
345{
346 //if (Sun.horizon("FACT").isUp)
347 // throw new Error("Sun is above FACT-horizon, voltage cannot be switched on.");
348
349 console.out(" Voltage on: start");
350
351 var isOff = dim.state("BIAS_CONTROL").name=="VoltageOff";
352
353 if (isOff)
354 {
355 console.out(" Voltage on: switch on");
356 // console.out(JSON.stringify(dim.state("BIAS_CONTROL")));
357
358 dim.send("BIAS_CONTROL/SET_GLOBAL_DAC", 1);
359 }
360
361 // Wait until voltage on
362 dim.wait("BIAS_CONTROL", "VoltageOn", 5000);
363
364 // From now on the feedback waits for a valid report from the FSC
365 // and than switchs to CurrentControl
366 dim.wait("FEEDBACK", "CurrentControl", 60000);
367
368 if (isOff)
369 {
370 this.cnt = this.get().counter;
371 console.out(" Voltage on: cnt="+this.cnt);
372 }
373
374 console.out(" Voltage on: end");
375}
376
377
378
379service_feedback.waitForVoltageOn = function()
380{
381 // waiting 45sec for the current control to stabilize...
382 // v8.sleep(45000);
383
384 // ----- Wait for at least three updates -----
385 // The feedback is started as if the camera where at 0deg
386 // Then after the first temp update, the temperature will be set to the
387 // correct value (this has already happened)
388 // So we only have to wait for the current to get stable.
389 // This should happen after three to five current updates.
390 // So we want one recent temperature update
391 // and three recent current updates
392 console.out(" Voltage wait: start");
393 while (this.cnt==undefined || this.get().counter<=this.cnt+2)
394 v8.sleep();
395 console.out(" Voltage wait: end [cnt="+this.get().counter+"]");
396}
397
398// ================================================================
399// Crosscheck all states
400// ================================================================
401
402include('scripts/Startup.js');//Startup();
403
404/*
405include('scripts/CheckStates.js');
406
407var table =
408[
409 [ "TNG_WEATHER" ],
410 [ "MAGIC_WEATHER" ],
411 [ "CHAT" ],
412 [ "SMART_FACT" ],
413 [ "FSC_CONTROL", [ "Connected" ] ],
414 [ "MCP", [ "Idle" ] ],
415 [ "TIME_CHECK", [ "Valid" ] ],
416 [ "PWR_CONTROL", [ "SystemOn" ] ],
417 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
418 [ "BIAS_CONTROL", [ "VoltageOff" ] ],
419 [ "FEEDBACK", [ "CurrentControl", "CurrentCtrlIdle", "Connected" ] ],
420 [ "RATE_SCAN", [ "Connected" ] ],
421 [ "RATE_CONTROL", [ "Connected" ] ],
422 [ "LID_CONTROL", [ "Open", "Closed" ] ],
423 [ "DRIVE_CONTROL", [ "Armed", "Tracking", "OnTrack" ] ],
424 [ "FTM_CONTROL", [ "Idle", "TriggerOn" ] ],
425 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
426 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
427];
428
429console.out("Checking states.");
430if (!checkStates(table, 10000))
431{
432 throw new Error"Something unexpected has happened. Although the startup-",
433 "procedure has finished, not all servers are in the state",
434 "in which they ought to be. Please, try to find out what",
435 "happened...");
436}
437
438console.out("Checking states: done.");
439*/
440// ----------------------------------------------------------------
441
442console.out("Checking send.");
443checkSend(["MCP", "DRIVE_CONTROL", "LID_CONTROL", "FAD_CONTROL", "FEEDBACK"]);
444console.out("Checking send: done");
445
446// ----------------------------------------------------------------
447
448console.out("Feedback init: start.");
449service_feedback.get(5000);
450
451dim.send("FEEDBACK/ENABLE_OUTPUT", true);
452dim.send("FEEDBACK/START_CURRENT_CONTROL", 0.);
453
454console.out("Feedback init: end.");
455
456// ----------------------------------------------------------------
457// ================================================================
458// ----------------------------------------------------------------
459
460// this file just contains the definition of
461// the variable observations, which builds our nightly schedule, hence the filename
462include('scripts/schedule.js');
463
464// make Observation objects from user input and check if 'date' is increasing.
465for (var i=0; i<observations.length; i++)
466{
467 observations[i] = new Observation(observations[i]);
468
469 // check if the start date given by the user is increasing.
470 if (i>0 && observations[i].start <= observations[i-1].start)
471 {
472 throw new Error("Start time '"+ observations[i].start.toUTCString()+
473 "' in row "+i+" exceeds start time in row "+(i-1));
474 }
475}
476
477
478
479// ----------------------------------------------------------------
480// Bring the system into a well defined state
481// ----------------------------------------------------------------
482
483console.out("Drs runs init: start.");
484
485// FIMXE: Double subscription is not allowed!
486// also Startup needs DRS_RUNS
487var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
488service_drs.get(5000, false);
489
490console.out("Drs runs init: end.");
491
492// FIXME: Check if the last DRS calibration was complete?
493// ----------------------------------------------------------------
494
495// We have to stup a few things here which might not by set by Startup.js
496dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
497
498// ----------------------------------------------------------------
499
500console.out("Start main loop.");
501
502function Startup()
503{
504 /**** dummy ****/
505 console.out(" => [STARTUP] called.");
506}
507
508function Shutdown()
509{
510 /**** dummy ****/
511 //console.out(" => [SHUTDOWN] called.");
512 console.out("Shutdown: start");
513 service_feedback.voltageOff();
514 CloseLid();
515 dim.send("DRIVE_CONTROL/PARK");
516 dim.wait("DRIVE_CONTROL", "Moving", 3000);
517 dim.wait("DRIVE_CONTROL", "Armed", 120000);
518 console.out("Shutdown: end");
519}
520
521// Get the observation scheduled for 'now' from the table and
522// return its index
523function getObservation(now)
524{
525 if (now==undefined)
526 now = new Date();
527
528 if (isNaN(now.valueOf()))
529 throw new Error("Date argument in getObservation invalid.");
530
531 for (var i=0; i<observations.length; i++)
532 if (now<observations[i].start)
533 return i-1;
534
535 return observations.length-1;
536}
537
538
539// DN: using so called magic numbers to encode certain
540// states of the logic is considered pretty bad coding as far as I understand.
541// the reader at this point has no idea why run is -2 ... this is the first time she
542// reads about this variable and there is not a word of explanation found.
543var run = -2;
544var lastObs;
545
546var test = getObservation();
547if (test!=undefined && test<observations.length)
548{
549 var t = observations[test].start;
550 var n = new Date();
551 if (t>n)
552 console.out(n.toUTCString()+": First observation scheduled for "+t.toUTCString());
553 else
554 console.out(n.toUTCString()+": First observation should start immediately.");
555 if (t>n+12*3600*1000)
556 console.out(n.toUTCString()+": No observations scheduled for the next 12 hours!");
557}
558
559while (1)
560{
561 // Check if observation position is still valid
562 // If source position has changed, set run=0
563 var idxObs = getObservation();
564 if (idxObs===undefined)
565 exit();
566
567 if (idxObs==-1)
568 {
569 v8.sleep(1000);
570 continue;
571 }
572
573 var obs = observations[idxObs];
574 var nextObs = observations[idxObs+1];
575
576 // Check if observation target has changed
577 if (lastObs!=idxObs)
578 {
579 console.out("--- "+idxObs+" ---");
580 console.out("Current time: "+new Date());
581 console.out("Current observation: "+obs);
582 console.out("Next observation: "+nextObs);
583 console.out("");
584
585 // This is the first source, but we do not come from
586 // a scheduled 'START', so we have to check if the
587 // telescop is operational already
588 if (run==-2)
589 {
590 Startup(); // -> Bias On/Off?, Lid open/closed?
591 CloseLid();
592 }
593
594 run = 0;
595 }
596 lastObs = idxObs;
597
598 // We have performed startup or shutdown... wait for next observation
599 if (run==-1)
600 {
601 v8.sleep(1000);
602 continue;
603 }
604
605 // Check if obs.task is one of the one-time-tasks
606 switch (obs.task)
607 {
608 case "STARTUP":
609 console.out(" STARTUP", "");
610 Startup(); // BiasOn/Off?, Lid open/close?
611 CloseLid();
612
613 console.out(" Take DRS calibration.");
614 doDrsCalibration(); // -> VoltageOff
615
616 service_feedback.voltageOn();
617 service_feedback.waitForVoltageOn();
618
619 // Before we can switch to 3000 we have to make the right DRS calibration
620 console.out(" Take single p.e. run.");
621 while (!takeRun("pedestal", 5000));
622
623 service_feedback.voltageOff();
624
625 dim.send("RATE_CONTROL/STOP"); // get out of GlobalThresholdSet
626 dim.wait("RATE_CONTROL", "Connected", 3000);
627
628 console.out(" Waiting for first scheduled observation.","");
629 run = -1;
630 continue;
631
632 case "SHUTDOWN":
633 console.out(" SHUTDOWN","");
634 Shutdown();
635
636 console.out(" Waiting for next startup.", "");
637 run = -1;
638 continue;
639
640 case "RATESCAN":
641 console.out(" RATESCAN ");
642
643 dim.send("DRIVE_CONTROL/STOP");
644 dim.wait("DRIVE_CONTROL", "Armed", 5000);
645
646 if (obs.source != undefined)
647 dim.send("DRIVE_CONTROL/TRACK_ON", obs.source);
648 else
649 dim.send("DRIVE_CONTROL/TRACK", obs.ra, obs.dec);
650
651 //OpenLid();
652 dim.wait("DRIVE_CONTROL", "OnTrack", 300000);
653
654 OpenLid();
655
656 service_feedback.voltageOn();
657 service_feedback.waitForVoltageOn();
658
659 // Checking if system is Ready for Data Taking, which is in this case
660 // the same as Ready for RateScan.
661 console.out(" Checking states [ratescan]");
662 var table =
663 [
664 [ "TNG_WEATHER" ],
665 [ "MAGIC_WEATHER" ],
666 [ "CHAT" ],
667 [ "SMART_FACT" ],
668 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
669 [ "FSC_CONTROL", [ "Connected" ] ],
670 [ "MCP", [ "Idle" ] ],
671 [ "TIME_CHECK", [ "Valid" ] ],
672 [ "PWR_CONTROL", [ "SystemOn" ] ],
673 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
674 [ "BIAS_CONTROL", [ "VoltageOn", "Ramping" ] ],
675 [ "FEEDBACK", [ "CurrentControl" ] ],
676 [ "RATE_SCAN", [ "Connected" ] ],
677 [ "RATE_CONTROL", [ "Connected", "InProgress" ] ],
678 [ "LID_CONTROL", [ "Open" ] ],
679 [ "DRIVE_CONTROL", [ "Tracking", "OnTrack" ] ],
680 [ "FTM_CONTROL", [ "Idle", ] ],
681 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
682 ];
683
684 if (!checkStates(table))
685 {
686 throw new Error("Something unexpected has happened. One of the servers"+
687 "is in a state in which it should not be. Please,"+
688 "try to find out what happened...");
689 }
690
691 // Start rate scan
692 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 50, 1000, -10);
693
694 // lets wait if the Ratescan really starts .. it should be started after 10sec max.
695 dim.wait("RATE_SCAN", "InProgress", 10000);
696 dim.wait("RATE_SCAN", "Connected", 2700000);
697
698 // this line is actually some kind of hack.
699 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
700 // So I decided to put this line here as a kind of patchwork....
701 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
702
703 console.out("Ratescan done.");
704 run = -1;
705 continue;
706 }
707/*
708 if (Sun.horizon("FACT").isUp)
709 {
710 console.out(" SHUTDOWN","");
711 Shutdown();
712 console.out(" Exit forced due to broken schedule", "");
713 exit();
714 }
715*/
716 // Calculate remaining time for this observation in minutes
717 var remaining = (nextObs.start-new Date())/60000;
718
719 // ------------------------------------------------------------
720
721 // Checking for 'Ramping' in the BIAS_CONTROL is not ideal, but at the moment
722 // it is not possible to distinguish between a real ramping and the short
723 // ramping which takes place whenever the feedback updated the voltages.
724
725 console.out(" Checking states [mainloop]");
726 var table =
727 [
728 [ "TNG_WEATHER" ],
729 [ "MAGIC_WEATHER" ],
730 [ "CHAT" ],
731 [ "SMART_FACT" ],
732 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
733 [ "FSC_CONTROL", [ "Connected" ] ],
734 [ "MCP", [ "Idle" ] ],
735 [ "TIME_CHECK", [ "Valid" ] ],
736 [ "PWR_CONTROL", [ "SystemOn" ] ],
737 [ "AGILENT_CONTROL", [ "VoltageOn" ] ],
738 [ "BIAS_CONTROL", [ "VoltageOff", "VoltageOn", "Ramping" ] ],
739 [ "FEEDBACK", [ "CurrentCtrlIdle", "CurrentControl" ] ],
740 [ "RATE_SCAN", [ "Connected" ] ],
741 [ "RATE_CONTROL", [ "Connected", "InProgress" ] ],
742 [ "LID_CONTROL", [ "Open", "Closed" ] ],
743 [ "DRIVE_CONTROL", [ "Armed", "Tracking", "OnTrack" ] ],
744 [ "FTM_CONTROL", [ "Idle", "TriggerOn" ] ],
745 [ "FAD_CONTROL", [ "Connected", "WritingData" ] ],
746 ];
747
748 if (!checkStates(table))
749 {
750 //dim.alarm("System inconsistent");
751 //dim.alarm();
752 throw new Error("Something unexpected has happened. One of the servers "+
753 "is in a state in which it should not be. Please, "+
754 "try to find out what happened...");
755 }
756
757 console.out(" Checking states: end.");
758
759 // ------------------------------------------------------------
760
761 console.out(" Run #"+run+" ("+parseInt(remaining)+"min)");
762
763 // ----- Time since last DRS Calibration [min] ------
764 var runs = service_drs.get(0, false);
765 var diff = (new Date()-runs.time)/60000;
766
767 // Warning: 'roi=300' is a number which is not intrisically fixed
768 // but can change depending on the taste of the observers
769 var valid = runs.data[1][2]>0 && runs.data[0]==300;
770
771 if (valid)
772 console.out(" Last DRS calib: %.1fmin ago".$(diff));
773 else
774 console.out(" No valid drs calibration");
775
776 // Changine pointing position and take calibration...
777 // ...every four runs (every ~20min)
778 // ...if at least ten minutes of observation time are left
779 // ...if this is the first run on the source
780 var point = (run%4==0 && remaining>10) || run==0;
781
782 // Take DRS Calib...
783 // ...every four runs (every ~20min)
784 // ...at last every two hours
785 // ...when DRS temperature has changed by more than 2deg (?)
786 // ...when more than 15min of observation are left
787 // ...no drs calibration was done yet
788 var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
789
790 if (point)
791 {
792 // Change wobble position every four runs,
793 // start with alternating wobble positions each day
794 var wobble = (parseInt(run/4) + parseInt(new Date()/1000/3600/24-0.5))%2;
795
796 //console.out(" Move telescope to '"+source+"' "+offset+" "+wobble);
797 console.out(" Move telescope to '"+obs.source+"' ["+wobble+"]");
798
799 //var offset = observations[obs][2];
800 //var wobble = observations[obs][3 + parseInt(run/4)%2];
801
802 //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
803
804 dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble+1, obs.source);
805
806 // Do we have to check if the telescope is really moving?
807 // We can cross-check the SOURCE service later
808 }
809
810 if (drscal)
811 {
812 console.out(" Take DRS calibration.");
813 doDrsCalibration(); // -> VoltageOff
814 }
815
816 OpenLid();
817
818 // voltage must be switched on after the lid is open for the
819 // feedback to adapt the voltage properly to the night-sky
820 // background light level.
821 service_feedback.voltageOn();
822
823 // This is now th right time to wait for th drive to be stable
824 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
825
826 // Now we have to be prepared for data-taking:
827 // make sure voltage is on
828 service_feedback.waitForVoltageOn();
829
830 // If pointing had changed, do calibration
831 if (point)
832 {
833 console.out(" Calibration.");
834
835 // Calibration (2% of 20')
836 while (1)
837 {
838 if (!takeRun("pedestal", 1000)) // 80 Hz -> 10s
839 continue;
840 if (!takeRun("light-pulser-ext", 1000)) // 80 Hz -> 10s
841 continue;
842 break;
843 }
844 }
845
846 console.out(" Taking data: start [5min]");
847
848 var len = 300;
849 while (len>0)
850 {
851 var time = new Date();
852 if (takeRun("data", -1, len)) // Take data (5min)
853 break;
854
855 len -= parseInt((new Date()-time)/1000);
856 }
857
858 //v8.sleep(360000);
859 console.out(" Taking data: done");
860
861 run++;
862}
863
864service_drs.close();
Note: See TracBrowser for help on using the repository browser.