Low-Energy Muon (LEM) Experiment  0.5.1
LakeShore340.c
Go to the documentation of this file.
1 /********************************************************************\
2 
3  Name: LakeShore340.c
4  Created by: Andreas Suter 2003/10/22
5 
6  Contents: device driver for the LakeShore 340 temperature controller,
7  defined as a multi class device.
8 
9  RS232: 19200 baud, 8 data bits, 1 stop bit, no parity bit,
10  protocol: no flow control, termination \r\n (CR\LF)
11 
12 \********************************************************************/
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <math.h>
19 #include <time.h>
20 
21 #include "midas.h"
22 #include "msystem.h"
23 
24 #include "LakeShore340.h"
25 
26 #include "ets_logout.h"
27 #include "lemSCWatchdog.h"
28 
29 /*---- globals -----------------------------------------------------*/
30 
31 #define LS340_SHUTDOWN -999
32 
33 #define LS340_MAX_SENSORS 10
34 #define LS340_DELTA_R 2.0
35 #define LS340_TIME_OUT 2000
36 
37 /* --------- to handle error messages ------------------------------*/
38 #define LS340_MAX_ERROR 3
39 #define LS340_DELTA_TIME_ERROR 3600
40 #define LS340_MAX_TRY_MANY 10
41 #define LS340_MAX_TRY_LESS 3
42 
43 #define LS340_WAIT 500
44 
45 #define LS340_INIT_ERROR -2
46 #define LS340_READ_ERROR -1
47 
48 #define LS340_MAX_AVG 100
50 
52 #define LS340_DEBUG 0
53 
55 #define LS340_MAX_READBACK_FAILURE 5
56 #define LS340_MAX_RECONNECTION_FAILURE 5
57 
59 #define LS340_ETS_LOGOUT_SLEEP 10000
60 
62 typedef struct {
63  char datetime[32];
64  INT type[LS340_MAX_SENSORS];
65  INT curve[LS340_MAX_SENSORS];
66  char channel[LS340_MAX_SENSORS][4];
67  char name[LS340_MAX_SENSORS][NAME_LENGTH];
68  float raw_value_1;
69  float raw_value_2;
70  float raw_value_3;
71  float raw_value_4;
72  float raw_value_5;
73  float raw_value_6;
74  float raw_value_7;
75  float raw_value_8;
76  float raw_value_9;
77  float raw_value_10;
79 
81 #define LS340_SENSORS_STR "\
82 Date and Time = STRING : [32] \n\
83 Sensor Type = INT[10]: \n\
84 1 \n\
85 1 \n\
86 1 \n\
87 1 \n\
88 1 \n\
89 1 \n\
90 1 \n\
91 1 \n\
92 1 \n\
93 1 \n\
94 Calibration Curve = INT[10]: \n\
95 1 \n\
96 1 \n\
97 1 \n\
98 1 \n\
99 1 \n\
100 1 \n\
101 1 \n\
102 1 \n\
103 1 \n\
104 1 \n\
105 Channel = STRING[10]: \n\
106 [4] A\n\
107 [4] B\n\
108 [4] C1\n\
109 [4] C2\n\
110 [4] C3\n\
111 [4] C4\n\
112 [4] D1\n\
113 [4] D2\n\
114 [4] D3\n\
115 [4] D4\n\
116 Sensor Name = STRING[10]: \n\
117 [32] LS_\n\
118 [32] LS_\n\
119 [32] LS_\n\
120 [32] LS_\n\
121 [32] LS_\n\
122 [32] LS_\n\
123 [32] LS_\n\
124 [32] LS_\n\
125 [32] LS_\n\
126 [32] LS_\n\
127 Raw Input Ch 1 = FLOAT : 0.0\n\
128 Raw Input Ch 2 = FLOAT : 0.0\n\
129 Raw Input Ch 3 = FLOAT : 0.0\n\
130 Raw Input Ch 4 = FLOAT : 0.0\n\
131 Raw Input Ch 5 = FLOAT : 0.0\n\
132 Raw Input Ch 6 = FLOAT : 0.0\n\
133 Raw Input Ch 7 = FLOAT : 0.0\n\
134 Raw Input Ch 8 = FLOAT : 0.0\n\
135 Raw Input Ch 9 = FLOAT : 0.0\n\
136 Raw Input Ch 10 = FLOAT : 0.0\n\
137 "
138 /*---------------------------------------------------------------------*/
139 
141 typedef struct {
142  char ctrl_ch[4];
148 } LS340_LOOP1; // see lakeshore 340 manual chapter 9 (CSET, PID, CLIMIT)
149 
151 #define LS340_LOOP1_STR "\
152 CTRL_CH = STRING : [4] A\n\
153 SetPoint Limit = FLOAT : 350.f\n\
154 Max. Current Tag = INT : 4\n\
155 Max. User Current = FLOAT : 0.85\n\
156 Max. Heater Range = INT : 5\n\
157 Heater Resistance = FLOAT : 25.0\n\
158 "
159 /*---------------------------------------------------------------------*/
160 
162 typedef struct {
171  char odb_output[2*NAME_LENGTH];
172  INT remote;
175 
177 #define LS340_INTERNAL_STR "\
178 Detailed Messages = INT : 0\n\
179 ETS_IN_USE = INT : 1\n\
180 SCW_IN_USE = INT : 0\n\
181 No Connection = INT : 1\n\
182 Reconnection Timeout = INT : 10\n\
183 Read Timeout = INT : 5\n\
184 Read Raw Data = BOOL : FALSE\n\
185 ODB Offset = INT : 0\n\
186 ODB Output Path = STRING : [64] /Equipment/LS340 Moddy/Variables/Output\n\
187 Remote = INT : 1\n\
188 # Sensors = INT : 7\n\
189 "
190 
191 /*---------------------------------------------------------------------*/
192 
198 #define LS340_ZONE_STR "\
199 Zone = STRING[10]: \n\
200 [32] 1, 1, 7, 500, 300, 0, 0, 3\n\
201 [32] 1, 2, 10, 500, 200, 2, 0, 4\n\
202 [32] 1, 3, 15, 500, 100, 2, 0, 4\n\
203 [32] 1, 4, 20, 500, 50, 2, 0, 4\n\
204 [32] 1, 5, 30, 500, 20, 2, 0, 4\n\
205 [32] 1, 6, 320, 500, 20, 2, 0, 5\n\
206 [32] 1, 7, 320, 500, 20, 2, 0, 5\n\
207 [32] 1, 8, 320, 500, 20, 2, 0, 5\n\
208 [32] 1, 9, 320, 500, 20, 2, 0, 5\n\
209 [32] 1, 10, 320, 500, 20, 2, 0, 5\n\
210 "
211 
212 /*---------------------------------------------------------------------*/
213 
215 typedef struct {
219  char zone[10*NAME_LENGTH];
221 
222 /*---------------------------------------------------------------------*/
223 
225 typedef struct {
226  char ls_name[NAME_LENGTH];
227  char names_in[8][NAME_LENGTH];
228  char names_out[8][NAME_LENGTH];
230 
232 #define LS340_ODB_NAMES_STR "\
233 LakeShore 340 Name = STRING : [32] Moderator\n\
234 Names In = STRING[8] : \n\
235 [32] LS_Heater\n\
236 [32] LS_SetPoint (read back)\n\
237 [32] LS_Gain P (read back)\n\
238 [32] LS_Reset I (read back)\n\
239 [32] LS_Rate D (read back)\n\
240 [32] LS_HeaterRange (read back)\n\
241 [32] LS_ControlMode (read back)\n\
242 [32] LS_Ramp (read back)\n\
243 Names Out = STRING[8] : \n\
244 [32] LS_Remote (1/0)\n\
245 [32] LS_SetPoint (K)\n\
246 [32] LS_Gain P\n\
247 [32] LS_Reset I\n\
248 [32] LS_Rate D\n\
249 [32] LS_HeaterRange\n\
250 [32] LS_ControlMode\n\
251 [32] LS_Ramp\n\
252 "
253 
255 #define LS340_SCW_STR "\
256 Proc Name = STRING : [32]\n\
257 PID = INT : -1\n\
258 Log Name = STRING : [64]\n\
259 DD Name = STRING : [32]\n\
260 Last Updated = DWORD : 0\n\
261 Timeout = DWORD : 180\n\
262 "
263 
264 /*---------------------------------------------------------------------*/
265 
268 typedef struct {
271  LEM_SC_WATCHDOG scw;
272  char cryo_name[NAME_LENGTH];
273  HNDLE hDB;
274  HNDLE hkey;
277  HNDLE hkey_raw_value[10];
280  INT (*bd)(INT cmd, ...);
281  void *bd_info;
282  DWORD read_timer[20];
285  DWORD lasterrtime;
286  DWORD last_value[15];
294  float setpoint;
295  float cmode;
296  float history[LS340_MAX_AVG];
297  int ihis;
298  BOOL his_full;
300 } LS340_INFO;
301 
303 
304 /*---- support routines --------------------------------------------*/
314 INT ls340_send_rcv(LS340_INFO *info, char *cmd, char *str, int max_try)
315 {
316  char tmpstr[128];
317  INT status, status_yield, i;
318 
319  if (!info->bd_connected) // bus driver not connected at the moment
320  return 0;
321 
322  status = 0;
323  i = 0;
324  do {
325 
326  BD_PUTS(cmd);
327  status = BD_GETS(tmpstr, sizeof(tmpstr), "\r\n", LS340_TIME_OUT);
328  if (LS340_DEBUG)
329  cm_msg(MINFO,"ls340_send_rcv", "LS340: %s: trial %d, status = %d, str = %s",
330  info->ls340_odb_names.ls_name, i, status, tmpstr);
331  i++;
332 
333  if (status <= 0) {
334  status_yield = cm_yield(10);
335  if ((status_yield == RPC_SHUTDOWN) || (status_yield == SS_ABORT)) {
336  cm_msg(MINFO, "ls340_send_rcv", "ls340_send_rcv: status of cm_yield = %d", status_yield);
337  return LS340_SHUTDOWN;
338  }
339  ss_sleep(LS340_WAIT);
340  }
341 
342  } while ((status<=0) && (i < max_try));
343 
344  strcpy(str, tmpstr);
345 
346  if (LS340_DEBUG)
347  cm_msg(MINFO,"ls340_send_rcv", "LS340: %s: str = %s", info->ls340_odb_names.ls_name, str);
348 
349  return status;
350 }
351 
352 /*------------------------------------------------------------------*/
360 INT ls340_get_decode(LS340_INFO *info, INT ch, int *sub_tag)
361 {
362  int cmd_tag=0;
363 
364  if (ch < info->ls340_settings.intern.no_of_sensors) { // read temperature
365  cmd_tag=0;
366  }
367 
368  if (ch == info->ls340_settings.intern.no_of_sensors) { // heater output
369  cmd_tag=1;
370  }
371 
372  if (ch == info->ls340_settings.intern.no_of_sensors+1) { // setpoint
373  cmd_tag=2;
374  }
375 
376  if ((ch >= info->ls340_settings.intern.no_of_sensors+2) &&
377  (ch <= info->ls340_settings.intern.no_of_sensors+4)) { // PID's
378  cmd_tag=3;
379  switch (ch-info->ls340_settings.intern.no_of_sensors-2) { // check if P, I or D
380  case 0:
381  *sub_tag=0;
382  break;
383  case 1:
384  *sub_tag=1;
385  break;
386  case 2:
387  *sub_tag=2;
388  break;
389  default:
390  *sub_tag=0;
391  break;
392  }
393  }
394 
395  if (ch == info->ls340_settings.intern.no_of_sensors+5) { // heater range
396  cmd_tag=4;
397  }
398 
399  if (ch == info->ls340_settings.intern.no_of_sensors+6) { // control mode
400  cmd_tag=5;
401  }
402 
403  if (ch == info->ls340_settings.intern.no_of_sensors+7) { // ramp
404  cmd_tag=6;
405  }
406 
407  return cmd_tag;
408 }
409 
410 /*------------------------------------------------------------------*/
425 {
426  HNDLE hDB, keyOut;
427  INT status, size;
428  float value[3];
429  char cmd[128], qry[128], rcv[128];
430  int control_mode;
431 
432  cm_get_experiment_database(&hDB, NULL);
433 
434  // get Output key
435  status = db_find_key(hDB, 0, info->ls340_settings.intern.odb_output, &keyOut);
436  if (status != FE_SUCCESS) { // couldn't get the output key
437  cm_msg(MERROR, "ls340_force_update", "ls340_force_update: %s. Couldn't get the Output key.",
438  info->ls340_odb_names.ls_name);
439  return status;
440  }
441 
442  size = sizeof(float);
443 
444  // update 'set point'
445  db_get_data_index(hDB, keyOut, &value[0], &size, 1+info->ls340_settings.intern.odb_offset, TID_FLOAT);
446  sprintf(cmd, "SETP 1, %05.2f\r\n", value[0]); // setpoint loop1
447  info->setpoint = value[0]; // store in info
448  sprintf(qry, "SETP? 1\r\n");
449  status = ls340_send_rcv(info, cmd, rcv, LS340_MAX_TRY_MANY); // send command
450  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY); // query
451  if ( !status )
452  cm_msg(MERROR,"ls340_force_update","ls340_force_update: %s: Failed to query %s",
453  info->ls340_odb_names.ls_name, qry);
454  else
455  cm_msg(MINFO,"ls340_force_update", "ls340_force_update: %s: Result of query %s = %s",
456  info->ls340_odb_names.ls_name, qry, rcv);
457 
458  // update control mode
459  db_get_data_index(hDB, keyOut, &value[0], &size, 6+info->ls340_settings.intern.odb_offset, TID_FLOAT);
460  control_mode = (int) value[0]; // store in order to made decision on PID
461  sprintf(cmd, "CMODE 1, %d\r\n", (int)value[0]); // control mode
462  sprintf(qry, "CMODE? 1\r\n");
463  status = ls340_send_rcv(info, cmd, rcv, LS340_MAX_TRY_MANY); // send command
464  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY); // query
465  if ( !status )
466  cm_msg(MERROR,"ls340_force_update","ls340_force_update: %s: Failed to query %s",
467  info->ls340_odb_names.ls_name, qry);
468  else
469  cm_msg(MINFO,"ls340_force_update", "ls340_force_update: %s: Result of query %s = %s",
470  info->ls340_odb_names.ls_name, qry, rcv);
471 
472  // update PID's
473  if (control_mode != 2) { // i.e. not ZONE
474  db_get_data_index(hDB, keyOut, &value[0], &size, 2+info->ls340_settings.intern.odb_offset, TID_FLOAT); // gain 'P'
475  db_get_data_index(hDB, keyOut, &value[1], &size, 3+info->ls340_settings.intern.odb_offset, TID_FLOAT); // reset 'I'
476  db_get_data_index(hDB, keyOut, &value[2], &size, 4+info->ls340_settings.intern.odb_offset, TID_FLOAT); // rate 'D'
477  sprintf(cmd, "PID 1, %d, %d, %d\r\n", (int)value[0], (int)value[1], (int)value[2]);
478  sprintf(qry, "PID? 1\r\n");
479  status = ls340_send_rcv(info, cmd, rcv, LS340_MAX_TRY_MANY); // send command
480  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY); // query
481  if ( !status )
482  cm_msg(MERROR,"ls340_force_update","ls340_force_update: %s: Failed to query %s",
483  info->ls340_odb_names.ls_name, qry);
484  else
485  cm_msg(MINFO,"ls340_force_update", "ls340_force_update: %s: Result of query %s = %s",
486  info->ls340_odb_names.ls_name, qry, rcv);
487 
488  // update heater range
489  db_get_data_index(hDB, keyOut, &value[0], &size, 5+info->ls340_settings.intern.odb_offset, TID_FLOAT);
490  sprintf(cmd, "RANGE %d\r\n", (int)value[0]); // heater range
491  sprintf(qry, "RANGE?\r\n");
492  status = ls340_send_rcv(info, cmd, rcv, LS340_MAX_TRY_MANY); // send command
493  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY); // query
494  if ( !status )
495  cm_msg(MERROR,"ls340_force_update","ls340_force_update: %s: Failed to query %s",
496  info->ls340_odb_names.ls_name, qry);
497  else
498  cm_msg(MINFO,"ls340_force_update", "ls340_force_update: %s: Result of query %s = %s",
499  info->ls340_odb_names.ls_name, qry, rcv);
500  }
501 
502  // update ramp
503  db_get_data_index(hDB, keyOut, &value[0], &size, 7+info->ls340_settings.intern.odb_offset, TID_FLOAT);
504  if (value[0] == 0) // ramp rate == 0, i.e. no ramp wished
505  value[1] = 0;
506  else
507  value[1] = 1;
508  sprintf(cmd, "RAMP 1, %d, %d\r\n", (int)value[1], (int)value[0]); // ramp
509  sprintf(qry, "RAMP? 1\r\n");
510  status = ls340_send_rcv(info, cmd, rcv, LS340_MAX_TRY_MANY); // send command
511  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY); // query
512  if ( !status )
513  cm_msg(MERROR,"ls340_force_update","ls340_force_update: %s: Failed to query %s",
514  info->ls340_odb_names.ls_name, qry);
515  else
516  cm_msg(MINFO,"ls340_force_update", "ls340_force_update: %s: Result of query %s = %s",
517  info->ls340_odb_names.ls_name, qry, rcv);
518 
519  return FE_SUCCESS;
520 }
521 
522 /*------------------------------------------------------------------*/
529 void ls340_no_connection(LS340_INFO *info, INT value)
530 {
531  db_set_data(info->hDB, info->hkey_no_connection, &value, sizeof(value), 1, TID_INT);
532 }
533 
534 /*------------------------------------------------------------------*/
575 void ls340_cryo_name_changed(HNDLE hDB, HNDLE dummy, void *pinfo)
576 {
577  LS340_INFO *info;
578  int i, ch_no, value[4];
579  int status, size;
580  float fvalue;
581  float heater_resistance;
582  int sensor_type[10], calib_curve[10];
583  char str[128], cmd[128];
584  char sensor_name[10*NAME_LENGTH], channel[10*NAME_LENGTH], zone[10*NAME_LENGTH];
585  char ch[NAME_LENGTH+1];
586  HNDLE hKey, hWorkKey, hSubKey;
587  INT loop, zone_no, range, zone_diff=0;;
588  float top_temp, pid_p, pid_i, pid_d, man_out;
589  float zone_dd[6], zone_ls340[6];
590 
591  info = (LS340_INFO *) pinfo;
592 
593  if (strstr(info->cryo_name, "no cryostat")) // "no cryostat" name chosen
594  return;
595 
596  strcpy(info->ls340_odb_names.ls_name, info->cryo_name);
597 
598  cm_msg(MINFO, "ls340_cryo_name_changed", "cryo name = %s", info->cryo_name);
599 
600  // check if the proper DD entry is present
601  sprintf(str, "DD/Cryos/%s", info->cryo_name);
602  status = db_find_key(info->hDB, info->hkey, str, &hKey);
603  if (status != DB_SUCCESS) {
604  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find ../%s in the ODB", str);
605  return;
606  }
607 
608  // handle heater resistance ----------------------------------------------
609 
610  // find ODB key
611  status = db_find_key(info->hDB, hKey, "Heater Resistance", &hSubKey);
612  if (status != DB_SUCCESS) {
613  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Heater Resistance' key!");
614  return;
615  }
616 
617  // get data
618  size = sizeof(float);
619  status = db_get_data(info->hDB, hSubKey, (void*)&heater_resistance, &size, TID_FLOAT);
620 
621  // write data to DD ODB (in case of a restart)
622  status = db_find_key(info->hDB, info->hkey, "DD/Loop1/Heater Resistance", &hWorkKey);
623  if (status != DB_SUCCESS) {
624  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Loop1/Heater Resistance' key!");
625  return;
626  }
627  db_set_data(info->hDB, hWorkKey, (void *)&heater_resistance, sizeof(float), 1, TID_FLOAT);
628 
629  // handle Max. Current Tag ----------------------------------------------
630 
631  // find ODB key
632  status = db_find_key(info->hDB, hKey, "Max. Current Tag", &hSubKey);
633  if (status != DB_SUCCESS) {
634  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Max. Current Tag' key!");
635  return;
636  }
637 
638  // get data
639  size = sizeof(float);
640  status = db_get_data(info->hDB, hSubKey, (void*)&value[0], &size, TID_INT);
641 
642  // write data to DD ODB (in case of a restart)
643  status = db_find_key(info->hDB, info->hkey, "DD/Loop1/Max. Current Tag", &hWorkKey);
644  if (status != DB_SUCCESS) {
645  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Loop1/Max. Current Tag' key!");
646  return;
647  }
648  db_set_data(info->hDB, hWorkKey, (void *)&value[0], sizeof(int), 1, TID_INT);
649 
650  // handle Max. User Current ----------------------------------------------
651 
652  // find ODB key
653  status = db_find_key(info->hDB, hKey, "Max. User Current", &hSubKey);
654  if (status != DB_SUCCESS) {
655  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Max. User Current' key!");
656  return;
657  }
658 
659  // get data
660  size = sizeof(float);
661  status = db_get_data(info->hDB, hSubKey, (void*)&fvalue, &size, TID_FLOAT);
662 
663  // write data to DD ODB (in case of a restart)
664  status = db_find_key(info->hDB, info->hkey, "DD/Loop1/Max. User Current", &hWorkKey);
665  if (status != DB_SUCCESS) {
666  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Loop1/Max. User Current' key!");
667  return;
668  }
669  db_set_data(info->hDB, hWorkKey, (void *)&fvalue, sizeof(float), 1, TID_FLOAT);
670 
671  // handle Max. Heater Range ----------------------------------------------
672 
673  // find ODB key
674  status = db_find_key(info->hDB, hKey, "Max. Heater Range", &hSubKey);
675  if (status != DB_SUCCESS) {
676  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Max. Heater Range' key!");
677  return;
678  }
679 
680  // get data
681  size = sizeof(float);
682  status = db_get_data(info->hDB, hSubKey, (void*)&value[0], &size, TID_INT);
683 
684  // write data to DD ODB (in case of a restart)
685  status = db_find_key(info->hDB, info->hkey, "DD/Loop1/Max. Heater Range", &hWorkKey);
686  if (status != DB_SUCCESS) {
687  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Loop1/Max. Heater Range' key!");
688  return;
689  }
690  db_set_data(info->hDB, hWorkKey, (void *)&value[0], sizeof(int), 1, TID_INT);
691 
692  // handle sensor type ----------------------------------------------------
693 
694  // find ODB key
695  status = db_find_key(info->hDB, hKey, "Sensor Type", &hSubKey);
696  if (status != DB_SUCCESS) {
697  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Sensor Type' key!");
698  return;
699  }
700 
701  // get data
702  size = sizeof(sensor_type);
703  status = db_get_data(info->hDB, hSubKey, (void*)&sensor_type, &size, TID_INT);
704 
705  // write data to DD ODB (in case of a restart)
706  status = db_find_key(info->hDB, info->hkey, "DD/Sensors/Sensor Type", &hWorkKey);
707  if (status != DB_SUCCESS) {
708  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Sensors/Sensor Type' key!");
709  return;
710  }
711  db_set_data(info->hDB, hWorkKey, (void *)&sensor_type, sizeof(sensor_type), 10, TID_INT);
712 
713 
714  // handle calibration curves ----------------------------------------------
715 
716  // find ODB key
717  status = db_find_key(info->hDB, hKey, "Calibration Curve", &hSubKey);
718  if (status != DB_SUCCESS) {
719  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Calibration Curve' key!");
720  return;
721  }
722 
723  // get data
724  size = sizeof(calib_curve);
725  status = db_get_data(info->hDB, hSubKey, (void*)&calib_curve, &size, TID_INT);
726 
727  // write data to DD ODB (in case of a restart)
728  status = db_find_key(info->hDB, info->hkey, "DD/Sensors/Calibration Curve", &hWorkKey);
729  if (status != DB_SUCCESS) {
730  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Sensors/Calibration Curve' key!");
731  return;
732  }
733  db_set_data(info->hDB, hWorkKey, (void *)&calib_curve, sizeof(calib_curve), 10, TID_INT);
734 
735  // handle channel assignments ---------------------------------------------
736 
737  // find ODB key
738  status = db_find_key(info->hDB, hKey, "Channel", &hSubKey);
739  if (status != DB_SUCCESS) {
740  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Channel' key!");
741  return;
742  }
743 
744  // get data
745  size = sizeof(channel);
746  status = db_get_data(info->hDB, hSubKey, (void*)&channel, &size, TID_STRING);
747 
748  // write data to DD ODB (in case of a restart)
749  status = db_find_key(info->hDB, info->hkey, "DD/Sensors/Channel", &hWorkKey);
750  if (status != DB_SUCCESS) {
751  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Sensors/Channel' key!");
752  return;
753  }
754  for (i=0; i<10; i++) {
755  memset(ch, 0, sizeof(ch));
756  memcpy(ch, &channel[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
757  db_set_data_index(info->hDB, hWorkKey, (void *)&ch, 4*sizeof(char), i, TID_STRING);
758  }
759 
760  // handle sensor names ----------------------------------------------------
761 
762  // find ODB key
763  status = db_find_key(info->hDB, hKey, "Sensor Name", &hSubKey);
764  if (status != DB_SUCCESS) {
765  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Sensor Name' key!");
766  return;
767  }
768 
769  // get data
770  size = sizeof(sensor_name);
771  status = db_get_data(info->hDB, hSubKey, (void*)&sensor_name, &size, TID_STRING);
772 
773  // write data to DD ODB (in case of a restart)
774  status = db_find_key(info->hDB, info->hkey, "DD/Sensors/Sensor Name", &hWorkKey);
775  if (status != DB_SUCCESS) {
776  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Sensors/Sensor Name' key!");
777  return;
778  }
779  for (i=0; i<10; i++) {
780  memset(ch, 0, sizeof(ch));
781  memcpy(ch, &sensor_name[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
782  db_set_data_index(info->hDB, hWorkKey, (void *)&ch, NAME_LENGTH*sizeof(char), i, TID_STRING);
783  }
784 
785  // find ODB key for Settings/Names Input
786  status = db_find_key(info->hDB, info->hkey, "../../Names Input", &hWorkKey);
787  if (status != DB_SUCCESS) {
788  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Settings/Names Input' key!");
789  return;
790  }
791  for (i=0; i<info->ls340_settings.intern.no_of_sensors; i++) {
792  memset(ch, 0, sizeof(ch));
793  memcpy(ch, &sensor_name[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
794  db_set_data_index(info->hDB, hWorkKey, (void *)&ch, NAME_LENGTH*sizeof(char),
795  i+info->ls340_settings.intern.odb_offset, TID_STRING);
796  }
797 
798 
799  // handle zone settings ---------------------------------------------------
800 
801  // find ODB key
802  status = db_find_key(info->hDB, hKey, "Zone", &hSubKey);
803  if (status != DB_SUCCESS) {
804  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'Zone' key!");
805  return;
806  }
807 
808  // get data
809  size = sizeof(zone);
810  status = db_get_data(info->hDB, hSubKey, (void*)&zone, &size, TID_STRING);
811 
812  // write data to DD ODB (in case of a restart)
813  status = db_find_key(info->hDB, info->hkey, "DD/Zone/Zone", &hWorkKey);
814  if (status != DB_SUCCESS) {
815  cm_msg(MINFO, "ls340_cryo_name_changed", "couldn't find 'DD/Zone/Zone' key!");
816  return;
817  }
818  for (i=0; i<10; i++) {
819  memset(ch, 0, sizeof(ch));
820  memcpy(ch, &zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
821  db_set_data_index(info->hDB, hWorkKey, (void *)&ch, NAME_LENGTH*sizeof(char), i, TID_STRING);
822  }
823 
824  // send all the stuff to the LS340 ----------------------------------------
825 
826  for (i=0; i<info->ls340_settings.intern.no_of_sensors; i++) {
827 
828  // specifing sensor type
829  memset(ch, 0, sizeof(ch));
830  memcpy(ch, &channel[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
831  sprintf(cmd, "INTYPE %s, %d\r\n", ch, sensor_type[i]);
832  BD_PUTS(cmd);
833  sprintf(cmd, "INTYPE? %s\r\n", ch);
834  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
835  if ( !status ) { // no response
836  cm_msg(MERROR, "ls340_cryo_name_changed", "LS340: %s: Error getting channel %s type assignment.",
837  info->ls340_odb_names.ls_name, ch);
838  return;
839  }
840 
841  // specifing curve which is used to convert to temperature
842  sprintf(cmd, "INCRV %s, %d\r\n", ch, calib_curve[i]);
843  BD_PUTS(cmd);
844  sprintf(cmd, "INCRV? %s\r\n", ch);
845  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
846  if ( !status ) { // no response
847  cm_msg(MERROR, "ls340_cryo_name_changed", "LS340: %s: Error getting channel %s curve assignment.",
848  info->ls340_odb_names.ls_name, ch);
849  return;
850  }
851 
852  // read the header related to a curve
853  sscanf(str, "%d", &ch_no);
854  sprintf(cmd, "CRVHDR? %d\r\n", ch_no);
855  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
856  if ( !status ) { // no response
857  cm_msg(MERROR, "ls340_cryo_name_changed", "LS340: %s: Error getting channel %s curve header.",
858  info->ls340_odb_names.ls_name, ch);
859  return;
860  }
861 
862  // status output message
863  cm_msg(MINFO,"ls340_cryo_name_changed",
864  "LS340: %s: Channel %s curve = (ODB=%d,LS340=%d).\n LS340=%d -> %s",
865  info->ls340_odb_names.ls_name, ch, sensor_type[i], ch_no, ch_no, str);
866  }
867 
868  // set heater resistance setting of the LakeShore 340 ----------------------------
869  sprintf(cmd, "CDISP 1,1,%d\r\n", (int)truncf(heater_resistance));
870  cm_msg(MINFO, "ls340_cryo_name_changed", "LS340: %s: going to set the heater resistance to %d(Ohm)",
871  info->ls340_odb_names.ls_name, (int)truncf(heater_resistance));
872  BD_PUTS(cmd);
873  // check if the heater resistance is set properly
874  sprintf(cmd, "CDISP? 1\r\n");
875  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
876  if ( !status ) { // no response
877  cm_msg(MERROR, "ls340_cryo_name_changed", "LS340: %s: Failed reading the heater resistance settings of loop1.",
878  info->ls340_odb_names.ls_name);
879  return;
880  }
881  sscanf(str, "%d,%d,%d,%d", &value[0], &value[1], &value[2], &value[3]);
882  fvalue = (float)value[1];
883  if (fabs(fvalue-heater_resistance)>LS340_DELTA_R)
884  cm_msg(MERROR, "ls340_cryo_name_changed",
885  "LS340: %s: Controll loop1 heater resistance: ODB entry %2.0f(Ohm) is inconsistent with readback value %2.0f(Ohm)",
886  info->ls340_odb_names.ls_name, heater_resistance, fvalue);
887 
888  // specify setpoint units (necessary, otherwise the setpoint is in V!! stupid LS340 firmware)
889  sprintf(cmd, "CSET 1, , 1, 1\r\n"); // CSET loop1, , Kelvin, enable Heater
890  BD_PUTS(cmd);
891  sprintf(cmd, "CSET? 1\r\n");
892  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
893  if ( !status ) { // no response
894  cm_msg(MERROR, "ls340_cryo_name_changed",
895  "LS340: %s: Error in configuring control loop parameter.",
896  info->ls340_odb_names.ls_name);
897  return; // since the whole things hangs otherwise
898  }
899  cm_msg(MINFO, "ls340_cryo_name_changed",
900  "LS340: %s: Controll loop1 settings: %s",
901  info->ls340_odb_names.ls_name, str);
902 
903  // set control loop1 limits to protect the equipment
904  sprintf(cmd, "CLIMIT 1, %f, , , %d, %d\r\n", info->ls340_settings.loop1.setpoint_limit,
906  BD_PUTS(cmd);
907  sprintf(cmd, "CLIMIT? 1\r\n");
908  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
909  if ( !status ) { // no response
910  cm_msg(MERROR, "ls340_cryo_name_changed", "LS340: %s: Error in configuring control loop limit parameter.",
911  info->ls340_odb_names.ls_name);
912  }
913  cm_msg(MINFO, "ls340_cryo_name_changed", "LS340: %s: Control loop1 limits: %s", info->ls340_odb_names.ls_name, str);
914 
915  // if max_current_tag == 5, i.e. User, set to max. user current
916  if (info->ls340_settings.loop1.max_current_tag == 5) {
917  if ((info->ls340_settings.loop1.max_user_current > 0.0) && (info->ls340_settings.loop1.max_user_current < 2.0)) {
918  sprintf(cmd, "CLIMI %f\r\n", info->ls340_settings.loop1.max_user_current);
919  BD_PUTS(cmd);
920  sprintf(cmd, "CLIMI?\r\n");
921  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
922  if ( !status ) { // no response
923  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error in configuring control loop max. user current.",
924  info->ls340_odb_names.ls_name);
925  }
926  cm_msg(MINFO, "ls340_cryo_name_changed", "LS340: %s: Control max. user current: %s (A)", info->ls340_odb_names.ls_name, str);
927  }
928  }
929 
930  // write zone settings to the LS340 and validate them --------------------------------------
931  for (i=0; i<10; i++) {
932  memset(str, 0, sizeof(str));
933  memcpy(str, &zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
934  status = sscanf(str, "%d, %d, %f, %f, %f, %f, %f, %d",
935  &loop, &zone_no, &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
936  if (status != 8) {
937  cm_msg(MINFO, "ls340_cryo_name_changed", "%s. Couldn't get the zone settings from the DD.",
938  info->ls340_odb_names.ls_name);
939  } else {
940  sprintf(cmd, "ZONE %d, %d, %0.1f, %0.1f, %0.1f, %0.1f, %0.1f, %d\r\n",
941  loop, zone_no, top_temp, pid_p, pid_i, pid_d, man_out, range);
942  BD_PUTS(cmd);
943  }
944  ss_sleep(500); // needed since bloody LS340 is sooo slow
945  }
946  // validate zone settings
947  for (i=0; i<10; i++) {
948  sprintf(cmd, "ZONE? 1, %d\r\n", i+1);
949  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
950  // settings form the dd
951  memset(cmd, 0, sizeof(cmd));
952  memcpy(cmd, &zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
953  sscanf(cmd, "%d, %d, %f, %f, %f, %f, %f, %d",
954  &loop, &zone_no, &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
955  zone_dd[0] = top_temp;
956  zone_dd[1] = pid_p;
957  zone_dd[2] = pid_i;
958  zone_dd[3] = pid_d;
959  zone_dd[4] = man_out;
960  zone_dd[5] = range;
961  // settings form the LS340
962  sscanf(str, "%f, %f, %f, %f, %f, %d",
963  &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
964  zone_ls340[0] = top_temp;
965  zone_ls340[1] = pid_p;
966  zone_ls340[2] = pid_i;
967  zone_ls340[3] = pid_d;
968  zone_ls340[4] = man_out;
969  zone_ls340[5] = range;
970  // check them
971  if ((zone_dd[0] != zone_ls340[0]) || (zone_dd[1] != zone_ls340[1]) || (zone_dd[2] != zone_ls340[2]) ||
972  (zone_dd[3] != zone_ls340[3]) || (zone_dd[4] != zone_ls340[4]) || (zone_dd[5] != zone_ls340[5])) {
973  cm_msg(MINFO, "ls340_cryo_name_changed",
974  "%s. Zone settings from the DD and from the LS340 are different.",
975  info->ls340_odb_names.ls_name);
976  zone_diff = 1;
977  }
978  }
979  if (!zone_diff)
980  cm_msg(MINFO, "ls340_cryo_name_changed",
981  "%s. Zone settings successfully transferred to the LS340.",
982  info->ls340_odb_names.ls_name);
983 
984  cm_msg(MINFO, "ls340_cryo_name_changed", "successfully switched to %s",
985  info->ls340_odb_names.ls_name);
986 }
987 
988 /*---- device driver routines --------------------------------------*/
1000 INT ls340_in_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
1001 {
1002  INT status, size, i, ch, value[4];
1003  INT loop, zone, range, zone_diff=0;;
1004  float top_temp, pid_p, pid_i, pid_d, man_out;
1005  float zone_dd[6], zone_ls340[6];
1006  float fvalue;
1007  char str[128], cmd[128];
1008  HNDLE hDB, hkeydd;
1009  time_t tt;
1010  struct tm tm;
1011 
1012  cm_get_experiment_database(&hDB, NULL);
1013 
1014  // allocate info structure
1015  info = calloc(1, sizeof(LS340_INFO));
1016  *pinfo = info;
1017 
1018  // create LS340 odb names record
1019  status = db_create_record(hDB, hKey, "DD/ODB Names", LS340_ODB_NAMES_STR);
1020  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1021  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/ODB Names in ODB: status=%d", status);
1022  cm_yield(0);
1023  return FE_ERR_ODB;
1024  }
1025 
1026  // create LS340 internal record
1027  status = db_create_record(hDB, hKey, "DD/Internal", LS340_INTERNAL_STR);
1028  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1029  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/Internal in ODB: status=%d", status);
1030  cm_yield(0);
1031  return FE_ERR_ODB;
1032  }
1033 
1034  // create LS340 sensors record
1035  status = db_create_record(hDB, hKey, "DD/Sensors", LS340_SENSORS_STR);
1036  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1037  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/Sensors in ODB: status=%d", status);
1038  cm_yield(0);
1039  return FE_ERR_ODB;
1040  }
1041 
1042  // create LS340 loop1 record
1043  status = db_create_record(hDB, hKey, "DD/Loop1", LS340_LOOP1_STR);
1044  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1045  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/Loop1 in ODB: status=%d", status);
1046  return FE_ERR_ODB;
1047  }
1048 
1049  // create LS340 zone record
1050  status = db_create_record(hDB, hKey, "DD/Zone", LS340_ZONE_STR);
1051  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1052  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/Zone in ODB: status=%d", status);
1053  cm_yield(0);
1054  return FE_ERR_ODB;
1055  }
1056 
1057  // create slowcontrol watchdog info structure
1058  status = db_create_record(hDB, hKey, "DD/SCW", LS340_SCW_STR);
1059  if ((status != DB_SUCCESS) && (status != DB_OPEN_RECORD)) {
1060  cm_msg(MERROR, "ls340_in_init", "ls340_in_init: Couldn't create DD/SCW in ODB: status=%d", status);
1061  cm_yield(0);
1062  return FE_ERR_ODB;
1063  }
1064 
1065  // open hot-links to different DD subtrees
1066  db_find_key(hDB, hKey, "DD/ODB Names/LakeShore 340 Name", &hkeydd);
1067  db_open_record(hDB, hkeydd, (void *)&info->cryo_name, sizeof(info->cryo_name), MODE_READ,
1068  &ls340_cryo_name_changed, (void *)info);
1069  db_find_key(hDB, hKey, "DD/ODB Names", &hkeydd);
1070  db_open_record(hDB, hkeydd, (void *)&info->ls340_odb_names, sizeof(info->ls340_odb_names),
1071  MODE_READ, NULL, NULL);
1072  db_find_key(hDB, hKey, "DD/Internal", &hkeydd);
1073  db_open_record(hDB, hkeydd, (void *)&info->ls340_settings.intern, sizeof(info->ls340_settings.intern),
1074  MODE_READ, NULL, NULL);
1075  db_find_key(hDB, hKey, "DD/Sensors", &hkeydd);
1076  db_open_record(hDB, hkeydd, (void *)&info->ls340_settings.sensor, sizeof(info->ls340_settings.sensor),
1077  MODE_READ, NULL, NULL);
1078  db_find_key(hDB, hKey, "DD/Loop1", &hkeydd);
1079  db_open_record(hDB, hkeydd, (void *)&info->ls340_settings.loop1, sizeof(info->ls340_settings.loop1),
1080  MODE_READ, NULL, NULL);
1081  db_find_key(hDB, hKey, "DD/Zone", &hkeydd);
1082  db_open_record(hDB, hkeydd, (void *)&info->ls340_settings.zone, sizeof(info->ls340_settings.zone),
1083  MODE_READ, NULL, NULL);
1084  db_find_key(hDB, hKey, "DD/SCW", &hkeydd);
1085  db_open_record(hDB, hkeydd, (void *)&info->scw, sizeof(info->scw),
1086  MODE_READ, NULL, NULL);
1087 
1088  // initialize driver
1089  info->hDB = hDB;
1090  info->hkey = hKey;
1091  info->num_channels_in = channels;
1092  info->bd = bd;
1093  info->read_timer[0] = ss_millitime();
1094  for (i=1; i<18; i++)
1095  info->read_timer[i] = info->read_timer[0];
1096  info->errorcount = 0;
1097  info->lasterrtime = ss_time();
1098  info->startup_error = 0;
1099  info->bd_connected = 0;
1100  info->last_reconnect = ss_time();
1101  info->readback_failure = 0;
1102  info->reconnection_failures = 0;
1103  info->readback_err = 0;
1104  info->heater_setting = 0;
1105  info->first_bd_error = 1;
1106  info->set_startup_counter = 0;
1107 
1108  // check if the control channel is valid
1109  if (!strstr(info->ls340_settings.loop1.ctrl_ch, "A") && !strstr(info->ls340_settings.loop1.ctrl_ch, "B") &&
1110  !strstr(info->ls340_settings.loop1.ctrl_ch, "C1") && !strstr(info->ls340_settings.loop1.ctrl_ch, "C2") &&
1111  !strstr(info->ls340_settings.loop1.ctrl_ch, "C3") && !strstr(info->ls340_settings.loop1.ctrl_ch, "C4") &&
1112  !strstr(info->ls340_settings.loop1.ctrl_ch, "D1") && !strstr(info->ls340_settings.loop1.ctrl_ch, "D2") &&
1113  !strstr(info->ls340_settings.loop1.ctrl_ch, "D3") && !strstr(info->ls340_settings.loop1.ctrl_ch, "D4") &&
1114  !strstr(info->ls340_settings.loop1.ctrl_ch, "C") && !strstr(info->ls340_settings.loop1.ctrl_ch, "D")) {
1115  cm_msg(MINFO, "LS340_in_init", "LS340_in_init: ctrl loop channel %s is not allowed, will set it to A. Only channels A/B/C1-C4/D1-D4 are possible.", info->ls340_settings.loop1.ctrl_ch);
1116  cm_yield(0);
1117  strcpy(info->ls340_settings.loop1.ctrl_ch, "A");
1118  }
1119 
1120  // initialize history
1121  info->ihis = 0;
1122  info->his_full = FALSE;
1123  for (i=0; i<LS340_MAX_AVG; i++) info->history[i] = 0.0;
1124 
1125  // find datetime dd entry
1126  status = db_find_key(hDB, hKey, "DD/Sensors/Date and Time", &info->hkey_datetime);
1127  // find bd connected dd entry
1128  status = db_find_key(hDB, hKey, "DD/Internal/No Connection", &info->hkey_no_connection);
1129  // find raw_value dd entry
1130  for (i=0; i<LS340_MAX_SENSORS; i++) {
1131  sprintf(str, "DD/Sensors/Raw Input Ch %d", i+1);
1132  status = db_find_key(hDB, hKey, str, &info->hkey_raw_value[i]);
1133  }
1134 
1135  if (!bd)
1136  return FE_ERR_ODB;
1137 
1138  // initialize bus driver
1139  status = info->bd(CMD_INIT, hKey, &info->bd_info);
1140  if (status != FE_SUCCESS) {
1141  info->startup_error = 1;
1142  return status;
1143  }
1144  info->bd_connected = 1;
1145  // set bd connected flag in DD entry
1146  ls340_no_connection(info, 0);
1147 
1148  // initialize LS340
1149  strcpy(cmd, "*IDN?\r\n");
1150  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1151  if ( !status ) { // error occurred
1152  cm_msg(MERROR,"LS340_in_init", "Error getting device query from LS340, %s",info->ls340_odb_names.ls_name);
1153  info->startup_error = 1;
1154  return FE_SUCCESS;//FE_ERR_HW;
1155  }
1156  cm_msg(MINFO,"LS340_in_init", "Device query of LS340 yields %s = %s", info->ls340_odb_names.ls_name,str);
1157  cm_yield(0);
1158 
1159  // sync date-time between computer and LakeShore340
1160  tt = time(NULL);
1161  tm = *localtime(&tt);
1162  sprintf(cmd, "DATETIME %d, %d, %d, %d, %d, %d, %d", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900, tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
1163  cm_msg(MDEBUG, "ls340_in_init", "ls340_in_init: set date and time to %s", cmd);
1164  cm_yield(0);
1165  BD_PUTS(cmd);
1166 
1167  // set/query the input type and calibration curve assigned
1168  for (i=0; i<info->ls340_settings.intern.no_of_sensors; i++) {
1169 
1170  // specifing sensor type
1171  sprintf(cmd, "INTYPE %s, %d\r\n", info->ls340_settings.sensor.channel[i], info->ls340_settings.sensor.type[i]);
1172  BD_PUTS(cmd);
1173  sprintf(cmd, "INTYPE? %s\r\n", info->ls340_settings.sensor.channel[i]);
1174  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1175  if ( !status ) { // no response
1176  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error getting channel %s type assignment.",
1178  cm_yield(0);
1179  info->startup_error = 1;
1180  return FE_SUCCESS; // since the whole things hangs otherwise
1181  }
1182 
1183  // specifing curve which is used to convert to temperature
1184  sprintf(cmd, "INCRV %s, %d\r\n", info->ls340_settings.sensor.channel[i], info->ls340_settings.sensor.curve[i]);
1185  BD_PUTS(cmd);
1186  sprintf(cmd, "INCRV? %s\r\n", info->ls340_settings.sensor.channel[i]);
1187  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1188  if ( !status ) { // no response
1189  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error getting channel %s curve assignment.",
1191  cm_yield(0);
1192  info->startup_error = 1;
1193  return FE_SUCCESS; // since the whole things hangs otherwise
1194  }
1195 
1196  // read the header related to a curve
1197  sscanf(str, "%d", &ch);
1198  sprintf(cmd, "CRVHDR? %d\r\n", ch);
1199  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1200  if ( !status ) { // no response
1201  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error getting channel %s curve header.",
1203  cm_yield(0);
1204  info->startup_error = 1;
1205  return FE_SUCCESS; // since the whole things hangs otherwise
1206  }
1207 
1208  // status output message
1209  cm_msg(MINFO,"LS340_in_init", "LS340: %s: Channel %s curve = (ODB=%d,LS340=%d).\n LS340=%d -> %s",
1211  info->ls340_settings.sensor.type[i], ch, ch, str);
1212  cm_yield(0);
1213  } // for
1214 
1215  // specify setpoint units
1216  //sprintf(cmd, "CSET 1, %s, 2, 1\r\n", info->ls340_settings.loop1.ctrl_ch); // CSET loop1, ctrl ch (A/B), Celsius, enable Heater
1217  sprintf(cmd, "CSET 1, %s, 1, 1\r\n", info->ls340_settings.loop1.ctrl_ch); // CSET loop1, ctrl ch (A/B), Kelvin, enable Heater
1218  BD_PUTS(cmd);
1219  sprintf(cmd, "CSET? 1\r\n");
1220  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1221  if ( !status ) { // no response
1222  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error in configuring control loop parameter.",
1223  info->ls340_odb_names.ls_name);
1224  cm_yield(0);
1225  info->startup_error = 1;
1226  return FE_SUCCESS; // since the whole things hangs otherwise
1227  }
1228  cm_msg(MINFO, "LS340_in_init", "LS340: %s: Control loop1 settings: %s", info->ls340_odb_names.ls_name, str);
1229  cm_yield(0);
1230 
1231  // set control loop1 limits to protect the equipment
1232  sprintf(cmd, "CLIMIT 1, %f, , , %d, %d\r\n", info->ls340_settings.loop1.setpoint_limit,
1234  BD_PUTS(cmd);
1235  sprintf(cmd, "CLIMIT? 1\r\n");
1236  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1237  if ( !status ) { // no response
1238  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error in configuring control loop limit parameter.",
1239  info->ls340_odb_names.ls_name);
1240  info->startup_error = 1;
1241  return FE_SUCCESS; // since the whole things hangs otherwise
1242  }
1243  cm_msg(MINFO, "LS340_in_init", "LS340: %s: Control loop1 limits: %s", info->ls340_odb_names.ls_name, str);
1244  cm_yield(0);
1245 
1246  // if max_current_tag == 5, i.e. User, set to max. user current
1247  if (info->ls340_settings.loop1.max_current_tag == 5) {
1248  if ((info->ls340_settings.loop1.max_user_current > 0.0) && (info->ls340_settings.loop1.max_user_current < 2.0)) {
1249  sprintf(cmd, "CLIMI %f\r\n", info->ls340_settings.loop1.max_user_current);
1250  BD_PUTS(cmd);
1251  sprintf(cmd, "CLIMI?\r\n");
1252  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1253  if ( !status ) { // no response
1254  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Error in configuring control loop max. user current.",
1255  info->ls340_odb_names.ls_name);
1256  info->startup_error = 1;
1257  return FE_SUCCESS; // since the whole things hangs otherwise
1258  }
1259  cm_msg(MINFO, "LS340_in_init", "LS340: %s: Control max. user current: %s (A)", info->ls340_odb_names.ls_name, str);
1260  cm_yield(0);
1261  }
1262  }
1263 
1264  // check if heater resistance corresponds to the ODB settings
1265  sprintf(cmd, "CDISP? 1\r\n");
1266  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1267  if ( !status ) { // no response
1268  cm_msg(MERROR, "LS340_in_init", "LS340: %s: Reading the heater resistance settings of loop1.",
1269  info->ls340_odb_names.ls_name);
1270  cm_yield(0);
1271  info->startup_error = 1;
1272  return FE_SUCCESS; // since the whole things hangs otherwise
1273  }
1274  sscanf(str, "%d,%d,%d,%d", &value[0], &value[1], &value[2], &value[3]);
1275  fvalue = (float)value[1];
1276  if (fabs(fvalue-info->ls340_settings.loop1.heater_resistance)>LS340_DELTA_R) {
1277  cm_msg(MERROR, "LS340_in_init",
1278  "LS340: %s: Controll loop1 heater resistance: ODB entry %2.0f(Ohm) is inconsistent with readback value %2.0f(Ohm)",
1280  cm_yield(0);
1281  }
1282 
1283  // write zone settings to the LS340 and validate them --------------------------------------
1284  for (i=0; i<10; i++) {
1285  memset(str, 0, sizeof(str));
1286  memcpy(str, &info->ls340_settings.zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
1287  status = sscanf(str, "%d, %d, %f, %f, %f, %f, %f, %d",
1288  &loop, &zone, &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
1289  if (status != 8) {
1290  cm_msg(MINFO, "LS340_in_init", "%s. Couldn't get the zone settings from the DD.",
1291  info->ls340_odb_names.ls_name);
1292  cm_yield(0);
1293  } else {
1294  sprintf(cmd, "ZONE %d, %d, %0.1f, %0.1f, %0.1f, %0.1f, %0.1f, %d\r\n",
1295  loop, zone, top_temp, pid_p, pid_i, pid_d, man_out, range);
1296  BD_PUTS(cmd);
1297  }
1298  ss_sleep(500); // needed since bloody LS340 is sooo slow
1299  }
1300  // validate zone settings
1301  for (i=0; i<10; i++) {
1302  sprintf(cmd, "ZONE? 1, %d\r\n", i+1);
1303  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_MANY);
1304  // settings form the dd
1305  memset(cmd, 0, sizeof(str));
1306  memcpy(cmd, &info->ls340_settings.zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
1307  sscanf(cmd, "%d, %d, %f, %f, %f, %f, %f, %d",
1308  &loop, &zone, &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
1309  zone_dd[0] = top_temp;
1310  zone_dd[1] = pid_p;
1311  zone_dd[2] = pid_i;
1312  zone_dd[3] = pid_d;
1313  zone_dd[4] = man_out;
1314  zone_dd[5] = range;
1315  // settings form the LS340
1316  sscanf(str, "%f, %f, %f, %f, %f, %d",
1317  &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
1318  zone_ls340[0] = top_temp;
1319  zone_ls340[1] = pid_p;
1320  zone_ls340[2] = pid_i;
1321  zone_ls340[3] = pid_d;
1322  zone_ls340[4] = man_out;
1323  zone_ls340[5] = range;
1324  // check them
1325  if ((zone_dd[0] != zone_ls340[0]) || (zone_dd[1] != zone_ls340[1]) || (zone_dd[2] != zone_ls340[2]) ||
1326  (zone_dd[3] != zone_ls340[3]) || (zone_dd[4] != zone_ls340[4]) || (zone_dd[5] != zone_ls340[5])) {
1327  cm_msg(MINFO, "LS340_in_init", "%s. Zone settings from the DD and from the LS340 are different.",
1328  info->ls340_odb_names.ls_name);
1329  zone_diff = 1;
1330  }
1331  }
1332  if (!zone_diff) {
1333  cm_msg(MINFO, "LS340_in_init", "%s. Zone settings successfully transferred to the LS340.", info->ls340_odb_names.ls_name);
1334  cm_yield(0);
1335  }
1336 
1337  if (info->ls340_settings.intern.scw_in_use) { // slowcontrol watchdog shall be used
1338  // register with the slowcontrol watchdog -------------------------------------
1339  // find scw record in DD
1340  db_find_key(hDB, hKey, "DD/SCW", &hkeydd);
1341  // get record
1342  size = sizeof(info->scw);
1343  db_get_record(hDB, hkeydd, &info->scw, &size, 0);
1344  // fill watchdog structure
1345  info->scw.pid = ss_getpid();
1346  info->scw.last_updated = ss_time();
1347  strncpy(info->scw.name, info->cryo_name, sizeof(info->scw.name));
1348  // write info back into ODB
1349  db_set_record(hDB, hkeydd, &info->scw, sizeof(info->scw), 0);
1350 
1351  // register with slowcontrol watchdog
1352  status = lem_scw_init(&info->scw);
1353  if (status != LEM_SCW_SUCCESS) {
1354  cm_msg(MINFO, "ls340_in_init", "Couldn't register with lem watchdog");
1355  cm_yield(0);
1356  }
1357  }
1358 
1359  return FE_SUCCESS;
1360 }
1361 
1362 /*----------------------------------------------------------------------------*/
1373 INT ls340_out_init(HNDLE hKey, void **pinfo, INT channels, INT (*bd)(INT cmd, ...))
1374 {
1375  info->num_channels_out = channels;
1376  *pinfo = info;
1377 
1378  return FE_SUCCESS;
1379 }
1380 
1381 /*----------------------------------------------------------------------------*/
1389 {
1390  // call EXIT function of bus driver, usually closes device
1391  info->bd(CMD_EXIT, info->bd_info);
1392 
1393  if (info->ls340_settings.intern.scw_in_use && !info->startup_error) { // slowcontrol watchdog in use
1394  // deregister from the slowcontrol watchdog
1395  lem_scw_exit(&info->scw);
1396  }
1397 
1398  free(info);
1399 
1400  return FE_SUCCESS;
1401 }
1402 
1403 /*----------------------------------------------------------------------------*/
1412 INT ls340_set(LS340_INFO *info, INT channel, float value)
1413 {
1414  char str[128], qry[128], rcv[128];
1415  INT status, i;
1416 
1417  // at startup, PID and Range set will NOT be executed! This is important if CMODE == 2, i.e. ZONE
1418  // This also means for CMODE != 2, PID and Range needs to be set once explicitly! Since the ususal
1419  // operation is CMODE == 2, this is not too bad
1420  if (info->set_startup_counter < info->num_channels_out) {
1421  info->set_startup_counter++;
1422  switch (channel) {
1423  case 2: // P
1424  case 3: // I
1425  case 4: // D
1426  case 5: // Range
1427  return FE_SUCCESS;
1428  break;
1429  default:
1430  break;
1431  }
1432  }
1433 
1434  // get out if not remote or startup error
1435  if (info->ls340_settings.intern.remote == 0 || info->startup_error == 1) {
1436  ss_sleep(10);
1437  return FE_SUCCESS;
1438  }
1439 
1440  if (!info->bd_connected) {
1441  ss_sleep(10);
1442  if (info->first_bd_error) {
1443  info->first_bd_error = 0;
1444  cm_msg(MINFO, "LS340_set",
1445  "LS340_set: %s: set values not possible at the moment, since the bus driver is not available!",
1446  info->ls340_odb_names.ls_name);
1447  }
1448  return FE_SUCCESS;
1449  }
1450 
1451  // check if someone wants to switch to remote
1452  if (channel == 0) {
1453  if (value == 0) { // switch to local message
1454  cm_msg(MINFO, "LS340_set", "LS340_set: %s: switch to local", info->ls340_odb_names.ls_name);
1455  } else { // switch to remote
1456  if (info->ls340_settings.intern.remote == 0) { // check if not already on remote
1457  ls340_force_update(info);
1458  cm_msg(MINFO, "LS340_set", "LS340_set: %s: switch to remote", info->ls340_odb_names.ls_name);
1459  }
1460  }
1461  info->ls340_settings.intern.remote = value;
1462  return FE_SUCCESS;
1463  }
1464 
1465  switch (channel) { // relies on the order of the DD/ODB Names/Names Out!!!
1466  case 1: // setpoint, loop1
1467  if ( value > info->ls340_settings.loop1.setpoint_limit ) {
1468  value = info->ls340_settings.loop1.setpoint_limit;
1469  cm_msg(MERROR, "LS340_set", "LS340: %s: Max. allowed setpoint is set to %f",
1471  }
1472  sprintf(str, "SETP 1, %.3f\r\n", value); // setpoint loop1
1473  info->setpoint = value; // store in info
1474  sprintf(qry, "SETP? 1\r\n");
1475  break;
1476  case 2: // gain P, loop1
1477  if ( value > 1000.f || value < 0.f)
1478  value = 0.f;
1479  sprintf(str, "PID 1, %d\r\n", (int)value); // gain P, loop1
1480  sprintf(qry, "PID? 1\r\n");
1481  break;
1482  case 3: // reset I, loop1
1483  if ( value > 1000.f || value < 1.f)
1484  value = 0.f;
1485  sprintf(str, "PID 1, , %d\r\n", (int)value); // reset I, loop1
1486  sprintf(qry, "PID? 1\r\n");
1487  break;
1488  case 4:
1489  if ( value > 1000.f || value < 1.f)
1490  value = 0.f;
1491  sprintf(str, "PID 1, , , %d\r\n", (int)value); // rate D, loop1
1492  sprintf(qry, "PID? 1\r\n");
1493  break;
1494  case 5: // heater range
1495  if ( value > (float)info->ls340_settings.loop1.max_heater_range || value < 0.f ) {
1496  value = 0.f;
1497  cm_msg(MERROR, "LS340_set", "LS340_set: %s: The heater range must be in the integer range [0,%d]",
1499  }
1500  sprintf(str, "RANGE %d\r\n", (int)value); // heater range
1501  sprintf(qry, "RANGE?\r\n");
1502  info->heater_setting = value; // keep new heater setting
1503  break;
1504  case 6: // control mode loop1
1505  if ( value > 6.f || value < 1.f )
1506  value = 1.f; // i.e. manual
1507  sprintf(str, "CMODE 1, %d\r\n", (int)value); // control mode
1508  sprintf(qry, "CMODE? 1\r\n");
1509  break;
1510  case 7:
1511  if (value > 100.f) {
1512  value = 0.f;
1513  cm_msg(MERROR, "LS340_set",
1514  "LS340_set: %s: setpoint ramping only in the range [0.1, 100] (K/min) possible",
1515  info->ls340_odb_names.ls_name);
1516  }
1517  if (value <= 0.f)
1518  sprintf(str, "RAMP 1, 0, 0.1\r\n"); // no ramp
1519  else
1520  sprintf(str, "RAMP 1, 1, %0.1f\r\n", value); // ramp
1521  sprintf(qry, "RAMP? 1\r\n");
1522  break;
1523  default:
1524  return FE_SUCCESS;
1525  }
1526 
1527  //--- send command and query parameter to check ---
1528  status = i = 0;
1529  do {
1530  if (LS340_DEBUG)
1531  cm_msg(MINFO,"LS340_set", "LS340_set: %s: command = %s", info->ls340_odb_names.ls_name, str);
1532  BD_PUTS(str);
1533  status = ls340_send_rcv(info, qry, rcv, LS340_MAX_TRY_MANY);
1534  i++;
1535  if (!status)
1536  ss_sleep(LS340_WAIT);
1537  } while (!status && (i < LS340_MAX_TRY_MANY));
1538 
1539  if ( !status )
1540  cm_msg(MERROR,"LS340_set","LS340_set: %s: Failed to query %s", info->ls340_odb_names.ls_name, qry);
1541  else
1542  cm_msg(MINFO,"LS340_set", "LS340_set: %s: Result of query %s = %s", info->ls340_odb_names.ls_name, qry, rcv);
1543 
1544  return FE_SUCCESS;
1545 }
1546 
1547 /*----------------------------------------------------------------------------*/
1554 {
1555  char cmd[128], str[128], *s;
1556  INT status, value[4], i;
1557  float loop, zone_no, top_temp, pid_p, pid_i, pid_d, man_out;
1558  INT range;
1559 
1560  if (!info->bd_connected) // bus driver not connected at the moment
1561  return;
1562 
1563  // check heater state
1564  strcpy(cmd, "HTRST?\r\n");
1565  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1566  if (!status) {
1567  ls340_no_connection(info, 1);
1569  cm_msg(MINFO, "ls340_check_heater",
1570  "%s: ls340_check_heater: WARNING: couldn't check heater state",
1571  info->ls340_odb_names.ls_name);
1572  return;
1573  }
1574 
1575  sscanf(str, "%d", &value[0]);
1576 
1577  switch (value[0]) {
1578  case 1:
1579  cm_msg(MERROR, "ls340_check_heater", "%s: power supply over voltage",
1580  info->ls340_odb_names.ls_name);
1581  break;
1582  case 2:
1583  cm_msg(MERROR, "ls340_check_heater", "%s: power supply under voltage",
1584  info->ls340_odb_names.ls_name);
1585  break;
1586  case 3:
1587  cm_msg(MERROR, "ls340_check_heater", "%s: output DAC error",
1588  info->ls340_odb_names.ls_name);
1589  break;
1590  case 4:
1591  cm_msg(MERROR, "ls340_check_heater", "%s: current limit DAC error",
1592  info->ls340_odb_names.ls_name);
1593  break;
1594  case 5:
1595  cm_msg(MERROR, "ls340_check_heater", "%s: open heater load",
1596  info->ls340_odb_names.ls_name);
1597  break;
1598  case 6:
1599  cm_msg(MERROR, "ls340_check_heater", "%s: heater load less than 10 ohms",
1600  info->ls340_odb_names.ls_name);
1601  break;
1602  default:
1603  break;
1604  }
1605 
1606  // check control loop 1 parameters
1607  strcpy(cmd, "CSET? 1\r\n");
1608  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1609  if (!status) {
1611  cm_msg(MINFO, "ls340_check_heater",
1612  "%s: ls340_check_heater: WARNING: couldn't check control loop 1 parameters",
1613  info->ls340_odb_names.ls_name);
1614  return;
1615  }
1616  s = strstr(str, ","); // shift the pointer over the channel assignment
1617  if (s == NULL)
1618  return;
1619  sscanf(s, ",%d,%d,%d", &value[0], &value[1], &value[2]);
1620 
1621  if (value[1] == 0) { // heater output loop1 has been disabled
1622  cm_msg(MERROR, "ls340_check_heater",
1623  "%s: heater output disabled. Will try to switch it on again. NO guarantee that it will work. CHECK it!", info->ls340_odb_names.ls_name);
1624  // enable heater power
1625  strcpy(cmd, "CSET 1,,1,1\r\n");
1626  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1627  // set the heater power back to its previous value
1628  sprintf(cmd, "RANGE %d\r\n", info->heater_setting); // heater range
1629  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1630 
1631  // check if the heater range is still ok
1632  strcpy(cmd, "RANGE?\r\n");
1633  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1634  sscanf(str, "%d", &value[0]);
1635  // check if heater range changed. If so set it back
1636  if ((value[0] != info->heater_setting) && (info->heater_setting !=0)) {
1637  // set the heater power back to its previous value
1638  sprintf(cmd, "RANGE %d\r\n", info->heater_setting); // heater range
1639  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1641  cm_msg(MINFO, "ls340_check_heater",
1642  "%s, heater range readback is %d, should be %d, will set it to its demand value",
1643  info->ls340_odb_names.ls_name, value[0], info->heater_setting);
1644  }
1645  }
1646 
1647  // check if the heater range is still ok
1648  strcpy(cmd, "RANGE?\r\n");
1649  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1650  if (!status) {
1652  cm_msg(MINFO, "ls340_check_heater",
1653  "%s: ls340_check_heater: WARNING: couldn't check heater range",
1654  info->ls340_odb_names.ls_name);
1655  return;
1656  }
1657  sscanf(str, "%d", &value[0]);
1658 
1659  if (info->cmode != 2) { // no ZONE settings
1660  // check if heater range changed. If so set it back
1661  if ((value[0] != info->heater_setting) && (info->heater_setting !=0)) {
1662  // set the heater power back to its previous value
1663  sprintf(cmd, "RANGE %d\r\n", info->heater_setting); // heater range
1664  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1666  cm_msg(MINFO, "ls340_check_heater",
1667  "%s, heater range readback is %d, should be %d, will set it to its demand value",
1668  info->ls340_odb_names.ls_name, value[0], info->heater_setting);
1669  }
1670  } else { // ZONE settings
1671  // find the proper zone
1672  for (i=0; i<10; i++) {
1673  memset(str, 0, sizeof(str));
1674  memcpy(str, &info->ls340_settings.zone[i*NAME_LENGTH], NAME_LENGTH*sizeof(char));
1675  sscanf(str, "%f, %f, %f, %f, %f, %f, %f, %d",
1676  &loop, &zone_no, &top_temp, &pid_p, &pid_i, &pid_d, &man_out, &range);
1677  if (info->setpoint < top_temp)
1678  break;
1679  }
1680  // check if heater is ok
1681  if (value[0] != range) {
1682  // set the heater power back to its proper value
1683  sprintf(cmd, "RANGE %d\r\n", range); // heater range
1684  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1686  cm_msg(MINFO, "ls340_check_heater",
1687  "%s, heater range readback is %d, should be %d, will set it to its demand value",
1688  info->ls340_odb_names.ls_name, value[0], range);
1689  }
1690  }
1691 }
1692 
1693 /*----------------------------------------------------------------------------*/
1701 INT ls340_get(LS340_INFO *info, INT channel, float *pvalue)
1702 {
1703  char str[128], cmd[128], datetime[32];
1704  INT cmd_tag, sub_tag, status;
1705  int size, i, enabled;
1706  float pid_p, pid_i, pid_d, fvalue;
1707  DWORD nowtime, difftime;
1708 
1709 
1710  // check for startup_error
1711  if ( info->startup_error == 1 ) { // error during CMD_INIT, return -2
1712  *pvalue = (float) LS340_INIT_ERROR;
1713  ss_sleep(10); // to keep CPU load low when Run active
1714  return FE_SUCCESS;
1715  }
1716 
1717  // check if time limiter for reading is set
1718  if (info->ls340_settings.intern.read_timeout != 0) {
1719  nowtime = ss_millitime();
1720  if ( nowtime - info->read_timer[channel] > 1000 * info->ls340_settings.intern.read_timeout )
1721  info->read_timer[channel] = nowtime; // reset timer and go on
1722  else
1723  return FE_SUCCESS; // not yet time to read anything
1724  }
1725 
1726  // error handling routines
1727  nowtime = ss_time();
1728  difftime = nowtime - info->lasterrtime;
1729 
1730  if ( difftime > LS340_DELTA_TIME_ERROR ) {
1731  info->errorcount = 0;
1732  info->lasterrtime = nowtime;
1733  }
1734 
1736  *pvalue = (float) LS340_READ_ERROR;
1738  cm_msg(MERROR, "LS340_get", "too many reconnection failures, bailing out :-(");
1739  info->reconnection_failures++;
1740  }
1741  return FE_SUCCESS;
1742  }
1743 
1744  if (info->ls340_settings.intern.scw_in_use) { // slowcontrol watchdog in use
1745  // feed slowcontrol watchdog
1746  info->scw.last_updated = ss_time();
1747  lem_scw_update(&info->scw);
1748  }
1749 
1750  // check the heater state before proceeding
1751  ls340_check_heater(info);
1752 
1753  sub_tag = 0;
1754  cmd_tag = ls340_get_decode(info, channel, &sub_tag);
1755 
1756  switch(cmd_tag) {
1757  case 0: // read temperature
1758  //sprintf(cmd, "CRDG? %s\r\n", info->ls340_settings.sensor.channel[channel]); // Celsius
1759  sprintf(cmd, "KRDG? %s\r\n", info->ls340_settings.sensor.channel[channel]); // Kelvin
1760  break;
1761  case 1: // heater output
1762  strcpy(cmd, "HTR?\r\n");
1763  break;
1764  case 2: // set point read back from loop1
1765  strcpy(cmd, "SETP? 1\r\n");
1766  break;
1767  case 3: // PID read back from loop1
1768  strcpy(cmd, "PID? 1\r\n");
1769  break;
1770  case 4: // heater range read back
1771  strcpy(cmd, "RANGE?\r\n");
1772  break;
1773  case 5: // control mode read back from loop1
1774  strcpy(cmd, "CMODE? 1\r\n");
1775  break;
1776  case 6:
1777  strcpy(cmd, "RAMP? 1\r\n");
1778  break;
1779  default:
1780  *pvalue = (float) LS340_READ_ERROR;
1781  return FE_SUCCESS;
1782  }
1783 
1784  // if cmd_tag = 0, i.e. read temp, then look whether info->settings.sensor.channel[channel] == "AVA",
1785  // in that case return average value of sensor A
1786 
1787  if ((cmd_tag == 0) && strstr(info->ls340_settings.sensor.name[channel],"AVA")) {
1788  *pvalue = 0.0;
1789  for (i=0; i<LS340_MAX_AVG; i++)
1790  *pvalue += info->history[i];
1791  if (info->his_full)
1792  *pvalue /= LS340_MAX_AVG;
1793  else
1794  if (info->ihis != 0)
1795  *pvalue /= info->ihis;
1796  return FE_SUCCESS;
1797  }
1798 
1799  ss_sleep(100); // try to keep mscb happy
1800  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1801  if (status == LS340_SHUTDOWN) {
1802  return FE_SUCCESS;
1803  }
1804  if (status <= 0) { // error
1805  ls340_no_connection(info, 1);
1806  if (cmd_tag != 3) // not a PID value
1807  *pvalue = info->last_value[channel]; // return last valid value
1808  else // PID value
1809  *pvalue = (float) LS340_READ_ERROR;
1810 
1811  if (info->errorcount < LS340_MAX_ERROR) {
1813  cm_msg(MERROR, "LS340_get", "LS340: %s: LakeShore340 does not respond.",
1814  info->ls340_odb_names.ls_name);
1815  info->errorcount++;
1816  }
1817 
1818  info->readback_failure++;
1819 
1821  info->readback_failure = 0;
1822  // try to disconnect and reconnect the bus driver
1823  if ((ss_time()-info->last_reconnect > info->ls340_settings.intern.reconnect_timeout) && info->bd_connected) { // disconnect bus driver
1824  status = info->bd(CMD_EXIT, info->bd_info);
1826  cm_msg(MINFO, "LS340_get", "LS340: %s: try to disconnect and reconnect the bus driver (status = %d)",
1827  info->ls340_odb_names.ls_name, status);
1828  info->last_reconnect = ss_time();
1829  info->bd_connected = 0;
1830  if (info->ls340_settings.intern.ets_in_use)
1832  }
1833  }
1834 
1835  // try to reconnect after a timeout
1836  if ((ss_time()-info->last_reconnect > info->ls340_settings.intern.reconnect_timeout) && !info->bd_connected) {
1837  status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
1838  if (status != FE_SUCCESS) {
1840  cm_msg(MINFO, "LS340_get", "LS340: %s: reconnection attempted failed (status = %d)",
1841  info->ls340_odb_names.ls_name, status);
1842  info->reconnection_failures++;
1843  info->last_reconnect = ss_time(); // in order not to block anything
1844  return FE_ERR_HW;
1845  } else {
1846  info->bd_connected = 1; // bus driver is connected again
1847  info->errorcount = 0; // reinitialize error counter
1848  info->reconnection_failures = 0; // reset counter
1849  info->last_reconnect = ss_time();
1850  info->first_bd_error = 1;
1852  cm_msg(MINFO, "LS340_get", "LS340: %s: successfully reconnected", info->ls340_odb_names.ls_name);
1853  }
1854  }
1855  return FE_SUCCESS;
1856  }
1857 
1858  ls340_no_connection(info, 0);
1859 
1860  if (cmd_tag == 3) { // filter PID's
1861  sscanf(str, "%f,%f,%f", &pid_p, &pid_i, &pid_d);
1862  switch (sub_tag) {
1863  case 0:
1864  if (strlen(str)==20)
1865  *pvalue = pid_p;
1866  else // something fishy
1867  *pvalue = (float) LS340_READ_ERROR;
1868  break;
1869  case 1:
1870  if (strlen(str)==20)
1871  *pvalue = pid_i;
1872  else // something fishy
1873  *pvalue = (float) LS340_READ_ERROR;
1874  break;
1875  case 2:
1876  if (strlen(str)==20)
1877  *pvalue = pid_d;
1878  else // something fishy
1879  *pvalue = (float) LS340_READ_ERROR;
1880  break;
1881  default:
1882  *pvalue = (float) LS340_READ_ERROR;
1883  break;
1884  }
1885  } else if (cmd_tag == 6) { // ramp
1886  sscanf(str, "%d, %f", &enabled, &fvalue);
1887  if (!enabled) // ramp not enabled
1888  fvalue = 0.f;
1889  *pvalue = fvalue;
1890  info->last_value[channel] = fvalue;
1891  } else if (cmd_tag == 4) { // heater setting
1892  sscanf(str, "%f", pvalue);
1893  if (*pvalue != 0.0) {
1894  info->heater_setting = *pvalue;
1895  }
1896  info->last_value[channel] = *pvalue; // keep last valid value
1897  info->readback_failure = 0;
1898  } else { // all the others
1899  if (channel < info->ls340_settings.intern.no_of_sensors) { // temp reading
1900  if (!(strlen(str)==13) || !(str[0]='+')) { // something fishy
1901  *pvalue = info->last_value[channel];
1902  info->readback_err++;
1903  if (info->readback_err == 10)
1904  cm_msg(MINFO, "LS340_get", "LS340_get: WARNING: Too many temp. readback errors! Please check %s",
1905  info->ls340_odb_names.ls_name);
1906  return FE_SUCCESS;
1907  } else {
1908  info->readback_err = 0;
1909  }
1910  // update history if cmd_tag = 0 and channel = 0
1911  if ((cmd_tag == 0) && strstr(info->ls340_settings.sensor.channel[channel],"A")) {
1912  info->history[info->ihis] = *pvalue;
1913  info->ihis++;
1914  if ( info->ihis == LS340_MAX_AVG ) {
1915  info->ihis = 0;
1916  info->his_full = TRUE;
1917  }
1918  }
1919  }
1920  sscanf(str, "%f", pvalue);
1921  info->last_value[channel] = *pvalue; // keep last valid value
1922  info->readback_failure = 0;
1923 
1924  if (cmd_tag == 2) // setpoint
1925  info->setpoint = *pvalue;
1926  if (cmd_tag == 5) // cmode
1927  info->cmode = *pvalue;
1928  }
1929 
1930  // for diagnostic and calibration purposes
1931  if (channel == 0) {
1932  // read date and time
1933  strcpy(cmd, "DATETIME?\r\n");
1934  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1935  if (status == LS340_SHUTDOWN) {
1936  return FE_SUCCESS;
1937  }
1938  if (status > 0) {
1939  strncpy(datetime, str, 32);
1940  size = strlen(datetime);
1941  if (strstr(datetime, "\r\n"))
1942  datetime[size-2]=0;
1943  db_set_data(info->hDB, info->hkey_datetime, datetime, sizeof(datetime), 1, TID_STRING);
1944  }
1945 
1946  // read raw input values if enabled
1947  if (info->ls340_settings.intern.read_raw_data) {
1948  for (i=0; i<LS340_MAX_SENSORS; i++) {
1949  sprintf(cmd, "SRDG? %s\r\n", info->ls340_settings.sensor.channel[i]);
1950  status = ls340_send_rcv(info, cmd, str, LS340_MAX_TRY_LESS);
1951  if (status == LS340_SHUTDOWN) {
1952  return FE_SUCCESS;
1953  }
1954  if (status > 0) {
1955  sscanf(str, "%f", &fvalue);
1956  size = sizeof(fvalue);
1957  db_set_data(info->hDB, info->hkey_raw_value[i], &fvalue, size, 1, TID_FLOAT);
1958  }
1959  }
1960  }
1961  }
1962 
1963  return FE_SUCCESS;
1964 }
1965 
1966 /*----------------------------------------------------------------------------*/
1975 INT ls340_in_get_label(LS340_INFO *info, INT channel, char *name)
1976 {
1977 
1978  if (channel < info->ls340_settings.intern.no_of_sensors) { // sensor names
1979  strcpy(name, info->ls340_settings.sensor.name[channel]);
1980  } else { // loops related stuff
1981  strcpy(name, info->ls340_odb_names.names_in[channel-info->ls340_settings.intern.no_of_sensors]);
1982  }
1983  return FE_SUCCESS;
1984 }
1985 
1986 /*----------------------------------------------------------------------------*/
1995 INT ls340_out_get_label(LS340_INFO *info, INT channel, char *name)
1996 {
1997  strcpy(name, info->ls340_odb_names.names_out[channel]);
1998  return FE_SUCCESS;
1999 }
2000 
2001 /*---- device driver entry point -----------------------------------*/
2002 INT ls340_in(INT cmd, ...)
2003 {
2004 va_list argptr;
2005 HNDLE hKey;
2006 INT channel, status;
2007 float *pvalue;
2008 void *info, *bd;
2009 char *name;
2010 DWORD flags;
2011 
2012  va_start(argptr, cmd);
2013  status = FE_SUCCESS;
2014 
2015  switch (cmd)
2016  {
2017  case CMD_INIT:
2018  hKey = va_arg(argptr, HNDLE);
2019  info = va_arg(argptr, void *);
2020  channel = va_arg(argptr, INT);
2021  flags = va_arg(argptr, DWORD);
2022  bd = va_arg(argptr, void *);
2023  status = ls340_in_init(hKey, info, channel, bd);
2024  break;
2025 
2026  case CMD_EXIT:
2027  info = va_arg(argptr, void *);
2028  status = ls340_exit(info);
2029  break;
2030 
2031  case CMD_GET:
2032  info = va_arg(argptr, void *);
2033  channel = va_arg(argptr, INT);
2034  pvalue = va_arg(argptr, float*);
2035  status = ls340_get(info, channel, pvalue);
2036  break;
2037 
2038  case CMD_GET_LABEL:
2039  info = va_arg(argptr, void *);
2040  channel = va_arg(argptr, INT);
2041  name = va_arg(argptr, char *);
2042  status = ls340_in_get_label(info, channel, name);
2043  break;
2044 
2045  default:
2046  break;
2047  }
2048 
2049  va_end(argptr);
2050  return status;
2051 }
2052 
2053 INT ls340_out(INT cmd, ...)
2054 {
2055 va_list argptr;
2056 HNDLE hKey;
2057 INT channel, status;
2058 float value;
2059 void *info, *bd;
2060 char *name;
2061 DWORD flags;
2062 
2063  va_start(argptr, cmd);
2064  status = FE_SUCCESS;
2065 
2066  switch (cmd)
2067  {
2068  case CMD_INIT:
2069  hKey = va_arg(argptr, HNDLE);
2070  info = va_arg(argptr, void *);
2071  channel = va_arg(argptr, INT);
2072  flags = va_arg(argptr, DWORD);
2073  bd = va_arg(argptr, void *);
2074  status = ls340_out_init(hKey, info, channel, bd);
2075  break;
2076 
2077  case CMD_SET:
2078  info = va_arg(argptr, void *);
2079  channel = va_arg(argptr, INT);
2080  value = (float) va_arg(argptr, double);
2081  status = ls340_set(info, channel, value);
2082  break;
2083 
2084  case CMD_GET_LABEL:
2085  info = va_arg(argptr, void *);
2086  channel = va_arg(argptr, INT);
2087  name = va_arg(argptr, char *);
2088  status = ls340_out_get_label(info, channel, name);
2089  break;
2090 
2091  default:
2092  break;
2093  }
2094 
2095  va_end(argptr);
2096 
2097  return status;
2098 }
2099 
2100 /*------------------------------------------------------------------*/
#define LS340_MAX_RECONNECTION_FAILURE
Definition: LakeShore340.c:56
INT read_timeout
get data every read_timeout (sec), if zero midas has the timing control
Definition: LakeShore340.c:168
INT detailed_msg
flag indicating if detailed status/error messages are wanted
Definition: LakeShore340.c:163
float max_user_current
max. current (in A) for user current tag 5
Definition: LakeShore340.c:145
BOOL read_raw_data
flag indicating if raw data shall be read
Definition: LakeShore340.c:169
char names_out[8][NAME_LENGTH]
names of the out-channels
Definition: LakeShore340.c:228
INFO info
Definition: vme_fe.c:206
INT ls340_force_update(LS340_INFO *info)
Definition: LakeShore340.c:424
DWORD lasterrtime
timer for error handling
Definition: LakeShore340.c:285
float raw_value_7
raw sensor reading channel 7
Definition: LakeShore340.c:74
char names_in[8][NAME_LENGTH]
names of the in-channels
Definition: LakeShore340.c:227
#define LS340_ODB_NAMES_STR
initializing string for LS340_ODB_NAMES
Definition: LakeShore340.c:232
stores internal informations within the DD.
Definition: LakeShore340.c:225
LS340_INTERNAL intern
Definition: LakeShore340.c:216
#define LS340_INIT_ERROR
initialize error tag
Definition: LakeShore340.c:45
#define LS340_SENSORS_STR
initializing string for LS340_SENSORS
Definition: LakeShore340.c:81
INT ls340_out_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
INT ls340_get_decode(LS340_INFO *info, INT ch, int *sub_tag)
Definition: LakeShore340.c:360
INT ls340_in(INT cmd,...)
float raw_value_2
raw sensor reading channel 2
Definition: LakeShore340.c:69
void ls340_check_heater(LS340_INFO *info)
int ihis
index in history
Definition: LakeShore340.c:297
char name[LS340_MAX_SENSORS][NAME_LENGTH]
name for each channel
Definition: LakeShore340.c:67
void * bd_info
private info of bus driver
Definition: LakeShore340.c:281
LS340_LOOP1 loop1
Definition: LakeShore340.c:218
INT ls340_out_get_label(LS340_INFO *info, INT channel, char *name)
#define LS340_SHUTDOWN
Definition: LakeShore340.c:31
HNDLE hkey_raw_value[10]
handle to the raw value input DD entry
Definition: LakeShore340.c:277
INT errorcount
error counter
Definition: LakeShore340.c:283
HNDLE hDB
main handle to the ODB
Definition: LakeShore340.c:273
#define LS340_MAX_TRY_MANY
maximum number of communication attempts for important reads
Definition: LakeShore340.c:40
float history[LS340_MAX_AVG]
stores last temperatures of sensor 1
Definition: LakeShore340.c:296
INT ls340_send_rcv(LS340_INFO *info, char *cmd, char *str, int max_try)
Definition: LakeShore340.c:314
INT num_channels_in
number of in-channels
Definition: LakeShore340.c:278
int ets_logout(void *info, int wait, int detailed_msg)
Definition: ets_logout.c:113
float raw_value_8
raw sensor reading channel 8
Definition: LakeShore340.c:75
HNDLE hKey
Definition: write_summary.c:97
#define LS340_MAX_READBACK_FAILURE
maximum number of readback failures before a reconnect will take place
Definition: LakeShore340.c:55
HNDLE hkey_datetime
handle to the date and time DD entry
Definition: LakeShore340.c:276
#define LS340_TIME_OUT
time out in msecs for read (rs232)
Definition: LakeShore340.c:35
INT ls340_in_get_label(LS340_INFO *info, INT channel, char *name)
DWORD read_timer[20]
timer telling the system when to read data (via LS340_get, in (ms))
Definition: LakeShore340.c:282
DWORD last_value[15]
stores the last valid value
Definition: LakeShore340.c:286
INT curve[LS340_MAX_SENSORS]
sensor calibration curve: see LakeShore340 manual, p.9-33
Definition: LakeShore340.c:65
BOOL his_full
flag used to indicate that the history buffer is full
Definition: LakeShore340.c:298
LEM_SC_WATCHDOG scw
slowcontrol watchdog info structure
Definition: LakeShore340.c:271
INT no_of_sensors
number of sensors used
Definition: LakeShore340.c:173
int max_current_tag
1-&gt;0.25A, 2-&gt;0.5A, 3-&gt;1.0A, 4-&gt;2.0A, 5-&gt;User
Definition: LakeShore340.c:144
INT(* bd)(INT cmd,...)
bus driver entry function
Definition: LakeShore340.c:280
HNDLE hDB
Definition: write_summary.c:97
float raw_value_10
raw sensor reading channel 10
Definition: LakeShore340.c:77
INT heater_setting
current output heater setting
Definition: LakeShore340.c:293
#define LS340_INTERNAL_STR
initializing string for LS340_INTERNAL
Definition: LakeShore340.c:177
#define LS340_MAX_TRY_LESS
maximum number of communication attempts for less important reads
Definition: LakeShore340.c:41
INT scw_in_use
flag indicating if the slowcontrol watchdog shall be used
Definition: LakeShore340.c:165
char odb_output[2 *NAME_LENGTH]
odb output variable path. Needed by the forced update routine
Definition: LakeShore340.c:171
INT readback_failure
counts the number of readback failures
Definition: LakeShore340.c:290
int max_heater_range
upper limit for the heater range (see LakeShore340 manual, 6-9, 9-27)
Definition: LakeShore340.c:146
char zone[10 *NAME_LENGTH]
Definition: LakeShore340.c:219
char cryo_name[NAME_LENGTH]
name of the LS340
Definition: LakeShore340.c:272
#define LS340_MAX_AVG
max. length of the average array
Definition: LakeShore340.c:49
float raw_value_4
raw sensor reading channel 4
Definition: LakeShore340.c:71
INT readback_err
number of readback errors for the temperature reading
Definition: LakeShore340.c:292
stores internal informations within the DD.
Definition: LakeShore340.c:215
INT odb_offset
odb offset for the output variables. Needed by the forced update routine
Definition: LakeShore340.c:170
float raw_value_9
raw sensor reading channel 9
Definition: LakeShore340.c:76
#define LS340_WAIT
time (ms) to wait between commands
Definition: LakeShore340.c:43
INT ls340_exit(LS340_INFO *info)
#define LS340_MAX_ERROR
maximum number of error messages
Definition: LakeShore340.c:38
float heater_resistance
heater resistance in OhmLakeShore340.sav
Definition: LakeShore340.c:147
char ls_name[NAME_LENGTH]
name of the LS340
Definition: LakeShore340.c:226
float setpoint_limit
in Kelvin
Definition: LakeShore340.c:143
INT num_channels_out
number of out-channels
Definition: LakeShore340.c:279
INT ls340_set(LS340_INFO *info, INT channel, float value)
#define LS340_DELTA_R
max. allowed deviation between ODB heater resistance and LS340 readback
Definition: LakeShore340.c:34
#define LS340_DELTA_TIME_ERROR
reset error counter after LS340_DELTA_TIME_ERROR seconds
Definition: LakeShore340.c:39
#define LS340_SCW_STR
defines the slowcontrol default watchdog info structure
Definition: LakeShore340.c:255
float cmode
prevailing control mode
Definition: LakeShore340.c:295
INT ets_in_use
flag indicating if the rs232 terminal server is in use
Definition: LakeShore340.c:164
INT ls340_get(LS340_INFO *info, INT channel, float *pvalue)
stores internal informations within the DD.
Definition: LakeShore340.c:162
INT reconnect_timeout
reconnection timeout in (sec)
Definition: LakeShore340.c:167
void ls340_no_connection(LS340_INFO *info, INT value)
Definition: LakeShore340.c:529
int set_startup_counter
counter to supress setting of PID and Range at startup
Definition: LakeShore340.c:299
LS340_SENSORS sensor
Definition: LakeShore340.c:217
char ctrl_ch[4]
which channel is used for control loop (A/B/C1-C4/D1-D4 possible)
Definition: LakeShore340.c:142
float raw_value_1
raw sensor reading channel 1
Definition: LakeShore340.c:68
#define LS340_DEBUG
debug tag, if set to TRUE, additional messages will be displayed at execution time ...
Definition: LakeShore340.c:52
LS340_SETTINGS ls340_settings
ODB data for the DD.
Definition: LakeShore340.c:269
INT startup_error
startup error tag
Definition: LakeShore340.c:284
char channel[LS340_MAX_SENSORS][4]
which channel: A, B, C1-C4, D1-D4
Definition: LakeShore340.c:66
INT no_connection
flag showing that there is no connection at the moment
Definition: LakeShore340.c:166
INT type[LS340_MAX_SENSORS]
sensor type: 1-12, see LakeShore340 manual, p.9-33
Definition: LakeShore340.c:64
LS340_ODB_NAMES ls340_odb_names
ODB data for the DD.
Definition: LakeShore340.c:270
HNDLE hkey
handle to the BD key
Definition: LakeShore340.c:274
HNDLE hkey_no_connection
handle to the no connection flag
Definition: LakeShore340.c:275
void ls340_cryo_name_changed(HNDLE hDB, HNDLE dummy, void *pinfo)
Definition: LakeShore340.c:575
int bd_connected
flag showing if bus driver is connected
Definition: LakeShore340.c:287
#define LS340_MAX_SENSORS
max. number of possible input sensors
Definition: LakeShore340.c:33
float raw_value_6
raw sensor reading channel 6
Definition: LakeShore340.c:73
float raw_value_5
raw sensor reading channel 5
Definition: LakeShore340.c:72
#define LS340_ZONE_STR
Definition: LakeShore340.c:198
float raw_value_3
raw sensor reading channel 3
Definition: LakeShore340.c:70
stores internal informations within the DD.
Definition: LakeShore340.c:141
stores internal informations within the DD.
Definition: LakeShore340.c:62
INT remote
stores if the LS340 is computer controlled of not
Definition: LakeShore340.c:172
INT reconnection_failures
how many reconnection failures took place
Definition: LakeShore340.c:291
float setpoint
prevailing setpoint
Definition: LakeShore340.c:294
INT ls340_in_init(HNDLE hKey, void **pinfo, INT channels, INT(*bd)(INT cmd,...))
#define LS340_READ_ERROR
read error tag
Definition: LakeShore340.c:46
INT ls340_out(INT cmd,...)
int first_bd_error
flag showing if the bus driver error message is already given
Definition: LakeShore340.c:288
#define LS340_ETS_LOGOUT_SLEEP
sleep time (us) between the telnet commands of the ets_logout
Definition: LakeShore340.c:59
DWORD last_reconnect
timer for bus driver reconnect error handlingLakeShore340.sav
Definition: LakeShore340.c:289
#define LS340_LOOP1_STR
initializing string for LS340_LOOP1
Definition: LakeShore340.c:151