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

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