source: branches/fscctrl_safety_limits/src/fscctrl.cc@ 18342

Last change on this file since 18342 was 18342, checked in by dneise, 9 years ago
removing a struct and renamed some variables as Thomas wanted it.
File size: 41.0 KB
Line 
1#include <functional>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "StateMachineAsio.h"
8#include "Connection.h"
9#include "LocalControl.h"
10#include "Configuration.h"
11#include "Console.h"
12#include "Converter.h"
13#include "externals/Interpolator2D.h"
14
15#include "tools.h"
16
17#include "HeadersFSC.h"
18
19namespace ba = boost::asio;
20namespace bs = boost::system;
21namespace dummy = ba::placeholders;
22
23using namespace std;
24using namespace FSC;
25
26// ------------------------------------------------------------------------
27
28class ConnectionFSC : public Connection
29{
30 FSC::BinaryOutput_t fMsg; // A single message
31
32 bool fIsVerbose;
33 bool fIsAutoReconnect;
34
35 size_t fNumConsecutiveErrors; // Number of consecutive messages with errors
36 size_t fNumConsecutiveMessages; // Number of consecutive message which are ok
37
38 boost::asio::deadline_timer fReconnectTimeout;
39
40protected:
41 vector<Interpolator2D::vec> fPositionsSensors;
42 vector<Interpolator2D::vec> fPositionsBias;
43
44 double fEthernetSwitchCurrentLimit;
45 double fFFCcurrentLimit;
46 double fFLPcurrentLimit;
47 double fFADdigitalCurrentLimit;
48 double fFADnegativeCurrentLimit;
49 double fFADpositiveCurrentLimit;
50 double fFPAdigitalCurrentLimit;
51 double fFPAnegativeCurrentLimit;
52 double fFPApositiveCurrentLimit;
53
54
55 bool fSecurityLimitsExceeded;
56
57 virtual void UpdateTemp(float, const vector<float> &)
58 {
59 }
60
61 virtual void UpdateHum(float, const vector<float>&)
62 {
63 }
64
65 virtual void UpdateVolt(float, const vector<float>&)
66 {
67 }
68
69 virtual void UpdateCur(float, const vector<float>&)
70 {
71 }
72
73private:
74 //
75 // From: http://de.wikipedia.org/wiki/Pt100
76 //
77 double GetTempPT1000(double R) const
78 {
79 // This is precise within the range 5degC and 25degC
80 // by 3e-3 degC. At 0degC and 30degC it overestimates the
81 // temperature by 0.025 degC. At -10degC it is ~0.9degC
82 // and at 40degC ~0.05degC.
83 const double x = R/1000;
84 return -193.804 + 96.0651*x + 134.673*x*x - 36.9091*x*x*x;
85
86 //for a reasonable range:
87 // R=970 -> -7.6 degC
88 // R=1300 -> 77.6 degC
89
90 //const double R0 = 1000; // 1kOhm
91 //const double a = 3.893e-3;
92 //return (R/R0 - 1)/a;
93 }
94
95 bool CheckChecksum()
96 {
97 const uint16_t volt_checksum = Tools::Fletcher16(fMsg.adc_values, kNumVoltageChannels);
98 const uint16_t resi_checksum = Tools::Fletcher16(fMsg.ad7719_values, kNumResistanceChannels);
99
100 const bool volt_ok = volt_checksum == fMsg.adc_values_checksum;
101 const bool resi_ok = resi_checksum == fMsg.ad7719_values_checksum;
102
103 if (volt_ok && resi_ok)
104 return true;
105
106 fNumConsecutiveErrors++;
107
108 ostringstream out;
109 out << "Checksum error (V:";
110 out << hex << setfill('0');
111
112 if (volt_ok)
113 out << "----|----";
114 else
115 {
116 out << setw(4) << volt_checksum;
117 out << "|";
118 out << setw(4) << fMsg.adc_values_checksum;
119 }
120
121 out << ", R:";
122
123 if (resi_ok)
124 out << "----|----";
125 else
126 {
127 out << setw(4) << resi_checksum;
128 out << "|";
129 out << setw(4) << fMsg.ad7719_values_checksum;
130 }
131
132 out << ", " << dec;
133 out << "Nok=" << fNumConsecutiveMessages << ", ";
134 out << "Nerr=" << fNumConsecutiveErrors << ")";
135
136 Warn(out);
137
138 fNumConsecutiveMessages = 0;
139
140 return false;
141 }
142
143 bool ProcessMessage()
144 {
145 if (fIsVerbose)
146 Out() << "Received one_message of FSC::BinaryOutput_t ... will now process it" << endl;
147
148 if (!CheckChecksum())
149 return false;
150
151 // That looks a bit odd because it copies the values twice for no reason.
152 // This is historical and keeps the following code consistent with the
153 // previous code which was reading ascii data from the fsc
154 vector<float> volt( fMsg.adc_values, fMsg.adc_values + kNumVoltageChannels);
155 vector<float> resist(fMsg.ad7719_values, fMsg.ad7719_values + kNumResistanceChannels);
156
157 const float time = fMsg.time_sec + fMsg.time_ms/1000.;
158
159 // We want to convert the pure ADC values from the FSC board to mV and kOhm respectively
160 // So we do:
161 for (unsigned int i=0; i<volt.size(); i++)
162 volt[i] /= 10;
163
164 for (unsigned int i=0; i<resist.size(); i++)
165 resist[i] *= (6.25 * 1024) / (1 << 25);
166
167 int mapv[] =
168 {
169 0, 16, 24, 8,
170 1, 17, 25, 9,
171 2, 18, 26, 10,
172 //
173 3, 19, 27, 11,
174 4, 20, 28, 12,
175 5, 21, 29, 13,
176 //
177 32, 36, 33, 34, 37, 38,
178 //
179 -1
180 };
181
182 int mapc[] =
183 {
184 40, 56, 64, 48,
185 41, 57, 65, 49,
186 42, 58, 66, 50,
187 //
188 43, 59, 67, 51,
189 44, 60, 68, 52,
190 45, 61, 69, 53,
191 //
192 72, 76, 73, 74, 77, 78,
193 //
194 -1
195 };
196
197
198 int maprh[] =
199 {
200 80, 81, 82, 83, -1
201 };
202
203 int offrh[] =
204 {
205 821, 822, 816, 822,
206 };
207
208 int mapt[] =
209 {
210 // sensor compartment temperatures
211 0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
212 61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
213 25, 26, 27, 28, 29, 30, 31,
214 // crate temperatures (0-3, back/front)
215 12, 13, 52, 53, 44, 46, 20, 21,
216 //crate power supply temperatures (0-3)
217 8, 9, 48, 49, 40, 41, 16, 17,
218 // aux power supplies (FTM-side top/bot, FSC-side top/bot)
219 45, 50, 19, 42,
220 // backpanel (FTM-side top/bot, FSC-side top/bot)
221 11, 51, 18, 43,
222 // switch boxes (top front/back, bottom front/back)
223 15, 14, 47, 10,
224 //
225 -1
226 };
227
228 vector<float> voltages;
229 vector<float> currents;
230 vector<float> humidities;
231 vector<float> temperatures;
232
233 for (int *pv=mapv; *pv>=0; pv++)
234 voltages.push_back(volt[*pv]*0.001);
235
236 for (int *pc=mapc; *pc>=0; pc++)
237 currents.push_back(volt[*pc]*0.005);
238
239 for (int idx=0; idx<4; idx++)
240 {
241 voltages[idx +8] *= -1;
242 voltages[idx+20] *= -1;
243 currents[idx +8] *= -1;
244 currents[idx+20] *= -1;
245 }
246 voltages[12] *= 2;
247 voltages[13] *= 2;
248 voltages[14] *= 2;
249 voltages[15] *= 2;
250
251 voltages[24] *= 2;
252 voltages[25] *= 2;
253
254 voltages[27] *= -1;
255 voltages[29] *= -1;
256
257 currents[27] *= -1;
258 currents[29] *= -1;
259
260 int idx=0;
261 for (int *ph=maprh; *ph>=0; ph++, idx++)
262 humidities.push_back((volt[*ph]-offrh[idx])*0.0313);
263
264 //1019=4.8
265 //1005=1.3
266 //970=-7.6
267 //1300=76
268 for (int *pt=mapt; *pt>=0; pt++)
269 //temperatures.push_back(resist[*pt]>800&&resist[*pt]<2000 ? GetTempPT1000(resist[*pt]) : 0);
270 temperatures.push_back(resist[*pt]>970&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
271 //temperatures.push_back(resist[*pt]>1019&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
272
273 // 0 = 3-(3+0)%4
274 // 3 = 3-(3+1)%4
275 // 2 = 3-(3+2)%4
276 // 1 = 3-(3+3)%4
277
278 /*
279 index unit offset scale crate for board:
280 0 mV 0 1 0 FAD 3.3V
281 24 mV 0 1 1 FAD 3.3V
282 16 mV 0 1 2 FAD 3.3V
283 8 mV 0 1 3 FAD 3.3V
284
285 1 mV 0 1 0 FAD 3.3V
286 25 mV 0 1 1 FAD 3.3V
287 17 mV 0 1 2 FAD 3.3V
288 9 mV 0 1 3 FAD 3.3V
289
290 2 mV 0 -1 0 FAD -2.0V
291 26 mV 0 -1 1 FAD -2.0V
292 18 mV 0 -1 2 FAD -2.0V
293 10 mV 0 -1 3 FAD -2.0V
294
295 --
296
297 3 mV 0 1 0 FPA 5.0V
298 27 mV 0 1 1 FPA 5.0V
299 19 mV 0 1 2 FPA 5.0V
300 11 mV 0 1 3 FPA 5.0V
301
302 4 mV 0 1 0 FPA 3.3V
303 28 mV 0 1 1 FPA 3.3V
304 20 mV 0 1 2 FPA 3.3V
305 12 mV 0 1 3 FPA 3.3V
306
307 5 mV 0 -1 0 FPA -3.3V
308 29 mV 0 -1 1 FPA -3.3V
309 21 mV 0 -1 2 FPA -3.3V
310 13 mV 0 -1 3 FPA -3.3V
311
312 --
313
314 32 mV 0 1 bottom ETH 5V
315 36 mV 0 1 top ETH 5V
316
317 33 mV 0 1 bottom FTM 3.3V
318 34 mV 0 -1 bottom FTM -3.3V
319
320 37 mV 0 1 top FFC 3.3V
321 38 mV 0 -1 top FLP -3.3V
322
323 -----
324
325 40 mA 0 5 0 FAD
326 64 mA 0 5 1 FAD
327 56 mA 0 5 2 FAD
328 48 mA 0 5 3 FAD
329
330 41 mA 0 5 0 FAD
331 65 mA 0 5 1 FAD
332 57 mA 0 5 2 FAD
333 49 mA 0 5 3 FAD
334
335 42 mA 0 -5 0 FAD
336 66 mA 0 -5 1 FAD
337 58 mA 0 -5 2 FAD
338 50 mA 0 -5 3 FAD
339
340 --
341
342 43 mA 0 5 0 FPA
343 67 mA 0 5 1 FPA
344 59 mA 0 5 2 FPA
345 51 mA 0 5 3 FPA
346
347 44 mA 0 5 0 FPA
348 68 mA 0 5 1 FPA
349 60 mA 0 5 2 FPA
350 52 mA 0 5 3 FPA
351
352 45 mA 0 -5 0 FPA
353 69 mA 0 -5 1 FPA
354 61 mA 0 -5 2 FPA
355 53 mA 0 -5 3 FPA
356
357 ---
358
359 72 mA 0 5 bottom ETH
360 76 mA 0 5 top ETH
361
362 73 mA 0 5 bottom FTM
363 74 mA 0 -5 bottom FTM
364
365 77 mA 0 5 top FFC
366 78 mA 0 -5 top FLP
367
368 ----
369
370 80 % RH -821 0.0313 FSP000
371 81 % RH -822 0.0313 FSP221
372 82 % RH -816 0.0313 Sector0
373 83 % RH -822 0.0313 Sector2
374 */
375
376 // TEMPERATURES
377 // 31 x Sensor plate
378 // 8 x Crate
379 // 12 x PS
380 // 4 x Backpanel
381 // 4 x Switchbox
382
383
384
385 /*
386 0 ohms FSP 000
387 1 ohms FSP 010
388 2 ohms FSP 023
389 3 ohms FSP 043
390 4 ohms FSP 072
391 5 ohms FSP 080
392 6 ohms FSP 092
393 56 ohms FSP 103
394 57 ohms FSP 111
395 58 ohms FSP 121
396 59 ohms FSP 152
397 60 ohms FSP 163
398 61 ohms FSP 171
399 62 ohms FSP 192
400 32 ohms FSP 200
401 33 ohms FSP 210
402 34 ohms FSP 223
403 35 ohms FSP 233
404 36 ohms FSP 243
405 63 ohms FSP 252
406 37 ohms FSP 280
407 38 ohms FSP 283
408 39 ohms FSP 293
409 24 ohms FSP 311
410 25 ohms FSP 321
411 26 ohms FSP 343
412 27 ohms FSP 352
413 28 ohms FSP 363
414 29 ohms FSP 371
415 30 ohms FSP 381
416 31 ohms FSP 392
417 8 ohms Crate0 ?
418 9 ohms Crate0 ?
419 48 ohms Crate1 ?
420 49 ohms Crate1 ?
421 40 ohms Crate2 ?
422 41 ohms Crate2 ?
423 16 ohms Crate3 ?
424 17 ohms Crate3 ?
425 10 ohms PS Crate 0
426 11 ohms PS Crate 0
427 50 ohms PS Crate 1
428 51 ohms PS Crate 1
429 42 ohms PS Crate 2
430 43 ohms PS Crate 2
431 18 ohms PS Crate 3
432 19 ohms PS Crate 3
433 12 ohms PS Aux0
434 52 ohms PS Aux0
435 20 ohms PS Aux1
436 44 ohms PS Aux1
437 13 ohms Backpanel ?
438 21 ohms Backpanel ?
439 45 ohms Backpanel ?
440 53 ohms Backpanel ?
441 14 ohms Switchbox0 ?
442 15 ohms Switchbox0 ?
443 46 ohms Switchbox1 ?
444 47 ohms Switchbox1 ?
445 7 ohms nc nc
446 22 ohms nc nc
447 23 ohms nc nc
448 54 ohms nc nc
449 55 ohms nc nc
450 */
451
452 CheckCurrentLimits(currents);
453 if (fIsVerbose)
454 {
455 /*
456 for (size_t i=0; i<resist.size(); i++)
457 //if (resist[i]>800 && resist[i]<2000)
458 if (resist[i]>970 && resist[i]<1300)
459 //if (resist[i]>1019 && resist[i]<1300)
460 Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << setprecision(1) << fixed << GetTempPT1000(resist[i]) << endl;
461 else
462 Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << "----" << endl;
463 */
464 PrintTemperaturesNicely(temperatures);
465 PrintVoltagesNicely(voltages, currents);
466 Out() << "\n" << "fSecurityLimitsExceeded:" << fSecurityLimitsExceeded << endl;
467 }
468
469 UpdateTemp(time, temperatures);
470 UpdateVolt(time, voltages);
471 UpdateCur( time, currents);
472 UpdateHum( time, humidities);
473
474 fNumConsecutiveErrors = 0;
475 fNumConsecutiveMessages++;
476
477
478 return true;
479 }
480
481 void PrintTemperaturesNicely(const vector<float> &t)
482 {
483 /*
484 "FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
485 "|t[s]:FSC uptime"
486 "|T_sens[deg C]:Sensor compartment temperatures"
487 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (b/f), 2 (b/f), 3 (b/f)"
488 "|T_ps[deg C]:Temp power supplies crate 0 (back/front), 1, 2, 3"
489 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (t/b)"
490 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
491 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (f/b)"),
492 // sensor compartment temperatures
493 0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
494 61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
495 25, 26, 27, 28, 29, 30, 31,
496 // crate temperatures (0-3, back/front)
497 12, 13, 52, 53, 44, 46, 20, 21,
498 //crate power supply temperatures (0-3)
499 8, 9, 48, 49, 40, 41, 16, 17,
500 // aux power supplies (FTM-side top/bot, FSC-side top/bot)
501 45, 50, 19, 42,
502 // backpanel (FTM-side top/bot, FSC-side top/bot)
503 11, 51, 18, 43,
504 // switch boxes (top front/back, bottom front/back)
505 15, 14, 47, 10,
506 */
507 //Out() << "0 1 2 3 4 5 6 7 " << endl;
508 //Out() << "01234567890123456789012345678901234567890123456789012345678901234567890123456789" << endl;
509 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
510 Out() << "T_sens:";
511 for (int i=0; i<31; i++){
512 if (i%16==0){
513 Out() << "\n";
514 }
515 Out() << setw(4) << setprecision(1) << fixed << t[i] << " ";
516 }
517 Out() << endl;
518 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
519
520 Out() << "T_crate: (B:back, F:front)" << endl;
521 Out() << "0: B| F|1: B| F|2: B| F|3: B| F|" << endl;
522 for (int i=31; i<31+8; i++){
523 Out() << setw(4) << setprecision(1) << fixed << t[i] << "|";
524 }
525 Out() << endl;
526 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
527
528 Out() << "T_ps: crate power supplies (B:back, F:front)" << endl;
529 Out() << "0: B| F|1: B| F|2: B| F|3: B| F|" << endl;
530 for (int i=31+8; i<31+8+8; i++){
531 Out() << setw(4) << setprecision(1) << fixed << t[i] << "|";
532 }
533 Out() << endl;
534 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
535 Out() << "T_aux: auxiliary power supplies" << endl;
536 Out() << "FTM top| bot|FSC top| bot|" << endl;
537 for (int i=31+8+8; i<31+8+8+4; i++){
538 Out() << setw(7) << setprecision(1) << fixed << t[i] << "|";
539 }
540 Out() << endl;
541 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
542 Out() << "T_back: backpanel temperatures" << endl;
543 Out() << "FTM top| bot|FSC top| bot|" << endl;
544 for (int i=31+8+8+4; i<31+8+8+4+4; i++){
545 Out() << setw(7) << setprecision(1) << fixed << t[i] << "|";
546 }
547 Out() << endl;
548 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
549 Out() << "T_ethernet: switch boxes" << endl;
550 Out() << "top front| back|bot front| back|" << endl;
551 for (int i=31+8+8+4; i<31+8+8+4+4; i++){
552 Out() << setw(9) << setprecision(1) << fixed << t[i] << "|";
553 }
554 Out() << endl;
555 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
556 }
557
558 void PrintVoltagesNicely(const vector<float> &v, const vector<float> &c)
559 {
560 /*
561
562 F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
563
564 "|FAD_Ud[V]:FAD digital (crate 0-3)"
565 "|FAD_Up[V]:FAD positive (crate 0-3)"
566 "|FAD_Un[V]:FAD negative (crate 0-3)"
567 "|FPA_Ud[V]:FPA digital (crate 0-3)"
568 "|FPA_Up[V]:FPA positive (crate 0-3)"
569 "|FPA_Un[V]:FPA negative (crate 0-3)"
570
571 "|ETH_U[V]:Ethernet switch (pos/neg)"
572 "|FTM_U[V]:FTM - trigger master (pos/neg)"
573 "|FFC_U[V]:FFC"
574 "|FLP_U[V]:FLP - light pulser"),
575 */
576 const char* const voltage_names[] = {
577 "FAD_d | ",
578 "FAD_p | ",
579 "FAD_n | ",
580 "FPA_d | ",
581 "FPA_p | ",
582 "FPA_n | ",
583 "Etherne| ",
584 "FTM | ",
585 "FFC | ",
586 "FLP | ",
587 };
588 const int length_per_group[] = {
589 4, 4, 4, 4, 4, 4, 2, 2, 1, 1,
590 };
591
592 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
593
594 Out() << " | Voltages | Currents" << endl;
595 Out() << "-------| 0 | 1 | 2 | 3 | | 0 | 1 | 2 | 3 |" << endl;
596
597 int pos=0;
598 for (int i=0; i<10; i++)
599 {
600 Out() << voltage_names[i];
601 for (int j=0; j<length_per_group[i]; j++)
602 {
603 Out() << setw(6) << setprecision(2) << fixed << v[pos++] << "| ";
604 }
605 pos -= length_per_group[i];
606 for (int j=0; j<4-length_per_group[i]; j++)
607 {
608 Out() << " ";
609 }
610 Out() << "|";
611 for (int j=0; j<length_per_group[i]; j++)
612 {
613 Out() << setw(6) << setprecision(2) << fixed << c[pos++] << "| ";
614 }
615 Out() << endl;
616 }
617
618 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
619
620
621 }
622
623 bool CheckCurrentLimits(const vector<float> &currents)
624 {
625 /*
626 F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
627 "|FAD_Id[A]:FAD digital (crate 0-3)"
628 "|FAD_Ip[A]:FAD positive (crate 0-3)"
629 "|FAD_In[A]:FAD negative (crate 0-3)"
630 "|FPA_Id[A]:FPA digital (crate 0-3)"
631 "|FPA_Ip[A]:FPA positive (crate 0-3)"
632 "|FPA_In[A]:FPA negative (crate 0-3)"
633 "|ETH_I[A]:Ethernet switch (pos/neg)"
634 "|FTM_I[A]:FTM - trigger master (pos/neg)"
635 "|FFC_I[A]:FFC"
636 "|FLP_I[A]:FLP - light pulser")
637 */
638 fSecurityLimitsExceeded = false;
639
640 const double current_limits[] = {
641 fFADdigitalCurrentLimit,
642 fFADnegativeCurrentLimit,
643 fFADpositiveCurrentLimit,
644 fFPAdigitalCurrentLimit,
645 fFPAnegativeCurrentLimit,
646 fFPApositiveCurrentLimit,
647 fEthernetSwitchCurrentLimit,
648 INFINITY,
649 fFFCcurrentLimit,
650 fFLPcurrentLimit,
651 };
652
653 const int channels_per_group[] = {
654 4, 4, 4, 4, 4, 4, 2, 2, 1, 1,
655 };
656
657 const int groups = 10;
658
659 const char* const group_names[] = {
660 "FAD_digital",
661 "FAD_positive",
662 "FAD_negative",
663 "FPA_digital",
664 "FPA_positive",
665 "FPA_negative",
666 "ethernet_switch",
667 "",
668 "FFC",
669 "FLP",
670 };
671
672 const char* const channel_names[][4] = {
673 {"crate 0", "crate 1", "crate 2", "crate 3"},
674 {"crate 0", "crate 1", "crate 2", "crate 3"},
675 {"crate 0", "crate 1", "crate 2", "crate 3"},
676 {"crate 0", "crate 1", "crate 2", "crate 3"},
677 {"crate 0", "crate 1", "crate 2", "crate 3"},
678 {"crate 0", "crate 1", "crate 2", "crate 3"},
679 {"FTM side", "FSC side"},
680 {""},
681 {"-"},
682 {"-"},
683 };
684
685
686 int offset=0;
687 for (int g=0; g<groups; g++){
688 for (int c=0; c<channels_per_group[g]; c++)
689 {
690 int id = offset+c;
691 if (abs(currents[id]) > abs(current_limits[g])){
692 Out() << "current limit exeeded!! ";
693 Out() << "group: "<< group_names[g];
694 Out() << " channel: "<< channel_names[g][c];
695 Out() << " value: "<< currents[id];
696 Out() << " limit: "<< current_limits[g];
697 Out() << endl;
698 fSecurityLimitsExceeded = true;
699 }
700
701 }
702 offset += channels_per_group[g];
703 }
704 return fSecurityLimitsExceeded;
705 }
706
707
708
709 void StartRead()
710 {
711 ba::async_read(*this, ba::buffer(&fMsg, sizeof(FSC::BinaryOutput_t)),
712 boost::bind(&ConnectionFSC::HandleRead, this,
713 dummy::error, dummy::bytes_transferred));
714
715 AsyncWait(fInTimeout, 35000, &Connection::HandleReadTimeout); // 30s
716 }
717
718 void HandleRead(const boost::system::error_code& err, size_t bytes_received)
719 {
720 // Do not schedule a new read if the connection failed.
721 if (bytes_received==0 || err)
722 {
723 if (err==ba::error::eof)
724 return;
725
726 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
727 // 125: Operation canceled
728 if (err && err!=ba::error::eof && // Connection closed by remote host
729 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
730 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
731 {
732 ostringstream str;
733 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
734 Error(str);
735 }
736 PostClose(err!=ba::error::basic_errors::operation_aborted);
737 return;
738 }
739
740 if (!ProcessMessage())
741 {
742 fIsAutoReconnect = true;
743 fReconnectTimeout.expires_from_now(boost::posix_time::seconds(10));
744 fReconnectTimeout.async_wait(boost::bind(&ConnectionFSC::HandleReconnectTimeout,
745 this, dummy::error));
746 PostClose(true);
747 return;
748 }
749
750 StartRead();
751 }
752
753 void ConnectionEstablished()
754 {
755 fNumConsecutiveErrors = 0;
756 fNumConsecutiveMessages = 0;
757 fIsAutoReconnect = false;
758
759 StartRead();
760 }
761
762 void HandleReconnectTimeout(const bs::error_code &)
763 {
764 fIsAutoReconnect = false;
765 }
766
767 void HandleReadTimeout(const bs::error_code &error)
768 {
769 if (error==ba::error::basic_errors::operation_aborted)
770 return;
771
772 if (error)
773 {
774 ostringstream str;
775 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
776 Error(str);
777
778 PostClose();
779 return;
780
781 }
782
783 if (!is_open())
784 {
785 // For example: Here we could schedule a new accept if we
786 // would not want to allow two connections at the same time.
787 return;
788 }
789
790 // Check whether the deadline has passed. We compare the deadline
791 // against the current time since a new asynchronous operation
792 // may have moved the deadline before this actor had a chance
793 // to run.
794 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
795 return;
796
797 Error("Timeout reading data from "+URL());
798
799 PostClose();
800 }
801
802public:
803 ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
804 fIsVerbose(false), fIsAutoReconnect(false), fReconnectTimeout(ioservice)
805 {
806 SetLogStream(&imp);
807 }
808
809 void SetVerbose(bool b)
810 {
811 fIsVerbose = b;
812 }
813
814 void SetPositionsSensors(const vector<Interpolator2D::vec> &vec)
815 {
816 fPositionsSensors = vec;
817 }
818
819 void SetEthernetSwitchCurrentLimit(double lim)
820 {
821 fEthernetSwitchCurrentLimit = lim;
822 }
823
824 void SetFFCcurrentLimit(double lim)
825 {
826 fFFCcurrentLimit = lim;
827 }
828
829 void SetFLPcurrentLimit(double lim)
830 {
831 fFLPcurrentLimit = lim;
832 }
833
834 void SetFADdigitalCurrentLimit(double lim)
835 {
836 fFADdigitalCurrentLimit = lim;
837 }
838
839 void SetFADnegativeCurrentLimit(double lim)
840 {
841 fFADnegativeCurrentLimit = lim;
842 }
843
844 void SetFADpositiveCurrentLimit(double lim)
845 {
846 fFADpositiveCurrentLimit = lim;
847 }
848
849 void SetFPAdigitalCurrentLimit(double lim)
850 {
851 fFPAdigitalCurrentLimit = lim;
852 }
853
854 void SetFPAnegativeCurrentLimit(double lim)
855 {
856 fFPAnegativeCurrentLimit = lim;
857 }
858
859 void SetFPApositiveCurrentLimit(double lim)
860 {
861 fFPApositiveCurrentLimit = lim;
862 }
863
864 void SetPositionsBias(const vector<Interpolator2D::vec> &vec)
865 {
866 fPositionsBias = vec;
867 }
868
869 bool IsSecurityLimitExceeded() const
870 {
871 return fSecurityLimitsExceeded;
872 }
873
874 bool IsOpen() const
875 {
876 return IsConnected() || fIsAutoReconnect;
877 }
878};
879
880// ------------------------------------------------------------------------
881
882#include "DimDescriptionService.h"
883
884class ConnectionDimFSC : public ConnectionFSC
885{
886private:
887
888 vector<double> fLastRms;
889
890 DimDescribedService fDimTemp;
891 DimDescribedService fDimTemp2;
892 DimDescribedService fDimHum;
893 DimDescribedService fDimVolt;
894 DimDescribedService fDimCurrent;
895
896 void Update(DimDescribedService &svc, vector<float> data, float time) const
897 {
898 data.insert(data.begin(), time);
899 svc.Update(data);
900 }
901
902 void UpdateTemp(float time, const vector<float> &temp)
903 {
904 Update(fDimTemp, temp, time);
905
906 vector<double> T;
907 vector<Interpolator2D::vec> xy;
908
909 T.reserve(31);
910 xy.reserve(31);
911
912 double avg = 0;
913 double rms = 0;
914
915 // Create a list of all valid sensors
916 for (int i=0; i<31; i++)
917 if (temp[i]!=0)
918 {
919 T.emplace_back(temp[i]);
920 xy.emplace_back(fPositionsSensors[i]);
921
922 avg += temp[i];
923 rms += temp[i]*temp[i];
924 }
925
926 if (T.size()==0)
927 {
928 Warn("No valid sensor temperatures.");
929 return;
930 }
931
932 avg /= T.size();
933 rms /= T.size();
934 rms -= avg*avg;
935 rms = rms<0 ? 0 : sqrt(rms);
936
937 // Clean broken reports
938 const double cut_val = 0.015;
939 const bool reject = rms>4 || (fabs(fLastRms[0]-fLastRms[1])<=cut_val && fabs(rms-fLastRms[0])>cut_val);
940
941 fLastRms[1] = fLastRms[0];
942 fLastRms[0] = rms;
943
944 if (reject)
945 {
946 Warn("Suspicious temperature values rejecte for BIAS_TEMP.");
947 return;
948 }
949
950 // Create interpolator for the corresponding sensor positions
951 Interpolator2D inter(xy);
952
953 // Calculate weights for the output positions
954 if (!inter.SetOutputGrid(fPositionsBias))
955 {
956 Warn("Temperature values rejecte for BIAS_TEMP (calculation of weights failed).");
957 return;
958 }
959
960 // Interpolate the data
961 T = inter.Interpolate(T);
962
963 avg = 0;
964 rms = 0;
965 for (int i=0; i<320; i++)
966 {
967 avg += T[i];
968 rms += T[i]*T[i];
969 }
970
971 avg /= 320;
972 rms /= 320;
973 rms -= avg*avg;
974 rms = rms<0 ? 0 : sqrt(rms);
975
976 vector<float> out;
977 out.reserve(322);
978 out.assign(T.cbegin(), T.cend());
979 out.emplace_back(avg);
980 out.emplace_back(rms);
981
982 // Update the Dim service with the interpolated positions
983 Update(fDimTemp2, out, time);
984 }
985
986 void UpdateHum(float time, const vector<float> &hum)
987 {
988 Update(fDimHum, hum, time);
989 }
990
991 void UpdateVolt(float time, const vector<float> &volt)
992 {
993 Update(fDimVolt, volt, time);
994 }
995
996 void UpdateCur(float time, const vector<float> &curr)
997 {
998 Update(fDimCurrent, curr, time);
999 }
1000
1001public:
1002 ConnectionDimFSC(ba::io_service& ioservice, MessageImp &imp) :
1003 ConnectionFSC(ioservice, imp), fLastRms(2),
1004 fDimTemp ("FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
1005 "|t[s]:FSC uptime"
1006 "|T_sens[deg C]:Sensor compartment temperatures"
1007 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (b/f), 2 (b/f), 3 (b/f)"
1008 "|T_ps[deg C]:Temp power supplies crate 0 (back/front), 1, 2, 3"
1009 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (t/b)"
1010 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
1011 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (f/b)"),
1012 fDimTemp2 ("FSC_CONTROL/BIAS_TEMP", "F:1;F:320;F:1;F:1",
1013 "|t[s]:FSC uptime"
1014 "|T[deg C]:Interpolated temperatures at bias patch positions"
1015 "|T_avg[deg C]:Average temperature calculated from all patches"
1016 "|T_rms[deg C]:Temperature RMS calculated from all patches"),
1017 fDimHum ("FSC_CONTROL/HUMIDITY", "F:1;F:4",
1018 "|t[s]:FSC uptime"
1019 "|H[%]:Humidity sensors readout"),
1020 fDimVolt ("FSC_CONTROL/VOLTAGE",
1021 "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
1022 "|t[s]:FSC uptime"
1023 "|FAD_Ud[V]:FAD digital (crate 0-3)"
1024 "|FAD_Up[V]:FAD positive (crate 0-3)"
1025 "|FAD_Un[V]:FAD negative (crate 0-3)"
1026 "|FPA_Ud[V]:FPA digital (crate 0-3)"
1027 "|FPA_Up[V]:FPA positive (crate 0-3)"
1028 "|FPA_Un[V]:FPA negative (crate 0-3)"
1029 "|ETH_U[V]:Ethernet switch (pos/neg)"
1030 "|FTM_U[V]:FTM - trigger master (pos/neg)"
1031 "|FFC_U[V]:FFC"
1032 "|FLP_U[V]:FLP - light pulser"),
1033 fDimCurrent("FSC_CONTROL/CURRENT", "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
1034 "|t[s]:FSC uptime"
1035 "|FAD_Id[A]:FAD digital (crate 0-3)"
1036 "|FAD_Ip[A]:FAD positive (crate 0-3)"
1037 "|FAD_In[A]:FAD negative (crate 0-3)"
1038 "|FPA_Id[A]:FPA digital (crate 0-3)"
1039 "|FPA_Ip[A]:FPA positive (crate 0-3)"
1040 "|FPA_In[A]:FPA negative (crate 0-3)"
1041 "|ETH_I[A]:Ethernet switch (pos/neg)"
1042 "|FTM_I[A]:FTM - trigger master (pos/neg)"
1043 "|FFC_I[A]:FFC"
1044 "|FLP_I[A]:FLP - light pulser")
1045 {
1046 fLastRms[0] = 1.5;
1047 }
1048
1049 // A B [C] [D] E [F] G H [I] J K [L] M N O P Q R [S] T U V W [X] Y Z
1050};
1051
1052// ------------------------------------------------------------------------
1053
1054template <class T, class S>
1055class StateMachineFSC : public StateMachineAsio<T>
1056{
1057private:
1058 S fFSC;
1059
1060 int Disconnect()
1061 {
1062 // Close all connections
1063 fFSC.PostClose(false);
1064
1065 return T::GetCurrentState();
1066 }
1067
1068 int Reconnect(const EventImp &evt)
1069 {
1070 // Close all connections to supress the warning in SetEndpoint
1071 fFSC.PostClose(false);
1072
1073 // Now wait until all connection have been closed and
1074 // all pending handlers have been processed
1075 ba::io_service::poll();
1076
1077 if (evt.GetBool())
1078 fFSC.SetEndpoint(evt.GetString());
1079
1080 // Now we can reopen the connection
1081 fFSC.PostClose(true);
1082
1083 return T::GetCurrentState();
1084 }
1085
1086 int Execute()
1087 {
1088 if (fFSC.IsSecurityLimitExceeded())
1089 {
1090 return State::kOverCurrent;
1091 }
1092 else if(fFSC.IsOpen())
1093 {
1094 return State::kConnected;
1095 }
1096 else
1097 {
1098 return State::kDisconnected;
1099 }
1100
1101 //return fFSC.IsOpen() ? State::kConnected : State::kDisconnected;
1102 }
1103
1104 bool CheckEventSize(size_t has, const char *name, size_t size)
1105 {
1106 if (has==size)
1107 return true;
1108
1109 ostringstream msg;
1110 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
1111 T::Fatal(msg);
1112 return false;
1113 }
1114
1115 int SetVerbosity(const EventImp &evt)
1116 {
1117 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
1118 return T::kSM_FatalError;
1119
1120 fFSC.SetVerbose(evt.GetBool());
1121
1122 return T::GetCurrentState();
1123 }
1124
1125public:
1126 StateMachineFSC(ostream &out=cout) :
1127 StateMachineAsio<T>(out, "FSC_CONTROL"), fFSC(*this, *this)
1128 {
1129 // State names
1130 T::AddStateName(State::kDisconnected, "Disconnected",
1131 "FSC board not connected via ethernet.");
1132
1133 T::AddStateName(State::kConnected, "Connected",
1134 "Ethernet connection to FSC established.");
1135
1136 T::AddStateName(State::kHighCurrent, "HighPowerConsumption",
1137 "FSC board measures high power consumption, c.f. FSC current limits in config-file or config-DB.");
1138
1139 T::AddStateName(State::kOverCurrent, "OverCurrent",
1140 "FSC board measures *too* power consumption, c.f. FSC current limits in config-file or config-DB.");
1141
1142 // Verbosity commands
1143 T::AddEvent("SET_VERBOSE", "B:1")
1144 (bind(&StateMachineFSC::SetVerbosity, this, placeholders::_1))
1145 ("set verbosity state"
1146 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1147
1148 // Conenction commands
1149 T::AddEvent("DISCONNECT", State::kConnected)
1150 (bind(&StateMachineFSC::Disconnect, this))
1151 ("disconnect from ethernet");
1152
1153 T::AddEvent("RECONNECT", "O", State::kDisconnected, State::kConnected)
1154 (bind(&StateMachineFSC::Reconnect, this, placeholders::_1))
1155 ("(Re)connect ethernet connection to FSC, a new address can be given"
1156 "|[host][string]:new ethernet address in the form <host:port>");
1157
1158 fFSC.StartConnect();
1159 }
1160
1161 void SetEndpoint(const string &url)
1162 {
1163 fFSC.SetEndpoint(url);
1164 }
1165
1166 int EvalOptions(Configuration &conf)
1167 {
1168 fFSC.SetVerbose(!conf.Get<bool>("quiet"));
1169
1170 const string fname1 = conf.Get<string>("sensor-pos-file");
1171 const auto v1 = Interpolator2D::ReadGrid(fname1);
1172 if (v1.size() != 31)
1173 {
1174 T::Error("Reading sensor positions from "+fname1+"failed ("+to_string(v1.size())+")");
1175 return 1;
1176 }
1177
1178 const string fname2 = conf.Get<string>("patch-pos-file");
1179 const auto v2 = Interpolator2D::ReadGrid(fname2);
1180 if (v2.size() != 320)
1181 {
1182 T::Error("Reading bias patch positions from "+fname2+"failed ("+to_string(v2.size())+")");
1183 return 1;
1184 }
1185
1186 fFSC.SetPositionsSensors(v1);
1187 fFSC.SetPositionsBias(v2);
1188
1189 fFSC.SetEthernetSwitchCurrentLimit( conf.Get<double>("ethernet_switch") );
1190 fFSC.SetFFCcurrentLimit( conf.Get<double>("FFC") );
1191 fFSC.SetFLPcurrentLimit( conf.Get<double>("FLP") );
1192 fFSC.SetFADdigitalCurrentLimit( conf.Get<double>("FAD_digital") );
1193 fFSC.SetFADnegativeCurrentLimit( conf.Get<double>("FAD_negative") );
1194 fFSC.SetFADpositiveCurrentLimit( conf.Get<double>("FAD_positive") );
1195 fFSC.SetFPAdigitalCurrentLimit( conf.Get<double>("FPA_digital") );
1196 fFSC.SetFPAnegativeCurrentLimit( conf.Get<double>("FPA_negative") );
1197 fFSC.SetFPApositiveCurrentLimit( conf.Get<double>("FPA_positive") );
1198
1199 SetEndpoint(conf.Get<string>("addr"));
1200
1201 return -1;
1202 }
1203};
1204
1205// ------------------------------------------------------------------------
1206
1207#include "Main.h"
1208
1209template<class T, class S, class R>
1210int RunShell(Configuration &conf)
1211{
1212 return Main::execute<T, StateMachineFSC<S, R>>(conf);
1213}
1214
1215void SetupConfiguration(Configuration &conf)
1216{
1217 po::options_description control("FTM control options");
1218 control.add_options()
1219 ("no-dim", po_bool(), "Disable dim services")
1220 ("addr,a", var<string>("localhost:5000"), "Network address of FSC")
1221 ("sensor-pos-file", var<string>()->required(), "File with the positions of the 31 temperature sensors")
1222 ("patch-pos-file", var<string>()->required(), "File with the positions of the 320 bias patches")
1223 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
1224 ;
1225
1226 po::options_description current_limits("Security current limits");
1227 current_limits.add_options()
1228 ("ethernet_switch", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1229 ("FFC", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1230 ("FLP", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1231 ("FAD_digital", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1232 ("FAD_negative", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1233 ("FAD_positive", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1234 ("FPA_digital", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1235 ("FPA_negative", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1236 ("FPA_positive", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1237 ;
1238
1239 conf.AddOptions(control);
1240 conf.AddOptions(current_limits);
1241}
1242
1243/*
1244 Extract usage clause(s) [if any] for SYNOPSIS.
1245 Translators: "Usage" and "or" here are patterns (regular expressions) which
1246 are used to match the usage synopsis in program output. An example from cp
1247 (GNU coreutils) which contains both strings:
1248 Usage: cp [OPTION]... [-T] SOURCE DEST
1249 or: cp [OPTION]... SOURCE... DIRECTORY
1250 or: cp [OPTION]... -t DIRECTORY SOURCE...
1251 */
1252void PrintUsage()
1253{
1254 cout <<
1255 "The fscctrl controls the FSC (FACT Slow Control) board.\n"
1256 "\n"
1257 "The default is that the program is started without user intercation. "
1258 "All actions are supposed to arrive as DimCommands. Using the -c "
1259 "option, a local shell can be initialized. With h or help a short "
1260 "help message about the usuage can be brought to the screen.\n"
1261 "\n"
1262 "Usage: fscctrl [-c type] [OPTIONS]\n"
1263 " or: fscctrl [OPTIONS]\n";
1264 cout << endl;
1265}
1266
1267void PrintHelp()
1268{
1269 Main::PrintHelp<StateMachineFSC<StateMachine, ConnectionFSC>>();
1270
1271 /* Additional help text which is printed after the configuration
1272 options goes here */
1273
1274 /*
1275 cout << "bla bla bla" << endl << endl;
1276 cout << endl;
1277 cout << "Environment:" << endl;
1278 cout << "environment" << endl;
1279 cout << endl;
1280 cout << "Examples:" << endl;
1281 cout << "test exam" << endl;
1282 cout << endl;
1283 cout << "Files:" << endl;
1284 cout << "files" << endl;
1285 cout << endl;
1286 */
1287}
1288
1289int main(int argc, const char* argv[])
1290{
1291 Configuration conf(argv[0]);
1292 conf.SetPrintUsage(PrintUsage);
1293 Main::SetupConfiguration(conf);
1294 SetupConfiguration(conf);
1295
1296 if (!conf.DoParse(argc, argv, PrintHelp))
1297 return 127;
1298
1299 //try
1300 {
1301 // No console access at all
1302 if (!conf.Has("console"))
1303 {
1304 if (conf.Get<bool>("no-dim"))
1305 return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
1306 else
1307 return RunShell<LocalStream, StateMachineDim, ConnectionDimFSC>(conf);
1308 }
1309 // Cosole access w/ and w/o Dim
1310 if (conf.Get<bool>("no-dim"))
1311 {
1312 if (conf.Get<int>("console")==0)
1313 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
1314 else
1315 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
1316 }
1317 else
1318 {
1319 if (conf.Get<int>("console")==0)
1320 return RunShell<LocalShell, StateMachineDim, ConnectionDimFSC>(conf);
1321 else
1322 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFSC>(conf);
1323 }
1324 }
1325 /*catch (std::exception& e)
1326 {
1327 cerr << "Exception: " << e.what() << endl;
1328 return -1;
1329 }*/
1330
1331 return 0;
1332}
Note: See TracBrowser for help on using the repository browser.