API
zaberStage.hpp
Go to the documentation of this file.
1 /** \file zaberStage.hpp
2  * \brief A class with details of a single zaber stage
3  *
4  * \ingroup zaberLowLevel_files
5  */
6 
7 #ifndef zaberStage_hpp
8 #define zaberStage_hpp
9 
10 #include <iostream>
11 
12 
13 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
14 
15 #include "za_serial.h"
16 
17 
18 namespace MagAOX
19 {
20 namespace app
21 {
22 
23 /// A class to manage the details of one stage in a Zaber system.
24 /**
25  * \ingroup zaberLowLevel
26  */
27 template<class parentT>
29 {
30 protected:
31  parentT * m_parent {nullptr}; //The parent MagAOXApp
32 
33  std::string m_name; ///< The stage's name.
34 
35  std::string m_serial; ///< The stage's serial number.
36 
37  int m_deviceAddress {-1}; ///< The device's address, a.k.a. its order in the chain
38 
39  int m_axisNumber{0}; ///< The axis number at the address (normally 0 in MagAO-X)
40 
41  bool m_commandStatus {true}; ///< The status of the last command sent. true = OK, false = RJ (rejected)
42 
43  char m_deviceStatus {'U'}; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
44 
45  bool m_homing {false};
46 
47  long m_rawPos; ///< The raw position reported by the device, in microsteps.
48 
49  long m_tgtPos {0}; ///< The tgt position last sent to the device, in microsteps.
50 
51  long m_maxPos; ///< The max position allowed for the device, set by config. Will be set to no larger m_maxPosHW.
52 
53  float m_temp {-999}; ///< The driver temperature, in C.
54 
55  bool m_warn {false};
56 
57  bool m_warnFD {false};
58  bool m_warnFDreported {false};
59  bool m_warnFQ {false};
60  bool m_warnFQreported {false};
61  bool m_warnFS {false};
62  bool m_warnFSreported {false};
63  bool m_warnFT {false};
64  bool m_warnFTreported {false};
65  bool m_warnFB {false};
66  bool m_warnFBreported {false};
67  bool m_warnFP {false};
68  bool m_warnFPreported {false};
69  bool m_warnFE {false};
70  bool m_warnFEreported {false};
71  bool m_warnWH {false};
72  bool m_warnWHreported {false};
73  bool m_warnWL {false};
74  bool m_warnWLreported {false};
75  bool m_warnWP {false};
76  bool m_warnWPreported {false};
77  bool m_warnWV {false};
78  bool m_warnWVreported {false};
79  bool m_warnWT {false};
80  bool m_warnWTreported {false};
81  bool m_warnWM {false};
82  bool m_warnWMreported {false};
83  bool m_warnWR {false};
84  bool m_warnWRreported {false};
85  bool m_warnNC {false};
86  bool m_warnNCreported {false};
87  bool m_warnNI {false};
88  bool m_warnNIreported {false};
89  bool m_warnND {false};
90  bool m_warnNDreported {false};
91  bool m_warnNU {false};
92  bool m_warnNUreported {false};
93  bool m_warnNJ {false};
94  bool m_warnNJreported {false};
95  bool m_warnUNK {false};
96 
97 public:
98 
99  zaberStage() = delete;
100 
101  zaberStage( parentT * parent)
102  {
103  m_parent = parent;
104  }
105  /// Get the device name
106  /**
107  * \returns the current value of m_name
108  */
109  std::string name();
110 
111  /// Set the device name
112  /**
113  * \returns 0 on success
114  * \returns -1 on error
115  */
116  int name( const std::string & n /**< [in] the new device name*/);
117 
118  /// Get the device serial number
119  /**
120  * \returns the current value of m_serial
121  */
122  std::string serial();
123 
124  /// Set the device serial
125  /**
126  * \returns 0 on success
127  * \returns -1 on error
128  */
129  int serial( const std::string & s /**< [in] the new device serial*/);
130 
131  /// Get the device address
132  /**
133  * \returns the current value of m_deviceAddress
134  */
136 
137  /// Set the device address
138  /**
139  * \returns 0 on success
140  * \returns -1 on error
141  */
142  int deviceAddress( const int & da /**< [in] the new device address*/);
143 
144  /// Get the axis number
145  /**
146  * \returns the current value of m_axisNumber
147  */
148  int axisNumber();
149 
150  /// Set the axis number
151  /**
152  * \returns 0 on success
153  * \returns -1 on error
154  */
155  int axisNumber( const int & an /**< [in] the new axis number */);
156 
157  /// Get the command status
158  /**
159  * \returns the current value of m_commandStatus
160  */
162 
163  /// Get the device status
164  /**
165  * \returns the current value of m_deviceStatus
166  */
167  char deviceStatus();
168 
169  /// Get the homing status
170  /**
171  * \returns the current value of m_homing
172  */
173  bool homing();
174 
175  /// Get the current raw position, in counts
176  /**
177  * \returns the current value of m_rawPos
178  */
179  long rawPos();
180 
181  /// Get the current tgt position, in counts
182  /**
183  * \returns the current value of m_tgtPos
184  */
185  long tgtPos();
186 
187  /// Get the max position, in counts
188  /**
189  * \returns the current value of m_maxPos
190  */
191  long maxPos();
192 
193  /// Get the status of the warning flag
194  /**
195  * \returns the current value of m_warn
196  */
197  bool warn();
198 
199  /// Get the temperature, in C
200  /**
201  * \returns the current value of m_temp
202  */
203  float temp();
204 
205  /// Get the warning state
206  /**
207  * \returns the true if any warning flags are set.
208  */
209  bool warningState();
210 
211  bool warnFD();
212  bool warnFQ();
213  bool warnFS();
214  bool warnFT();
215  bool warnFB();
216  bool warnFP();
217  bool warnFE();
218  bool warnWH();
219  bool warnWL();
220  bool warnWP();
221  bool warnWV();
222  bool warnWT();
223  bool warnWM();
224  bool warnWR();
225  bool warnNC();
226  bool warnNI();
227  bool warnND();
228  bool warnNU();
229  bool warnNJ();
230  bool warnUNK();
231 
232  /// Get a response from the device, after a command has been sent.
233  /** Parses the standard parts of the response in this stage's fields,
234  * and extracts the response string.
235  *
236  * \returns 0 on success.
237  * \returns -1 on error.
238  */
239  int getResponse( std::string & response, ///< [out] the text response
240  const std::string & repBuff ///< [in] the reply buffer, not decoded.
241  );
242 
243  /// Get a response from the device, after a command has been sent.
244  /** Parses the standard parts of the response in this stages fields,
245  * and extracts the response string.
246  *
247  * \overload
248  *
249  * \returns 0 on success.
250  * \returns -1 on error.
251  */
252  int getResponse( std::string & response, ///< [out] the text response component
253  const za_reply & rep ///< [in] the decodedstage reply
254  );
255 
256  int sendCommand( std::string & response, ///< [out] the response received from the stage
257  z_port port, ///< [in] the port with which to communicate
258  const std::string & command ///< [in] the command to send
259  );
260 
261  int getMaxPos( z_port port /**< [in] the port with which to communicate */ );
262 
263  int updatePos( z_port port /**< [in] the port with which to communicate */ );
264 
265  int updateTemp( z_port port /**< [in] the port with which to communicate */ );
266 
267  int stop (z_port port );
268 
269  int estop (z_port port );
270 
271  int home( z_port port /**< [in] the port with which to communicate */ );
272 
273  int moveAbs( z_port port, ///< [in] the port with which to communicate
274  long rawPos ///< [in] the position to move to, in counts
275  );
276 
277  /// Sets all warning flags to false
278  /** This is not the same as clearing warnings on the device, this is just used for
279  * bookkeeping.
280  *
281  * \returns 0 on success (always)
282  */
284 
285  /// Process a single warning from the device, setting the appropriate flag.
286  /** Warnings are two ASCII characeters, e.g. "WR".
287  *
288  * \returns 0 if the warning is processed, including if it's not recognized.
289  * \returns -1 on an error, currently not possible.
290  */
291  int processWarning( std::string & warn /**< [in] the two-character warning flag */);
292 
293  /// Parse the warning response from the device.
294  /** Sends each warning flag to processWarning.
295  *
296  * \returns 0 on success
297  * \returns -1 on error
298  */
299  int parseWarnings(std::string & response /**< [in] the response from the warnings query*/);
300 
301  /// Get warnings from the device
302  /** Log entries will be made and flags will be set in this structure.
303  *
304  * \returns 0 on success
305  * \returns -1 on error.
306  */
307  int getWarnings( z_port port /**< [in] the port with which to communicate */ );
308 
309  /// Clear all state so that when the system is powered back on we get the correct new state.
310  int onPowerOff();
311 };
312 
313 template<class parentT>
315 {
316  return m_name;
317 }
318 
319 template<class parentT>
320 int zaberStage<parentT>::name( const std::string & n )
321 {
322  m_name = n;
323  return 0;
324 }
325 
326 template<class parentT>
328 {
329  return m_serial;
330 }
331 
332 template<class parentT>
333 int zaberStage<parentT>::serial( const std::string & s )
334 {
335  m_serial = s;
336  return 0;
337 }
338 
339 template<class parentT>
341 {
342  return m_deviceAddress;
343 }
344 
345 template<class parentT>
347 {
348  m_deviceAddress = da;
349  return 0;
350 }
351 
352 template<class parentT>
354 {
355  return m_axisNumber;
356 }
357 
358 template<class parentT>
359 int zaberStage<parentT>::axisNumber( const int & an )
360 {
361  m_axisNumber = an;
362  return 0;
363 }
364 
365 template<class parentT>
367 {
368  return m_commandStatus;
369 }
370 
371 template<class parentT>
373 {
374  return m_deviceStatus;
375 }
376 
377 template<class parentT>
379 {
380  return m_homing;
381 }
382 
383 template<class parentT>
385 {
386  return m_rawPos;
387 }
388 
389 template<class parentT>
391 {
392  return m_tgtPos;
393 }
394 
395 template<class parentT>
397 {
398  return m_maxPos;
399 }
400 
401 template<class parentT>
403 {
404  return m_warn;
405 }
406 
407 template<class parentT>
409 {
410  return m_temp;
411 }
412 
413 template<class parentT>
415 {
416  return m_warn;
417 }
418 
419 template<class parentT>
421 {
422  return m_warnFD;
423 }
424 
425 template<class parentT>
427 {
428  return m_warnFQ;
429 }
430 
431 template<class parentT>
433 {
434  return m_warnFS;
435 }
436 
437 template<class parentT>
439 {
440  return m_warnFT;
441 }
442 
443 template<class parentT>
445 {
446  return m_warnFB;
447 }
448 
449 template<class parentT>
451 {
452  return m_warnFP;
453 }
454 
455 template<class parentT>
457 {
458  return m_warnFE;
459 }
460 
461 template<class parentT>
463 {
464  return m_warnWH;
465 }
466 
467 template<class parentT>
469 {
470  return m_warnWL;
471 }
472 
473 template<class parentT>
475 {
476  return m_warnWP;
477 }
478 
479 template<class parentT>
481 {
482  return m_warnWV;
483 }
484 
485 template<class parentT>
487 {
488  return m_warnWT;
489 }
490 
491 template<class parentT>
493 {
494  return m_warnWM;
495 }
496 
497 template<class parentT>
499 {
500  return m_warnWR;
501 }
502 
503 template<class parentT>
505 {
506  return m_warnNC;
507 }
508 
509 template<class parentT>
511 {
512  return m_warnNI;
513 }
514 
515 template<class parentT>
517 {
518  return m_warnND;
519 }
520 
521 template<class parentT>
523 {
524  return m_warnNU;
525 }
526 
527 template<class parentT>
529 {
530  return m_warnNJ;
531 }
532 
533 template<class parentT>
535 {
536  return m_warnUNK;
537 }
538 
539 template<class parentT>
540 int zaberStage<parentT>::getResponse( std::string & response,
541  const std::string & repBuff
542  )
543 {
544  za_reply rep;
545  int rv = za_decode(&rep, repBuff.c_str(), repBuff.size());
546  if(rv != Z_SUCCESS)
547  {
548  if(m_parent)
549  {
550  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
551  }
552 
553  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "za_decode !=Z_SUCCESS"});
554  return rv;
555  }
556 
557  return getResponse(response, rep);
558 }
559 
560 template<class parentT>
561 int zaberStage<parentT>::getResponse( std::string & response,
562  const za_reply & rep
563  )
564 {
565  if(rep.device_address == m_deviceAddress)
566  {
567  if(rep.reply_flags[0] == 'O') m_commandStatus = true;
568  else m_commandStatus = false;
569 
570 
571  m_deviceStatus = rep.device_status[0];
572 
573  if(m_deviceStatus == 'I' && m_homing)
574  {
575  m_warnWR = false; //Clear preemptively
576  m_homing = false;
577  }
578 
579  if(rep.warning_flags[0] == '-') unsetWarnings();
580  else m_warn = true;
581 
582  response = rep.response_data;
583 
584  return 0;
585  }
586  else
587  {
588  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "wrong device"});
589  return -1;
590  }
591 }
592 
593 template<class parentT>
594 int zaberStage<parentT>::sendCommand( std::string & response,
595  z_port port,
596  const std::string & command
597  )
598 {
599  MagAOXAppT::log<text_log>(std::string("Sending: ") + command, logPrio::LOG_DEBUG2);
600 
601  za_send(port, command.c_str(), command.size());
602 
603  char buff[256];
604 
605  while(1)
606  {
607  int rv = za_receive(port, buff, sizeof(buff));
608  if(rv == Z_ERROR_TIMEOUT)
609  {
610  if(m_parent)
611  {
612  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
613  }
614 
615  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "Z_ERROR_TIMEOUT"});
616  break; //assume error and just get out.
617  }
618  else if(rv < 0)
619  {
620  if(m_parent)
621  {
622  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
623  }
624 
625  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_receive !=Z_SUCCESS"});
626  break;
627  }
628  za_reply rep;
629 
630 
631  MagAOXAppT::log<text_log>(std::string("Received: ") + buff, logPrio::LOG_DEBUG2);
632 
633  rv = za_decode(&rep, buff, sizeof(buff));
634  if(rv != Z_SUCCESS)
635  {
636  if(m_parent)
637  {
638  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
639  }
640 
641  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_decode !=Z_SUCCESS"});
642  break;
643  }
644 
645  if(rep.device_address == m_deviceAddress) return getResponse(response, rep);
646  }
647 
648  response = "";
649 
650  return -1;
651 }
652 
653 template<class parentT>
655 {
656  if(m_deviceAddress < 1)
657  {
658  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
659  }
660 
661  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
662  com += "get limit.max";
663 
664  std::string response;
665 
666  int rv = sendCommand(response, port, com);
667 
668  if(rv == 0)
669  {
670  if( m_commandStatus )
671  {
672  m_maxPos = mx::ioutils::convertFromString<long>(response);
673  return 0;
674  }
675  else
676  {
677  if(m_parent)
678  {
679  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
680  }
681 
682  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get limit.max Command Rejected"});
683  return -1;
684  }
685  }
686  else
687  {
688  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
689  if(m_parent)
690  {
691  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
692  }
693 
694  return -1;
695  }
696 }
697 
698 template<class parentT>
700 {
701  if(m_deviceAddress < 1)
702  {
703  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
704  }
705 
706  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
707  com += "get pos";
708 
709  std::string response;
710 
711  int rv = sendCommand(response, port, com);
712 
713  if(rv == 0)
714  {
715  if( m_commandStatus )
716  {
717  m_rawPos = mx::ioutils::convertFromString<long>(response);
718  return 0;
719  }
720  else
721  {
722  if(m_parent)
723  {
724  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
725  }
726 
727  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get pos Command Rejected"});
728  return -1;
729  }
730  }
731  else
732  {
733  if(m_parent)
734  {
735  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
736  }
737 
738  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
739  return -1;
740  }
741 }
742 
743 template<class parentT>
745 {
746  if(m_deviceAddress < 1)
747  {
748  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
749  }
750 
751  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
752  com += "get driver.temperature";
753 
754  std::string response;
755 
756  int rv = sendCommand(response, port, com);
757 
758  if(rv == 0)
759  {
760  if( m_commandStatus )
761  {
762  m_temp = mx::ioutils::convertFromString<float>(response);
763  return 0;
764  }
765  else
766  {
767  if(m_parent)
768  {
769  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
770  }
771 
772  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get driver.temperature Command Rejected"});
773  return -1;
774  }
775  }
776  else
777  {
778  if(m_parent)
779  {
780  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
781  }
782 
783  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
784  return -1;
785  }
786 }
787 
788 template<class parentT>
789 int zaberStage<parentT>::stop( z_port port )
790 {
791  if(m_deviceAddress < 1)
792  {
793  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
794  }
795 
796  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
797  com += "stop";
798 
799  std::string response;
800 
801  int rv = sendCommand(response, port, com);
802 
803  if(rv == 0)
804  {
805  if( m_commandStatus )
806  {
807  return 0;
808  }
809  else
810  {
811  if(m_parent)
812  {
813  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
814  }
815 
816  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " stop Command Rejected"});
817  return -1;
818  }
819  }
820  else
821  {
822  if(m_parent)
823  {
824  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
825  }
826 
827  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
828  return -1;
829  }
830 }
831 
832 template<class parentT>
833 int zaberStage<parentT>::estop( z_port port )
834 {
835  if(m_deviceAddress < 1)
836  {
837  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
838  }
839 
840  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
841  com += "estop";
842 
843  std::string response;
844 
845  int rv = sendCommand(response, port, com);
846 
847  if(rv == 0)
848  {
849  if( m_commandStatus )
850  {
851  return 0;
852  }
853  else
854  {
855  if(m_parent)
856  {
857  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
858  }
859 
860  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " estop Command Rejected"});
861  return -1;
862  }
863  }
864  else
865  {
866  if(m_parent)
867  {
868  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
869  }
870 
871  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
872  return -1;
873  }
874 }
875 
876 template<class parentT>
877 int zaberStage<parentT>::home( z_port port )
878 {
879  if(m_deviceAddress < 1)
880  {
881  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
882  }
883 
884  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
885  com += "home";
886 
887  std::string response;
888 
889  int rv = sendCommand(response, port, com);
890 
891  if(rv == 0)
892  {
893  if( m_commandStatus )
894  {
895  m_homing = true;
896  return 0;
897  }
898  else
899  {
900  if(m_parent)
901  {
902  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
903  }
904 
905  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "Home Command Rejected"});
906  return -1;
907  }
908  }
909  else
910  {
911  if(m_parent)
912  {
913  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
914  }
915 
916  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
917  return -1;
918  }
919 }
920 
921 template<class parentT>
923  long rawPos
924  )
925 {
926  if(m_deviceAddress < 1)
927  {
928  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
929  }
930 
931  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
932  com += "move abs " + std::to_string(rawPos);
933 
934  m_tgtPos = rawPos;
935 
936  std::string response;
937 
938  int rv = sendCommand(response, port, com);
939 
940  if(rv == 0)
941  {
942  if( m_commandStatus )
943  {
944  return 0;
945  }
946  else
947  {
948  if(m_parent)
949  {
950  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
951  }
952 
953  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "move abs Command Rejected"});
954  return -1;
955  }
956  }
957  else
958  {
959  if(m_parent)
960  {
961  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
962  }
963 
964  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
965  return -1;
966  }
967 }
968 
969 template<class parentT>
971 {
972  m_warn = false;
973 
974  m_warnFD = false;
975  m_warnFQ = false;
976  m_warnFS = false;
977  m_warnFT = false;
978  m_warnFB = false;
979  m_warnFP = false;
980  m_warnFE = false;
981  m_warnWH = false;
982  m_warnWL = false;
983  m_warnWP = false;
984  m_warnWV = false;
985  m_warnWT = false;
986  m_warnWM = false;
987  m_warnWR = false;
988  m_warnNC = false;
989  m_warnNI = false;
990  m_warnND = false;
991  m_warnNU = false;
992  m_warnNJ = false;
993  m_warnUNK = false;
994 
995  return 0;
996 }
997 
998 template<class parentT>
999 int zaberStage<parentT>::processWarning( std::string & warn )
1000 {
1001  if(warn == "FD")
1002  {
1003  if(!m_warnFDreported)
1004  {
1005  MagAOXAppT::log<text_log>(m_name + " Driver Disabled (FD): The driver has disabled itself due to overheating." , logPrio::LOG_EMERGENCY);
1006  m_warnFDreported = true;
1007  }
1008 
1009  m_warnFD = true;
1010  return 0;
1011  }
1012  else if(warn == "FQ")
1013  {
1014  if(!m_warnFQreported)
1015  {
1016  MagAOXAppT::log<text_log>(m_name + " warning FQ: you should probably check." , logPrio::LOG_EMERGENCY);
1017  m_warnFQreported = true;
1018  }
1019 
1020  m_warnFQ = true;
1021  return 0;
1022  }
1023  else if(warn == "FS")
1024  {
1025  if(!m_warnFSreported)
1026  {
1027  MagAOXAppT::log<text_log>(m_name + " Stalled and Stopped (FS): Stalling was detected and the axis has stopped itself. " , logPrio::LOG_WARNING);
1028  m_warnFSreported = true;
1029  }
1030  m_warnFS = true;
1031  return 0;
1032  }
1033  else if(warn == "FT")
1034  {
1035  if(!m_warnFTreported)
1036  {
1037  MagAOXAppT::log<text_log>(m_name + " Excessive Twist (FT): The lockstep group has exceeded allowable twist and has stopped. " , logPrio::LOG_WARNING);
1038  m_warnFTreported = true;
1039  }
1040 
1041  m_warnFT = true;
1042  return 0;
1043  }
1044  else if(warn == "FB")
1045  {
1046  if(!m_warnFBreported)
1047  {
1048  MagAOXAppT::log<text_log>(m_name + " Stream Bounds Error (FB): A previous streamed motion could not be executed because it failed a precondition" , logPrio::LOG_WARNING);
1049  m_warnFBreported = true;
1050  }
1051 
1052  m_warnFB = true;
1053  return 0;
1054  }
1055  else if(warn == "FP")
1056  {
1057  if(!m_warnFPreported)
1058  {
1059  MagAOXAppT::log<text_log>(m_name + " Interpolated Path Deviation (FP): Streamed or sinusoidal motion was terminated because an axis slipped and thus the device deviated from the requested path. " , logPrio::LOG_WARNING);
1060  m_warnFPreported = true;
1061  }
1062 
1063  m_warnFP = true;
1064  return 0;
1065  }
1066  else if(warn == "FE")
1067  {
1068  if(!m_warnFEreported)
1069  {
1070  MagAOXAppT::log<text_log>(m_name + " Limit Error (FE): The target limit sensor cannot be reached or is faulty. " , logPrio::LOG_WARNING);
1071  m_warnFEreported = true;
1072  }
1073 
1074  m_warnFE = true;
1075  return 0;
1076  }
1077  else if(warn == "WH")
1078  {
1079  if(m_warnWHreported == false)
1080  {
1081  MagAOXAppT::log<text_log>(m_name + " Device not homed (WH): The device has a position reference, but has not been homed." , logPrio::LOG_WARNING);
1082  m_warnWHreported = true;
1083  }
1084 
1085  m_warnWH = true;
1086  return 0;
1087  }
1088  else if(warn == "WL")
1089  {
1090  if(!m_warnWLreported)
1091  {
1092  MagAOXAppT::log<text_log>(m_name + " Unexpected Limit Trigger warning (WL): A movement operation did not complete due to a triggered limit sensor." , logPrio::LOG_WARNING);
1093  m_warnWLreported = true;
1094  }
1095 
1096  m_warnWL = true;
1097  return 0;
1098  }
1099  else if(warn == "WP")
1100  {
1101  if(!m_warnWPreported)
1102  {
1103  MagAOXAppT::log<text_log>(m_name + " Invalid calibration type (WP): The saved calibration data type is unsupported" , logPrio::LOG_WARNING);
1104  m_warnWPreported = true;
1105  }
1106 
1107  m_warnWP = true;
1108  return 0;
1109  }
1110  else if(warn == "WV")
1111  {
1112  if(!m_warnWVreported)
1113  {
1114  MagAOXAppT::log<text_log>(m_name + " Voltage Out of Range (WV): The supply voltage is outside the recommended operating range of the device" , logPrio::LOG_WARNING);
1115  m_warnWVreported = true;
1116  }
1117 
1118  m_warnWV = true;
1119  return 0;
1120  }
1121  else if(warn == "WT")
1122  {
1123  if(!m_warnWTreported)
1124  {
1125  MagAOXAppT::log<text_log>(m_name + " Controller Temperature High (WT): The internal temperature of the controller has exceeded the recommended limit for the device." , logPrio::LOG_WARNING);
1126  m_warnWTreported = true;
1127  }
1128 
1129  m_warnWT = true;
1130  return 0;
1131  }
1132  else if(warn == "WM")
1133  {
1134  if(m_warnWMreported == false)
1135  {
1136  MagAOXAppT::log<text_log>(m_name + " Displaced when Stationary (WM): While not in motion, the axis has been forced out of its position." , logPrio::LOG_WARNING);
1137  m_warnWMreported = true;
1138  }
1139 
1140  m_warnWM = true;
1141  return 0;
1142  }
1143  else if(warn == "WR")
1144  {
1145  if(m_warnWRreported == false)
1146  {
1147  MagAOXAppT::log<text_log>(m_name + " No Reference Position (WR): Axis has not had a reference position established. [homing required]" , logPrio::LOG_WARNING);
1148  m_warnWRreported = true;
1149  }
1150 
1151  m_warnWR = true;
1152  return 0;
1153  }
1154  else if(warn == "NC")
1155  {
1156  if(!m_warnNCreported)
1157  {
1158  MagAOXAppT::log<text_log>(m_name + " Manual Control (NC): Axis is busy due to manual control via the knob." , logPrio::LOG_WARNING);
1159  m_warnNCreported = true;
1160  }
1161 
1162  m_warnNC = true;
1163  return 0;
1164  }
1165  else if(warn == "NI")
1166  {
1167  if(m_parent)
1168  {
1169  if(m_homing == true || warnWR()) return 0; //ignore this during homing
1170  }
1171 
1172  if(!m_warnNIreported)
1173  {
1174  MagAOXAppT::log<text_log>(m_name + " Command Interrupted (NI): A movement operation (command or manual control) was requested while the axis was executing another movement command." , logPrio::LOG_WARNING);
1175  m_warnNIreported = true;
1176  }
1177 
1178  m_warnNI = true;
1179  return 0;
1180  }
1181  else if(warn == "ND")
1182  {
1183  if(!m_warnNDreported)
1184  {
1185  MagAOXAppT::log<text_log>(m_name + " Stream Discontinuity (ND): The device has slowed down while following a streamed motion path because it has run out of queued motions." , logPrio::LOG_WARNING);
1186  m_warnNDreported = true;
1187  }
1188 
1189  m_warnND = true;
1190  return 0;
1191  }
1192  else if(warn == "NU")
1193  {
1194  if(!m_warnNUreported)
1195  {
1196  MagAOXAppT::log<text_log>(m_name + " Setting Update Pending (NU): A setting is pending to be updated or a reset is pending." , logPrio::LOG_WARNING);
1197  m_warnNUreported = true;
1198  }
1199 
1200  m_warnNU = true;
1201  return 0;
1202  }
1203  else if(warn == "NJ")
1204  {
1205  if(!m_warnNJreported)
1206  {
1207  MagAOXAppT::log<text_log>(m_name + " Joystick Calibrating (NJ): Joystick calibration is in progress." , logPrio::LOG_WARNING);
1208  m_warnNJreported = true;
1209  }
1210 
1211  m_warnNJ = true;
1212  return 0;
1213  }
1214  else
1215  {
1216  MagAOXAppT::log<software_warning>({__FILE__, __LINE__, m_name + " unknown stage warning: " + warn});
1217 
1218  m_warnUNK = true;
1219 
1220  return 0;
1221  }
1222 
1223  return -1;
1224 }
1225 
1226 template<class parentT>
1227 int zaberStage<parentT>::parseWarnings( std::string & response )
1228 {
1229  size_t nwarn = std::stoi( response.substr(0, 2));
1230 
1231  if(nwarn > 0) m_warn = true;
1232 
1233  for(size_t n =0; n< nwarn; ++n)
1234  {
1235  if(response.size() < 3 + n*3)
1236  {
1237  if(m_parent)
1238  {
1239  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1240  }
1241 
1242  MagAOXAppT::log<software_error>({__FILE__, __LINE__, "parsing incomplete warning response"});
1243  return -1;
1244  }
1245 
1246  std::string warn = response.substr(3 + n*3, 2);
1247 
1248  int rv = processWarning(warn);
1249  if(rv < 0)
1250  {
1251  if(m_parent)
1252  {
1253  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1254  }
1255 
1256  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1257  return -1;
1258  }
1259  }
1260 
1261  if(m_warnFDreported)
1262  {
1263  if(!m_warnFD)
1264  {
1265  m_warnFDreported = false;
1266  }
1267  }
1268 
1269  if(m_warnFQreported)
1270  {
1271  if(!m_warnFQ)
1272  {
1273  m_warnFQreported = false;
1274  }
1275  }
1276 
1277  if(m_warnFSreported)
1278  {
1279  if(!m_warnFS)
1280  {
1281  m_warnFSreported = false;
1282  }
1283  }
1284 
1285  if(m_warnFTreported)
1286  {
1287  if(!m_warnFT)
1288  {
1289  m_warnFTreported = false;
1290  }
1291  }
1292 
1293  if(m_warnFBreported)
1294  {
1295  if(!m_warnFB)
1296  {
1297  m_warnFBreported = false;
1298  }
1299  }
1300 
1301  if(m_warnFPreported)
1302  {
1303  if(!m_warnFP)
1304  {
1305  m_warnFPreported = false;
1306  }
1307  }
1308 
1309  if(m_warnFEreported)
1310  {
1311  if(!m_warnFE)
1312  {
1313  m_warnFEreported = false;
1314  }
1315  }
1316 
1317  if(m_warnWHreported)
1318  {
1319  if(!m_warnWH)
1320  {
1321  m_warnWHreported = false;
1322  }
1323  }
1324 
1325  if(m_warnWLreported)
1326  {
1327  if(!m_warnWL)
1328  {
1329  m_warnWLreported = false;
1330  }
1331  }
1332 
1333  if(m_warnWPreported)
1334  {
1335  if(!m_warnWP)
1336  {
1337  m_warnWPreported = false;
1338  }
1339  }
1340 
1341  if(m_warnWVreported)
1342  {
1343  if(!m_warnWV)
1344  {
1345  m_warnWVreported = false;
1346  }
1347  }
1348 
1349  if(m_warnWTreported)
1350  {
1351  if(!m_warnWT)
1352  {
1353  m_warnWTreported = false;
1354  }
1355  }
1356 
1357  if(m_warnWMreported)
1358  {
1359  if(!m_warnWM)
1360  {
1361  m_warnWMreported = false;
1362  }
1363  }
1364 
1365  if(m_warnWRreported)
1366  {
1367  if(!m_warnWR)
1368  {
1369  m_warnWRreported = false;
1370  }
1371  }
1372 
1373  if(m_warnNCreported)
1374  {
1375  if(!m_warnNC)
1376  {
1377  m_warnNCreported = false;
1378  }
1379  }
1380 
1381  if(m_warnNIreported)
1382  {
1383  if(!m_warnNI)
1384  {
1385  m_warnNIreported = false;
1386  }
1387  }
1388 
1389  if(m_warnNDreported)
1390  {
1391  if(!m_warnND)
1392  {
1393  m_warnNDreported = false;
1394  }
1395  }
1396 
1397  if(m_warnNUreported)
1398  {
1399  if(!m_warnNU)
1400  {
1401  m_warnNUreported = false;
1402  }
1403  }
1404 
1405  if(m_warnNJreported)
1406  {
1407  if(!m_warnNJ)
1408  {
1409  m_warnNJreported = false;
1410  }
1411  }
1412 
1413  return 0;
1414 
1415 }
1416 
1417 template<class parentT>
1419 {
1420  if(m_deviceAddress < 1)
1421  {
1422  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
1423  }
1424 
1425  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
1426  com += "warnings";
1427 
1428  std::string response;
1429 
1430  int rv = sendCommand(response, port, com);
1431 
1432  if(rv == 0)
1433  {
1434  if( m_commandStatus )
1435  {
1436  unsetWarnings(); //Clear all the flags before setting them to stay current.
1437  return parseWarnings(response);
1438 
1439  }
1440  else
1441  {
1442  if(m_parent)
1443  {
1444  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1445  }
1446 
1447  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "warnings Command Rejected"});
1448  return -1;
1449  }
1450  }
1451  else
1452  {
1453  if(m_parent)
1454  {
1455  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1456  }
1457 
1458  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1459  return -1;
1460  }
1461 }
1462 
1463 template<class parentT>
1465 {
1466  m_commandStatus = true; ///< The status of the last command sent. true = OK, false = RJ (rejected)
1467 
1468  m_deviceStatus = 'U'; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
1469 
1470  m_homing = false;
1471 
1472  //We don't 0 rawPos so it is retained
1473 
1474  m_tgtPos = 0; ///< The tgt position last sent to the device, in microsteps.
1475 
1476  m_temp = -999; ///< The driver temperature, in C.
1477 
1478  unsetWarnings();
1479  m_warnWRreported = false;
1480 
1481  return 0;
1482 }
1483 
1484 } //namespace app
1485 } //namespace MagAOX
1486 
1487 #endif //zaberStage_hpp
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1804
A class to manage the details of one stage in a Zaber system.
Definition: zaberStage.hpp:29
long m_maxPos
The max position allowed for the device, set by config. Will be set to no larger m_maxPosHW.
Definition: zaberStage.hpp:51
int getMaxPos(z_port port)
Definition: zaberStage.hpp:654
int serial(const std::string &s)
Set the device serial.
Definition: zaberStage.hpp:333
char deviceStatus()
Get the device status.
Definition: zaberStage.hpp:372
int axisNumber(const int &an)
Set the axis number.
Definition: zaberStage.hpp:359
int getWarnings(z_port port)
Get warnings from the device.
float m_temp
The driver temperature, in C.
Definition: zaberStage.hpp:53
long rawPos()
Get the current raw position, in counts.
Definition: zaberStage.hpp:384
int processWarning(std::string &warn)
Process a single warning from the device, setting the appropriate flag.
Definition: zaberStage.hpp:999
bool warn()
Get the status of the warning flag.
Definition: zaberStage.hpp:402
std::string name()
Get the device name.
Definition: zaberStage.hpp:314
int home(z_port port)
Definition: zaberStage.hpp:877
int stop(z_port port)
Definition: zaberStage.hpp:789
bool m_commandStatus
The status of the last command sent. true = OK, false = RJ (rejected)
Definition: zaberStage.hpp:41
long maxPos()
Get the max position, in counts.
Definition: zaberStage.hpp:396
bool homing()
Get the homing status.
Definition: zaberStage.hpp:378
long tgtPos()
Get the current tgt position, in counts.
Definition: zaberStage.hpp:390
int sendCommand(std::string &response, z_port port, const std::string &command)
Definition: zaberStage.hpp:594
int m_axisNumber
The axis number at the address (normally 0 in MagAO-X)
Definition: zaberStage.hpp:39
int deviceAddress(const int &da)
Set the device address.
Definition: zaberStage.hpp:346
int onPowerOff()
Clear all state so that when the system is powered back on we get the correct new state.
int moveAbs(z_port port, long rawPos)
Definition: zaberStage.hpp:922
int axisNumber()
Get the axis number.
Definition: zaberStage.hpp:353
zaberStage(parentT *parent)
Definition: zaberStage.hpp:101
long m_rawPos
The raw position reported by the device, in microsteps.
Definition: zaberStage.hpp:47
int updatePos(z_port port)
Definition: zaberStage.hpp:699
int parseWarnings(std::string &response)
Parse the warning response from the device.
std::string serial()
Get the device serial number.
Definition: zaberStage.hpp:327
bool commandStatus()
Get the command status.
Definition: zaberStage.hpp:366
long m_tgtPos
The tgt position last sent to the device, in microsteps.
Definition: zaberStage.hpp:49
int estop(z_port port)
Definition: zaberStage.hpp:833
std::string m_serial
The stage's serial number.
Definition: zaberStage.hpp:35
int updateTemp(z_port port)
Definition: zaberStage.hpp:744
int name(const std::string &n)
Set the device name.
Definition: zaberStage.hpp:320
int deviceAddress()
Get the device address.
Definition: zaberStage.hpp:340
int getResponse(std::string &response, const za_reply &rep)
Get a response from the device, after a command has been sent.
Definition: zaberStage.hpp:561
int m_deviceAddress
The device's address, a.k.a. its order in the chain.
Definition: zaberStage.hpp:37
char m_deviceStatus
Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
Definition: zaberStage.hpp:43
float temp()
Get the temperature, in C.
Definition: zaberStage.hpp:408
int getResponse(std::string &response, const std::string &repBuff)
Get a response from the device, after a command has been sent.
Definition: zaberStage.hpp:540
std::string m_name
The stage's name.
Definition: zaberStage.hpp:33
bool warningState()
Get the warning state.
Definition: zaberStage.hpp:414
int unsetWarnings()
Sets all warning flags to false.
Definition: zaberStage.hpp:970
Definition: dm.hpp:24
constexpr static logPrioT LOG_DEBUG2
Used for debugging, providing a 2nd level.
Definition: logPriority.hpp:55
constexpr static logPrioT LOG_EMERGENCY
Normal operations of the entire system should be shut down immediately.
Definition: logPriority.hpp:31
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
Definition: logPriority.hpp:43
Software ERR log entry.
@ Z_SUCCESS
Definition: z_common.h:65
@ Z_ERROR_TIMEOUT
Definition: z_common.h:78
int za_receive(z_port port, char *destination, int length)
Definition: za_serial.c:151
int za_decode(struct za_reply *destination, const char *reply, size_t sMaxSz)
Definition: za_serial.c:539
int za_send(z_port port, const char *command, size_t sMaxSz)
Definition: za_serial.c:112
Provides a set of functions for interacting with Zaber devices in the ASCII protocol.
char device_status[5]
Definition: za_serial.h:44
int device_address
Definition: za_serial.h:37
char reply_flags[3]
Definition: za_serial.h:42
char warning_flags[3]
Definition: za_serial.h:47
char response_data[128]
Definition: za_serial.h:50