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 temperature, in C
194  /**
195  * \returns the current value of m_temp
196  */
197  float temp();
198 
199  /// Get the warning state
200  /**
201  * \returns the true if any warning flags are set.
202  */
203  bool warningState();
204 
205  bool warnFD();
206  bool warnFQ();
207  bool warnFS();
208  bool warnFT();
209  bool warnFB();
210  bool warnFP();
211  bool warnFE();
212  bool warnWH();
213  bool warnWL();
214  bool warnWP();
215  bool warnWV();
216  bool warnWT();
217  bool warnWM();
218  bool warnWR();
219  bool warnNC();
220  bool warnNI();
221  bool warnND();
222  bool warnNU();
223  bool warnNJ();
224  bool warnUNK();
225 
226  /// Get a response from the device, after a command has been sent.
227  /** Parses the standard parts of the response in this stage's fields,
228  * and extracts the response string.
229  *
230  * \returns 0 on success.
231  * \returns -1 on error.
232  */
233  int getResponse( std::string & response, ///< [out] the text response
234  const std::string & repBuff ///< [in] the reply buffer, not decoded.
235  );
236 
237  /// Get a response from the device, after a command has been sent.
238  /** Parses the standard parts of the response in this stages fields,
239  * and extracts the response string.
240  *
241  * \overload
242  *
243  * \returns 0 on success.
244  * \returns -1 on error.
245  */
246  int getResponse( std::string & response, ///< [out] the text response component
247  const za_reply & rep ///< [in] the decodedstage reply
248  );
249 
250  int sendCommand( std::string & response, ///< [out] the response received from the stage
251  z_port port, ///< [in] the port with which to communicate
252  const std::string & command ///< [in] the command to send
253  );
254 
255  int getMaxPos( z_port port /**< [in] the port with which to communicate */ );
256 
257  int updatePos( z_port port /**< [in] the port with which to communicate */ );
258 
259  int updateTemp( z_port port /**< [in] the port with which to communicate */ );
260 
261  int stop (z_port port );
262 
263  int estop (z_port port );
264 
265  int home( z_port port /**< [in] the port with which to communicate */ );
266 
267  int moveAbs( z_port port, ///< [in] the port with which to communicate
268  long rawPos ///< [in] the position to move to, in counts
269  );
270 
271  /// Sets all warning flags to false
272  /** This is not the same as clearing warnings on the device, this is just used for
273  * bookkeeping.
274  *
275  * \returns 0 on success (always)
276  */
278 
279  /// Process a single warning from the device, setting the appropriate flag.
280  /** Warnings are two ASCII characeters, e.g. "WR".
281  *
282  * \returns 0 if the warning is processed, including if it's not recognized.
283  * \returns -1 on an error, currently not possible.
284  */
285  int processWarning( std::string & warn /**< [in] the two-character warning flag */);
286 
287  /// Parse the warning response from the device.
288  /** Sends each warning flag to processWarning.
289  *
290  * \returns 0 on success
291  * \returns -1 on error
292  */
293  int parseWarnings(std::string & response /**< [in] the response from the warnings query*/);
294 
295  /// Get warnings from the device
296  /** Log entries will be made and flags will be set in this structure.
297  *
298  * \returns 0 on success
299  * \returns -1 on error.
300  */
301  int getWarnings( z_port port /**< [in] the port with which to communicate */ );
302 
303  /// Clear all state so that when the system is powered back on we get the correct new state.
304  int onPowerOff();
305 };
306 
307 template<class parentT>
309 {
310  return m_name;
311 }
312 
313 template<class parentT>
314 int zaberStage<parentT>::name( const std::string & n )
315 {
316  m_name = n;
317  return 0;
318 }
319 
320 template<class parentT>
322 {
323  return m_serial;
324 }
325 
326 template<class parentT>
327 int zaberStage<parentT>::serial( const std::string & s )
328 {
329  m_serial = s;
330  return 0;
331 }
332 
333 template<class parentT>
335 {
336  return m_deviceAddress;
337 }
338 
339 template<class parentT>
341 {
342  m_deviceAddress = da;
343  return 0;
344 }
345 
346 template<class parentT>
348 {
349  return m_axisNumber;
350 }
351 
352 template<class parentT>
353 int zaberStage<parentT>::axisNumber( const int & an )
354 {
355  m_axisNumber = an;
356  return 0;
357 }
358 
359 template<class parentT>
361 {
362  return m_commandStatus;
363 }
364 
365 template<class parentT>
367 {
368  return m_deviceStatus;
369 }
370 
371 template<class parentT>
373 {
374  return m_homing;
375 }
376 
377 template<class parentT>
379 {
380  return m_rawPos;
381 }
382 
383 template<class parentT>
385 {
386  return m_tgtPos;
387 }
388 
389 template<class parentT>
391 {
392  return m_maxPos;
393 }
394 
395 template<class parentT>
397 {
398  return m_temp;
399 }
400 
401 template<class parentT>
403 {
404  return m_warn;
405 }
406 
407 template<class parentT>
409 {
410  return m_warnFD;
411 }
412 
413 template<class parentT>
415 {
416  return m_warnFQ;
417 }
418 
419 template<class parentT>
421 {
422  return m_warnFS;
423 }
424 
425 template<class parentT>
427 {
428  return m_warnFT;
429 }
430 
431 template<class parentT>
433 {
434  return m_warnFB;
435 }
436 
437 template<class parentT>
439 {
440  return m_warnFP;
441 }
442 
443 template<class parentT>
445 {
446  return m_warnFE;
447 }
448 
449 template<class parentT>
451 {
452  return m_warnWH;
453 }
454 
455 template<class parentT>
457 {
458  return m_warnWL;
459 }
460 
461 template<class parentT>
463 {
464  return m_warnWP;
465 }
466 
467 template<class parentT>
469 {
470  return m_warnWV;
471 }
472 
473 template<class parentT>
475 {
476  return m_warnWT;
477 }
478 
479 template<class parentT>
481 {
482  return m_warnWM;
483 }
484 
485 template<class parentT>
487 {
488  return m_warnWR;
489 }
490 
491 template<class parentT>
493 {
494  return m_warnNC;
495 }
496 
497 template<class parentT>
499 {
500  return m_warnNI;
501 }
502 
503 template<class parentT>
505 {
506  return m_warnND;
507 }
508 
509 template<class parentT>
511 {
512  return m_warnNU;
513 }
514 
515 template<class parentT>
517 {
518  return m_warnNJ;
519 }
520 
521 template<class parentT>
523 {
524  return m_warnUNK;
525 }
526 
527 template<class parentT>
528 int zaberStage<parentT>::getResponse( std::string & response,
529  const std::string & repBuff
530  )
531 {
532  za_reply rep;
533  int rv = za_decode(&rep, repBuff.c_str());
534  if(rv != Z_SUCCESS)
535  {
536  if(m_parent)
537  {
538  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
539  }
540 
541  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "za_decode !=Z_SUCCESS"});
542  return rv;
543  }
544 
545  return getResponse(response, rep);
546 }
547 
548 template<class parentT>
549 int zaberStage<parentT>::getResponse( std::string & response,
550  const za_reply & rep
551  )
552 {
553  if(rep.device_address == m_deviceAddress)
554  {
555  if(rep.reply_flags[0] == 'O') m_commandStatus = true;
556  else m_commandStatus = false;
557 
558 
559  m_deviceStatus = rep.device_status[0];
560 
561  if(m_deviceStatus == 'I' && m_homing)
562  {
563  m_warnWR = false; //Clear preemptively
564  m_homing = false;
565  }
566 
567  if(rep.warning_flags[0] == '-') unsetWarnings();
568  else m_warn = true;;
569 
570  response = rep.response_data;
571 
572  return 0;
573  }
574  else
575  {
576  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "wrong device"});
577  return -1;
578  }
579 }
580 
581 template<class parentT>
582 int zaberStage<parentT>::sendCommand( std::string & response,
583  z_port port,
584  const std::string & command
585  )
586 {
587  MagAOXAppT::log<text_log>(std::string("Sending: ") + command, logPrio::LOG_DEBUG2);
588 
589  za_send(port, command.c_str());
590 
591  char buff[256];
592 
593  while(1)
594  {
595  int rv = za_receive(port, buff, sizeof(buff));
596  if(rv == Z_ERROR_TIMEOUT)
597  {
598  if(m_parent)
599  {
600  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
601  }
602 
603  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "Z_ERROR_TIMEOUT"});
604  break; //assume error and just get out.
605  }
606  else if(rv < 0)
607  {
608  if(m_parent)
609  {
610  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
611  }
612 
613  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_receive !=Z_SUCCESS"});
614  break;
615  }
616  za_reply rep;
617 
618 
619  MagAOXAppT::log<text_log>(std::string("Received: ") + buff, logPrio::LOG_DEBUG2);
620 
621  rv = za_decode(&rep, buff);
622  if(rv != Z_SUCCESS)
623  {
624  if(m_parent)
625  {
626  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
627  }
628 
629  MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_decode !=Z_SUCCESS"});
630  break;
631  }
632 
633  if(rep.device_address == m_deviceAddress) return getResponse(response, rep);
634  }
635 
636  response = "";
637 
638  return -1;
639 }
640 
641 template<class parentT>
643 {
644  if(m_deviceAddress < 1)
645  {
646  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
647  }
648 
649  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
650  com += "get limit.max";
651 
652  std::string response;
653 
654  int rv = sendCommand(response, port, com);
655 
656  if(rv == 0)
657  {
658  if( m_commandStatus )
659  {
660  m_maxPos = mx::ioutils::convertFromString<long>(response);
661  return 0;
662  }
663  else
664  {
665  if(m_parent)
666  {
667  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
668  }
669 
670  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get limit.max Command Rejected"});
671  return -1;
672  }
673  }
674  else
675  {
676  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
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  return -1;
683  }
684 }
685 
686 template<class parentT>
688 {
689  if(m_deviceAddress < 1)
690  {
691  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
692  }
693 
694  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
695  com += "get pos";
696 
697  std::string response;
698 
699  int rv = sendCommand(response, port, com);
700 
701  if(rv == 0)
702  {
703  if( m_commandStatus )
704  {
705  m_rawPos = mx::ioutils::convertFromString<long>(response);
706  return 0;
707  }
708  else
709  {
710  if(m_parent)
711  {
712  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
713  }
714 
715  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get pos Command Rejected"});
716  return -1;
717  }
718  }
719  else
720  {
721  if(m_parent)
722  {
723  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
724  }
725 
726  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
727  return -1;
728  }
729 }
730 
731 template<class parentT>
733 {
734  if(m_deviceAddress < 1)
735  {
736  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
737  }
738 
739  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
740  com += "get driver.temperature";
741 
742  std::string response;
743 
744  int rv = sendCommand(response, port, com);
745 
746  if(rv == 0)
747  {
748  if( m_commandStatus )
749  {
750  m_temp = mx::ioutils::convertFromString<float>(response);
751  return 0;
752  }
753  else
754  {
755  if(m_parent)
756  {
757  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
758  }
759 
760  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get driver.temperature Command Rejected"});
761  return -1;
762  }
763  }
764  else
765  {
766  if(m_parent)
767  {
768  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
769  }
770 
771  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
772  return -1;
773  }
774 }
775 
776 template<class parentT>
777 int zaberStage<parentT>::stop( z_port port )
778 {
779  if(m_deviceAddress < 1)
780  {
781  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
782  }
783 
784  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
785  com += "stop";
786 
787  std::string response;
788 
789  int rv = sendCommand(response, port, com);
790 
791  if(rv == 0)
792  {
793  if( m_commandStatus )
794  {
795  return 0;
796  }
797  else
798  {
799  if(m_parent)
800  {
801  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
802  }
803 
804  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " stop Command Rejected"});
805  return -1;
806  }
807  }
808  else
809  {
810  if(m_parent)
811  {
812  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
813  }
814 
815  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
816  return -1;
817  }
818 }
819 
820 template<class parentT>
821 int zaberStage<parentT>::estop( z_port port )
822 {
823  if(m_deviceAddress < 1)
824  {
825  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
826  }
827 
828  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
829  com += "estop";
830 
831  std::string response;
832 
833  int rv = sendCommand(response, port, com);
834 
835  if(rv == 0)
836  {
837  if( m_commandStatus )
838  {
839  return 0;
840  }
841  else
842  {
843  if(m_parent)
844  {
845  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
846  }
847 
848  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " estop Command Rejected"});
849  return -1;
850  }
851  }
852  else
853  {
854  if(m_parent)
855  {
856  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
857  }
858 
859  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
860  return -1;
861  }
862 }
863 
864 template<class parentT>
865 int zaberStage<parentT>::home( z_port port )
866 {
867  if(m_deviceAddress < 1)
868  {
869  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
870  }
871 
872  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
873  com += "home";
874 
875  std::string response;
876 
877  int rv = sendCommand(response, port, com);
878 
879  if(rv == 0)
880  {
881  if( m_commandStatus )
882  {
883  m_homing = true;
884  return 0;
885  }
886  else
887  {
888  if(m_parent)
889  {
890  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
891  }
892 
893  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "Home Command Rejected"});
894  return -1;
895  }
896  }
897  else
898  {
899  if(m_parent)
900  {
901  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
902  }
903 
904  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
905  return -1;
906  }
907 }
908 
909 template<class parentT>
911  long rawPos
912  )
913 {
914  if(m_deviceAddress < 1)
915  {
916  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
917  }
918 
919  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
920  com += "move abs " + std::to_string(rawPos);
921 
922  m_tgtPos = rawPos;
923 
924  std::string response;
925 
926  int rv = sendCommand(response, port, com);
927 
928  if(rv == 0)
929  {
930  if( m_commandStatus )
931  {
932  return 0;
933  }
934  else
935  {
936  if(m_parent)
937  {
938  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
939  }
940 
941  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "move abs Command Rejected"});
942  return -1;
943  }
944  }
945  else
946  {
947  if(m_parent)
948  {
949  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
950  }
951 
952  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
953  return -1;
954  }
955 }
956 
957 template<class parentT>
959 {
960  m_warn = false;
961 
962  m_warnFD = false;
963  m_warnFQ = false;
964  m_warnFS = false;
965  m_warnFT = false;
966  m_warnFB = false;
967  m_warnFP = false;
968  m_warnFE = false;
969  m_warnWH = false;
970  m_warnWL = false;
971  m_warnWP = false;
972  m_warnWV = false;
973  m_warnWT = false;
974  m_warnWM = false;
975  m_warnWR = false;
976  m_warnNC = false;
977  m_warnNI = false;
978  m_warnND = false;
979  m_warnNU = false;
980  m_warnNJ = false;
981  m_warnUNK = false;
982 
983  return 0;
984 }
985 
986 template<class parentT>
987 int zaberStage<parentT>::processWarning( std::string & warn )
988 {
989  if(warn == "FD")
990  {
991  MagAOXAppT::log<text_log>(m_name + " Driver Disabled (FD): The driver has disabled itself due to overheating." , logPrio::LOG_EMERGENCY);
992  m_warnFD = true;
993  return 0;
994  }
995  else if(warn == "FQ")
996  {
997  MagAOXAppT::log<text_log>(m_name + " Encoder Error (FQ): The encoder-measured position may be unreliable. [home recommended]" , logPrio::LOG_WARNING);
998  m_warnFQ = true;
999  return 0;
1000  }
1001  else if(warn == "FS")
1002  {
1003  MagAOXAppT::log<text_log>(m_name + " Stalled and Stopped (FS): Stalling was detected and the axis has stopped itself. " , logPrio::LOG_WARNING);
1004  m_warnFS = true;
1005  return 0;
1006  }
1007  else if(warn == "FT")
1008  {
1009  MagAOXAppT::log<text_log>(m_name + " Excessive Twist (FT): The lockstep group has exceeded allowable twist and has stopped. " , logPrio::LOG_WARNING);
1010  m_warnFT = true;
1011  return 0;
1012  }
1013  else if(warn == "FB")
1014  {
1015  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);
1016  m_warnFB = true;
1017  return 0;
1018  }
1019  else if(warn == "FP")
1020  {
1021  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);
1022  m_warnFP = true;
1023  return 0;
1024  }
1025  else if(warn == "FE")
1026  {
1027  MagAOXAppT::log<text_log>(m_name + " Limit Error (FE): The target limit sensor cannot be reached or is faulty. " , logPrio::LOG_WARNING);
1028  m_warnFE = true;
1029  return 0;
1030  }
1031  else if(warn == "WH")
1032  {
1033  if(m_warnWHreported == false)
1034  {
1035  MagAOXAppT::log<text_log>(m_name + " Device not homed (WH): The device has a position reference, but has not been homed." , logPrio::LOG_WARNING);
1036  m_warnWHreported = true;
1037  }
1038  m_warnWH = true;
1039  return 0;
1040  }
1041  else if(warn == "WL")
1042  {
1043  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);
1044  m_warnWL = true;
1045  return 0;
1046  }
1047  else if(warn == "WP")
1048  {
1049  MagAOXAppT::log<text_log>(m_name + " Invalid calibration type (WP): The saved calibration data type is unsupported" , logPrio::LOG_WARNING);
1050  m_warnWP = true;
1051  return 0;
1052  }
1053  else if(warn == "WV")
1054  {
1055  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);
1056  m_warnWV = true;
1057  return 0;
1058  }
1059  else if(warn == "WT")
1060  {
1061  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);
1062  m_warnWT = true;
1063  return 0;
1064  }
1065  else if(warn == "WM")
1066  {
1067  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);
1068  m_warnWM = true;
1069  return 0;
1070  }
1071  else if(warn == "WR")
1072  {
1073  if(m_warnWRreported == false)
1074  {
1075  //MagAOXAppT::log<text_log>(m_name + " No Reference Position (WR): Axis has not had a reference position established. [homing required]" , logPrio::LOG_WARNING);
1076  m_warnWRreported = true;
1077  }
1078  m_warnWR = true;
1079  return 0;
1080  }
1081  else if(warn == "NC")
1082  {
1083  MagAOXAppT::log<text_log>(m_name + " Manual Control (NC): Axis is busy due to manual control via the knob." , logPrio::LOG_WARNING);
1084  m_warnNC = true;
1085  return 0;
1086  }
1087  else if(warn == "NI")
1088  {
1089  if(m_parent)
1090  {
1091  if(m_homing == true || warnWR()) return 0; //ignore this during homing
1092  }
1093  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);
1094  m_warnNI = true;
1095  return 0;
1096  }
1097  else if(warn == "ND")
1098  {
1099  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);
1100  m_warnND = true;
1101  return 0;
1102  }
1103  else if(warn == "NU")
1104  {
1105  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);
1106  m_warnNU = true;
1107  return 0;
1108  }
1109  else if(warn == "NJ")
1110  {
1111  MagAOXAppT::log<text_log>(m_name + " Joystick Calibrating (NJ): Joystick calibration is in progress." , logPrio::LOG_WARNING);
1112  m_warnNJ = true;
1113  return 0;
1114  }
1115  else
1116  {
1117  m_warnUNK = true;
1118  MagAOXAppT::log<software_warning>({__FILE__, __LINE__, m_name + " unknown stage warning: " + warn});
1119  return 0;
1120  }
1121 
1122  return -1;
1123 }
1124 
1125 template<class parentT>
1126 int zaberStage<parentT>::parseWarnings( std::string & response )
1127 {
1128  size_t nwarn = std::stoi( response.substr(0, 2));
1129 
1130  if(nwarn > 0) m_warn = true;
1131 
1132  for(size_t n =0; n< nwarn; ++n)
1133  {
1134  if(response.size() < 3 + n*3)
1135  {
1136  if(m_parent)
1137  {
1138  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1139  }
1140 
1141  MagAOXAppT::log<software_error>({__FILE__, __LINE__, "parsing incomplete warning response"});
1142  return -1;
1143  }
1144 
1145  std::string warn = response.substr(3 + n*3, 2);
1146 
1147  int rv = processWarning(warn);
1148  if(rv < 0)
1149  {
1150  if(m_parent)
1151  {
1152  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1153  }
1154 
1155  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1156  return -1;
1157  }
1158  }
1159 
1160 
1161  if(m_warnWHreported)
1162  {
1163  if(!m_warnWH) m_warnWHreported = false;
1164  }
1165 
1166  if(m_warnWRreported)
1167  {
1168  if(!m_warnWR)
1169  {
1170  //MagAOXAppT::log<text_log>(m_name + " homed. WR clear." , logPrio::LOG_NOTICE);
1171  m_warnWRreported = false;
1172  }
1173  }
1174 
1175  return 0;
1176 
1177 }
1178 
1179 template<class parentT>
1181 {
1182  if(m_deviceAddress < 1)
1183  {
1184  return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
1185  }
1186 
1187  std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
1188  com += "warnings";
1189 
1190  std::string response;
1191 
1192  int rv = sendCommand(response, port, com);
1193 
1194  if(rv == 0)
1195  {
1196  if( m_commandStatus )
1197  {
1198  unsetWarnings(); //Clear all the flags before setting them to stay current.
1199  return parseWarnings(response);
1200 
1201  }
1202  else
1203  {
1204  if(m_parent)
1205  {
1206  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1207  }
1208 
1209  MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "warnings Command Rejected"});
1210  return -1;
1211  }
1212  }
1213  else
1214  {
1215  if(m_parent)
1216  {
1217  if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1218  }
1219 
1220  MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1221  return -1;
1222  }
1223 }
1224 
1225 template<class parentT>
1227 {
1228  m_commandStatus = true; ///< The status of the last command sent. true = OK, false = RJ (rejected)
1229 
1230  m_deviceStatus = 'U'; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
1231 
1232  m_homing = false;
1233 
1234  //We don't 0 rawPos so it is retained
1235 
1236  m_tgtPos = 0; ///< The tgt position last sent to the device, in microsteps.
1237 
1238  m_temp = -999; ///< The driver temperature, in C.
1239 
1240  unsetWarnings();
1241  m_warnWRreported = false;
1242 
1243  return 0;
1244 }
1245 
1246 } //namespace app
1247 } //namespace MagAOX
1248 
1249 #endif //zaberStage_hpp
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1590
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:642
int serial(const std::string &s)
Set the device serial.
Definition: zaberStage.hpp:327
char deviceStatus()
Get the device status.
Definition: zaberStage.hpp:366
int axisNumber(const int &an)
Set the axis number.
Definition: zaberStage.hpp:353
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:378
int processWarning(std::string &warn)
Process a single warning from the device, setting the appropriate flag.
Definition: zaberStage.hpp:987
std::string name()
Get the device name.
Definition: zaberStage.hpp:308
int home(z_port port)
Definition: zaberStage.hpp:865
int stop(z_port port)
Definition: zaberStage.hpp:777
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:390
bool homing()
Get the homing status.
Definition: zaberStage.hpp:372
long tgtPos()
Get the current tgt position, in counts.
Definition: zaberStage.hpp:384
int sendCommand(std::string &response, z_port port, const std::string &command)
Definition: zaberStage.hpp:582
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:340
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:910
int axisNumber()
Get the axis number.
Definition: zaberStage.hpp:347
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:687
int parseWarnings(std::string &response)
Parse the warning response from the device.
std::string serial()
Get the device serial number.
Definition: zaberStage.hpp:321
bool commandStatus()
Get the command status.
Definition: zaberStage.hpp:360
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:821
std::string m_serial
The stage's serial number.
Definition: zaberStage.hpp:35
int updateTemp(z_port port)
Definition: zaberStage.hpp:732
int name(const std::string &n)
Set the device name.
Definition: zaberStage.hpp:314
int deviceAddress()
Get the device address.
Definition: zaberStage.hpp:334
int getResponse(std::string &response, const za_reply &rep)
Get a response from the device, after a command has been sent.
Definition: zaberStage.hpp:549
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:396
int getResponse(std::string &response, const std::string &repBuff)
Get a response from the device, after a command has been sent.
Definition: zaberStage.hpp:528
std::string m_name
The stage's name.
Definition: zaberStage.hpp:33
bool warningState()
Get the warning state.
Definition: zaberStage.hpp:402
int unsetWarnings()
Sets all warning flags to false.
Definition: zaberStage.hpp:958
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_decode(struct za_reply *destination, const char *reply)
Definition: za_serial.c:527
int za_receive(z_port port, char *destination, int length)
Definition: za_serial.c:148
int za_send(z_port port, const char *command)
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