API
 
Loading...
Searching...
No Matches
filterWheelCtrl.hpp
Go to the documentation of this file.
1/** \file filterWheelCtrl.hpp
2 * \brief The MagAO-X Filter Wheel Controller
3 *
4 * \ingroup filterWheelCtrl_files
5 */
6
7#ifndef filterWheelCtrl_hpp
8#define filterWheelCtrl_hpp
9
10#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
11#include "../../magaox_git_version.h"
12
13/** \defgroup filterWheelCtrl Filter Wheel Control
14 * \brief Control of MagAO-X MCBL-based f/w.
15 *
16 * <a href="../handbook/operating/software/apps/filterWheelCtrl.html">Application Documentation</a>
17 *
18 * \ingroup apps
19 *
20 */
21
22/** \defgroup filterWheelCtrl_files Filter Wheel Control Files
23 * \ingroup filterWheelCtrl
24 */
25
26namespace MagAOX
27{
28namespace app
29{
30
31/** MagAO-X application to control a Faulhaber MCBL controlled filter wheel.
32 *
33 * \todo add temperature monitoring
34 * \todo add INDI props to md doc
35 * \todo should move in least time direction, rather than always in the same direction.
36 * \todo add tests
37 * \todo should be an iodevice
38 *
39 * \ingroup filterWheelCtrl
40 */
41class filterWheelCtrl : public MagAOXApp<>,
42 public tty::usbDevice,
43 public dev::stdMotionStage<filterWheelCtrl>,
44 public dev::telemeter<filterWheelCtrl>
45{
46
48
49 friend class dev::telemeter<filterWheelCtrl>;
50
51 protected:
52 /** \name Non-configurable parameters
53 *@{
54 */
55
56 int m_motorType{ 2 };
57
58 ///@}
59
60 /** \name Configurable Parameters
61 * @{
62 */
63
64 int m_writeTimeOut{ 1000 }; ///< The timeout for writing to the device [msec].
65 int m_readTimeOut{ 1000 }; ///< The timeout for reading from the device [msec].
66
67 double m_acceleration{ 100 };
68 double m_deceleration{ 50 };
69 double m_motorSpeed{ 3000 };
70
71 long m_circleSteps{ 0 }; ///< The number of position counts in 1 360-degree revolution.
72 long m_homeOffset{ 0 }; ///< The number of position counts to offset from the home position
73
74 ///@}
75
76 /** \name Status
77 * @{
78 */
79
80 bool m_switch{ false }; ///< The home switch status
81
82 long m_rawPos{ 0 }; ///< The position of the wheel in motor counts.
83
84 int m_homingState{ 0 }; ///< The homing state, tracks the stages of homing.
85 ///@}
86
87 public:
88 /// Default c'tor.
90
91 /// D'tor, declared and defined for noexcept.
95
96 /// Setup the configuration system (called by MagAOXApp::setup())
97 virtual void setupConfig();
98
99 /// load the configuration system results (called by MagAOXApp::setup())
100 virtual void loadConfig();
101
102 /// Startup functions
103 /** Setsup the INDI vars.
104 *
105 * \returns 0 on success
106 * \returns -1 on error.
107 */
108 virtual int appStartup();
109
110 /// Implementation of the FSM for the TTM Modulator
111 /**
112 * \returns 0 on success
113 * \returns -1 on error.
114 */
115 virtual int appLogic();
116
117 /// Do any needed shutdown tasks. Currently nothing in this app.
118 /**
119 * \returns 0 on success
120 * \returns -1 on error.
121 */
122 virtual int appShutdown();
123
124 /// This method is called when the change to poweroff is detected.
125 /**
126 * \returns 0 on success.
127 * \returns -1 on any error which means the app should exit.
128 */
129 virtual int onPowerOff();
130
131 /// This method is called while the power is off, once per FSM loop.
132 /**
133 * \returns 0 on success.
134 * \returns -1 on any error which means the app should exit.
135 */
136 virtual int whilePowerOff();
137
138 protected:
139 // declare our properties
140
141 /// The position of the wheel in counts
142 pcf::IndiProperty m_indiP_counts;
143
144 public:
146
147 protected:
148 // Each of these should have m_indiMutex locked before being called.
149
150 /// Set up the MCBL controller, called after each power-on/connection
151 /**
152 * \returns 0 on success.
153 * \returns -1 on error.
154 */
155 int onPowerOnConnect();
156
157 /// Get the home switch status, sets m_switch to true or false.
158 /**
159 * \returns 0 on success.
160 * \returns -1 on error.
161 */
162 int getSwitch();
163
164 /// Get the moving-state of the wheel, sets m_moving to true or false.
165 /**
166 * \returns 0 on success.
167 * \returns -1 on error.
168 */
169 int getMoving();
170
171 /// Get the current position of the wheel, sets m_rawPos to the current motor counts.
172 /**
173 * \returns 0 on success.
174 * \returns -1 on error.
175 */
176 int getPos();
177
178 /// Start a high-level homing sequence.
179 /** For this device this includes the homing dither.
180 *
181 * \returns 0 on success.
182 * \returns -1 on error.
183 */
184 int startHoming();
185
186 int presetNumber();
187
188 /// Start a low-level homing sequence.
189 /** This initiates the device homing sequence.
190 *
191 * \returns 0 on success.
192 * \returns -1 on error.
193 */
194 int home();
195
196 /// Stop the wheel motion immediately.
197 /**
198 * \returns 0 on success.
199 * \returns -1 on error.
200 */
201 int stop();
202
203 /// Move to an absolute position in raw counts.
204 /**
205 * \returns 0 on success.
206 * \returns -1 on error.
207 */
208 int moveToRaw( const long &counts /**< [in] The new position in absolute motor counts*/ );
209
210 /// Move to a new position relative to current, in raw counts.
211 /**
212 * \returns 0 on success.
213 * \returns -1 on error.
214 */
215 int moveToRawRelative( const long &counts /**< [in] The new position in relative motor counts*/ );
216
217 /// Move to an absolute position in filter units.
218 /**
219 * \returns 0 on success.
220 * \returns -1 on error.
221 */
222 int moveTo( const double &filters /**< [in] The new position in absolute filter units*/ );
223
224 /** \name Telemeter Interface
225 *
226 * @{
227 */
228 int checkRecordTimes();
229
230 int recordTelem( const telem_stage * );
231
232 int recordTelem( const telem_position * );
233
234 int recordStage( bool force = false );
235
236 int recordPosition( bool force = false );
237
238 ///@}
239};
240
241inline filterWheelCtrl::filterWheelCtrl() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
242{
243 m_presetNotation = "filter"; // sets the name of the configs, etc.
244
245 m_powerMgtEnabled = true;
246
247 return;
248}
249
251{
253
254 config.add( "timeouts.write",
255 "",
256 "timeouts.write",
257 argType::Required,
258 "timeouts",
259 "write",
260 false,
261 "int",
262 "The timeout for writing to the device [msec]. Default = 1000" );
263 config.add( "timeouts.read",
264 "",
265 "timeouts.read",
266 argType::Required,
267 "timeouts",
268 "read",
269 false,
270 "int",
271 "The timeout for reading the device [msec]. Default = 1000" );
272
273 config.add( "motor.acceleration",
274 "",
275 "motor.acceleration",
276 argType::Required,
277 "motor",
278 "acceleration",
279 false,
280 "real",
281 "The motor acceleration parameter. Default=100." );
282 config.add( "motor.deceleration",
283 "",
284 "motor.deceleration",
285 argType::Required,
286 "motor",
287 "deceleration",
288 false,
289 "real",
290 "The motor deceleration parameter. Default=50." );
291 config.add( "motor.speed",
292 "",
293 "motor.speed",
294 argType::Required,
295 "motor",
296 "speed",
297 false,
298 "real",
299 "The motor speed parameter. Default=3000." );
300 config.add( "motor.circleSteps",
301 "",
302 "motor.circleSteps",
303 argType::Required,
304 "motor",
305 "circleSteps",
306 false,
307 "long",
308 "The number of steps in 1 revolution." );
309 config.add( "stage.homeOffset",
310 "",
311 "stage.homeOffset",
312 argType::Required,
313 "stage",
314 "homeOffset",
315 false,
316 "long",
317 "The homing offset in motor counts." );
318
320
322}
323
325{
326 this->m_baudRate = B9600; // default for MCBL controller. Will be overridden by any config setting.
327
328 int rv = tty::usbDevice::loadConfig( config );
329
330 if( rv != 0 && rv != TTY_E_NODEVNAMES && rv != TTY_E_DEVNOTFOUND ) // Ignore error if not plugged in
331 {
333 }
334
335 config( m_writeTimeOut, "timeouts.write" );
336 config( m_readTimeOut, "timeouts.read" );
337
338 config( m_acceleration, "motor.acceleration" );
339 config( m_deceleration, "motor.deceleration" );
340 config( m_motorSpeed, "motor.speed" );
341 config( m_circleSteps, "motor.circleSteps" );
342 config( m_homeOffset, "stage.homeOffset" );
343
345
347}
348
350{
352 {
353 log<text_log>( "In appStartup but in state UNINITIALIZED.", logPrio::LOG_CRITICAL );
354 return -1;
355 }
356
357 // set up the INDI properties
359 m_indiP_counts, "counts", std::numeric_limits<long>::lowest(), std::numeric_limits<long>::max(), 0.0, "%ld" );
361
363
365 {
366 return log<software_error, -1>( { __FILE__, __LINE__ } );
367 }
368
369 return 0;
370}
371
373{
375 {
376 log<text_log>( "In appLogic but in state INITIALIZED.", logPrio::LOG_CRITICAL );
377 return -1;
378 }
379
380 if( state() == stateCodes::POWERON )
381 {
382 if( m_deviceName == "" )
384 else
385 {
387 std::stringstream logs;
388 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " found in udev as "
389 << m_deviceName;
390 log<text_log>( logs.str() );
391 }
392 }
393
394 if( state() == stateCodes::NODEVICE )
395 {
397 if( rv < 0 && rv != TTY_E_DEVNOTFOUND && rv != TTY_E_NODEVNAMES )
398 {
400 if( !stateLogged() )
401 {
403 }
404 return -1;
405 }
406
408 {
410
411 if( !stateLogged() )
412 {
413 std::stringstream logs;
414 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " not found in udev";
415 log<text_log>( logs.str() );
416 }
417 return 0;
418 }
419 else
420 {
422 if( !stateLogged() )
423 {
424 std::stringstream logs;
425 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " found in udev as "
426 << m_deviceName;
427 log<text_log>( logs.str() );
428 }
429 }
430 }
431
433 {
434 int rv;
435 {
437 rv = connect();
438 }
439
440 if( rv < 0 )
441 {
443 if( nrv < 0 && nrv != TTY_E_DEVNOTFOUND && nrv != TTY_E_NODEVNAMES )
444 {
446 if( !stateLogged() )
448 return -1;
449 }
450
452 {
454
455 if( !stateLogged() )
456 {
457 std::stringstream logs;
458 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial
459 << " no longer found in udev";
460 log<text_log>( logs.str() );
461 }
462 return 0;
463 }
464
465 // if connect failed, and there is a device, then we have some other problem.
466 sleep( 1 ); // wait to see if power state updates
467 if( m_powerState == 0 )
468 return 0;
469
470 // Ok we can't figure this out, die.
472 if( !stateLogged() )
474 return -1;
475 }
476
477 if( getPos() == 0 )
479 else
480 {
481 return 0;
482 }
483
485 {
486 std::stringstream logs;
487 logs << "Connected to filter wheel on " << m_deviceName;
488 log<text_log>( logs.str() );
489 }
490 }
491
493 {
494 int rv = onPowerOnConnect();
495
496 if( rv < 0 )
497 {
500
501 return 0;
502 }
503
504 std::string landfill;
505 tty::ttyRead( landfill, "\r", m_fileDescrip, m_readTimeOut ); // read to timeout to kill any missed chars.
506
507 if( m_powerOnHome )
508 {
509 std::lock_guard<std::mutex> guard( m_indiMutex );
510
511 if( startHoming() < 0 )
512 {
515 return 0;
516 }
517 }
518 else
520 }
521
524 {
525 { // mutex scope
526 // Make sure we have exclusive attention of the device
527 std::lock_guard<std::mutex> guard( m_indiMutex ); // Lock the mutex before conducting any communications.
528
529 int rv = getSwitch();
530
531 if( rv != 0 )
532 {
534 return 0;
535 }
536
537 rv = getMoving();
538
539 if( rv != 0 )
540 {
542 return 0;
543 }
544
545 rv = getPos();
546
547 if( rv != 0 )
548 {
550 return 0;
551 }
552
554 }
555
556 if( m_moving )
557 {
558 // Started moving but we don't know yet.
559 if( state() == stateCodes::READY )
561 }
562 else
563 {
565 {
566 if( m_movingState == 1 )
567 {
568 std::lock_guard<std::mutex> guard( m_indiMutex );
569 if( moveToRawRelative( -20000 ) < 0 )
570 {
571 sleep( 1 );
572 if( m_powerState == 0 )
573 return 0;
574
577 }
578
579 m_movingState = 2;
580 }
581 else if( m_movingState == 2 )
582 {
583 std::lock_guard<std::mutex> guard( m_indiMutex );
584 if( moveTo( m_preset_target ) < 0 )
585 {
586 sleep( 1 );
587 if( m_powerState == 0 )
588 return 0;
589
592 }
593
594 m_movingState = 3;
595 }
596 else
597 {
598 m_movingState = 0;
599 state( stateCodes::READY ); // stopped moving but was just changing pos
600 }
601 }
602 else if( state() == stateCodes::HOMING ) // stopped moving but was in the homing sequence
603 {
604 if( m_homingState == 1 )
605 {
606 std::lock_guard<std::mutex> guard( m_indiMutex );
607 if( moveToRawRelative( -50000 ) < 0 )
608 {
609 sleep( 1 );
610 if( m_powerState == 0 )
611 return 0;
612
615 }
616
617 m_homingState = 2;
618 }
619 else if( m_homingState == 2 )
620 {
621 std::lock_guard<std::mutex> guard( m_indiMutex );
622 if( home() < 0 )
623 {
624 sleep( 1 );
625 if( m_powerState == 0 )
626 return 0;
627
630 }
631 m_homingState = 3;
632 }
633 else if( m_homingState == 3 )
634 {
635 std::lock_guard<std::mutex> guard( m_indiMutex );
636 if( moveToRaw( m_homeOffset ) < 0 )
637 {
638 sleep( 1 );
639 if( m_powerState == 0 )
640 return 0;
641
644 }
645 m_homingState = 4;
646 }
647 else if( m_homingState == 4 )
648 {
649 if( m_homePreset >= 0 )
650 {
653
655 }
656 m_homingState = 5;
657 }
658 else
659 {
660 m_homingState = 0;
662
664 }
665 }
666 }
667
668 std::lock_guard<std::mutex> guard( m_indiMutex );
669
670 if( m_moving )
671 {
673 }
674 else
675 {
677 }
678
680
682 recordStage();
683
685 {
687 return 0;
688 }
689
690 return 0;
691 }
692
693 if( state() == stateCodes::ERROR )
694 {
695 sleep( 1 );
696 if( m_powerState == 0 )
697 return 0;
698
699 return log<software_error, -1>(
700 { __FILE__, __LINE__, "In state ERROR but no recovery implemented. Terminating." } );
701 }
702
703 return log<software_error, -1>( { __FILE__, __LINE__, "appLogic fell through. Terminating." } );
704}
705
707{
708 // don't bother
709 return 0;
710}
711
713{
715 {
717 }
718
719 recordStage( true );
720 recordPosition( true );
721
722 return 0;
723}
724
726{
728 {
730 }
731
732 // record telem if it's been longer than 10 sec:
734 {
736 }
737
738 return 0;
739}
740
741INDI_NEWCALLBACK_DEFN( filterWheelCtrl, m_indiP_counts )( const pcf::IndiProperty &ipRecv )
742{
743 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_counts, ipRecv );
744
745 double counts = -1;
746 double target_abs = -1;
747 if( ipRecv.find( "current" ) )
748 {
749 counts = ipRecv["current"].get<double>();
750 }
751 if( ipRecv.find( "target" ) )
752 {
753 target_abs = ipRecv["target"].get<double>();
754 }
755 if( target_abs == -1 )
756 target_abs = counts;
757
758 clearPresetNameTracking();
759 m_movingState = 0;
760 m_preset_target = ( (double)target_abs - m_homeOffset ) / m_circleSteps * m_presetNames.size() + 1.0;
761 std::lock_guard<std::mutex> guard( m_indiMutex );
762 return moveToRaw( target_abs );
763}
764
766{
767 std::string com;
768
769 int rv;
770
771 std::lock_guard<std::mutex> guard( m_indiMutex );
772
773 rv = tty::ttyWrite( "ANSW0\r", m_fileDescrip, m_writeTimeOut ); // turn off replies and asynchronous comms.
774 if( rv < 0 )
776
777 // Send motor type
778 com = "MOTTYP" + std::to_string( m_motorType ) + "\r";
780 if( rv < 0 )
782
783 // Set up acceleration and speed.
784 com = "AC" + std::to_string( m_acceleration ) + "\r";
786 if( rv < 0 )
788
789 // Set up acceleration and speed.
790 com = "DEC" + std::to_string( m_deceleration ) + "\r";
792 if( rv < 0 )
794
795 com = "SP" + std::to_string( m_motorSpeed ) + "\r";
797 if( rv < 0 )
799
800 return 0;
801}
802
804{
805 int rv;
806 std::string resp;
807
808 rv = tty::ttyWriteRead( resp, "GAST\r", "\r\n", false, m_fileDescrip, m_writeTimeOut, m_readTimeOut );
809
810 if( rv == 0 )
811 {
812
813 if( resp == "1011" )
814 m_switch = true;
815 else
816 m_switch = false;
817
818 return 0;
819 }
820
821 return rv;
822}
823
825{
826 int rv;
827 std::string resp;
828
829 rv = tty::ttyWriteRead( resp, "GN\r", "\r\n", false, m_fileDescrip, m_writeTimeOut, m_readTimeOut );
830
831 if( rv == 0 )
832 {
833 int speed;
834 try
835 {
836 speed = std::stol( resp.c_str() );
837 }
838 catch( ... )
839 {
840 speed = 0;
841 }
842
843 if( fabs( speed ) > 0.1 * m_motorSpeed )
844 {
845 if( m_homingState )
846 m_moving = 2;
847 else
848 m_moving = 1;
849 }
850 else
851 m_moving = 0;
852
853 return 0;
854 }
855
856 return rv;
857}
858
860{
861 int rv;
862 std::string resp;
863
864 rv = tty::ttyWriteRead( resp, "POS\r", "\r\n", false, m_fileDescrip, m_writeTimeOut, m_readTimeOut );
865
866 if( rv == 0 )
867 {
868 try
869 {
870 m_rawPos = std::stol( resp.c_str() );
871 }
872 catch( ... )
873 {
874 m_rawPos = 0;
875 }
876 }
877
878 return rv;
879}
880
882{
883 m_homingState = 1;
884 m_moving = 2;
885 recordStage( true );
886 recordPosition( true );
887
888 updateSwitchIfChanged( m_indiP_home, "request", pcf::IndiElement::Off, INDI_IDLE );
889 return home();
890}
891
893{
894 // First we calculate current preset name
895 int n = floor( m_preset + 0.5 ) - 1;
896 if( n < 0 )
897 {
898 while( n < 0 )
899 n += m_presetNames.size();
900 }
901 if( n > (long)m_presetNames.size() - 1 )
902 {
903 while( n > (long)m_presetNames.size() - 1 )
904 n -= m_presetNames.size();
905 }
906
907 if( n < 0 )
908 {
909 log<software_error>( { __FILE__, __LINE__, "error calculating " + m_presetNotation + " index, n < 0" } );
910 return -1;
911 }
912
913 return n;
914}
915
917{
918
920
921 int rv;
922
924 if( rv < 0 )
926
928 if( rv < 0 )
930
932 if( rv < 0 )
934
935 rv = tty::ttyWrite( "CAHOSEQ\r", m_fileDescrip, m_writeTimeOut );
936 if( rv < 0 )
938
940 if( rv < 0 )
942
943 std::string com = "HOSP" + std::to_string( m_motorSpeed ) + "\r";
945 if( rv < 0 )
947
948 rv = tty::ttyWrite( "GOHOSEQ\r", m_fileDescrip, m_writeTimeOut );
949 if( rv < 0 )
951
952 return 0;
953}
954
956{
957 m_homingState = 0;
958 // First try without locking
960
961 // Now make sure it goes through
962 std::lock_guard<std::mutex> guard( m_indiMutex );
964
965 updateSwitchIfChanged( m_indiP_stop, "request", pcf::IndiElement::Off, INDI_IDLE );
966
967 if( rv < 0 )
969
970 return 0;
971}
972
973int filterWheelCtrl::moveToRaw( const long &counts )
974{
975
976 std::string com;
977 int rv;
978
979 m_moving = 1;
980 recordStage( true );
981 recordPosition( true );
982
984 if( rv < 0 )
986
987 com = "LA" + std::to_string( counts ) + "\r";
989 if( rv < 0 )
991
993 if( rv < 0 )
995
996 updateIfChanged( m_indiP_counts, "target", counts, pcf::IndiProperty::Busy );
997
998 return 0;
999}
1000
1001int filterWheelCtrl::moveToRawRelative( const long &counts_relative )
1002{
1003
1004 std::string com;
1005 int rv;
1006
1007 m_moving = 1;
1008 recordStage( true );
1009 recordPosition( true );
1010
1012 if( rv < 0 )
1013 return log<software_error, -1>( { __FILE__, __LINE__, rv, tty::ttyErrorString( rv ) } );
1014
1015 com = "LR" + std::to_string( counts_relative ) + "\r";
1017 if( rv < 0 )
1018 return log<software_error, -1>( { __FILE__, __LINE__, rv, tty::ttyErrorString( rv ) } );
1019
1021 if( rv < 0 )
1022 return log<software_error, -1>( { __FILE__, __LINE__, rv, tty::ttyErrorString( rv ) } );
1023
1024 return 0;
1025}
1026
1027int filterWheelCtrl::moveTo( const double &filters )
1028{
1029 long counts;
1030
1031 if( m_circleSteps == 0 || m_presetNames.size() == 0 )
1032 counts = filters;
1033 else
1034 counts = m_homeOffset + m_circleSteps / m_presetNames.size() * ( filters - 1 );
1035
1036 return moveToRaw( counts );
1037}
1038
1043
1045{
1046 return recordStage( true );
1047}
1048
1050{
1051 return recordPosition( true );
1052}
1053
1058
1060{
1061 static long last_pos = 999999999999;
1062
1063 if( m_rawPos != last_pos || force )
1064 {
1065 float fpos = m_rawPos;
1066
1068
1070 }
1071
1072 return 0;
1073}
1074
1075} // namespace app
1076} // namespace MagAOX
1077
1078#endif // filterWheelCtrl_hpp
Internal class to manage setuid privilege escalation with RAII.
The base-class for XWCTk applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int m_powerState
Current power state, 1=On, 0=Off, -1=Unk.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::mutex m_indiMutex
Mutex for locking INDI communications.
MagAO-X standard motion stage interface.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::vector< std::string > m_presetNames
The names of each position on the stage.
bool m_powerOnHome
If true, then the motor is homed at startup (by this software or actual power on)
std::string m_presetNotation
Notation used to refer to a preset, should be singular, as in "preset" or "filter".
float m_preset_target
The target numerical preset position [1.0 is index 0 in the preset name vector].
pcf::IndiProperty m_indiP_home
Command the stage to home. .
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_homePreset
If >=0, this preset position is moved to after homing.
pcf::IndiProperty m_indiP_stop
Command the stage to halt.
pcf::IndiProperty m_indiP_preset
The position of the stage in presets.
float m_preset
The current numerical preset position [1.0 is index 0 in the preset name vector].
int appStartup()
Startup function.
int recordStage(bool force=false)
Record the stage telemetry state.
virtual int appLogic()
Implementation of the FSM for the TTM Modulator.
long m_circleSteps
The number of position counts in 1 360-degree revolution.
int home()
Start a low-level homing sequence.
int recordPosition(bool force=false)
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
virtual int whilePowerOff()
This method is called while the power is off, once per FSM loop.
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
int getSwitch()
Get the home switch status, sets m_switch to true or false.
pcf::IndiProperty m_indiP_counts
The position of the wheel in counts.
int startHoming()
Start a high-level homing sequence.
int moveToRaw(const long &counts)
Move to an absolute position in raw counts.
long m_homeOffset
The number of position counts to offset from the home position.
INDI_NEWCALLBACK_DECL(filterWheelCtrl, m_indiP_counts)
int onPowerOnConnect()
Set up the MCBL controller, called after each power-on/connection.
int recordStage(bool force=false)
int getPos()
Get the current position of the wheel, sets m_rawPos to the current motor counts.
long m_rawPos
The position of the wheel in motor counts.
int moveTo(const double &filters)
Move to an absolute position in filter units.
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
virtual int onPowerOff()
This method is called when the change to poweroff is detected.
int m_writeTimeOut
The timeout for writing to the device [msec].
bool m_switch
The home switch status.
int moveToRawRelative(const long &counts)
Move to a new position relative to current, in raw counts.
~filterWheelCtrl() noexcept
D'tor, declared and defined for noexcept.
int m_homingState
The homing state, tracks the stages of homing.
int recordTelem(const telem_stage *)
int getMoving()
Get the moving-state of the wheel, sets m_moving to true or false.
int m_readTimeOut
The timeout for reading from the device [msec].
virtual int appStartup()
Startup functions.
int stop()
Stop the wheel motion immediately.
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
int ttyWriteRead(std::string &strRead, const std::string &strWrite, const std::string &eot, bool swallowEcho, int fd, int timeoutWrite, int timeoutRead)
Write to a tty on an open file descriptor, then get the result.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
Definition ttyErrors.cpp:15
int ttyWrite(const std::string &buffWrite, int fd, int timeoutWrite)
Write to the tty console indicated by a file descriptor.
int ttyRead(std::string &strRead, int bytes, int fd, int timeoutRead)
Read from a tty console indicated by a file-descriptor, until a given number of bytes are read.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
#define INDI_IDLE
Definition indiUtils.hpp:27
#define INDI_BUSY
Definition indiUtils.hpp:29
const pcf::IndiProperty & ipRecv
Definition dm.hpp:19
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
A device base class which saves telemetry.
Definition telemeter.hpp:75
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ NOTHOMED
The device has not been homed.
@ HOMING
The device is homing.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ UNINITIALIZED
The application is unitialized, the default.
@ INITIALIZED
The application has been initialized, set just before calling appStartup().
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
Software ERR log entry.
Log entry recording position stage specific status.
Log entry recording stdMotionStage status.
A USB device as a TTY device.
Definition usbDevice.hpp:33
std::string m_deviceName
The device path name, e.g. /dev/ttyUSB0.
Definition usbDevice.hpp:40
int m_fileDescrip
The file descriptor.
Definition usbDevice.hpp:42
int connect()
Connect to the device.
int getDeviceName()
Get the device name from udev using the vendor, product, and serial number.
std::string m_idProduct
The product id 4-digit code.
Definition usbDevice.hpp:35
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the USB section.
Definition usbDevice.cpp:24
std::string m_serial
The serial number.
Definition usbDevice.hpp:36
int loadConfig(mx::app::appConfigurator &config)
Load the USB section from an application configurator.
Definition usbDevice.cpp:34
speed_t m_baudRate
The baud rate specification.
Definition usbDevice.hpp:38
std::string m_idVendor
The vendor id 4-digit code.
Definition usbDevice.hpp:34
#define TTY_E_NODEVNAMES
Definition ttyErrors.hpp:28
#define TTY_E_DEVNOTFOUND
Definition ttyErrors.hpp:30