tempcontrol.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13  ***************************************************************************/
14 #include "tempcontrol.h"
15 #include "ui_tempcontrolform.h"
16 #include "interface.h"
17 #include "analyzer.h"
18 #include "xnodeconnector.h"
19 #include <QStatusBar>
20 #include <QToolBox>
21 
22 XTempControl::XChannel::XChannel(const char *name, bool runtime,
23  Transaction &tr_list, const shared_ptr<XThermometerList> &list) :
24  XNode(name, runtime),
25  m_thermometer(create<XItemNode<XThermometerList,
26  XThermometer> > ("Thermometer", false, ref(tr_list), list)),
27  m_excitation(create<XComboNode> ("Excitation", false)),
28  m_thermometers(list) {}
29 
30 XTempControl::Loop::Loop(const char *name, bool runtime, shared_ptr<XTempControl> tempctrl, Transaction &tr,
31  unsigned int idx, Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
32  XNode(name, runtime),
33  m_tempctrl(tempctrl),
34  m_idx(idx),
35  m_targetTemp(create<XDoubleNode> ("TargetTemp" , true, "%.5g")),
36  m_manualPower(create<XDoubleNode> ("ManualPower", true, "%.4g")),
37  m_prop(create<XDoubleNode> ("P", false, "%.4g")),
38  m_int(create<XDoubleNode> ("I", false, "%.4g")),
39  m_deriv(create<XDoubleNode> ("D", false, "%.4g")),
40  m_heaterMode(create<XComboNode> ("HeaterMode", false, true)),
41  m_powerRange(create<XComboNode> ("PowerRange", false, true)),
42  m_powerMax(create<XDoubleNode> ("PowerMax", false, "%.4g")),
43  m_powerMin(create<XDoubleNode> ("PowerMin", false, "%.4g")),
44  m_heaterPower(create<XDoubleNode> ("HeaterPower", false, "%.4g")),
45  m_sourceTemp(create<XDoubleNode> ("SourceTemp", false, "%.5g")),
46  m_stabilized(create<XDoubleNode> ("Stabilized", true, "%g")),
47  m_extDevice(create<XItemNode<XDriverList, XDCSource, XFlowControllerDriver> > ("ExtDevice", false, ref(tr_meas), meas->drivers())),
48  m_extDCSourceChannel(create<XComboNode> ("ExtDCSourceChannel", false, true)),
49  m_extIsPositive(create<XBoolNode> ("ExtIsPositive", false)) {
50  m_currentChannel =
51  create<XItemNode<XChannelList, XChannel> >("CurrentChannel", true, ref(tr),
52  tempctrl->m_channels);
53 
54  iterate_commit([=](Transaction &tr){
55  m_lsnOnExtDeviceChanged = tr[ *m_extDevice].onValueChanged().connectWeakly(
56  shared_from_this(), &XTempControl::Loop::onExtDeviceChanged);
57  });
58 
59  m_currentChannel->setUIEnabled(false);
60  m_powerRange->setUIEnabled(false);
61  m_heaterMode->setUIEnabled(false);
62  m_prop->setUIEnabled(false);
63  m_int->setUIEnabled(false);
64  m_deriv->setUIEnabled(false);
65  m_manualPower->setUIEnabled(false);
66  m_powerMax->setUIEnabled(true);
67  m_powerMin->setUIEnabled(true);
68  m_targetTemp->setUIEnabled(false);
69 
70  m_extDevice->setUIEnabled(true);
71  m_extDCSourceChannel->setUIEnabled(true);
72  m_extIsPositive->setUIEnabled(true);
73 
74  tempctrl->m_form->m_toolBox->setItemText(m_idx, getLabel());
75 }
76 void
77 XTempControl::Loop::start() {
78  auto tempctrl = m_tempctrl.lock();
79  if( !tempctrl) return;
80  iterate_commit([=](Transaction &tr){
81  const Snapshot &shot(tr);
82  if(hasExtDevice(shot)) {
83  tr[ m_heaterMode].clear();
84  tr[ m_heaterMode].add("Off");
85  tr[ m_heaterMode].add("PID");
86  tr[ m_heaterMode].add("Man");
87  }
88  else
89  tr[ *m_powerRange].setUIEnabled(true);
90  });
91 
92  m_currentChannel->setUIEnabled(true);
93  m_heaterMode->setUIEnabled(true);
94  m_prop->setUIEnabled(true);
95  m_int->setUIEnabled(true);
96  m_deriv->setUIEnabled(true);
97  m_manualPower->setUIEnabled(true);
98  m_targetTemp->setUIEnabled(true);
99 
100  m_extDevice->setUIEnabled(false);
101  m_extDCSourceChannel->setUIEnabled(false);
102  m_extIsPositive->setUIEnabled(false);
103 
104  m_tempAvg = 0.0;
105  m_tempErrAvg = 0.0;
106  m_lasttime = XTime::now();
107 
108  iterate_commit([=](Transaction &tr){
109  m_lsnOnPChanged = tr[ *m_prop].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onPChanged);
110  m_lsnOnIChanged = tr[ *m_int].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onIChanged);
111  m_lsnOnDChanged = tr[ *m_deriv].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onDChanged);
112  m_lsnOnTargetTempChanged = tr[ *m_targetTemp].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onTargetTempChanged);
113  m_lsnOnManualPowerChanged = tr[ *m_manualPower].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onManualPowerChanged);
114  m_lsnOnHeaterModeChanged = tr[ *m_heaterMode].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onHeaterModeChanged);
115  m_lsnOnPowerRangeChanged = tr[ *m_powerRange].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onPowerRangeChanged);
116  m_lsnOnCurrentChannelChanged
117  = tr[ *m_currentChannel].onValueChanged().connectWeakly(shared_from_this(), &XTempControl::Loop::onCurrentChannelChanged);
118  });
119 }
120 void
121 XTempControl::Loop::stop() {
122  m_currentChannel->setUIEnabled(false);
123  m_powerRange->setUIEnabled(false);
124  m_heaterMode->setUIEnabled(false);
125  m_prop->setUIEnabled(false);
126  m_int->setUIEnabled(false);
127  m_deriv->setUIEnabled(false);
128  m_manualPower->setUIEnabled(false);
129  m_targetTemp->setUIEnabled(false);
130 
131  m_extDevice->setUIEnabled(true);
132  m_extDCSourceChannel->setUIEnabled(true);
133  m_extIsPositive->setUIEnabled(true);
134 
135  m_lsnOnPChanged.reset();
136  m_lsnOnIChanged.reset();
137  m_lsnOnDChanged.reset();
138  m_lsnOnTargetTempChanged.reset();
139  m_lsnOnManualPowerChanged.reset();
140  m_lsnOnPowerMaxChanged.reset();
141  m_lsnOnPowerMinChanged.reset();
142  m_lsnOnHeaterModeChanged.reset();
143  m_lsnOnPowerRangeChanged.reset();
144  m_lsnOnCurrentChannelChanged.reset();
145 }
146 void
147 XTempControl::Loop::update(double temp) {
148  auto tempctrl = m_tempctrl.lock();
149  if( !tempctrl) return;
150  Snapshot shot( *tempctrl);
151 
152  //calculates std. deviations in some periods
153  double tau = shot[ *m_int] * 4.0;
154  if(tau <= 1)
155  tau = 4.0;
156  XTime newtime = XTime::now();
157  double dt = newtime - m_lasttime;
158  m_lasttime = newtime;
159  double terr = temp - shot[ *m_targetTemp];
160  m_tempAvg = (m_tempAvg - temp) * exp( -dt / tau) + temp;
161  m_tempErrAvg = (m_tempErrAvg - terr * terr) * exp( -dt / tau) + terr * terr;
162  m_tempErrAvg = std::min(m_tempErrAvg, temp * temp * 0.04);
163 
164  double power = 0.0;
165  shared_ptr<XDCSource> dcsrc = shot[ *m_extDevice];
166  shared_ptr<XFlowControllerDriver> flowctrl = shot[ *m_extDevice];
167  if(dcsrc || flowctrl) {
168  double limit_min = shot[ *m_powerMin];
169  double limit_max = shot[ *m_powerMax];
170  if(shot[ *m_heaterMode].to_str() == "PID") {
171  power = pid(shot, newtime, temp);
172  }
173  if(shot[ *m_heaterMode].to_str() == "Man") {
174  power = shot[ *m_manualPower];
175  }
176  if(dcsrc) {
177  int ch = shot[ *m_extDCSourceChannel];
178  if(ch >= 0) {
179  limit_max = std::min(limit_max, dcsrc->max(ch, false));
180  power = (limit_max - limit_min) * sqrt(power) / 10.0 + limit_min;
181  dcsrc->changeValue(ch, power, false);
182  }
183  }
184  if(flowctrl) {
185  limit_max = std::min(limit_max, Snapshot( *flowctrl)[ *flowctrl].fullScale());
186  power = (limit_max - limit_min) * power / 100.0 + limit_min;
187  trans( *flowctrl->target()) = power;
188  }
189  }
190  else
191  power = tempctrl->getHeater(m_idx);
192 
193  iterate_commit([=](Transaction &tr){
194  tr[ *m_sourceTemp] = temp;
195  tr[ *m_stabilized] = sqrt(m_tempErrAvg); //stderr
196  tr[ *m_heaterPower] = power;
197  });
198  tempctrl->m_form->m_toolBox->setItemText(m_idx, XString(getLabel() + formatString(": %.5g K, %.3g%s", temp, power,
199  tempctrl->m_heaterPowerUnit(m_idx))));
200 }
201 
202 double XTempControl::Loop::pid(const Snapshot &shot, XTime time, double temp) {
203  double p = shot[ *m_prop];
204  double i = shot[ *m_int];
205  double d = shot[ *m_deriv];
206 
207  double dt = temp - shot[ *m_targetTemp];
208  if(shot[ *m_extIsPositive])
209  dt *= -1.0;
210  double dxdt = 0.0;
211  double acc = 0.0;
212  if((i > 0) && (time - m_pidLastTime < i)) {
213  m_pidAccum += (time - m_pidLastTime) * dt;
214  dxdt = (temp - m_pidLastTemp) / (time - m_pidLastTime);
215  acc = m_pidAccum / i;
216  acc = -std::min(std::max( -acc * p, -2.0), 100.0) / p;
217  m_pidAccum = acc * i;
218  }
219  else
220  m_pidAccum = 0;
221 
222  m_pidLastTime = time;
223  m_pidLastTemp = temp;
224 
225  return -(dt + acc + dxdt * d) * p;
226 }
227 void XTempControl::Loop::onExtDeviceChanged(const Snapshot &shot, XValueNodeBase *) {
228  iterate_commit([=](Transaction &tr){
229  const Snapshot &shot(tr);
230  tr[ *m_extDCSourceChannel].clear();
231  shared_ptr<XDCSource> dcsrc = shot[ *m_extDevice];
232  if(dcsrc) {
233  //registers channel names.
234  auto strings(dcsrc->channel()->itemStrings(Snapshot( *dcsrc)));
235  for(auto it = strings.begin(); it != strings.end(); it++) {
236  tr[ *m_extDCSourceChannel].add(it->label);
237  }
238  }
239  });
240 }
241 void XTempControl::Loop::onPChanged(const Snapshot &shot, XValueNodeBase *) {
242  auto tempctrl = m_tempctrl.lock();
243  if( !tempctrl) return;
244  try {
245  Snapshot shot( *this);
246  if( !hasExtDevice(shot))
247  tempctrl->onPChanged(m_idx, shot[ *m_prop]);
248  }
249  catch(XInterface::XInterfaceError& e) {
250  e.print();
251  }
252 }
253 void XTempControl::Loop::onIChanged(const Snapshot &shot, XValueNodeBase *) {
254  auto tempctrl = m_tempctrl.lock();
255  if( !tempctrl) return;
256  try {
257  Snapshot shot( *tempctrl);
258  if( !hasExtDevice(shot))
259  tempctrl->onIChanged(m_idx, shot[ *m_int]);
260  }
261  catch(XInterface::XInterfaceError& e) {
262  e.print();
263  }
264 }
265 void XTempControl::Loop::onDChanged(const Snapshot &shot, XValueNodeBase *) {
266  auto tempctrl = m_tempctrl.lock();
267  if( !tempctrl) return;
268  try {
269  Snapshot shot( *tempctrl);
270  if( !hasExtDevice(shot))
271  tempctrl->onDChanged(m_idx, shot[ *m_deriv]);
272  }
273  catch(XInterface::XInterfaceError& e) {
274  e.print();
275  }
276 }
277 void XTempControl::Loop::onTargetTempChanged(const Snapshot &shot, XValueNodeBase *) {
278  auto tempctrl = m_tempctrl.lock();
279  if( !tempctrl) return;
280  try {
281  Snapshot shot( *tempctrl);
282  if( !hasExtDevice(shot))
283  tempctrl->onTargetTempChanged(m_idx, shot[ *m_targetTemp]);
284  }
285  catch(XInterface::XInterfaceError& e) {
286  e.print();
287  }
288 }
289 void XTempControl::Loop::onManualPowerChanged(const Snapshot &shot, XValueNodeBase *) {
290  auto tempctrl = m_tempctrl.lock();
291  if( !tempctrl) return;
292  try {
293  Snapshot shot( *tempctrl);
294  if( !hasExtDevice(shot))
295  tempctrl->onManualPowerChanged(m_idx, shot[ *m_manualPower]);
296  }
297  catch(XInterface::XInterfaceError& e) {
298  e.print();
299  }
300 }
301 void XTempControl::Loop::onHeaterModeChanged(const Snapshot &shot, XValueNodeBase *) {
302  auto tempctrl = m_tempctrl.lock();
303  if( !tempctrl) return;
304  m_pidAccum = 0;
305  try {
306  Snapshot shot( *tempctrl);
307  if( !hasExtDevice(shot))
308  tempctrl->onHeaterModeChanged(m_idx, shot[ *m_heaterMode]);
309  }
310  catch(XInterface::XInterfaceError& e) {
311  e.print();
312  }
313 }
314 void XTempControl::Loop::onPowerMaxChanged(const Snapshot &shot, XValueNodeBase *) {
315  auto tempctrl = m_tempctrl.lock();
316  if( !tempctrl) return;
317  try {
318  Snapshot shot( *tempctrl);
319  if( !hasExtDevice(shot))
320  tempctrl->onPowerRangeChanged(m_idx, shot[ *m_powerMax]);
321  }
322  catch(XInterface::XInterfaceError& e) {
323  e.print();
324  }
325 }
326 void XTempControl::Loop::onPowerMinChanged(const Snapshot &shot, XValueNodeBase *) {
327  auto tempctrl = m_tempctrl.lock();
328  if( !tempctrl) return;
329  try {
330  Snapshot shot( *tempctrl);
331  if( !hasExtDevice(shot))
332  tempctrl->onPowerRangeChanged(m_idx, shot[ *m_powerMin]);
333  }
334  catch(XInterface::XInterfaceError& e) {
335  e.print();
336  }
337 }
338 void XTempControl::Loop::onPowerRangeChanged(const Snapshot &shot, XValueNodeBase *) {
339  auto tempctrl = m_tempctrl.lock();
340  if( !tempctrl) return;
341  try {
342  Snapshot shot( *tempctrl);
343  if( !hasExtDevice(shot))
344  tempctrl->onPowerRangeChanged(m_idx, shot[ *m_powerRange]);
345  }
346  catch(XInterface::XInterfaceError& e) {
347  e.print();
348  }
349 }
350 void XTempControl::Loop::onCurrentChannelChanged(const Snapshot &shot, XValueNodeBase *) {
351  auto tempctrl = m_tempctrl.lock();
352  if( !tempctrl) return;
353  m_pidAccum = 0;
354  try {
355  shared_ptr<XChannel> ch(shot[ *m_currentChannel]);
356  if( !ch)
357  return;
358  tempctrl->onCurrentChannelChanged(m_idx, ch);
359  }
360  catch(XInterface::XInterfaceError& e) {
361  e.print();
362  }
363 }
364 
365 XTempControl::XTempControl(const char *name, bool runtime,
366  Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
367  XPrimaryDriverWithThread(name, runtime, ref(tr_meas), meas),
368  m_channels(create<XChannelList> ("Channels", false)),
369  m_form(new FrmTempControl(g_pFrmMain)) {
370 
371  iterate_commit([=](Transaction &tr){
372  m_setupChannel =
373  create<XItemNode<XChannelList, XChannel> >(tr, "SetupChannel", true, ref(tr), m_channels);
374  });
375  m_conSetupChannel = xqcon_create<XQComboBoxConnector> (m_setupChannel,
376  m_form->m_cmbSetupChannel, Snapshot( *m_channels));
377 
378  iterate_commit([=](Transaction &tr){
379  m_lsnOnSetupChannelChanged = tr[ *m_setupChannel].onValueChanged().connectWeakly(
380  shared_from_this(), &XTempControl::onSetupChannelChanged);
381  });
382 
383  m_form->statusBar()->hide();
384  m_form->setWindowTitle(i18n("TempControl - ") + getLabel());
385 }
386 
388  //! impliment form->show() here
389  m_form->showNormal();
390  m_form->raise();
391 }
392 
394  try {
395  for(;;) {
396  //! Since raw buffer is Fast-in Fast-out, use the same sequence of push()es for pop()s
397  uint16_t chno = reader.pop<uint16_t> ();
398  reader.pop<uint16_t> (); //reserve
399  float raw = reader.pop<float> ();
400  float temp = reader.pop<float> ();
401  if( !m_multiread)
402  chno = 0;
403  if(chno >= m_entry_temps.size())
404  throw XBufferUnderflowRecordError(__FILE__, __LINE__);
405  m_entry_temps[chno]->value(tr, temp);
406  m_entry_raws[chno]->value(tr, raw);
407  }
408  }
409  catch(XRecordError&) {
410  }
411 }
413 }
414 
415 void XTempControl::onSetupChannelChanged(const Snapshot &shot, XValueNodeBase *) {
416  m_conThermometer.reset();
417  m_conExcitation.reset();
418  m_lsnOnExcitationChanged.reset();
419  shared_ptr<XChannel> channel = shot[ *m_setupChannel];
420  if( !channel)
421  return;
422  m_conThermometer = xqcon_create<XQComboBoxConnector> (
423  channel->thermometer(), m_form->m_cmbThermometer, Snapshot( *channel->thermometers()));
424  m_conExcitation = xqcon_create<XQComboBoxConnector> (channel->excitation(),
425  m_form->m_cmbExcitation, Snapshot( *channel->excitation()));
426  iterate_commit([=](Transaction &tr){
427  m_lsnOnExcitationChanged
428  = tr[ *channel->excitation()].onValueChanged().connectWeakly(
429  shared_from_this(),
430  &XTempControl::onExcitationChangedInternal);
431  });
432 }
433 
435  Transaction &tr_meas, const shared_ptr<XMeasure> &meas,
436  bool multiread, std::initializer_list<XString> channel_names,
437  std::initializer_list<XString> excitations,
438  std::initializer_list<XString> loop_names) {
439  shared_ptr<XScalarEntryList> entries(meas->scalarEntries());
440  m_multiread = multiread;
441 
442  iterate_commit([=, &tr_meas](Transaction &tr){
443  for(auto &&ch: channel_names) {
444  shared_ptr<XChannel> channel = m_channels->create<XChannel> (
445  tr, ch.c_str(), false, ref(tr_meas), meas->thermometers());
446  tr[ *channel->excitation()].add(excitations);
447  }
448  });
449  if(multiread) {
450  Snapshot shot( *m_channels);
451  if(shot.size()) {
452  const XNode::NodeList &list( *shot.list());
453  for(XNode::const_iterator it = list.begin(); it != list.end(); it++) {
454  shared_ptr<XChannel> channel =
455  dynamic_pointer_cast<XChannel> (*it);
456  shared_ptr<XScalarEntry> entry_temp(
457  create<XScalarEntry>(
458  QString("Ch.%1").arg(channel->getName()).toLocal8Bit().data(),
459  false, dynamic_pointer_cast<XDriver> (shared_from_this()), "%.5g"));
460  shared_ptr<XScalarEntry> entry_raw(
461  create<XScalarEntry> (
462  QString("Ch.%1.raw").arg(
463  channel->getName()).toLocal8Bit().data(), false,
464  dynamic_pointer_cast<XDriver> (shared_from_this()), "%.5g"));
465  m_entry_temps.push_back(entry_temp);
466  m_entry_raws.push_back(entry_raw);
467  entries->insert(tr_meas, entry_temp);
468  entries->insert(tr_meas, entry_raw);
469  }
470  }
471  }
472  else {
473  shared_ptr<XScalarEntry> entry_temp(create<XScalarEntry> (
474  "Temp", false,
475  dynamic_pointer_cast<XDriver> (shared_from_this()), "%.5g"));
476  shared_ptr<XScalarEntry> entry_raw(create<XScalarEntry> (
477  "Raw", false,
478  dynamic_pointer_cast<XDriver> (shared_from_this()), "%.5g"));
479  m_entry_temps.push_back(entry_temp);
480  m_entry_raws.push_back(entry_raw);
481  entries->insert(tr_meas, entry_temp);
482  entries->insert(tr_meas, entry_raw);
483  }
484  //creates loops.
485  unsigned int num_of_loops = 0;
486  for(auto &&lp: loop_names) {
487  shared_ptr<Loop> p;
488  iterate_commit([=, &p, &tr_meas](Transaction &tr){
489  p = create<Loop>(tr,
490  lp.c_str(), false,
491  dynamic_pointer_cast<XTempControl>(shared_from_this()), ref(tr), num_of_loops,
492  ref(tr_meas), meas);
493  });
494  m_loops.push_back(p);
495  num_of_loops++;
496  }
497  if(num_of_loops > 1) {
498  auto lp = loop(1);
499  lp->m_conUIs = {
500  xqcon_create<XQComboBoxConnector> (lp->m_currentChannel,
501  m_form->m_cmbSourceChannel2, Snapshot( *m_channels)),
502  xqcon_create<XQComboBoxConnector> (lp->m_powerRange,
503  m_form->m_cmbPowerRange2, Snapshot( *lp->m_powerRange)),
504  xqcon_create<XQComboBoxConnector> (lp->m_heaterMode,
505  m_form->m_cmbHeaterMode2, Snapshot( *lp->m_heaterMode)),
506  xqcon_create<XQLineEditConnector> (lp->m_prop, m_form->m_edP2),
507  xqcon_create<XQLineEditConnector> (lp->m_int, m_form->m_edI2),
508  xqcon_create<XQLineEditConnector> (lp->m_deriv, m_form->m_edD2),
509  xqcon_create<XQLineEditConnector> (lp->m_manualPower, m_form->m_edManHeater2),
510  xqcon_create<XQLineEditConnector> (lp->m_powerMax, m_form->m_edPowerMax2),
511  xqcon_create<XQLineEditConnector> (lp->m_powerMin, m_form->m_edPowerMin2),
512  xqcon_create<XQLineEditConnector> (lp->m_targetTemp, m_form->m_edTargetTemp2),
513  xqcon_create<XQLCDNumberConnector> (lp->m_heaterPower, m_form->m_lcdHeater2),
514  xqcon_create<XQLCDNumberConnector> (lp->m_sourceTemp, m_form->m_lcdSourceTemp2),
515  xqcon_create<XQComboBoxConnector> (lp->m_extDevice, m_form->m_cmbExtDevice2, ref(tr_meas)),
516  xqcon_create<XQComboBoxConnector> (
517  lp->m_extDCSourceChannel, m_form->m_cmbExtDCSrcCh2, Snapshot( *lp->m_extDCSourceChannel)),
518  xqcon_create<XQToggleButtonConnector>( lp->m_extIsPositive, m_form->m_ckbExtIsPositive2)
519  };
520 
521  }
522  else {
523  m_form->m_toolBox->removeItem(1);
524  m_form->m_pageLoop2->hide();
525  }
526  if(num_of_loops) {
527  auto lp = loop(0);
528  lp->m_conUIs = {
529  xqcon_create<XQComboBoxConnector> (lp->m_currentChannel,
530  m_form->m_cmbSourceChannel, Snapshot( *m_channels)),
531  xqcon_create<XQComboBoxConnector> (lp->m_powerRange,
532  m_form->m_cmbPowerRange, Snapshot( *lp->m_powerRange)),
533  xqcon_create<XQComboBoxConnector> (lp->m_heaterMode,
534  m_form->m_cmbHeaterMode, Snapshot( *lp->m_heaterMode)),
535  xqcon_create<XQLineEditConnector> (lp->m_prop, m_form->m_edP),
536  xqcon_create<XQLineEditConnector> (lp->m_int, m_form->m_edI),
537  xqcon_create<XQLineEditConnector> (lp->m_deriv, m_form->m_edD),
538  xqcon_create<XQLineEditConnector> (lp->m_manualPower, m_form->m_edManHeater),
539  xqcon_create<XQLineEditConnector> (lp->m_powerMax, m_form->m_edPowerMax),
540  xqcon_create<XQLineEditConnector> (lp->m_powerMin, m_form->m_edPowerMin),
541  xqcon_create<XQLineEditConnector> (lp->m_targetTemp, m_form->m_edTargetTemp),
542  xqcon_create<XQLCDNumberConnector> (lp->m_heaterPower, m_form->m_lcdHeater),
543  xqcon_create<XQLCDNumberConnector> (lp->m_sourceTemp, m_form->m_lcdSourceTemp),
544  xqcon_create<XQComboBoxConnector> (lp->m_extDevice, m_form->m_cmbExtDevice, ref(tr_meas)),
545  xqcon_create<XQComboBoxConnector> (
546  lp->m_extDCSourceChannel, m_form->m_cmbExtDCSrcCh, Snapshot( *lp->m_extDCSourceChannel)),
547  xqcon_create<XQToggleButtonConnector>( lp->m_extIsPositive, m_form->m_ckbExtIsPositive)
548  };
549  }
550  else {
551  m_form->m_toolBox->removeItem(0);
552  m_form->m_pageLoop1->hide();
553  }
554 }
555 
556 void *
557 XTempControl::execute(const atomic<bool> &terminated) {
558  for(auto it = m_loops.begin(); it != m_loops.end(); ++it) {
559  ( *it)->start();
560  }
561 
562  while( !terminated) {
563  msecsleep(10);
564 
565  auto writer = std::make_shared<RawData>();
566  Snapshot shot( *this);
567  double raw, temp;
568  XTime time_awared = XTime::now();
569  // try/catch exception of communication errors
570  try {
571  if(shot.size(m_channels)) {
572  const XNode::NodeList &list( *shot.list(m_channels));
573  unsigned int idx = 0;
574  for(XNode::const_iterator it = list.begin(); it != list.end(); it++) {
575  shared_ptr<XChannel> ch = static_pointer_cast<XChannel>( *it);
576  bool src_found = false;
577  for(auto lit = m_loops.begin(); lit != m_loops.end(); ++lit) {
578  shared_ptr<XChannel> curch = shot[ ( *lit)->m_currentChannel];
579  if(curch == ch)
580  src_found = true;;
581  }
582  if(m_multiread || src_found) {
583  shared_ptr<XThermometer> thermo = shot[ *ch->thermometer()];
584  raw = getRaw(ch);
585  temp = ( !thermo) ? getTemp(ch) : thermo->getTemp(raw);
586 
587  for(auto lit = m_loops.begin(); lit != m_loops.end(); ++lit) {
588  shared_ptr<XChannel> curch = shot[ ( *lit)->m_currentChannel];
589  if(curch == ch)
590  ( *lit)->update(temp);
591  }
592  writer->push((uint16_t) idx);
593  writer->push((uint16_t) 0); // reserve
594  writer->push(float(raw));
595  writer->push(float(temp));
596  }
597  idx++;
598  }
599  }
600 
601  }
602  catch(XKameError &e) {
603  e.print(getLabel() + "; ");
604  continue;
605  }
606  finishWritingRaw(writer, time_awared, XTime::now());
607  }
608 
609  trans( *m_setupChannel) = shared_ptr<XThermometer>();
610 
611  for(auto it = m_loops.begin(); it != m_loops.end(); ++it) {
612  ( *it)->stop();
613  }
614 
615  return NULL;
616 }
617 
618 void XTempControl::onExcitationChangedInternal(const Snapshot &, XValueNodeBase *node) {
619  try {
620  shared_ptr<XChannel> ch;
621  Snapshot shot( *channels());
622  if(shot.size()) {
623  const XNode::NodeList &list( *shot.list());
624  for(XNode::const_iterator it = list.begin(); it != list.end(); it++) {
625  shared_ptr<XChannel> ch__ =
626  dynamic_pointer_cast<XChannel> ( *it);
627  if(ch__->excitation().get() == node)
628  ch = ch__;
629  }
630  }
631  if( !ch)
632  return;
633  int exc = shot[ *ch->excitation()];
634  if(exc < 0)
635  return;
636  onExcitationChanged(ch, exc);
637  }
638  catch(XInterface::XInterfaceError& e) {
639  e.print();
640  }
641 }

Generated for KAME4 by  doxygen 1.8.3