Line data Source code
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>
28 : class zaberStage
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 6 : zaberStage( parentT * parent)
102 6 : {
103 6 : m_parent = parent;
104 6 : }
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 : */
135 : int deviceAddress();
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 : */
161 : bool commandStatus();
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 : */
283 : int unsetWarnings();
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>
314 0 : std::string zaberStage<parentT>::name()
315 : {
316 0 : return m_name;
317 : }
318 :
319 : template<class parentT>
320 0 : int zaberStage<parentT>::name( const std::string & n )
321 : {
322 0 : m_name = n;
323 0 : return 0;
324 : }
325 :
326 : template<class parentT>
327 0 : std::string zaberStage<parentT>::serial()
328 : {
329 0 : return m_serial;
330 : }
331 :
332 : template<class parentT>
333 0 : int zaberStage<parentT>::serial( const std::string & s )
334 : {
335 0 : m_serial = s;
336 0 : return 0;
337 : }
338 :
339 : template<class parentT>
340 0 : int zaberStage<parentT>::deviceAddress()
341 : {
342 0 : return m_deviceAddress;
343 : }
344 :
345 : template<class parentT>
346 0 : int zaberStage<parentT>::deviceAddress( const int & da )
347 : {
348 0 : m_deviceAddress = da;
349 0 : return 0;
350 : }
351 :
352 : template<class parentT>
353 : int zaberStage<parentT>::axisNumber()
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>
366 : bool zaberStage<parentT>::commandStatus()
367 : {
368 : return m_commandStatus;
369 : }
370 :
371 : template<class parentT>
372 0 : char zaberStage<parentT>::deviceStatus()
373 : {
374 0 : return m_deviceStatus;
375 : }
376 :
377 : template<class parentT>
378 0 : bool zaberStage<parentT>::homing()
379 : {
380 0 : return m_homing;
381 : }
382 :
383 : template<class parentT>
384 0 : long zaberStage<parentT>::rawPos()
385 : {
386 0 : return m_rawPos;
387 : }
388 :
389 : template<class parentT>
390 0 : long zaberStage<parentT>::tgtPos()
391 : {
392 0 : return m_tgtPos;
393 : }
394 :
395 : template<class parentT>
396 0 : long zaberStage<parentT>::maxPos()
397 : {
398 0 : return m_maxPos;
399 : }
400 :
401 : template<class parentT>
402 0 : bool zaberStage<parentT>::warn()
403 : {
404 0 : return m_warn;
405 : }
406 :
407 : template<class parentT>
408 0 : float zaberStage<parentT>::temp()
409 : {
410 0 : return m_temp;
411 : }
412 :
413 : template<class parentT>
414 6 : bool zaberStage<parentT>::warningState()
415 : {
416 6 : return m_warn;
417 : }
418 :
419 : template<class parentT>
420 6 : bool zaberStage<parentT>::warnFD()
421 : {
422 6 : return m_warnFD;
423 : }
424 :
425 : template<class parentT>
426 6 : bool zaberStage<parentT>::warnFQ()
427 : {
428 6 : return m_warnFQ;
429 : }
430 :
431 : template<class parentT>
432 6 : bool zaberStage<parentT>::warnFS()
433 : {
434 6 : return m_warnFS;
435 : }
436 :
437 : template<class parentT>
438 6 : bool zaberStage<parentT>::warnFT()
439 : {
440 6 : return m_warnFT;
441 : }
442 :
443 : template<class parentT>
444 6 : bool zaberStage<parentT>::warnFB()
445 : {
446 6 : return m_warnFB;
447 : }
448 :
449 : template<class parentT>
450 6 : bool zaberStage<parentT>::warnFP()
451 : {
452 6 : return m_warnFP;
453 : }
454 :
455 : template<class parentT>
456 6 : bool zaberStage<parentT>::warnFE()
457 : {
458 6 : return m_warnFE;
459 : }
460 :
461 : template<class parentT>
462 6 : bool zaberStage<parentT>::warnWH()
463 : {
464 6 : return m_warnWH;
465 : }
466 :
467 : template<class parentT>
468 6 : bool zaberStage<parentT>::warnWL()
469 : {
470 6 : return m_warnWL;
471 : }
472 :
473 : template<class parentT>
474 6 : bool zaberStage<parentT>::warnWP()
475 : {
476 6 : return m_warnWP;
477 : }
478 :
479 : template<class parentT>
480 6 : bool zaberStage<parentT>::warnWV()
481 : {
482 6 : return m_warnWV;
483 : }
484 :
485 : template<class parentT>
486 6 : bool zaberStage<parentT>::warnWT()
487 : {
488 6 : return m_warnWT;
489 : }
490 :
491 : template<class parentT>
492 6 : bool zaberStage<parentT>::warnWM()
493 : {
494 6 : return m_warnWM;
495 : }
496 :
497 : template<class parentT>
498 7 : bool zaberStage<parentT>::warnWR()
499 : {
500 7 : return m_warnWR;
501 : }
502 :
503 : template<class parentT>
504 6 : bool zaberStage<parentT>::warnNC()
505 : {
506 6 : return m_warnNC;
507 : }
508 :
509 : template<class parentT>
510 6 : bool zaberStage<parentT>::warnNI()
511 : {
512 6 : return m_warnNI;
513 : }
514 :
515 : template<class parentT>
516 6 : bool zaberStage<parentT>::warnND()
517 : {
518 6 : return m_warnND;
519 : }
520 :
521 : template<class parentT>
522 6 : bool zaberStage<parentT>::warnNU()
523 : {
524 6 : return m_warnNU;
525 : }
526 :
527 : template<class parentT>
528 6 : bool zaberStage<parentT>::warnNJ()
529 : {
530 6 : return m_warnNJ;
531 : }
532 :
533 : template<class parentT>
534 6 : bool zaberStage<parentT>::warnUNK()
535 : {
536 6 : 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 0 : int zaberStage<parentT>::getResponse( std::string & response,
562 : const za_reply & rep
563 : )
564 : {
565 0 : if(rep.device_address == m_deviceAddress)
566 : {
567 0 : if(rep.reply_flags[0] == 'O') m_commandStatus = true;
568 0 : else m_commandStatus = false;
569 :
570 :
571 0 : m_deviceStatus = rep.device_status[0];
572 :
573 0 : if(m_deviceStatus == 'I' && m_homing)
574 : {
575 0 : m_warnWR = false; //Clear preemptively
576 0 : m_homing = false;
577 : }
578 :
579 0 : if(rep.warning_flags[0] == '-') unsetWarnings();
580 0 : else m_warn = true;
581 :
582 0 : response = rep.response_data;
583 :
584 0 : return 0;
585 : }
586 : else
587 : {
588 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "wrong device"});
589 0 : return -1;
590 : }
591 : }
592 :
593 : template<class parentT>
594 0 : int zaberStage<parentT>::sendCommand( std::string & response,
595 : z_port port,
596 : const std::string & command
597 : )
598 : {
599 0 : MagAOXAppT::log<text_log>(std::string("Sending: ") + command, logPrio::LOG_DEBUG2);
600 :
601 0 : za_send(port, command.c_str(), command.size());
602 :
603 : char buff[256];
604 :
605 0 : while(1)
606 : {
607 0 : int rv = za_receive(port, buff, sizeof(buff));
608 0 : if(rv == Z_ERROR_TIMEOUT)
609 : {
610 0 : if(m_parent)
611 : {
612 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
613 : }
614 :
615 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "Z_ERROR_TIMEOUT"});
616 0 : break; //assume error and just get out.
617 : }
618 0 : else if(rv < 0)
619 : {
620 0 : if(m_parent)
621 : {
622 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
623 : }
624 :
625 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_receive !=Z_SUCCESS"});
626 0 : break;
627 : }
628 : za_reply rep;
629 :
630 :
631 0 : MagAOXAppT::log<text_log>(std::string("Received: ") + buff, logPrio::LOG_DEBUG2);
632 :
633 0 : rv = za_decode(&rep, buff, sizeof(buff));
634 0 : if(rv != Z_SUCCESS)
635 : {
636 0 : if(m_parent)
637 : {
638 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return rv; //don't log, but propagate error
639 : }
640 :
641 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, 0, "za_decode !=Z_SUCCESS"});
642 0 : break;
643 : }
644 :
645 0 : if(rep.device_address == m_deviceAddress) return getResponse(response, rep);
646 : }
647 :
648 0 : response = "";
649 :
650 0 : return -1;
651 : }
652 :
653 : template<class parentT>
654 0 : int zaberStage<parentT>::getMaxPos( z_port port )
655 : {
656 0 : if(m_deviceAddress < 1)
657 : {
658 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
659 : }
660 :
661 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
662 0 : com += "get limit.max";
663 :
664 0 : std::string response;
665 :
666 0 : int rv = sendCommand(response, port, com);
667 :
668 0 : if(rv == 0)
669 : {
670 0 : if( m_commandStatus )
671 : {
672 0 : m_maxPos = mx::ioutils::convertFromString<long>(response);
673 0 : return 0;
674 : }
675 : else
676 : {
677 0 : if(m_parent)
678 : {
679 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
680 : }
681 :
682 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get limit.max Command Rejected"});
683 0 : return -1;
684 : }
685 : }
686 : else
687 : {
688 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
689 0 : if(m_parent)
690 : {
691 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
692 : }
693 :
694 0 : return -1;
695 : }
696 0 : }
697 :
698 : template<class parentT>
699 0 : int zaberStage<parentT>::updatePos( z_port port )
700 : {
701 0 : if(m_deviceAddress < 1)
702 : {
703 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
704 : }
705 :
706 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
707 0 : com += "get pos";
708 :
709 0 : std::string response;
710 :
711 0 : int rv = sendCommand(response, port, com);
712 :
713 0 : if(rv == 0)
714 : {
715 0 : if( m_commandStatus )
716 : {
717 0 : m_rawPos = mx::ioutils::convertFromString<long>(response);
718 0 : return 0;
719 : }
720 : else
721 : {
722 0 : if(m_parent)
723 : {
724 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
725 : }
726 :
727 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get pos Command Rejected"});
728 0 : return -1;
729 : }
730 : }
731 : else
732 : {
733 0 : if(m_parent)
734 : {
735 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
736 : }
737 :
738 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
739 0 : return -1;
740 : }
741 0 : }
742 :
743 : template<class parentT>
744 0 : int zaberStage<parentT>::updateTemp( z_port port )
745 : {
746 0 : if(m_deviceAddress < 1)
747 : {
748 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
749 : }
750 :
751 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
752 0 : com += "get driver.temperature";
753 :
754 0 : std::string response;
755 :
756 0 : int rv = sendCommand(response, port, com);
757 :
758 0 : if(rv == 0)
759 : {
760 0 : if( m_commandStatus )
761 : {
762 0 : m_temp = mx::ioutils::convertFromString<float>(response);
763 0 : return 0;
764 : }
765 : else
766 : {
767 0 : if(m_parent)
768 : {
769 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
770 : }
771 :
772 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "get driver.temperature Command Rejected"});
773 0 : return -1;
774 : }
775 : }
776 : else
777 : {
778 0 : if(m_parent)
779 : {
780 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
781 : }
782 :
783 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
784 0 : return -1;
785 : }
786 0 : }
787 :
788 : template<class parentT>
789 0 : int zaberStage<parentT>::stop( z_port port )
790 : {
791 0 : if(m_deviceAddress < 1)
792 : {
793 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
794 : }
795 :
796 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
797 0 : com += "stop";
798 :
799 0 : std::string response;
800 :
801 0 : int rv = sendCommand(response, port, com);
802 :
803 0 : if(rv == 0)
804 : {
805 0 : if( m_commandStatus )
806 : {
807 0 : return 0;
808 : }
809 : else
810 : {
811 0 : if(m_parent)
812 : {
813 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
814 : }
815 :
816 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " stop Command Rejected"});
817 0 : return -1;
818 : }
819 : }
820 : else
821 : {
822 0 : if(m_parent)
823 : {
824 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
825 : }
826 :
827 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
828 0 : return -1;
829 : }
830 0 : }
831 :
832 : template<class parentT>
833 0 : int zaberStage<parentT>::estop( z_port port )
834 : {
835 0 : if(m_deviceAddress < 1)
836 : {
837 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
838 : }
839 :
840 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
841 0 : com += "estop";
842 :
843 0 : std::string response;
844 :
845 0 : int rv = sendCommand(response, port, com);
846 :
847 0 : if(rv == 0)
848 : {
849 0 : if( m_commandStatus )
850 : {
851 0 : return 0;
852 : }
853 : else
854 : {
855 0 : if(m_parent)
856 : {
857 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
858 : }
859 :
860 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + " estop Command Rejected"});
861 0 : return -1;
862 : }
863 : }
864 : else
865 : {
866 0 : if(m_parent)
867 : {
868 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
869 : }
870 :
871 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
872 0 : return -1;
873 : }
874 0 : }
875 :
876 : template<class parentT>
877 0 : int zaberStage<parentT>::home( z_port port )
878 : {
879 0 : if(m_deviceAddress < 1)
880 : {
881 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
882 : }
883 :
884 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
885 0 : com += "home";
886 :
887 0 : std::string response;
888 :
889 0 : int rv = sendCommand(response, port, com);
890 :
891 0 : if(rv == 0)
892 : {
893 0 : if( m_commandStatus )
894 : {
895 0 : m_homing = true;
896 0 : return 0;
897 : }
898 : else
899 : {
900 0 : if(m_parent)
901 : {
902 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
903 : }
904 :
905 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "Home Command Rejected"});
906 0 : return -1;
907 : }
908 : }
909 : else
910 : {
911 0 : if(m_parent)
912 : {
913 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
914 : }
915 :
916 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
917 0 : return -1;
918 : }
919 0 : }
920 :
921 : template<class parentT>
922 0 : int zaberStage<parentT>::moveAbs( z_port port,
923 : long rawPos
924 : )
925 : {
926 0 : if(m_deviceAddress < 1)
927 : {
928 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
929 : }
930 :
931 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
932 0 : com += "move abs " + std::to_string(rawPos);
933 :
934 0 : m_tgtPos = rawPos;
935 :
936 0 : std::string response;
937 :
938 0 : int rv = sendCommand(response, port, com);
939 :
940 0 : if(rv == 0)
941 : {
942 0 : if( m_commandStatus )
943 : {
944 0 : return 0;
945 : }
946 : else
947 : {
948 0 : if(m_parent)
949 : {
950 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
951 : }
952 :
953 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, m_name + "move abs Command Rejected"});
954 0 : return -1;
955 : }
956 : }
957 : else
958 : {
959 0 : if(m_parent)
960 : {
961 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
962 : }
963 :
964 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
965 0 : return -1;
966 : }
967 0 : }
968 :
969 : template<class parentT>
970 0 : int zaberStage<parentT>::unsetWarnings()
971 : {
972 0 : m_warn = false;
973 :
974 0 : m_warnFD = false;
975 0 : m_warnFQ = false;
976 0 : m_warnFS = false;
977 0 : m_warnFT = false;
978 0 : m_warnFB = false;
979 0 : m_warnFP = false;
980 0 : m_warnFE = false;
981 0 : m_warnWH = false;
982 0 : m_warnWL = false;
983 0 : m_warnWP = false;
984 0 : m_warnWV = false;
985 0 : m_warnWT = false;
986 0 : m_warnWM = false;
987 0 : m_warnWR = false;
988 0 : m_warnNC = false;
989 0 : m_warnNI = false;
990 0 : m_warnND = false;
991 0 : m_warnNU = false;
992 0 : m_warnNJ = false;
993 0 : m_warnUNK = false;
994 :
995 0 : return 0;
996 : }
997 :
998 : template<class parentT>
999 21 : int zaberStage<parentT>::processWarning( std::string & warn )
1000 : {
1001 21 : if(warn == "FD")
1002 : {
1003 1 : if(!m_warnFDreported)
1004 : {
1005 1 : MagAOXAppT::log<text_log>(m_name + " Driver Disabled (FD): The driver has disabled itself due to overheating." , logPrio::LOG_EMERGENCY);
1006 1 : m_warnFDreported = true;
1007 : }
1008 :
1009 1 : m_warnFD = true;
1010 1 : return 0;
1011 : }
1012 20 : else if(warn == "FQ")
1013 : {
1014 1 : if(!m_warnFQreported)
1015 : {
1016 1 : MagAOXAppT::log<text_log>(m_name + " warning FQ: you should probably check." , logPrio::LOG_EMERGENCY);
1017 1 : m_warnFQreported = true;
1018 : }
1019 :
1020 1 : m_warnFQ = true;
1021 1 : return 0;
1022 : }
1023 19 : else if(warn == "FS")
1024 : {
1025 1 : if(!m_warnFSreported)
1026 : {
1027 1 : MagAOXAppT::log<text_log>(m_name + " Stalled and Stopped (FS): Stalling was detected and the axis has stopped itself. " , logPrio::LOG_WARNING);
1028 1 : m_warnFSreported = true;
1029 : }
1030 1 : m_warnFS = true;
1031 1 : return 0;
1032 : }
1033 18 : else if(warn == "FT")
1034 : {
1035 1 : if(!m_warnFTreported)
1036 : {
1037 1 : MagAOXAppT::log<text_log>(m_name + " Excessive Twist (FT): The lockstep group has exceeded allowable twist and has stopped. " , logPrio::LOG_WARNING);
1038 1 : m_warnFTreported = true;
1039 : }
1040 :
1041 1 : m_warnFT = true;
1042 1 : return 0;
1043 : }
1044 17 : else if(warn == "FB")
1045 : {
1046 1 : if(!m_warnFBreported)
1047 : {
1048 1 : 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 1 : m_warnFBreported = true;
1050 : }
1051 :
1052 1 : m_warnFB = true;
1053 1 : return 0;
1054 : }
1055 16 : else if(warn == "FP")
1056 : {
1057 1 : if(!m_warnFPreported)
1058 : {
1059 1 : 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 1 : m_warnFPreported = true;
1061 : }
1062 :
1063 1 : m_warnFP = true;
1064 1 : return 0;
1065 : }
1066 15 : else if(warn == "FE")
1067 : {
1068 1 : if(!m_warnFEreported)
1069 : {
1070 1 : MagAOXAppT::log<text_log>(m_name + " Limit Error (FE): The target limit sensor cannot be reached or is faulty. " , logPrio::LOG_WARNING);
1071 1 : m_warnFEreported = true;
1072 : }
1073 :
1074 1 : m_warnFE = true;
1075 1 : return 0;
1076 : }
1077 14 : else if(warn == "WH")
1078 : {
1079 1 : if(m_warnWHreported == false)
1080 : {
1081 1 : 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 1 : m_warnWHreported = true;
1083 : }
1084 :
1085 1 : m_warnWH = true;
1086 1 : return 0;
1087 : }
1088 13 : else if(warn == "WL")
1089 : {
1090 1 : if(!m_warnWLreported)
1091 : {
1092 1 : 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 1 : m_warnWLreported = true;
1094 : }
1095 :
1096 1 : m_warnWL = true;
1097 1 : return 0;
1098 : }
1099 12 : else if(warn == "WP")
1100 : {
1101 1 : if(!m_warnWPreported)
1102 : {
1103 1 : MagAOXAppT::log<text_log>(m_name + " Invalid calibration type (WP): The saved calibration data type is unsupported" , logPrio::LOG_WARNING);
1104 1 : m_warnWPreported = true;
1105 : }
1106 :
1107 1 : m_warnWP = true;
1108 1 : return 0;
1109 : }
1110 11 : else if(warn == "WV")
1111 : {
1112 1 : if(!m_warnWVreported)
1113 : {
1114 1 : 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 1 : m_warnWVreported = true;
1116 : }
1117 :
1118 1 : m_warnWV = true;
1119 1 : return 0;
1120 : }
1121 10 : else if(warn == "WT")
1122 : {
1123 1 : if(!m_warnWTreported)
1124 : {
1125 1 : 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 1 : m_warnWTreported = true;
1127 : }
1128 :
1129 1 : m_warnWT = true;
1130 1 : return 0;
1131 : }
1132 9 : else if(warn == "WM")
1133 : {
1134 1 : if(m_warnWMreported == false)
1135 : {
1136 1 : 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 1 : m_warnWMreported = true;
1138 : }
1139 :
1140 1 : m_warnWM = true;
1141 1 : return 0;
1142 : }
1143 8 : else if(warn == "WR")
1144 : {
1145 2 : if(m_warnWRreported == false)
1146 : {
1147 2 : MagAOXAppT::log<text_log>(m_name + " No Reference Position (WR): Axis has not had a reference position established. [homing required]" , logPrio::LOG_WARNING);
1148 2 : m_warnWRreported = true;
1149 : }
1150 :
1151 2 : m_warnWR = true;
1152 2 : return 0;
1153 : }
1154 6 : else if(warn == "NC")
1155 : {
1156 1 : if(!m_warnNCreported)
1157 : {
1158 1 : MagAOXAppT::log<text_log>(m_name + " Manual Control (NC): Axis is busy due to manual control via the knob." , logPrio::LOG_WARNING);
1159 1 : m_warnNCreported = true;
1160 : }
1161 :
1162 1 : m_warnNC = true;
1163 1 : return 0;
1164 : }
1165 5 : else if(warn == "NI")
1166 : {
1167 1 : if(m_parent)
1168 : {
1169 1 : if(m_homing == true || warnWR()) return 0; //ignore this during homing
1170 : }
1171 :
1172 1 : if(!m_warnNIreported)
1173 : {
1174 1 : 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 1 : m_warnNIreported = true;
1176 : }
1177 :
1178 1 : m_warnNI = true;
1179 1 : return 0;
1180 : }
1181 4 : else if(warn == "ND")
1182 : {
1183 1 : if(!m_warnNDreported)
1184 : {
1185 1 : 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 1 : m_warnNDreported = true;
1187 : }
1188 :
1189 1 : m_warnND = true;
1190 1 : return 0;
1191 : }
1192 3 : else if(warn == "NU")
1193 : {
1194 1 : if(!m_warnNUreported)
1195 : {
1196 1 : 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 1 : m_warnNUreported = true;
1198 : }
1199 :
1200 1 : m_warnNU = true;
1201 1 : return 0;
1202 : }
1203 2 : else if(warn == "NJ")
1204 : {
1205 1 : if(!m_warnNJreported)
1206 : {
1207 1 : MagAOXAppT::log<text_log>(m_name + " Joystick Calibrating (NJ): Joystick calibration is in progress." , logPrio::LOG_WARNING);
1208 1 : m_warnNJreported = true;
1209 : }
1210 :
1211 1 : m_warnNJ = true;
1212 1 : return 0;
1213 : }
1214 : else
1215 : {
1216 1 : MagAOXAppT::log<software_warning>({__FILE__, __LINE__, m_name + " unknown stage warning: " + warn});
1217 :
1218 1 : m_warnUNK = true;
1219 :
1220 1 : return 0;
1221 : }
1222 :
1223 : return -1;
1224 : }
1225 :
1226 : template<class parentT>
1227 6 : int zaberStage<parentT>::parseWarnings( std::string & response )
1228 : {
1229 6 : size_t nwarn = std::stoi( response.substr(0, 2));
1230 :
1231 6 : if(nwarn > 0) m_warn = true;
1232 :
1233 48 : for(size_t n =0; n< nwarn; ++n)
1234 : {
1235 21 : if(response.size() < 3 + n*3)
1236 : {
1237 0 : if(m_parent)
1238 : {
1239 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1240 : }
1241 :
1242 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, "parsing incomplete warning response"});
1243 0 : return -1;
1244 : }
1245 :
1246 21 : std::string warn = response.substr(3 + n*3, 2);
1247 :
1248 21 : int rv = processWarning(warn);
1249 21 : if(rv < 0)
1250 : {
1251 0 : if(m_parent)
1252 : {
1253 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1254 : }
1255 :
1256 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1257 0 : return -1;
1258 : }
1259 : }
1260 :
1261 6 : if(m_warnFDreported)
1262 : {
1263 1 : if(!m_warnFD)
1264 : {
1265 0 : m_warnFDreported = false;
1266 : }
1267 : }
1268 :
1269 6 : if(m_warnFQreported)
1270 : {
1271 1 : if(!m_warnFQ)
1272 : {
1273 0 : m_warnFQreported = false;
1274 : }
1275 : }
1276 :
1277 6 : if(m_warnFSreported)
1278 : {
1279 1 : if(!m_warnFS)
1280 : {
1281 0 : m_warnFSreported = false;
1282 : }
1283 : }
1284 :
1285 6 : if(m_warnFTreported)
1286 : {
1287 1 : if(!m_warnFT)
1288 : {
1289 0 : m_warnFTreported = false;
1290 : }
1291 : }
1292 :
1293 6 : if(m_warnFBreported)
1294 : {
1295 1 : if(!m_warnFB)
1296 : {
1297 0 : m_warnFBreported = false;
1298 : }
1299 : }
1300 :
1301 6 : if(m_warnFPreported)
1302 : {
1303 1 : if(!m_warnFP)
1304 : {
1305 0 : m_warnFPreported = false;
1306 : }
1307 : }
1308 :
1309 6 : if(m_warnFEreported)
1310 : {
1311 1 : if(!m_warnFE)
1312 : {
1313 0 : m_warnFEreported = false;
1314 : }
1315 : }
1316 :
1317 6 : if(m_warnWHreported)
1318 : {
1319 1 : if(!m_warnWH)
1320 : {
1321 0 : m_warnWHreported = false;
1322 : }
1323 : }
1324 :
1325 6 : if(m_warnWLreported)
1326 : {
1327 1 : if(!m_warnWL)
1328 : {
1329 0 : m_warnWLreported = false;
1330 : }
1331 : }
1332 :
1333 6 : if(m_warnWPreported)
1334 : {
1335 1 : if(!m_warnWP)
1336 : {
1337 0 : m_warnWPreported = false;
1338 : }
1339 : }
1340 :
1341 6 : if(m_warnWVreported)
1342 : {
1343 1 : if(!m_warnWV)
1344 : {
1345 0 : m_warnWVreported = false;
1346 : }
1347 : }
1348 :
1349 6 : if(m_warnWTreported)
1350 : {
1351 1 : if(!m_warnWT)
1352 : {
1353 0 : m_warnWTreported = false;
1354 : }
1355 : }
1356 :
1357 6 : if(m_warnWMreported)
1358 : {
1359 1 : if(!m_warnWM)
1360 : {
1361 0 : m_warnWMreported = false;
1362 : }
1363 : }
1364 :
1365 6 : if(m_warnWRreported)
1366 : {
1367 2 : if(!m_warnWR)
1368 : {
1369 0 : m_warnWRreported = false;
1370 : }
1371 : }
1372 :
1373 6 : if(m_warnNCreported)
1374 : {
1375 1 : if(!m_warnNC)
1376 : {
1377 0 : m_warnNCreported = false;
1378 : }
1379 : }
1380 :
1381 6 : if(m_warnNIreported)
1382 : {
1383 1 : if(!m_warnNI)
1384 : {
1385 0 : m_warnNIreported = false;
1386 : }
1387 : }
1388 :
1389 6 : if(m_warnNDreported)
1390 : {
1391 1 : if(!m_warnND)
1392 : {
1393 0 : m_warnNDreported = false;
1394 : }
1395 : }
1396 :
1397 6 : if(m_warnNUreported)
1398 : {
1399 1 : if(!m_warnNU)
1400 : {
1401 0 : m_warnNUreported = false;
1402 : }
1403 : }
1404 :
1405 6 : if(m_warnNJreported)
1406 : {
1407 1 : if(!m_warnNJ)
1408 : {
1409 0 : m_warnNJreported = false;
1410 : }
1411 : }
1412 :
1413 6 : return 0;
1414 :
1415 : }
1416 :
1417 : template<class parentT>
1418 0 : int zaberStage<parentT>::getWarnings( z_port port )
1419 : {
1420 0 : if(m_deviceAddress < 1)
1421 : {
1422 0 : return MagAOXAppT::log<software_error, -1>({__FILE__, __LINE__, "stage " + m_name + " with with s/n " + m_serial + " not found in system."});
1423 : }
1424 :
1425 0 : std::string com = "/" + mx::ioutils::convertToString(m_deviceAddress) + " ";
1426 0 : com += "warnings";
1427 :
1428 0 : std::string response;
1429 :
1430 0 : int rv = sendCommand(response, port, com);
1431 :
1432 0 : if(rv == 0)
1433 : {
1434 0 : if( m_commandStatus )
1435 : {
1436 0 : unsetWarnings(); //Clear all the flags before setting them to stay current.
1437 0 : return parseWarnings(response);
1438 :
1439 : }
1440 : else
1441 : {
1442 0 : if(m_parent)
1443 : {
1444 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1445 : }
1446 :
1447 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__, rv, "warnings Command Rejected"});
1448 0 : return -1;
1449 : }
1450 : }
1451 : else
1452 : {
1453 0 : if(m_parent)
1454 : {
1455 0 : if(m_parent->powerState() != 1 || m_parent->powerStateTarget() != 1) return -1; //don't log, but propagate error
1456 : }
1457 :
1458 0 : MagAOXAppT::log<software_error>({__FILE__, __LINE__});
1459 0 : return -1;
1460 : }
1461 0 : }
1462 :
1463 : template<class parentT>
1464 0 : int zaberStage<parentT>::onPowerOff( )
1465 : {
1466 0 : m_commandStatus = true; ///< The status of the last command sent. true = OK, false = RJ (rejected)
1467 :
1468 0 : m_deviceStatus = 'U'; ///< Current status. Either 'I' for IDLE or 'B' for BUSY. Intializes to 'U' for UNKOWN.
1469 :
1470 0 : m_homing = false;
1471 :
1472 : //We don't 0 rawPos so it is retained
1473 :
1474 0 : m_tgtPos = 0; ///< The tgt position last sent to the device, in microsteps.
1475 :
1476 0 : m_temp = -999; ///< The driver temperature, in C.
1477 :
1478 0 : unsetWarnings();
1479 0 : m_warnWRreported = false;
1480 :
1481 0 : return 0;
1482 : }
1483 :
1484 : } //namespace app
1485 : } //namespace MagAOX
1486 :
1487 : #endif //zaberStage_hpp
|