API
 
Loading...
Searching...
No Matches
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
18namespace MagAOX
19{
20namespace app
21{
22
23/// A class to manage the details of one stage in a Zaber system.
24/**
25 * \ingroup zaberLowLevel
26 */
27template<class parentT>
29{
30protected:
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
97public:
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 */
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 */
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 */
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.
311};
312
313template<class parentT>
315{
316 return m_name;
317}
318
319template<class parentT>
320int zaberStage<parentT>::name( const std::string & n )
321{
322 m_name = n;
323 return 0;
324}
325
326template<class parentT>
328{
329 return m_serial;
330}
331
332template<class parentT>
333int zaberStage<parentT>::serial( const std::string & s )
334{
335 m_serial = s;
336 return 0;
337}
338
339template<class parentT>
341{
342 return m_deviceAddress;
343}
344
345template<class parentT>
347{
348 m_deviceAddress = da;
349 return 0;
350}
351
352template<class parentT>
354{
355 return m_axisNumber;
356}
357
358template<class parentT>
360{
361 m_axisNumber = an;
362 return 0;
363}
364
365template<class parentT>
367{
368 return m_commandStatus;
369}
370
371template<class parentT>
373{
374 return m_deviceStatus;
375}
376
377template<class parentT>
379{
380 return m_homing;
381}
382
383template<class parentT>
385{
386 return m_rawPos;
387}
388
389template<class parentT>
391{
392 return m_tgtPos;
393}
394
395template<class parentT>
397{
398 return m_maxPos;
399}
400
401template<class parentT>
403{
404 return m_warn;
405}
406
407template<class parentT>
409{
410 return m_temp;
411}
412
413template<class parentT>
415{
416 return m_warn;
417}
418
419template<class parentT>
421{
422 return m_warnFD;
423}
424
425template<class parentT>
427{
428 return m_warnFQ;
429}
430
431template<class parentT>
433{
434 return m_warnFS;
435}
436
437template<class parentT>
439{
440 return m_warnFT;
441}
442
443template<class parentT>
445{
446 return m_warnFB;
447}
448
449template<class parentT>
451{
452 return m_warnFP;
453}
454
455template<class parentT>
457{
458 return m_warnFE;
459}
460
461template<class parentT>
463{
464 return m_warnWH;
465}
466
467template<class parentT>
469{
470 return m_warnWL;
471}
472
473template<class parentT>
475{
476 return m_warnWP;
477}
478
479template<class parentT>
481{
482 return m_warnWV;
483}
484
485template<class parentT>
487{
488 return m_warnWT;
489}
490
491template<class parentT>
493{
494 return m_warnWM;
495}
496
497template<class parentT>
499{
500 return m_warnWR;
501}
502
503template<class parentT>
505{
506 return m_warnNC;
507}
508
509template<class parentT>
511{
512 return m_warnNI;
513}
514
515template<class parentT>
517{
518 return m_warnND;
519}
520
521template<class parentT>
523{
524 return m_warnNU;
525}
526
527template<class parentT>
529{
530 return m_warnNJ;
531}
532
533template<class parentT>
535{
536 return m_warnUNK;
537}
538
539template<class parentT>
540int 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
560template<class parentT>
561int 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
593template<class parentT>
594int 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
653template<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
698template<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
743template<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
788template<class parentT>
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
832template<class parentT>
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
876template<class parentT>
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
921template<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
969template<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
998template<class parentT>
999int 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
1226template<class parentT>
1227int 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
1417template<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
1463template<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.
A class to manage the details of one stage in a Zaber system.
long m_maxPos
The max position allowed for the device, set by config. Will be set to no larger m_maxPosHW.
int getMaxPos(z_port port)
int serial(const std::string &s)
Set the device serial.
char deviceStatus()
Get the device status.
int axisNumber(const int &an)
Set the axis number.
int getWarnings(z_port port)
Get warnings from the device.
float m_temp
The driver temperature, in C.
long rawPos()
Get the current raw position, in counts.
int processWarning(std::string &warn)
Process a single warning from the device, setting the appropriate flag.
bool warn()
Get the status of the warning flag.
std::string name()
Get the device name.
int home(z_port port)
int stop(z_port port)
bool m_commandStatus
The status of the last command sent. true = OK, false = RJ (rejected)
long maxPos()
Get the max position, in counts.
bool homing()
Get the homing status.
long tgtPos()
Get the current tgt position, in counts.
int sendCommand(std::string &response, z_port port, const std::string &command)
int m_axisNumber
The axis number at the address (normally 0 in MagAO-X)
int deviceAddress(const int &da)
Set the device address.
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)
int axisNumber()
Get the axis number.
zaberStage(parentT *parent)
long m_rawPos
The raw position reported by the device, in microsteps.
int updatePos(z_port port)
int parseWarnings(std::string &response)
Parse the warning response from the device.
std::string serial()
Get the device serial number.
bool commandStatus()
Get the command status.
long m_tgtPos
The tgt position last sent to the device, in microsteps.
int estop(z_port port)
std::string m_serial
The stage's serial number.
int updateTemp(z_port port)
int name(const std::string &n)
Set the device name.
int deviceAddress()
Get the device address.
int getResponse(std::string &response, const za_reply &rep)
Get a response from the device, after a command has been sent.
int m_deviceAddress
The device's address, a.k.a. its order in the chain.
char m_deviceStatus
Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
float temp()
Get the temperature, in C.
int getResponse(std::string &response, const std::string &repBuff)
Get a response from the device, after a command has been sent.
std::string m_name
The stage's name.
bool warningState()
Get the warning state.
int unsetWarnings()
Sets all warning flags to false.
Definition dm.hpp:24
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static constexpr logPrioT LOG_EMERGENCY
Normal operations of the entire system should be shut down immediately.
static constexpr logPrioT LOG_DEBUG2
Used for debugging, providing a 2nd level.
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