#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "monit.h" #include "tmcl.h" #include "tutil.h" #include "tuser.h" #include "terror.h" #ifdef SIMULATION #include "tmcl_simul.h" #define _MONIT_SESSION_TYPE_ "Simulated" #else #define _MONIT_SESSION_TYPE_ "Real-time" #endif #include "version.h" #ifdef WATCHDOG #include "watchdog.h" #endif #define MESSAGE_LEVEL 1 // verbose level #define MESSAGE_LEVEL_ON_ERROR 4 // verbose level /* * Declaration of RS232 file descriptor * (has physical meaning only for REAL-TIME mode) */ int fd_=-2; // this is RS232 port file descriptor (value <0 means not opened yet) //#ifndef STANDALONE //KN - for debugging purposes - March 2005 //const char kn_log_name[] = "/tmp/kn_mount.log"; //#endif /* * ts and tcp are global pointers to structures describing the * current status of the mount and the availability of a certain position, * respectively. */ struct TSTAT ts_, *ts = &ts_; //kn struct TCHKPOS tcp_, *tcp = &tcp_; //kn struct TASTRO ta_, *ta = &ta_; //kn extern struct CALIB calib; struct CFG_OPTION option_= /* order must match definition of struct CFG_OPTION */ { MONIT_DEFAULT_INIT_STOP_FLAG, // init_stop_flag MONIT_DEFAULT_INIT_CALIB_FLAG, // init_calib_flag MOUNT_DEFAULT_COMAPARELASTPOSITION_ENCODER_CHK, // init_encoder_chk {MOUNT_DEFAULT_COMAPARELASTPOSITION_ENCODER_ACCURACY, // init_encoder_thr (HA) MOUNT_DEFAULT_COMAPARELASTPOSITION_ENCODER_ACCURACY},// init_encoder_thr (DEC) MOUNT_DEFAULT_GETSTATUS_ENCODER_CHK, // getstatus_slide_chk {MOUNT_DEFAULT_GETSTATUS_ENCODER_ACCURACY, // getstatus_slide_thr (HA) MOUNT_DEFAULT_GETSTATUS_ENCODER_ACCURACY}, // getstatus_slide_thr (DEC) {MOUNT_DEFAULT_GETSTATUS_ENCODER_TIME_MIN, // getstatus_slide_delaymin (HA) MOUNT_DEFAULT_GETSTATUS_ENCODER_TIME_MIN}, // getstatus_slide_delaymin (DEC) {MOUNT_DEFAULT_GETSTATUS_ENCODER_TIME_MAX, // getstatus_slide_delaymax (HA) MOUNT_DEFAULT_GETSTATUS_ENCODER_TIME_MAX}, // getstatus_slide_delaymax (DEC) MOUNT_DEFAULT_CALIBRATE_MODE_HOME_ITER, // calib_niter_full MOUNT_DEFAULT_CALIBRATE_MODE_ALL_ITER, // calib_niter_full MOUNT_DEFAULT_CALIBRATE_ENCODER_FASTPOS, // calib_encoder_fastpos MOUNT_DEFAULT_CALIBRATE_ENCODER_ANGLE, // calib_encoder_angle {MOUNT_DEFAULT_CALIBRATE_ENCODER_IS_PRECISE, // calib_encoder_is_precise (HA) MOUNT_DEFAULT_CALIBRATE_ENCODER_IS_PRECISE}, // calib_encoder_is_precise (DEC) MOUNT_DEFAULT_FINDSWITCH_ENCODER_SAFEZONE_CHK, // findswitch_safezone_chk {MOUNT_DEFAULT_FINDSWITCH_ENCODER_SAFEZONE_THR, // findswitch_safezone_thr (HA) MOUNT_DEFAULT_FINDSWITCH_ENCODER_SAFEZONE_THR}, // findswitch_safezone_thr (DEC) MOUNT_DEFAULT_FINDSWITCH_ENCODER_SLIDE_CHK, // findswitch_slide_chk {MOUNT_DEFAULT_FINDSWITCH_ENCODER_SLIDE_THR, // findswitch_slide_thr (HA) MOUNT_DEFAULT_FINDSWITCH_ENCODER_SLIDE_THR}, // findswitch_slide_thr (DEC) {MOUNT_DEFAULT_FINDSWITCH_ENCODER_DELAY, // findswitch_encoder_delay (HA) MOUNT_DEFAULT_FINDSWITCH_ENCODER_DELAY}, // findswitch_encoder_delay (DEC) MOUNT_DEFAULT_FINDSWITCH_STEP_ANGLE, // findswitch_step_angle MONIT_DEFAULT_PARK_MINHEIGHT, // dopark_minheight MONIT_DEFAULT_PARK_MAXHEIGHT, // dopark_maxheight MONIT_DEFAULT_PARK_MINAZIMUTH, // dopark_minazimuth MONIT_DEFAULT_PARK_MAXAZIMUTH, // dopark_maxazimuth MONIT_DEFAULT_PARK_MAXITER, // dopark_maxiter MONIT_DEFAULT_PARK_AZ_SAFE, // dopark_az_safe MONIT_DEFAULT_PARK_H_SAFE, // dopark_h_safe MONIT_DEFAULT_PARK_SWITCH_CLEARANCE, // dopark_switch_clearance MONIT_DEFAULT_PARK_PRECISION, // dopark_precision MONIT_DEFAULT_ZENITH_SWITCH_CLEARANCE, // dozenith_switch_clearance MONIT_DEFAULT_ZENITH_PRECISION, // dozenith_precision {MOUNT_DEFAULT_ABSOLUTE_ENCODER_TYPE, // absolute_encoder_type (HA) MOUNT_DEFAULT_ABSOLUTE_ENCODER_TYPE}, // absolute_encoder_type (DEC) {MOUNT_DEFAULT_FINDENCODER_PREC_LOW, MOUNT_DEFAULT_FINDENCODER_PREC_LOW}, {MOUNT_DEFAULT_FINDENCODER_PREC_HIGH, MOUNT_DEFAULT_FINDENCODER_PREC_HIGH}, {MOUNT_DEFAULT_ASTRO_AG_MAXCORR_HA, // astro_ag_maxcorr (HA) MOUNT_DEFAULT_ASTRO_AG_MAXCORR_DEC}, // astro_ag_maxcorr (DEC) MOUNT_DEFAULT_ASTRO_AG_MINDELAY, // astro_ag_mindelay MOUNT_DEFAULT_ASTRO_MAXDELAY, // astro_maxdelay MOUNT_DEFAULT_ASTRO_ENCODER_CHK, // astro_encoder_chk {MOUNT_DEFAULT_ASTRO_ENCODER_CHK_THR, // astro_encoder_chk_thr (HA) MOUNT_DEFAULT_ASTRO_ENCODER_CHK_THR}, // astro_encoder_chk_thr (DEC) MONIT_DEFAULT_INIT_RS232_PORTNAME, // rs232_portname MONIT_DEFAULT_INIT_RS232_RECONNECT, // rs232_reconnect MONIT_DEFAULT_INIT_RS232_BAUDRATE, // rs232_baudrate // // HARDWARE PARAMETERS // TMCL_DEFAULT_CLK_FREQ, // TMC-428 clock frequency [Hz] TMCL_DEFAULT_MAX_MICROSTEP_FREQ, // TMC-428 max microstep frequency [Hz] {MOT_MAX_FS_FREQ_A, // max safe full step freq [Hz] (HA,DEC) MOT_MAX_FS_FREQ_D}, {MOT_FULL_STEPS_PER_HA_TURN, // motor_gear_ratio (HA) MOT_FULL_STEPS_PER_DEC_TURN}, // motor_gear_ratio (DEC) {MOT_HOME_POSITION_DEG_HA, // motor_home_offset (HA) MOT_HOME_POSITION_DEG_DEC}, // motor_home_offset (DEC) {MOTOR_DEFAULT_HA_POLARITY, // motor_polarity (HA) MOTOR_DEFAULT_DEC_POLARITY} // motor_polarity (DEC) }, *option=&option_; extern int noption; int mount_initialized=0; // mount is not initialized yet - MC - 26 March 2005 // will be changed by do_init(main) in STANDALONE), // do_pause, do_quit int autoguiding=0; // automatic correction of the tracking paramters // calculated from two subsequent externally //supplied astrometries; // mount must be tracking between two astrometry // measurements // (default is 0=OFF) int speed_mode=MOT_FAST_SPEED; // speed parameter set to be loaded // during fast positioning int strategy=MONIT_STRATEGY_FASTEST; // initialization of moving strategy int logging=0; // controls writing to logfile (default is 0=OFF) int autocalib=0; // controls automatic calibration from // potentiometer/encoder // in case of ERROR, SLIDE event int microtracking=0; // do not use by default logical steps exceeding // +/-2^23 range limited by hardware char log_name[1000]; // name of the logfile (appends) FILE *log_file=NULL; // pointer to logfile FILE *cal_file=NULL; // pointer to calibration data file /* char port_name[100]; // serial port device name: */ /* // "/dev/cua0" for RedHat */ /* // "/dev/ttyS0" for Fedora */ /* long baud_rate; // baud rate for RS-232 port */ char site_code[5]; // 3-letter code of the observation site char site_comment[100]; // full name of the observation site struct GLOB_TABLE { char *name; int type; } glob_table[] = { {"eeprom", 64}, {"baudrate", 65}, {"lock", 73}, {"tmcl_stat", 128}, {"download_mode", 129}, {"telegram_pause", 75} }; int nglob = sizeof(glob_table)/sizeof(struct GLOB_TABLE); struct TMCL_TABLE { char *name; int type; } tmcl_table[] = { {"target_pos", 0}, {"actual_pos", 1}, {"target_speed", 2}, {"actual_speed", 3}, {"max_speed", 4}, {"max_accel", 5}, {"max_current", 6}, {"standby_current", 7}, {"at_target_pos", 8}, {"ref_stat", 9}, {"right_lim_stat", 10}, {"left_lim_stat", 11}, {"right_lim_disable", 12}, {"left_lim_disable", 13}, {"min_speed", 130}, {"actual_accel", 135}, {"accel_thr", 136}, {"accel_div", 137}, {"ramp_mode", 138}, {"interrupts", 139}, {"microstep", 140}, {"ref_tol", 141}, {"snap_pos", 142}, {"max_curr_rest", 143}, {"max_curr_low", 144}, {"max_curr_high", 145}, {"accel_fac", 146}, {"ref_disable_flag", 147}, {"lim_disable_flag", 148}, {"soft_stop_flag", 149}, {"right_not_left", 150}, {"pos_latch_flag", 151}, {"interrupt_mask", 152}, {"ramp_div", 153}, {"pulse_div", 154}, {"refer_mode", 193}, {"ref_search_speed", 194}, {"ref_switch_speed", 195}, {"steps_per_cycle", 197}, {"driver_off_time", 198}, {"fast_decay_time", 200}, {"blank_time", 201}, {"mixed_decay_thr", 202}, {"fast_decay_thr", 203}, {"freewheeling_delay",204}, {"encoder", 209} }; int ntmcl = sizeof(tmcl_table)/sizeof(struct TMCL_TABLE); /* command table */ struct CMD_TABLE { char *name[8]; // each command can have up to 8 equivalent command-line calls for convenience int code; // unique code of a given command int (*cmd)(); // pointer to a function to be executed char *syntax; // description of the command's syntax char *details; // description of the command } cmd_table[] = { { {"init", "initialization", "initialize", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_INIT, #ifndef STANDALONE do_init, "init [nocalib]", "'init' initializes the mount.\n\n" "This command opens new logfile and (re)opens RS-232 communication with\n" "TMCM-300 unit. It also loads parameters from several configuration files:" "\n" "- "MOUNT_DEFAULT_FILE_CONFIG"\n" "- "MOUNT_DEFAULT_FILE_LOCATIONS_DB"\n" "- "MOUNT_DEFAULT_FILE_LAST_FULL_CALIB"\n" "- "MOUNT_DEFAULT_FILE_LAST_SAVE".\n" "'Init' must be called before any other command issued to the mount after\n" "starting any mount session.\n\n" "If called without arguments:\n" "Checks whether position of the mount matches the last one (i.e. stored\n" "by 'quit' or 'pause' commands) and takes an appropriate action:\n" "1. Same positions and slide not detected - no action\n" "2. Same positions and slide detected - starts 'calib 0'\n" "3. Positions differ - starts 'calib 0'.\n" "In the case of 'calib 0' failure (pts. 2 and 3) a coarse calibration\n" "from encoders/potentiometers will be performed by 'calib adc' command.\n" "The calibration during initialization can be disabled by setting\n" "INIT_CALIB_FLAG=0 in the config file.\n\n" "If called with 'nocalib' argument:\n" "No calibration will be performed during initialization and none of the\n" "motors will be stopped. It overrides INIT_CALIB_FLAG in the config file.\n\n" "NOTE: Beware, that when calibration during initialization is disabled\n" "(either by setting INIT_CALIB_FLAG=0, or by setting 'nocalib' option)\n" "and, both, the watchdog process and the automatic calibration from\n" "encoders/potentiometers are enabled, the mount will be calibrated by the watchdog\n" "process anyway few moments later. One has to disable either autocalibration or\n" "watchdog in the config file before starting a new mount session by setting\n" "AUTOCALIB=0 or WATCHDOG=0, respectively." #else NULL, "Command executes automatically", "Upon start of a new mount session the initialization procedure opens new logfiles\n" "and (re)opens RS-232 communication with TMCM-300 unit. It also loads parameters from\n" "several configuration files:" "\n" "- "MOUNT_DEFAULT_FILE_CONFIG"\n" "- "MOUNT_DEFAULT_FILE_LOCATIONS_DB"\n" "- "MOUNT_DEFAULT_FILE_LAST_FULL_CALIB"\n" "- "MOUNT_DEFAULT_FILE_LAST_SAVE".\n\n" "If mount session is called without command line arguments:\n" "Checks whether position of the mount matches the last one (i.e. stored\n" "by 'quit' or 'pause' commands) and takes an appropriate action:\n" "1. Same positions and slide not detected - no action\n" "2. Same positions and slide detected - starts 'calib 0'\n" "3. Positions differ - starts 'calib 0'.\n" "In the case of 'calib 0' failure (pts. 2 and 3) a coarse calibration\n" "from encoders/potentiometers will be performed by executing 'calib adc' command.\n" "The calibration during initialization can be disabled by setting\n" "INIT_CALIB_FLAG=0 in the config file.\n\n" "If mount session is called with 'nocalib' command line argument:\n" "No calibration will be performed during initialization and none of the\n" "motors will be stopped. It overrides INIT_CALIB_FLAG in the config file.\n\n" "NOTE: Beware, that when calibration during initialization is disabled\n" "(either by setting INIT_CALIB_FLAG=0, or by setting 'nocalib' option)\n" "and, both, the watchdog process and the automatic calibration from\n" "encoders/potentiometers are enabled, the mount will be calibrated by the watchdog\n" "process anyway few moments later. One has to disable either autocalibration or\n" "watchdog in the config file before starting a new mount session by setting\n" "AUTOCALIB=0 or WATCHDOG=0, respectively." #endif }, { {"ha", "hourangle", NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_HA, do_set_ha, "ha []", "'ha' sets HOUR ANGLE [deg]. Does not change DECLINATION.\n\n" "This command turns off tracking mode.\n" "Equivalent to 'goto ha=' command.\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: 'ha' called without an argument prints the current coordinates." }, { {"ra", "rightascension", "r", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_RA, do_set_ra, "ra []", "'ra' sets RIGHT ASCENSION angle [deg]. Does not change DECLINATION.\n\n" "After successful positioning turns on tracking mode.\n" "Equivalent to 'goto ra=' command.\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: 'ra' called without an argument prints the current coordinates." }, { {"dec", "declination", "d", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_DEC, do_set_dec, "dec []", "'dec' sets DECLINATION angle [deg]. Does not change HOUR ANGLE.\n\n" "This command turns off tracking mode.\n" "Equivalent to 'goto d=' command.\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: 'dec' called without an argument prints the current coordinates." }, { {"az", "azimuth", "a", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_AZ, do_set_az, "az []", "'az' sets astronomical AZIMUTH angle [deg]. Does not change HEIGHT.\n\n" "This command turns off tracking mode.\n" "Equivalent to 'goto az=' command.\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: astronomical AZ=0 corresponds to the Southern direction.\n" "NOTE: 'az' called without an argument prints the current coordinates." }, { { "height", "ht", "h", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_HEIGHT, do_set_h, "height []", "'height' sets HEIGHT [deg] above the horizon. Does not change AZIMUTH.\n\n" "This command turns off tracking mode.\n" "Equivalent to 'goto height=' command.\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: 'height' called without an argument prints the current coordinates." }, { {"goto", "go", "moveto", "move", "mv", "pos", "position", "setpos"}, MONIT_CODE_GOTO, do_set_coo, "goto (1) or\n" "goto ra= d[ec]= (2) or\n" "goto ra= (3) or\n" "goto ha= d[ec]= (4) or\n" "goto ha= (5) or\n" "goto d[ec]= (6) or\n" "goto az= h[eight]= (7) or\n" "goto az= (8) or\n" "goto h[eight]= (9)", "'goto' sets one or two coordinates at a time.\n\n" "If called with 2 arguments:\n" "Syntax (1): Two subsequent numbers without prefixes correspond\n" " to RIGHT ASCENSION [deg] followed by DECLINATION [deg].\n" " After successful positioning turns on tracking mode.\n" "Syntax (2): Sets RIGHT ASCENSION [deg] and DECLINATION [deg].\n" " After successful positioning turns on tracking mode.\n" "Syntax (4): Sets HOUR ANGLE [deg] and DECLINATION [deg].\n" " This command turns off tracking mode.\n" "Syntax (7): Sets astronomical AZIMUTH [deg] and HEIGHT [deg] above\n" " the horizon. This command turns off tracking mode.\n\n" "If called with 1 argument:\n" "Syntax (3): Sets RIGHT ASCENSION [deg]. Does not change DECLINATION.\n" " After successful positioning turns on tracking mode.\n" " Equivalent to 'ra ' command.\n" "Syntax (5): Sets HOUR ANGLE [deg]. Does not change DECLINATION.\n" " This command turns off tracking mode.\n" " Equivalent to 'ha ' command.\n" "Syntax (6): Sets DECLINATION [deg]. Does not change HOUR ANGLE.\n" " This command turns off tracking mode.\n" " Equivalent to 'dec ' command.\n" "Syntax (8): Sets astronomical AZIMUTH [deg]. Does not change HEIGHT\n" " above the horizon. This command turns off tracking mode.\n" " Equivalent to 'az ' command.\n" "Syntax (9): Sets HEIGHT [deg] above the horizon. Does not change\n" " AZIMUTH. This command turns off tracking mode.\n" " Equivalent to 'height ' command.\n\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: astronomical AZ=0 corresponds to the Southern direction.\n" "NOTE: 'goto' called without arguments prints current coordinates." }, { {"gotorel", "gorel", "movetorel", "moverel", "mvrel", "posrel", "positionrel", "setposrel"}, MONIT_CODE_GOTOREL, do_set_coo_relative, "gotorel (1) or\n" "gotorel ra= d[ec]= (2) or\n" "gotorel ra= (3) or\n" "gotorel ha= d[ec]= (4) or\n" "gotorel ha= (5) or\n" "gotorel d[ec]= (6) or\n" "gotorel az= h[eight]= (7) or\n" "gotorel az= (8) or\n" "gotorel h[eight]= (9)", "'gotorel' sets one or two coordinates at a time relative to current\n" "position.\n\n" "If called with 2 arguments:\n" "Syntax (1): Two subsequent numbers without prefixes correspond to\n" " increment of RIGHT ASCENSION [deg] followed by increment\n" " of DECLINATION [deg].\n" " After successful positioning turns on tracking mode.\n" "Syntax (2): Sets increments of RIGHT ASCENSION [deg] and \n" " DECLINATION [deg] as above.\n" " After successful positioning turns on tracking mode.\n" "Syntax (4): Sets increments of HOUR ANGLE [deg] and DECLINATION [deg].\n" " This command turns off tracking mode.\n" "Syntax (7): Sets increments of astronomical AZIMUTH [deg] and \n" " HEIGHT [deg] above the horizon. \n" " This command turns off tracking mode.\n\n" "If called with 1 argument:\n" "Syntax (3): Sets increment of RIGHT ASCENSION [deg].\n" " Does not change DECLINATION.\n" " After successful positioning turns on tracking mode.\n" "Syntax (5): Sets increment of HOUR ANGLE [deg].\n" " Does not change DECLINATION.\n" " This command turns off tracking mode.\n" "Syntax (6): Sets increment of DECLINATION [deg].\n" " Does not change HOUR ANGLE.\n" " This command turns off tracking mode.\n" "Syntax (8): Sets increment of astronomical AZIMUTH [deg].\n" " Does not change HEIGHT above the horizon.\n" " This command turns off tracking mode.\n" "Syntax (9): Sets increment of HEIGHT [deg] above the horizon.\n" " Does not change AZIMUTH.\n" " This command turns off tracking mode.\n\n" "Positioning strategy can be adjusted by 'strategy' command.\n" "NOTE: 'gotorel' called without arguments prints current coordinates." }, { {"check", "chk", "checkpos", "checkposition", "poscheck", "checkcoo", "checkcoordinates", "coocheck"}, MONIT_CODE_CHECKGOTO, do_check_coo, "check (1) or\n" "check ra= d[ec]= (2) or\n" "check ra= (3) or\n" "check ha= d[ec]= (4) or\n" "check ha= (5) or\n" "check d[ec]= (6) or\n" "check az= h[eight]= (7) or\n" "check az= (8) or\n" "check h[eight]= (9)", "'check' verifies whether a given position is within mount's range.\n\n" "If called with 2 arguments:\n" "Syntax (1): Two subsequent numbers without prefixes correspond\n" " to RIGHT ASCENSION [deg] followed by DECLINATION [deg].\n" "Syntax (2): Checks RIGHT ASCENSION [deg] and DECLINATION [deg].\n" "Syntax (4): Checks HOUR ANGLE [deg] and DECLINATION [deg].\n" "Syntax (7): Checks astronomical AZIMUTH [deg] and HEIGHT [deg] above\n" " the horizon.\n\n" "If called with 1 argument:\n" "Syntax (3): Checks RIGHT ASCENSION [deg] and current DECLINATION.\n" "Syntax (5): Checks HOUR ANGLE [deg] and current DECLINATION.\n" "Syntax (6): Checks DECLINATION [deg] and current HOUR ANGLE.\n" "Syntax (8): Checks astronomical AZIMUTH [deg] and current HEIGHT\n" " above the horizon.\n" "Syntax (9): Checks HEIGHT [deg] above the horizon and current\n" " astronomical AZIMUTH.\n\n" "NOTE: astronomical AZ=0 corresponds to the Southern direction.\n" "NOTE: 'check' called without arguments prints current coordinates." }, { {"coo", "coordinates", "getcoordinates", "getcoo", "getposition", "getpos", "showposition", "showpos"}, MONIT_CODE_COO, do_get_coo, "coo", "'coo' queries current coordinates.\n\n" "RIGHT ASCENSION [deg], HOUR ANGLE [deg], DECLINATION [deg], \n" "astronomical AZIMUTH [deg], HEIGHT [deg] above the horizon\n" "are printed.\n" "Equivalent to 'goto','ra','ha','dec','az','height' commands\n" "when called without an argument.\n" "NOTE: astronomical AZ=0 corresponds to the Southern direction." }, { {"version", "vers", "ver", "release", "build", NULL, NULL, NULL}, MONIT_CODE_VERSION, do_get_version, "version", "'version' queries version of the program that is currently running.\n\n" "The following information is displayed: time and date of compilation,\n" "kind of compilation (REAL-TIME/SIMULATION, STANDALONE/PIMAN)." }, { {"track", "tracking", "trk", "tr", NULL, NULL, NULL, NULL}, MONIT_CODE_TRACK, do_tracking, "track []", "'track' sets constant rotation speed in HOUR ANGLE and/or DECLINATION axes.\n\n" "mode={0,off} - Turns off tracking, stops all motors.\n" "mode={1,on} - Turns on tracking using the most recent tracking parameters.\n" "mode={2,default} - Turns on tracking using default values calculated from geometry\n" " parameters taken from the config file.\n" "NOTE: 'track' called without an argument displays the current tracking mode." }, { {"speed", "spd", NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_SPEED, do_set_speed, "speed []", "'speed' sets speed during fast movement of the mount.\n\n" "This command allows one to reduce the maximal allowed positioning\n" "speed. The duration of the following commands will be affected:\n" "goto, gotorel, ha, ra, dec, az, height, calib.\n\n" "mode={0,fast[est],max[imal]} - Fastest speed and \n" " acceleration (default).\n" "mode={1,slow[est],min[imal],half,medium} - Half of the fastest speed\n" " and acceleration.\n\n" "NOTE: 'speed' called without an argument prints the current " "speed mode." }, { {"strategy", "strat", "str", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_STRATEGY, do_set_strategy, "strategy []", "'strategy' controls positioning strategy.\n\n" "mode={0,fast[est],speed} - Whenever possible, reaches target\n" " position in the fastest way.\n" "mode={1,long[est],track[ing]} - Whenever possible, optimizes for\n" " long-time tracking.\n\n" "NOTE: 'strategy' called without an argument prints the current strategy." }, { {"autoguide", "autoguiding", "aguiding", "aguide", "agd", "ag", NULL, NULL}, MONIT_CODE_AUTOGUIDE, do_set_autoguide, "autoguide []", "'autoguide' enables automatic correction of the tracking parameters.\n\n" "The tracking parameters are corrected according to the difference\n" "between the current mount coordinates and two subsequent, externally\n" "supplied astrometries (see 'astro' command).\n\n" "mode={0,off} - Turns off automatic corrections.\n" "mode={1,on} - Turns on automatic corrections. Upon mode change tracking\n" " parameters will be altered starting from a second call of\n" " 'astro' command.\n" "NOTE: The correction procedure assumes UNINTERRUPTED tracking between\n" " subsequent astrometry measurements.\n" "NOTE: 'autoguide' called without an argument prints the current autoguiding strategy." }, #ifdef MICROTRACKING { {"microtracking", "microtrack", "microtrk", "microtr", "mtracking", "mtrack", "mtrk", "mtr"}, MONIT_CODE_MICROTRACK, do_set_microtracking, "microtracking []", "'microtracking' enables logical motor steps exceeding -2^23...2^23 range limited by\n" "TMCM-300 unit, thus fine microstepping up to 1/64 of the full motor step is possible.\n\n" "When enabled, the mount's coordinates are calculated from motor steps and then\n" "corrected for information read out from encoders/potentiometers.\n" "Currently microtracking is useful only for 'track' and 'astro' commands.\n" "It allows for a smoother tracking of the sky and finer speed corrections in autoguiding mode.\n\n" "mode={0,off} - Turns off microtracking.\n" "mode={1,on} - Turns on microtracking.\n" "NOTE: Actual change of the tracking mode will be effective only after next call to\n" " 'track on/off' or 'astro' commands.\n" "NOTE: 'microtracking' called without an argument prints the current microtracking mode." }, #endif { {"stat", "status", "sts", "st", NULL, NULL, NULL, NULL}, MONIT_CODE_STAT, do_status, "stat", "'stat' prints actual status of the mount, like: coordinates, \n" "tracking mode, strategy mode, status of the limit switches.\n" "The amount of information depends on the current verbose level\n" "which can be adjusted using 'verb' command." }, { {"calib", "calibration", "calibrate", "cal", NULL, NULL, NULL, NULL}, MONIT_CODE_CALIB, do_calib, "calib []", "'calib' sets initial HOME position.\n\n" "mode={0,fast}\n" " - Performs fast calibration. Finds HOME switch only.\n" " Upon success sets current HOUR ANGLE and DECLINATION to\n" " a predefined values corresponding to the HOME position.\n" " DOES NOT UPDATE the main calibration file.\n" "mode={1,full}\n" " - Performs full calibration. Finds LEFT, HOME and RIGHT\n" " limit switches. Upon success: sets current HOUR ANGLE and\n" " DECLINATION to a predefined values corresponding to the\n" " HOME position and DOES UPDATE the main calibration file.\n" "mode={2,test}\n" " - Performs fast calibration (like in mode=0), and,\n" " in addition, correlates encoder/potentiometer readings with stepper\n" " motor counts. Rotates from RIGHT to LEFT, then, from LEFT to\n" " RIGHT. The result of the scan is stored in a separate,\n" " dedicated file. DOES NOT UPDATE the main calibration file.\n" " This mode is useful ONLY FOR DEBUGGING.\n" "mode={3,rnd[_test],random[_test]}\n" " - Same as in mode=2, except that positions are randomly generated.\n" " Thus, this command needs much longer time to complete.\n" " DOES NOT UPDATE the main calibration file.\n" " This mode is useful ONLY FOR DEBUGGING.\n" #ifdef _HAS_DO_ASTROMETRY_ "mode={4,adc}\n" " - Equivalent to 'astro ADC' command, which gets coarse \"astrometry\"\n" " data from encoder/potentiometers rather than real astrometry.\n" " Such calibration is quite coarse and typical precision is 2-3 degrees.\n" " DOES NOT UPDATE the main calibration file.\n" "Modes 0..3 turn off tracking mode. " "Mode 4 (or ADC) does not change tracking mode.\n\n" #else "This command turns off tracking mode.\n\n" #endif "NOTE: 'calib' called without an argument prints the current " "calibration data." }, #ifdef AUTOCALIBRATION { {"autocalib", "autocalibration", "autocalibrate", "autocal", "acalibration", "acalibrate", "acalib", "acal"}, MONIT_CODE_AUTOCALIB, do_set_autocalib, "autocalib []", "'autocalib' enables autocalibration from encoder/potentiometers if a slide\n" "condition is detected.\n\n" "mode={0,off} - Turns off autocalibration feature.\n" "mode={1,on} - Turns on autocalibration feature.\n\n" "NOTE: 'autocalib' called without an argument prints the current " "autocalibration mode." }, #endif #ifdef WATCHDOG { {"watchdog", "watchdg", "watch", "wdog", "wdg", NULL, NULL, NULL}, MONIT_CODE_WATCHDOG, do_set_watchdog, "watchdog [period(sec)]", "'watchdog' enables periodical checking and logging of the mount status." "\n\n" "period={0,off} - Turns off watchdog feature.\n" "period>1 - Turns on watchdog feature. Will update status every\n" " specified number of seconds.\n" "period=on - Turns on watchdog feature. Last period will be used.\n\n" "NOTE: 'watchdog' called without an argument prints the current " "watchdog status and its frequency of updates." }, #endif { {"park", "parking", "prk", "pk", NULL, NULL, NULL, NULL}, MONIT_CODE_PARK, do_park, "park", "'park' moves cameras to a safe, random parking position.\n\n" "A proper calibration of the mount is not required since this command\n" "uses encoders/potentiometers instead of motor steps for positioning.\n" "On success, the CCD cameras will be pointed down below the horizon." }, { {"zenith", "zen", "zth", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_ZENITH, do_zenith, // "zenith []", "zenith", "'zenith' points cameras to the Zenith position and stops the motors." "\n\n" // "precision={0,low} - use coarse precision\n" // "precision={1,high} - use better precision\n\n" "A proper calibration of the mount is not required since this command\n" "uses encoders/potentiometers rather than motor steps for positioning.\n" "Such positioning is rather coarse, however. Typical precision \n" "is 2-3 degrees." }, { {"verb", "verbose", "vb", "v", "debug", "debugging", "logging", "level"}, MONIT_CODE_VERB, do_verb, "verb []", "'verb' controls amount of information put on a screen and\n" "into a log file.\n\n" "level=0 - Disables all debugging information.\n" "level>1 - The greater value the more verbose information is printed.\n\n" "NOTE: 'verb' called without an argument prints the current verbose level." }, { {"site", "location", "loc", "observatory", "observer", "obs", "whereami", "where"}, MONIT_CODE_SITE, do_site, "site", "'site' displays information about current observation site." }, { {"help", "hlp", "?", "info", "inf", "man", "manual", "whatis"}, MONIT_CODE_HELP, do_help, #ifdef DEBUG "help [] (1) or\n" "help set (2) or\n" "help get (3)", #else "help []", #endif "'help' displays information about syntax and action of the\n" "specified command.\n\n" "NOTE: 'help' called without an argument lists available commands." }, { {"pause", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_PAUSE, do_pause, "pause", "'pause' closes logfiles and shuts down RS-232 communication with the\n" "TMCM-300 unit." #ifdef STANDALONE "\n\n" "NOTE: In standalone mode 'pause' is equivalent to 'quit' command." #else " However, the mount_server process will still run in \n" "the background." #endif }, { {"quit", "end", "exit", "logout", NULL, NULL, NULL, NULL}, MONIT_CODE_QUIT, do_quit, "quit", "'quit' closes logfiles and shuts down RS-232 communication with the\n" "TMCM-300 unit." #ifdef STANDALONE "\n\n" "NOTE: In standalone mode 'quit' is equivalent to 'pause' command." #else " The mount_server process will be terminated, as well." #endif }, { {"flats", "flat", "flts", "flt", "fls", "fl", NULL, NULL}, MONIT_CODE_FLATS, do_flats, "flats at= dt=\n" " modulo= residue= (1) or\n" "flats dt=\n" " modulo= residue= (2) or\n" "flats (3) or\n" "flats at= dt= (4) or\n" "flats [dt=] (5)", "'flats' performs slight movements from the current position.\n\n" "Starts tracking, then slightly increases DECLINATION every MODULO\n" "seconds (i.e. when a residue of the system time [sec] modulo MODULO\n" "is equal to RESIDUE). On exit goes back to the original position.\n\n" "If called with 4 arguments:\n" "Syntax (1): Sets TIMESTAMP [sec] (since 00:00:00 01/01/1970 UTC), \n" " DURATION [sec], MODULO [sec] and RESIDUE[sec].\n" " The movement won't start before the specified time instant\n" " given by TIMESTAMP. A total duration of the \"flats\"\n" " tracking mode is controlled by DURATION parameter.\n\n" "If called with 3 arguments:\n" "Syntax (2): Sets DURATION [sec], MODULO [sec] and RESIDUE[sec].\n" " The movement will start at the earliest opportunity.\n\n" "If called with 2 arguments:\n" "Syntax (3): Two subsequent numbers without prefixes correspond\n" " to TIMESTAMP [sec] followed by DURATION [sec].\n" "Syntax (4): Sets TIMESTAMP [sec] and DURATION [sec] as above.\n\n" "If called with 1 argument:\n" "Syntax (5): Sets DURATION [sec] of the \"flats\" tracking mode.\n" " The movement will start at the earliest opportunity.\n\n" "Example:\n" "1. To start immediately \"flats\" taking mode lasting 30 minutes with\n" " default MODULE and RESIDUE values:\n" " flats 1800\n" "2. To start \n" "NOTE: TIMESTAMP=0 means that the movement will be started immediately.\n" "NOTE: If MODULO and RESIDUE arguments are missing (or both are zero) \n" " the default values will be assigned: MODULO=10 seconds and \n" " RESIDUE=5 seconds.\n" "NOTE: Values of MODULO parameter below 10 seconds should be avoided, as the\n" " motor of DEC axis needs about 4 seconds to complete its movement." }, #ifdef _HAS_DO_ASTROMETRY_ { {"astro", "astrometry", "astr", "ast", "as", NULL, NULL, NULL}, MONIT_CODE_ASTRO, do_calib_astro, #ifdef STANDALONE // STANDALONE #ifndef SIMULATION // STANDALONE,REAL-TIME : CCD(-) encoder(+) true(-) "astro", "'astro' corrects current coordinates using data from encoders/potentiometers.\n\n" #else // STANDALONE,SIMULATION: CCD(-) encoder(+) true(+) "astro (1) or\n" "astro ENCODER (2) or\n" "astro POTENTIOMETER (3) or\n" "astro ADC (4)", "In SIMULATION mode the 'astro' command corrects current coordinates using\n" "either data from a \"true\" hardware position of the mount or information from\n" "encoders/potentiometers.\n\n" "Syntax (1): correction is applied using internal \"true\" position.\n" "Syntax (2)-(4): correction is applied using encoders/potentiometers.\n\n" #endif #else // PIMAN #ifndef SIMULATION // PIMAN,REAL-TIME : CCD(+) encoder(+) true(-) "astro (1) or\n" "astro ENCODER (2) or\n" "astro POTENTIOMETER (3) or\n" "astro ADC (4) or\n" "astro FORCE (5)", "'astro' corrects current coordinates using an independent astrometry data or\n" "information from encoders/potentiometers.\n\n" "Syntax (1) or (5): correction is applied using astrometry data.\n" "Syntax (2)-(4): correction is applied using encoders/potentiometers.\n\n" #else // PIMAN,SIMULATION : CCD(-) encoder(+) true(+) "astro (1) or\n" "astro ENCODER (2) or\n" "astro POTENTIOMETER (3) or\n" "astro ADC (4) or\n" "astro FORCE (5)", "In SIMULATION mode the 'astro' command corrects current coordinates using\n" "either data from a \"true\" hardware position of the mount or information from\n" "encoders/potentiometers.\n\n" "Syntax (1) or (5): correction is applied using internal \"true\" position.\n" "Syntax (2)-(4): correction is applied using encoders/potentiometers.\n\n" #endif #endif "The RIGHT ASCENSION [deg], HOUR ANGLE [deg], DECLINATION [deg], \n" "astronomical AZIMUTH [deg], HEIGHT [deg] above the horizon\n" "will be adjusted. Stepper motor counts will be altered according\n" "to information from the main calibration file.\n\n" "This command normally does not change tracking mode. However, if the tracking mode is\n" "turned on and the autoguiding mode is turned on as well (either by calling\n" "'autoguide on' command or by setting AUTOGUIDE=1 in the config file)\n" "then a correction to the tracking speed will be applied. Such correction is\n" "only valid in the case of uninterrupted tracking since previous 'astro' command." "\n\n" "NOTE: In the case when mount is neither tracking nor stopped all motors will be stopped\n" " and corrections applied (forced) to the motor steps." #ifndef STANDALONE // PIMAN and (REAL-TIME or SIMULATION) "\n" "NOTE: In order to correct (micro)steps precisely an internal check is always\n" " performed whether one of the two conditions is satisfied:\n" " 1. Both motors were stopped between last astrometry measurement\n" " and current 'astro' command.\n" " 2. Both motors were tracking continuously\n" " between last astrometry measurement and current 'astro' command.\n" " In the later case the elapsed time must be less than 1 hour." " These cross checks can be suppressed by calling 'astro FORCE'." #endif #ifdef SIMULATION // (PIMAN or STANDALONE) and SIMULATION "\n\nExample:\n" "1. This example artificially generates slide in RA axis, and then\n" " corrects internal mount's position using simulated astrometry:\n" " stat\n" " slide 30,0\n" " stat\n" " astro\n" " stat\n\n" #endif }, #endif { {"stop", "stp", "abort", "kill", "halt", "arret", NULL, NULL}, MONIT_CODE_STOP, do_stop, "stop [[,]]", "'stop' decelerates and stops a given motor.\n\n" "number={0,RA,HA} - Corresponds to RIGHT ASCENSION axis.\n" "number={1,DEC} - Corresponds to DECLINATION axis.\n\n" "Examples:\n" "1. To stop all motors and verify their status afterward:\n" " stop RA,DEC\n" " stat\n" "2. To check the current motor number and stop this motor:\n" " motor\n" " stop\n" " stat" #ifdef DEBUG "\n\nNOTE: 'stop' called without an argument stops the motor specified by\n" " a previous call of the 'motor' command." #endif } #ifdef DEBUG ,{ {"motor", "mot", "m", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_MOTOR, do_motor, "motor []", "'motor' sets current motor number (for: stop/get/set).\n\n" "number={0,RA,HA} - Corresponds to RIGHT ASCENSION axis.\n" "number={1,DEC} - Corresponds to DECLINATION axis.\n\n" "NOTE: 'motor' called without an argument prints the current motor.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, { {"get", "getparameter", "getparam", "getpar", "getp", "gap", "ggp", "g"}, MONIT_CODE_GET, do_get, "get []", "'get' queries value of TMCM-300 global or axis parameter.\n\n" "The motor number can be set by calling 'motor' command first.\n" "Refer to \"TMCL Reference and Programming Manual\" and \"TMC 428 - Data Sheet\"\n" "by TRINAMIC Microchips GmbH for more details.\n\n" "Examples:\n" "1. To check actual position, speed and acceleration in RIGHT ASCENSION axis:\n" " motor 0\n" " get actual\n" "2. To check status of the RIGHT limit switch in DECLINATION axis:\n" " motor 1\n" " get right_lim_stat\n\n" "NOTE: 'get' called without an argument prints all parameters.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, { {"set", "setparameter", "setparam", "setpar", "setp", "sap", "sgp", "s"}, MONIT_CODE_SET, do_set, "set ", "'set' sets value of TMCM-300 global or axis parameter.\n\n" "The motor number can be set by calling 'motor' command first.\n" "Refer to \"TMCL Reference and Programming Manual\" and \"TMC 428 - Data Sheet\"\n" "by TRINAMIC Microchips GmbH for more details.\n\n" "Examples:\n" "1. To move to a new target position (POS in microsteps):\n" " motor MOT (MOT=0,1 for RA,DEC respectively)\n" " set target_pos POS\n" " set ramp_mode 0\n" "2. To enable automatic stop on LEFT and RIGHT limit switches:\n" " motor MOT (MOT=0,1 for RA,DEC respectively)\n" " set lim_disable_flag 0\n" " set right_lim_disable 0\n" " set left_lim_disable 0\n" " dout 0 0\n" " dout CH 0 (CH=2,3 for RA,DEC respectively)\n\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, { {"dout", "digitaloutput", "digitaloutp", "digitalout", "doutput", "doutp", "do", NULL}, MONIT_CODE_DOUT, do_dout, "dout [ ]", "'dout' controls TTL digital outputs of TMCM-300 unit.\n\n" " - channel number (0..7)\n" " - new value (0 or 1)\n\n" "Examples:\n" "1. To enable/disable HOME limit switch in RIGHT ASCENSION axis:\n" " dout 2 1 - for enabling HOME\n" " dout 2 0 - for disabling HOME\n" "2. To enable/disable HOME limit switch in DECLINATION axis:\n" " dout 3 1 - for enabling HOME\n" " dout 3 0 - for disabling HOME\n\n" "NOTE: 'dout' called without an argument prints status of\n" " all digital outputs.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, { {"ain", "analoginput", "analoginp", "analogin", "ainput", "ainp", "ai", NULL}, MONIT_CODE_AIN, do_ain, "ain []", "'ain' queries ADC counts from analog inputs of TMCM-300 unit.\n\n" " - channel number (0..7)\n\n" "ADC range is 0..1023 counts (i.e. 0..5 V DC).\n\n" "Examples:\n" "1. To check coarse position from potentiometer in RIGHT ASCENSION axis:\n" " ain 6\n" "2. To check coarse position from potentiometer in DECLINATION axis:\n" " ain 7\n\n" "NOTE: 'ain' called without an argument prints status of\n" " all analog inputs.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, { {"din", "digitalinput", "digitalinp", "digitalin", "dinput", "dinp", "di", NULL}, MONIT_CODE_DIN, do_din, "din []", "'din' queries status of TTL digital inputs of TMCM-300 unit.\n\n" " - channel number (0..7)\n\n" "Examples:\n" "1. To check status of LEFT limit switch in RIGHT ASCENSION axis:\n" " din 0\n" "2. To check status of HOME limit switch in RIGHT ASCENSION axis:\n" " din 1\n" "3. To check status of LEFT limit switch in DECLINATION axis:\n" " din 2\n" "4. To check status of HOME limit switch in DECLINATION axis:\n" " din 3\n\n" "NOTE: 'din' called without an argument prints status of\n" " all digital inputs.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." } #ifdef SIMULATION ,{{"slide", "setslide", "sld", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_SLIDE, do_slide, "slide (1) or\n" "slide ra= d[ec]= (2) or\n" "slide ra= (3) or\n" "slide ha= d[ec]= (4) or\n" "slide ha= (5) or\n" "slide d[ec]= (6)", "'slide' artificially generates mismatch between motor counts and\n" "potentiometers' ADC counts. This command exists only in simulation mode.\n\n" "It acts as if somebody has shifted the hardware position of the cameras\n" "by specific angle(s). The mismatch can be then corrected by executing\n" "'calib 0' command, for example.\n\n" "If called with 2 arguments:\n" "Syntax (1): Two subsequent numbers without prefixes correspond to\n" " shift angle [deg] in RIGHT ASCENSION axis followed by\n" " shift angle [deg] in DECLINATION axis.\n" "Syntax (2): Equivalent to 'slide ,'.\n" "Syntax (4): Sets shift angle [deg] in HOUR ANGLE axis and shift angle\n" " [deg] in DECLINATION axis.\n\n" "If called with 1 argument:\n" "Syntax (3): Sets shift angle [deg] in RIGHT ASCENSION axis only.\n" " Equivalent to 'slide ,0' command.\n" "Syntax (5): Sets shift angle [deg] in HOUR ANGLE axis only.\n" " Equivalent to 'slide ha=,0' command.\n" "Syntax (6): Sets shift angle [deg] in DECLINATION axis only.\n" " Equivalent to 'slide 0,' command.\n\n" "Example:\n" "1. To generate a slide alert in RIGHT ASCENSION axis:\n" " stat\n" " slide ha=40\n" " stat\n\n" "NOTE: This command should be used ONLY FOR DEBUGGING." } ,{{"home", "sethome", "gohome", NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_HOME, do_home_position, "home", "'home' sets simulated mount to a predefined HOME position.\n" "This command exists only in the simulation mode. It acts as if somebody\n" "has shifted the hardware position of the cameras to a reference position\n" "(HOME) and has reset motor step counters to 0 inside TMCM-300 module." } ,{{"dump", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_DUMP, do_dump_to_file, "dump", "'dump' stores current state of the mount's simulator to a file.\n\n" #ifdef STANDALONE "All parameters will be restored next time a standalone session is\n" "started (including hardware position and speed).\n\n" #else "All parameters will be restored during next call of 'init' command\n" "(including hardware position and speed).\n\n" #endif "NOTE: 'quit' and 'pause' overwrite the file created by 'dump'.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." } #endif #endif #if !defined(SIMULATION) && defined(STANDALONE) && defined(RS232_ERROR_STUDY) ,{{"rs232_disconnect", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_RS232_DISCONNECT, do_rs232_disconnect, "rs232_disconnect []", "'rs232_disconnect' emulates momentary RS-232 failure delayed by number\n" "of seconds specidfied by DELAY parameter.\n\n" "NOTE: 'rs232_disconnect' called without an argument closes RS-232\n" " connection immediately.\n" "NOTE: Re-connecting is possible by issuing 'rs232_connect' command.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, {{"rs232_connect", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_RS232_CONNECT, do_rs232_connect, "rs232_connect", "'rs232_connect' tries to re-establish RS-232 connection with " "TMCM-300 module using current port name and baud rate settings.\n\n" "NOTE: RS-232 port will be blocked indefinitely after 'rs232_block' \n" " command until next 'rs232_connect' command.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." }, {{"rs232_block", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, MONIT_CODE_RS232_BLOCK, do_rs232_block, "rs232_block []", "'rs232_block' emultes permanent RS-232 failure delayed by number of\n" "seconds specified by DELAY parameter.\n" "NOTE: RS-232 port will be blocked indefinitely after 'rs232_block' \n" " command untill next 'rs232_connect' command.\n" "NOTE: This command should be used ONLY FOR DEBUGGING." } #endif }; int ncmd = sizeof(cmd_table)/sizeof(struct CMD_TABLE); struct STD_PARAMETER cfg_table[] = { { FORMAT_STRING_1D, "PORT=%s", CFG_RS232_PORTNAME, { (void*)&option_.rs232_portname, NULL}}, { FORMAT_INT_1D, "PORT_RECONNECT=%d", CFG_RS232_RECONNECT, { (void*)&option_.rs232_reconnect, NULL}}, { FORMAT_LONG_1D, "PORT_BAUDRATE=%ld", CFG_RS232_BAUDRATE, { (void*)&option_.rs232_baudrate, NULL}}, { FORMAT_STRING_1D, "SITE=%3s", CFG_SITE, { (void*)site_code, NULL}}, { FORMAT_INT_1D, "LOGGING=%d", CFG_LOGGING, { (void*)&logging, NULL}}, { FORMAT_INT_1D, "INIT_CALIB_FLAG=%d", CFG_INIT_CALIB_FLAG, { (void*)&option_.init_calib_flag, NULL}}, { FORMAT_INT_1D, "INIT_STOP_FLAG=%d", CFG_INIT_STOP_FLAG, { (void*)&option_.init_stop_flag, NULL}}, { FORMAT_INT_1D, "INIT_ENCODER_CHK=%d", CFG_INIT_ENCODER_CHK, { (void*)&option_.init_encoder_chk, NULL}}, { FORMAT_LONG_2D, "INIT_ENCODER_THR=%ld,%ld", CFG_INIT_ENCODER_THR, { (void*)&option_.init_encoder_thr[MOT_A], (void*)&option_.init_encoder_thr[MOT_D] }}, { FORMAT_INT_1D, "GETSTATUS_SLIDE_CHK=%d", CFG_GETSTATUS_SLIDE_CHK, { (void*)&option_.getstatus_slide_chk, NULL}}, { FORMAT_LONG_2D, "GETSTATUS_SLIDE_THR=%ld,%ld", CFG_GETSTATUS_SLIDE_THR, { (void*)&option_.getstatus_slide_thr[MOT_A], (void*)&option_.getstatus_slide_thr[MOT_D] }}, { FORMAT_LONG_2D, "GETSTATUS_SLIDE_DELAYMIN=%ld,%ld", CFG_GETSTATUS_SLIDE_DELAYMIN, { (void*)&option_.getstatus_slide_delaymin[MOT_A], (void*)&option_.getstatus_slide_delaymin[MOT_D] }}, { FORMAT_LONG_2D, "GETSTATUS_SLIDE_DELAYMAX=%ld,%ld", CFG_GETSTATUS_SLIDE_DELAYMAX, { (void*)&option_.getstatus_slide_delaymax[MOT_A], (void*)&option_.getstatus_slide_delaymax[MOT_D] }}, { FORMAT_INT_1D, "CALIB_NITER_FAST=%d", CFG_CALIB_NITER_FAST, { (void*)&option_.calib_niter_fast, NULL}}, { FORMAT_INT_1D, "CALIB_NITER_FULL=%d", CFG_CALIB_NITER_FULL, { (void*)&option_.calib_niter_full, NULL}}, { FORMAT_INT_1D, "CALIB_ENCODER_FASTPOS=%d", CFG_CALIB_ENCODER_FASTPOS, { (void*)&option_.calib_encoder_fastpos, NULL}}, { FORMAT_DOUBLE_1D, "CALIB_ENCODER_ANGLE=%lf", CFG_CALIB_ENCODER_ANGLE, { (void*)&option_.calib_encoder_angle, NULL}}, { FORMAT_INT_1D, "CALIB_SAFEZONE_CHK=%d", CFG_CALIB_SAFEZONE_CHK, { (void*)&option_.findswitch_safezone_chk, NULL}}, { FORMAT_LONG_2D, "CALIB_SAFEZONE_THR=%ld,%ld", CFG_CALIB_SAFEZONE_THR, { (void*)&option_.findswitch_safezone_thr[MOT_A], (void*)&option_.findswitch_safezone_thr[MOT_D] }}, { FORMAT_INT_1D, "CALIB_SLIDE_CHK=%d", CFG_CALIB_SLIDE_CHK, { (void*)&option_.findswitch_slide_chk, NULL}}, { FORMAT_LONG_2D, "CALIB_SLIDE_THR=%ld,%ld", CFG_CALIB_SLIDE_THR, { (void*)&option_.findswitch_slide_thr[MOT_A], (void*)&option_.findswitch_slide_thr[MOT_D] }}, { FORMAT_LONG_2D, "CALIB_ENCODER_DELAY=%ld,%ld", CFG_CALIB_ENCODER_DELAY, { (void*)&option_.findswitch_encoder_delay[MOT_A], (void*)&option_.findswitch_encoder_delay[MOT_D] }}, { FORMAT_INT_2D, "CALIB_ENCODER_IS_PRECISE=%d,%d", CFG_CALIB_ENCODER_IS_PRECISE, { (void*)&option_.calib_encoder_is_precise[MOT_A], (void*)&option_.calib_encoder_is_precise[MOT_D] }}, { FORMAT_DOUBLE_1D, "CALIB_STEP_ANGLE=%lf", CFG_CALIB_STEP_ANGLE, { (void*)&option_.findswitch_step_angle, NULL}}, { FORMAT_DOUBLE_1D, "PARK_RND_MINHEIGHT=%lf", CFG_PARK_MINHEIGHT, { (void*)&option_.dopark_minheight, NULL}}, { FORMAT_DOUBLE_1D, "PARK_RND_MAXHEIGHT=%lf", CFG_PARK_MAXHEIGHT, { (void*)&option_.dopark_maxheight, NULL}}, { FORMAT_DOUBLE_1D, "PARK_RND_MINAZIMUTH=%lf", CFG_PARK_MINAZIMUTH, { (void*)&option_.dopark_minazimuth, NULL}}, { FORMAT_DOUBLE_1D, "PARK_RND_MAXAZIMUTH=%lf", CFG_PARK_MAXAZIMUTH, { (void*)&option_.dopark_maxazimuth, NULL}}, { FORMAT_INT_1D, "PARK_RND_MAXITER=%d", CFG_PARK_MAXITER, { (void*)&option_.dopark_maxiter, NULL}}, { FORMAT_DOUBLE_1D, "PARK_FAILSAFE_AZ=%lf", CFG_PARK_AZ_SAFE, { (void*)&option_.dopark_az_safe, NULL}}, { FORMAT_DOUBLE_1D, "PARK_FAILSAFE_H=%lf", CFG_PARK_H_SAFE, { (void*)&option_.dopark_h_safe, NULL}}, { FORMAT_DOUBLE_1D, "PARK_SWITCH_CLEARANCE=%lf", CFG_PARK_SWITCH_CLEARANCE, { (void*)&option_.dopark_switch_clearance, NULL}}, { FORMAT_INT_1D, "PARK_PRECISION=%d", CFG_PARK_PRECISION, { (void*)&option_.dopark_precision, NULL}}, { FORMAT_DOUBLE_1D, "ZENITH_SWITCH_CLEARANCE=%lf", CFG_ZENITH_SWITCH_CLEARANCE, { (void*)&option_.dozenith_switch_clearance, NULL}}, { FORMAT_INT_1D, "ZENITH_PRECISION=%d", CFG_ZENITH_PRECISION, { (void*)&option_.dozenith_precision, NULL}}, { FORMAT_INT_1D, "AUTOGUIDE=%d", CFG_AUTOGUIDE, { (void*)&autoguiding, NULL}}, { FORMAT_INT_2D, "ABSOLUTE_ENCODER_TYPE=%d,%d", CFG_ABSOLUTE_ENCODER_TYPE, { (void*)&option_.absolute_encoder_type[MOT_A], (void*)&option_.absolute_encoder_type[MOT_D] }}, { FORMAT_LONG_2D, "ABSOLUTE_ENCODER_PREC_LOW=%ld,%ld", CFG_ABSOLUTE_ENCODER_PREC_LOW, { (void*)&option_.absolute_encoder_prec_low[MOT_A], (void*)&option_.absolute_encoder_prec_low[MOT_D] }}, { FORMAT_LONG_2D, "ABSOLUTE_ENCODER_PREC_HIGH=%ld,%ld", CFG_ABSOLUTE_ENCODER_PREC_HIGH, { (void*)&option_.absolute_encoder_prec_high[MOT_A], (void*)&option_.absolute_encoder_prec_high[MOT_D] }}, { FORMAT_DOUBLE_2D, "ASTRO_AG_MAXCORR=%lf,%lf", CFG_ASTRO_AG_MAXCORR, { (void*)&option_.astro_ag_maxcorr[MOT_A], (void*)&option_.astro_ag_maxcorr[MOT_D] }}, { FORMAT_LONG_1D, "ASTRO_AG_MINDELAY=%ld", CFG_ASTRO_AG_MINDELAY, { (void*)&option_.astro_ag_mindelay, NULL}}, { FORMAT_LONG_1D, "ASTRO_MAXDELAY=%ld", CFG_ASTRO_MAXDELAY, { (void*)&option_.astro_maxdelay, NULL}}, { FORMAT_INT_1D, "ASTRO_ENCODER_CHK=%d", CFG_ASTRO_ENCODER_CHK, { (void*)&option_.astro_encoder_chk, NULL }}, { FORMAT_LONG_2D, "ASTRO_ENCODER_CHK_THR=%ld,%ld", CFG_ASTRO_ENCODER_CHK_THR, { (void*)&option_.astro_encoder_chk_thr[MOT_A], (void*)&option_.astro_encoder_chk_thr[MOT_D] }}, /////////////////////////////////////////////////////// // // paramters for pre-defined motor speeds // /////////////////////////////////////////////////////// { FORMAT_INT_2D, "MOTOR_FAST_PULSE_DIV=%d,%d", CFG_MOTOR_FAST_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_FAST_RAMP_DIV=%d,%d", CFG_MOTOR_FAST_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_FAST_MAX_CURRENT=%d,%d", CFG_MOTOR_FAST_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_FAST_MAX_SPEED=%d,%d", CFG_MOTOR_FAST_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_FAST_MIN_SPEED=%d,%d", CFG_MOTOR_FAST_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_FAST_MICROSTEP=%d,%d", CFG_MOTOR_FAST_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_FAST_MAX_ACCEL=%d,%d", CFG_MOTOR_FAST_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_FAST_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, /////////////////////////////////////////////////////////////////////////// { FORMAT_INT_2D, "MOTOR_MEDIUM_PULSE_DIV=%d,%d", CFG_MOTOR_MEDIUM_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_RAMP_DIV=%d,%d", CFG_MOTOR_MEDIUM_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_MAX_CURRENT=%d,%d", CFG_MOTOR_MEDIUM_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_MAX_SPEED=%d,%d", CFG_MOTOR_MEDIUM_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_MIN_SPEED=%d,%d", CFG_MOTOR_MEDIUM_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_MICROSTEP=%d,%d", CFG_MOTOR_MEDIUM_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_MEDIUM_MAX_ACCEL=%d,%d", CFG_MOTOR_MEDIUM_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_MEDIUM_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, /////////////////////////////////////////////////////////////////////////// { FORMAT_INT_2D, "MOTOR_TRACK_PULSE_DIV=%d,%d", CFG_MOTOR_TRACK_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_RAMP_DIV=%d,%d", CFG_MOTOR_TRACK_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_MAX_CURRENT=%d,%d", CFG_MOTOR_TRACK_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_MAX_SPEED=%d,%d", CFG_MOTOR_TRACK_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_MIN_SPEED=%d,%d", CFG_MOTOR_TRACK_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_MICROSTEP=%d,%d", CFG_MOTOR_TRACK_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_TRACK_MAX_ACCEL=%d,%d", CFG_MOTOR_TRACK_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_TRACK_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, /////////////////////////////////////////////////////////////////////////// { FORMAT_INT_2D, "MOTOR_CALIB_PULSE_DIV=%d,%d", CFG_MOTOR_CALIB_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_RAMP_DIV=%d,%d", CFG_MOTOR_CALIB_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_MAX_CURRENT=%d,%d", CFG_MOTOR_CALIB_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_MAX_SPEED=%d,%d", CFG_MOTOR_CALIB_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_MIN_SPEED=%d,%d", CFG_MOTOR_CALIB_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_MICROSTEP=%d,%d", CFG_MOTOR_CALIB_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_CALIB_MAX_ACCEL=%d,%d", CFG_MOTOR_CALIB_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_CALIB_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, /////////////////////////////////////////////////////////////////////////// { FORMAT_INT_2D, "MOTOR_FLATS_PULSE_DIV=%d,%d", CFG_MOTOR_FLATS_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_RAMP_DIV=%d,%d", CFG_MOTOR_FLATS_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_MAX_CURRENT=%d,%d", CFG_MOTOR_FLATS_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_MAX_SPEED=%d,%d", CFG_MOTOR_FLATS_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_MIN_SPEED=%d,%d", CFG_MOTOR_FLATS_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_MICROSTEP=%d,%d", CFG_MOTOR_FLATS_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_FLATS_MAX_ACCEL=%d,%d", CFG_MOTOR_FLATS_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_FLATS_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, /////////////////////////////////////////////////////////////////////////// #ifdef MICROTRACKING { FORMAT_INT_2D, "MOTOR_MICROTRACK_PULSE_DIV=%d,%d", CFG_MOTOR_MICROTRACK_PULSE_DIV, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_PULSE_DIV].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_RAMP_DIV=%d,%d", CFG_MOTOR_MICROTRACK_RAMP_DIV, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_RAMP_DIV].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_MAX_CURRENT=%d,%d", CFG_MOTOR_MICROTRACK_MAX_CURRENT, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_CURRENT].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_MAX_SPEED=%d,%d", CFG_MOTOR_MICROTRACK_MAX_SPEED, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_MIN_SPEED=%d,%d", CFG_MOTOR_MICROTRACK_MIN_SPEED, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MIN_SPEED].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_MICROSTEP=%d,%d", CFG_MOTOR_MICROTRACK_MICROSTEP, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MICROSTEP].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MICROSTEP].val }}, { FORMAT_INT_2D, "MOTOR_MICROTRACK_MAX_ACCEL=%d,%d", CFG_MOTOR_MICROTRACK_MAX_ACCEL, {(void*)&mot_speed [MOT_A][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val, (void*)&mot_speed [MOT_D][MOT_MICROTRACK_SPEED][MOT_SPEED_INDEX_MAX_ACCEL].val }}, #endif /////////////////////////////////////////////////////// // // common parameters for all speeds // /////////////////////////////////////////////////////// { FORMAT_INT_1D, "MOTOR_CURRENT_MAX=%d", CFG_MOTOR_CURRENT_MAX, { (void*)&mot_common[MOT_COMMON_INDEX_MAX_CURRENT].val, NULL }}, { FORMAT_INT_1D, "MOTOR_CURRENT_STANDBY=%d", CFG_MOTOR_CURRENT_STANDBY, { (void*)&mot_common[MOT_COMMON_INDEX_STANDBY_CURRENT].val, NULL }}, { FORMAT_INT_1D, "MOTOR_CURRENT_AT_REST=%d", CFG_MOTOR_CURRENT_AT_REST, { (void*)&mot_common[MOT_COMMON_INDEX_MAX_CURRENT_AT_REST].val, NULL }}, { FORMAT_INT_1D, "MOTOR_CURRENT_AT_LOW_ACC=%d", CFG_MOTOR_CURRENT_AT_LOW_ACC, { (void*)&mot_common[MOT_COMMON_INDEX_MAX_CURRENT_AT_LOW_ACC].val, NULL }}, { FORMAT_INT_1D, "MOTOR_CURRENT_AT_HIGH_ACC=%d", CFG_MOTOR_CURRENT_AT_HIGH_ACC, { (void*)&mot_common[MOT_COMMON_INDEX_MAX_CURRENT_AT_HIGH_ACC].val, NULL }}, { FORMAT_INT_1D, "MOTOR_ACCEL_THRESHOLD=%d", CFG_MOTOR_ACCEL_THRESHOLD, { (void*)&mot_common[MOT_COMMON_INDEX_ACCEL_THRESHOLD].val, NULL }}, { FORMAT_INT_1D, "MOTOR_REFERENCE_SPEED_SEARCH=%d", CFG_MOTOR_REFERENCE_SPEED_SEARCH, { (void*)&mot_common[MOT_COMMON_INDEX_REF_SEARCH_SPEED].val, NULL }}, { FORMAT_INT_1D, "MOTOR_REFERENCE_SPEED_CALIB=%d", CFG_MOTOR_REFERENCE_SPEED_CALIB, { (void*)&mot_common[MOT_COMMON_INDEX_REF_CALIB_SPEED].val, NULL }}, { FORMAT_INT_1D, "MOTOR_REFERENCE_DISABLE=%d", CFG_MOTOR_REFERENCE_DISABLE, { (void*)&mot_common[MOT_COMMON_INDEX_REF_DISABLE].val, NULL }}, { FORMAT_INT_1D, "MOTOR_LIMIT_DISABLE=%d", CFG_MOTOR_LIMIT_DISABLE, { (void*)&mot_common[MOT_COMMON_INDEX_LIMIT_DISABLE].val, NULL }}, { FORMAT_INT_1D, "MOTOR_LIMIT_DISABLE_LEFT=%d", CFG_MOTOR_LIMIT_DISABLE_LEFT, { (void*)&mot_common[MOT_COMMON_INDEX_LEFT_LIMIT_DISABLE].val, NULL }}, { FORMAT_INT_1D, "MOTOR_LIMIT_DISABLE_RIGHT=%d", CFG_MOTOR_LIMIT_DISABLE_RIGHT, { (void*)&mot_common[MOT_COMMON_INDEX_RIGHT_LIMIT_DISABLE].val, NULL }}, { FORMAT_INT_1D, "MOTOR_REFERENCE_TOLERANCE=%d", CFG_MOTOR_REFERENCE_TOLERANCE, { (void*)&mot_common[MOT_COMMON_INDEX_REF_TOLERANCE].val, NULL }}, { FORMAT_DOUBLE_1D, "MOTOR_CLK_FREQ=%lf", CFG_MOTOR_CLK_FREQ, { (void*)&option_.TMCL_CLK_FREQ, NULL}}, { FORMAT_DOUBLE_1D, "MOTOR_MICROSTEP_FREQ_MAX=%lf", CFG_MOTOR_MICROSTEP_FREQ_MAX, { (void*)&option_.TMCL_MICROSTEP_FREQ_MAX, NULL}}, { FORMAT_DOUBLE_2D, "MOTOR_FULLSTEP_FREQ_MAX=%lf,%lf", CFG_MOTOR_FULLSTEP_FREQ_MAX, { (void*)&option_.TMCL_FULLSTEP_FREQ_MAX[MOT_A], (void*)&option_.TMCL_FULLSTEP_FREQ_MAX[MOT_D] }}, { FORMAT_DOUBLE_2D, "MOTOR_GEAR_RATIO=%lf,%lf", CFG_MOTOR_GEARRATIO, { (void*)&option_.motor_gear_ratio[MOT_A], (void*)&option_.motor_gear_ratio[MOT_D] }}, { FORMAT_DOUBLE_2D, "MOTOR_HOME_OFFSET=%lf,%lf", CFG_MOTOR_HOMEOFFSET, { (void*)&option_.motor_home_offset[MOT_A], (void*)&option_.motor_home_offset[MOT_D] }}, { FORMAT_INT_2D, "MOTOR_POLARITY=%d,%d", CFG_MOTOR_POLARITY, { (void*)&option_.motor_polarity[MOT_A], (void*)&option_.motor_polarity[MOT_D] }} #ifdef WATCHDOG ,{ FORMAT_INT_1D, "WATCHDOG=%d", CFG_WATCHDOG, { (void*)&watchdog, NULL}} #endif #ifdef AUTOCALIBRATION ,{ FORMAT_INT_1D, "AUTOCALIB=%d", CFG_AUTOCALIB, { (void*)&autocalib, NULL}} #endif #ifdef MICROTRACKING ,{ FORMAT_INT_1D, "MICROTRACKING=%d", CFG_MICROTRACKING, { (void*)µtracking, NULL}} #endif #ifdef SIMULATION ,{ FORMAT_DOUBLE_1D, "SIMUL_TFACTOR=%lf", CFG_SIMUL_TFACTOR, { (void*)&TMCL_SIMUL_geom.time_factor, NULL}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_MIN=%lf,%lf", CFG_SIMUL_ANGLE_MIN, { (void*)&TMCL_SIMUL_geom.angle_MIN[MOT_A], (void*)&TMCL_SIMUL_geom.angle_MIN[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_LEFT=%lf,%lf", CFG_SIMUL_ANGLE_LEFT, { (void*)&TMCL_SIMUL_geom.angle_LEFT[MOT_A], (void*)&TMCL_SIMUL_geom.angle_LEFT[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_HL=%lf,%lf", CFG_SIMUL_ANGLE_HL, { (void*)&TMCL_SIMUL_geom.angle_HOMEL[MOT_A], (void*)&TMCL_SIMUL_geom.angle_HOMEL[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_HR=%lf,%lf", CFG_SIMUL_ANGLE_HR, { (void*)&TMCL_SIMUL_geom.angle_HOMER[MOT_A], (void*)&TMCL_SIMUL_geom.angle_HOMER[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_RIGHT=%lf,%lf", CFG_SIMUL_ANGLE_RIGHT, { (void*)&TMCL_SIMUL_geom.angle_RIGHT[MOT_A], (void*)&TMCL_SIMUL_geom.angle_RIGHT[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ANGLE_MAX=%lf,%lf", CFG_SIMUL_ANGLE_MAX, { (void*)&TMCL_SIMUL_geom.angle_MAX[MOT_A], (void*)&TMCL_SIMUL_geom.angle_MAX[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_FS_GEAR=%lf,%lf", CFG_SIMUL_FS_GEAR, { (void*)&TMCL_SIMUL_geom.fs_gear[MOT_A], (void*)&TMCL_SIMUL_geom.fs_gear[MOT_D]}}, /* { FORMAT_INT_2D, */ /* "SIMUL_FS_POL=%d,%d", CFG_SIMUL_FS_POL, */ /* { (void*)&TMCL_SIMUL_geom.fs_polarity[MOT_A], */ /* (void*)&TMCL_SIMUL_geom.fs_polarity[MOT_D]}}, */ { FORMAT_DOUBLE_2D, "SIMUL_FS_HOME=%lf,%lf", CFG_SIMUL_FS_HOME, { (void*)&TMCL_SIMUL_geom.fs_home[MOT_A], (void*)&TMCL_SIMUL_geom.fs_home[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ENC_GEAR=%lf,%lf", CFG_SIMUL_ENC_GEAR, { (void*)&TMCL_SIMUL_geom.enc_gear[MOT_A], (void*)&TMCL_SIMUL_geom.enc_gear[MOT_D]}}, { FORMAT_INT_2D, "SIMUL_ENC_POL=%d,%d", CFG_SIMUL_ENC_POL, { (void*)&TMCL_SIMUL_geom.enc_polarity[MOT_A], (void*)&TMCL_SIMUL_geom.enc_polarity[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ENC_HOME=%lf,%lf", CFG_SIMUL_ENC_HOME, { (void*)&TMCL_SIMUL_geom.enc_home[MOT_A], (void*)&TMCL_SIMUL_geom.enc_home[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_ENC_SMEAR=%lf,%lf", CFG_SIMUL_ENC_SMEAR, { (void*)&TMCL_SIMUL_geom.enc_rms[MOT_A], (void*)&TMCL_SIMUL_geom.enc_rms[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_POT_GEAR=%lf,%lf", CFG_SIMUL_POT_GEAR, { (void*)&TMCL_SIMUL_geom.pot_gear[MOT_A], (void*)&TMCL_SIMUL_geom.pot_gear[MOT_D]}}, { FORMAT_INT_2D, "SIMUL_POT_POL=%d,%d", CFG_SIMUL_POT_POL, { (void*)&TMCL_SIMUL_geom.pot_polarity[MOT_A], (void*)&TMCL_SIMUL_geom.pot_polarity[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_POT_HOME=%lf,%lf", CFG_SIMUL_POT_HOME, { (void*)&TMCL_SIMUL_geom.pot_home[MOT_A], (void*)&TMCL_SIMUL_geom.pot_home[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_POT_SMEAR=%lf,%lf", CFG_SIMUL_POT_SMEAR, { (void*)&TMCL_SIMUL_geom.pot_rms[MOT_A], (void*)&TMCL_SIMUL_geom.pot_rms[MOT_D]}}, { FORMAT_DOUBLE_2D, "SIMUL_HOME=%lf,%lf", CFG_SIMUL_OFFSET_HOME, { (void*)&TMCL_SIMUL_geom.offset_home[MOT_A], (void*)&TMCL_SIMUL_geom.offset_home[MOT_D]}} #endif }; int ncfg=sizeof(cfg_table)/sizeof(struct STD_PARAMETER); struct STD_PARAMETER loc_table[] = { {FORMAT_STRING_1D, "CODE=%s", LOC_CODE, { (void*)site_code, NULL}}, {FORMAT_STRING_1D, "COMMENT=%[^\n]", LOC_COMMENT, { (void*)site_comment,NULL}}, {FORMAT_DOUBLE_1D, "LATITUDE=%lf", LOC_LATITUDE, { (void*)&latitude, NULL}}, {FORMAT_DOUBLE_1D, "LONGITUDE=%lf", LOC_LONGITUDE, { (void*)&longitude, NULL}}, {FORMAT_DOUBLE_1D, "ALTITUDE=%lf", LOC_ALTITUDE, { (void*)&altitude, NULL}} }; int nloc = sizeof(loc_table)/sizeof(struct STD_PARAMETER); struct STD_PARAMETER cal_table[] = { {FORMAT_DOUBLE_2D, "GEAR_RATIO=%le,%le", CAL_GEAR, { (void*)&calib.gear_ratio[MOT_A], (void*)&calib.gear_ratio[MOT_D] }}, {FORMAT_DOUBLE_2D, "HOME_OFFSET=%le,%le", CAL_OFF, { (void*)&calib.home_offset[MOT_A], (void*)&calib.home_offset[MOT_D] }}, {FORMAT_INT_2D, "MOTOR_POLARITY=%d,%d", CAL_MOTPOL, { (void*)&calib.motor_polarity[MOT_A], (void*)&calib.motor_polarity[MOT_D]}}, {FORMAT_INT_2D, "MICROSTEP=%d,%d", CAL_MICROSTEP, { (void*)&calib.microstep[MOT_A], (void*)&calib.microstep[MOT_D] }}, {FORMAT_LONG_2D, "XL=%ld,%ld", CAL_XL, { (void*)&calib.XL[MOT_A], (void*)&calib.XL[MOT_D] }}, {FORMAT_LONG_2D, "XMIN=%ld,%ld", CAL_XMIN, { (void*)&calib.XMIN[MOT_A], (void*)&calib.XMIN[MOT_D] }}, {FORMAT_LONG_2D, "XHL=%ld,%ld", CAL_XHL, { (void*)&calib.XHL[MOT_A], (void*)&calib.XHL[MOT_D] }}, {FORMAT_LONG_2D, "XHR=%ld,%ld", CAL_XHR, { (void*)&calib.XHR[MOT_A], (void*)&calib.XHR[MOT_D] }}, {FORMAT_LONG_2D, "XMAX=%ld,%ld", CAL_XMAX, { (void*)&calib.XMAX[MOT_A], (void*)&calib.XMAX[MOT_D] }}, {FORMAT_LONG_2D, "XR=%ld,%ld", CAL_XR, { (void*)&calib.XR[MOT_A], (void*)&calib.XR[MOT_D] }}, {FORMAT_LONG_2D, "ADCL=%ld,%ld", CAL_ADCL, { (void*)&calib.ADCL[MOT_A], (void*)&calib.ADCL[MOT_D] }}, {FORMAT_LONG_2D, "ADCMIN=%ld,%ld", CAL_ADCMIN, { (void*)&calib.ADCMIN[MOT_A], (void*)&calib.ADCMIN[MOT_D] }}, {FORMAT_LONG_2D, "ADCHL=%ld,%ld", CAL_ADCHL, { (void*)&calib.ADCHL[MOT_A], (void*)&calib.ADCHL[MOT_D] }}, {FORMAT_LONG_2D, "ADCHR=%ld,%ld", CAL_ADCHR, { (void*)&calib.ADCHR[MOT_A], (void*)&calib.ADCHR[MOT_D] }}, {FORMAT_LONG_2D, "ADCMAX=%ld,%ld", CAL_ADCMAX, { (void*)&calib.ADCMAX[MOT_A], (void*)&calib.ADCMAX[MOT_D] }}, {FORMAT_LONG_2D, "ADCR=%ld,%ld", CAL_ADCR, { (void*)&calib.ADCR[MOT_A], (void*)&calib.ADCR[MOT_D] }} }; int ncal = sizeof(cal_table)/sizeof(struct STD_PARAMETER); struct STD_PARAMETER lastsave_table[] = { { FORMAT_LONG_1D, "TIMESTAMP=%ld", LASTSAVE_TIMESTAMP, { (void*)&lastsave.timestamp, NULL }}, { FORMAT_DOUBLE_1D, "LATITUDE=%le", LASTSAVE_LATITUDE, { (void*)&lastsave.latitude, NULL }}, { FORMAT_DOUBLE_1D, "LONGITUDE=%le", LASTSAVE_LONGITUDE, { (void*)&lastsave.longitude, NULL }}, { FORMAT_DOUBLE_2D, "GEAR_RATIO=%le,%le", LASTSAVE_GEAR_RATIO, { (void*)&lastsave.gear_ratio[MOT_A], (void*)&lastsave.gear_ratio[MOT_D] }}, { FORMAT_DOUBLE_2D, "HOME_OFFSET=%le,%le", LASTSAVE_HOME_OFFSET, { (void*)&lastsave.home_offset[MOT_A], (void*)&lastsave.home_offset[MOT_D] }}, { FORMAT_INT_2D, "MOTOR_POLARITY=%d,%d", LASTSAVE_MOTOR_POLARITY, { (void*)&lastsave.motor_polarity[MOT_A], (void*)&lastsave.motor_polarity[MOT_D] }}, { FORMAT_LONG_2D, "COUNT=%ld,%ld", LASTSAVE_COUNT, { (void*)&lastsave.pos[MOT_A], (void*)&lastsave.pos[MOT_D] }}, { FORMAT_INT_2D, "MICROSTEP=%d,%d", LASTSAVE_MICROSTEP, { (void*)&lastsave.microstep[MOT_A], (void*)&lastsave.microstep[MOT_D] }}, { FORMAT_INT_2D, "ADC=%ld,%ld", LASTSAVE_ADC, { (void*)&lastsave.adc[MOT_A], (void*)&lastsave.adc[MOT_D] }}, { FORMAT_INT_2D, "NEEDCALIB=%d,%d", LASTSAVE_NEEDCALIB, { (void*)&lastsave.needcalib_flag[MOT_A], (void*)&lastsave.needcalib_flag[MOT_D] }}, { FORMAT_INT_2D, "TRACK_MICROSTEP=%d,%d", LASTSAVE_TRACK_MICROSTEP, { (void*)&lastsave.track_microstep[MOT_A], (void*)&lastsave.track_microstep[MOT_D] }}, { FORMAT_INT_2D, "TRACK_PDIV=%d,%d", LASTSAVE_TRACK_PDIV, { (void*)&lastsave.track_pdiv[MOT_A], (void*)&lastsave.track_pdiv[MOT_D] }}, { FORMAT_INT_2D, "TRACK_SPEED=%d,%d", LASTSAVE_TRACK_SPEED, { (void*)&lastsave.track_speed[MOT_A], (void*)&lastsave.track_speed[MOT_D] }} #ifdef MICROTRACKING ,{ FORMAT_INT_2D, "MICROTRACK_MICROSTEP=%d,%d", LASTSAVE_MICROTRACK_MICROSTEP, { (void*)&lastsave.microtrack_microstep[MOT_A], (void*)&lastsave.microtrack_microstep[MOT_D] }}, { FORMAT_INT_2D, "MICROTRACK_PDIV=%d,%d", LASTSAVE_MICROTRACK_PDIV, { (void*)&lastsave.microtrack_pdiv[MOT_A], (void*)&lastsave.microtrack_pdiv[MOT_D] }}, { FORMAT_INT_2D, "MICROTRACK_SPEED=%d,%d", LASTSAVE_MICROTRACK_SPEED, { (void*)&lastsave.microtrack_speed[MOT_A], (void*)&lastsave.microtrack_speed[MOT_D] }} #endif }; /* int nlastsave = sizeof(lastsave_table)/sizeof(struct LASTSAVE_TABLE); */ int nlastsave = sizeof(lastsave_table)/sizeof(struct STD_PARAMETER); int motor=0; #ifdef STANDALONE /************************************************************ * old MAIN ************************************************* ************************************************************/ int main(argc,argv) int argc; char ** argv; { int mot,i,j; int *fd=&fd_; //mc: pointer to RS-232 file descriptor (a global variable) int found,icmd; char *buf=NULL, *tok=NULL, *arg=NULL; #define MSG_FUNC "monit" #else #define MSG_FUNC "do_init" int do_init(fd,arg,mot) //kn int *fd,mot; //mc: pointer to RS232 file descriptor declared elsewhere const char *arg; //kn { /* extern int fd; */ //kn int i; //kn //kn int found,icmd; //kn char *buf=NULL, *tok=NULL; #endif #ifdef SIMULATION extern TMCL_SIMUL_GEOMETRY TMCL_SIMUL_geom; #endif extern struct STD_PARAMETER loc_table[]; extern int nloc; /* extern struct STD_PARAMETER cal_table[]; */ /* extern int ncal; */ extern int mount_initialized; // MC - 26 March 2005 /* char port[1000], extra[100]; */ int keys_found; #ifdef STANDALONE //---------------------------------------------- STANDALONE int speed; // RS232 communication speed extern int status[2]; #endif //--------------------------------------------------------- STANDALONE int err=0; // no critical errors, so far int res; // fscanf result time_t t; // current time FILE *cfg_file=NULL; // config file FILE *loc_file=NULL; // site database file /* FILE *cal_file=NULL; // calibration file */ struct tm time_day; // broken-down current date and time /* #ifndef SIMULATION //-------------------------------------------- SIMULATION */ /* long baud_rate_EEPROM; */ /* #endif //-------------------------------------------------------- SIMULATION */ #ifdef STANDALONE //--------------------------------------------- STANDALONE int err1; #ifdef AUTOCALIBRATION //---------------------------------------- AUTOMATIC CALIBRATION #ifdef _HAS_DO_ASTROMETRY_ time_t tauto; #endif #endif //-------------------------------------------------------- AUTOMATIC CALIBRATION #endif //-------------------------------------------------------- STANDALONE #ifdef STANDALONE //--------------------------------------------- STANDALONE #ifdef WATCHDOG //----------------------------------------------- WATCHDOG time_t watch_t0; // updates WATCH_lastcmd structure in STANDALONE mode // (in CORBA mode do_init was executed by execute_command() // which takes care of updating WATCH_lastcmd structure) WATCH_lastcmd->cmd_start_timestamp=time(NULL); sprintf(WATCH_lastcmd->cmd_args,"%s","init"); WATCH_lastcmd->cmd_run_flag = 1; WATCH_lastcmd->cmd_end_timestamp = 0; WATCH_lastcmd->cmd_result = ERROR_RESULT_OK; WATCH_lastcmd->ra = 0; WATCH_lastcmd->ha = 0; WATCH_lastcmd->dec = 0; WATCH_lastcmd->az = 0; WATCH_lastcmd->h = 0; WATCH_lastcmd->timestamp = 0; WATCH_lastcmd->timestamp_coo = 0; WATCH_lastcmd->needcalib = 0; for(mot=0;mot<2;mot++) { status[mot] = MOT_STAT_BUSY; WATCH_lastcmd->FS_pos[mot] = 0; WATCH_lastcmd->ADC_pos[mot] = 0; WATCH_lastcmd->LEFTHOME_switch[mot] = 0; WATCH_lastcmd->RIGHT_switch[mot] = 0; WATCH_lastcmd->motor_status[mot] = status[mot]; WATCH_lastcmd->motor_status_coo[mot] = status[mot]; } #endif //-------------------------------------------------------- STANDALONE #endif //-------------------------------------------------------- WATCHDOG #ifndef STANDALONE // msg_filename(kn_log_name,MSG_FUNC": BEGIN: fd=%p, arg=%p |%s|, mot=%d\n",fd,arg,arg,mot); // mc if(fd!=NULL) printf(MSG_FUNC": BEGIN: fd=%p (val=%d), arg=%p |%s|, mot=%d\n", fd, *fd, arg, arg, mot); else printf(MSG_FUNC": BEGIN: fd=%p (val=UNKNOWN), arg=%p |%s|, mot=%d\n", fd, arg, arg, mot); fflush(0); #endif // printf(MSG_FUNC": checkpoint 0\n");fflush(0); // mc /* initializes random number geneartor */ rand_seed((unsigned int)t); // printf(MSG_FUNC": checkpoint 1\n");fflush(0); // mc /* closes old logfile (if any) */ if( log_file!=NULL ) { fflush(log_file); fclose(log_file); } // printf(MSG_FUNC": checkpoint 2\n");fflush(0); // mc #ifdef WATCHDOG /* terminates old watchdog daemon (if any) */ WATCH_destroy(); #endif #ifdef SIMULATION /* exits old simulator (if any) */ TMCL_SIMUL_destroy(); #else /* closes old serial port descriptor (if any) */ #ifndef STANDALONE printf(MSG_FUNC": before closing RS232 port.\n");fflush(0); // mc #endif if (fd!=NULL && *fd>=0) { if( close_serial(fd)!=0 ) msg(log_file, MSG_FUNC": Serial port close ERROR\n"); } #ifndef STANDALONE printf(MSG_FUNC": after closing RS232 port.\n");fflush(0); // mc #endif #endif //#ifndef STANDALONE // msg_filename(kn_log_name,MSG_FUNC": checkpoint1\n"); //#endif /* prepares new logfile */ t=time(NULL); localtime_r(&t,&time_day); sprintf(log_name,"%s%04d%02d%02d_%02d%02d%02d", MOUNT_DEFAULT_FILE_LOG, time_day.tm_year+1900, time_day.tm_mon+1, time_day.tm_mday, time_day.tm_hour, time_day.tm_min, time_day.tm_sec); log_file=fopen(log_name,"w"); if(log_file==NULL) { err=ERROR_RESULT_IO; msg(log_file,MSG_FUNC": Can't open log file: <%s>\n",log_name); fflush(log_file); } msg(log_file, MSG_FUNC": " _MONIT_SESSION_TYPE_ " TRINAMIC TMCM-300 session started at: %s" " %s\n",ctime(&t),_MONIT_BUILD_VERSION_); fflush(log_file); /* loads default values from CONFIG file */ if ( !err && (cfg_file=fopen(MOUNT_DEFAULT_FILE_CONFIG,"rt"))==NULL ) { err=ERROR_RESULT_CONFIG; msg(log_file,MSG_FUNC": Can't open configuration file <%s>\n", MOUNT_DEFAULT_FILE_CONFIG); fflush(log_file); } ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef SIMULATION for(mot=0;mot<2;mot++) { msg(log_file, "main:motor-%d: BEFORE_CONFIG_FILE: ptr=%p\n" " FULL_STEP: gear=%lf\n" " POT: pol=%d, gear=%lf\n" " ENCODER: pol=%d, gear=%lf\n", mot, &TMCL_SIMUL_geom, // TMCL_SIMUL_geom.fs_polarity[mot], TMCL_SIMUL_geom.fs_gear[mot], TMCL_SIMUL_geom.pot_polarity[mot], TMCL_SIMUL_geom.pot_gear[mot], TMCL_SIMUL_geom.enc_polarity[mot], TMCL_SIMUL_geom.enc_gear[mot] ); } #endif #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 1: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /* loads config parameters from file */ keys_found=0; if (!err) { /* loads configuration parameters from file */ for(i=0;i0 ) keys_found++; }; fclose(cfg_file); } /* end of if(!err) */ ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 2: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /* checks if all parameters have been read */ if (!err) { if( keys_found!=ncfg ) { // err=ERROR_RESULT_CONFIG; msg(log_file,MSG_FUNC": Some parameters are missing in <%s> " "(%d out of %d is OK)\n",MOUNT_DEFAULT_FILE_CONFIG,keys_found,ncfg); } else { msg(log_file, MSG_FUNC": All %d configuration parameters successfully loaded " "from file <%s>\n", ncfg,MOUNT_DEFAULT_FILE_CONFIG); } } ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef SIMULATION for(mot=0;mot<2;mot++) { msg(log_file, "main:motor-%d: AFTER_CONFIG_FILE: ptr=%p\n" " FULL_STEP: gear=%lf\n" " POT: pol=%d, gear=%lf\n" " ENCODER: pol=%d, gear=%lf\n", mot, &TMCL_SIMUL_geom, // TMCL_SIMUL_geom.fs_polarity[mot], TMCL_SIMUL_geom.fs_gear[mot], TMCL_SIMUL_geom.pot_polarity[mot], TMCL_SIMUL_geom.pot_gear[mot], TMCL_SIMUL_geom.enc_polarity[mot], TMCL_SIMUL_geom.enc_gear[mot] ); } #endif #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 3: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// #ifdef WATCHDOG /* checks if all parameters are OK */ if ( !err && /* keys_found==ncfg && */ watchdog<0 ) { watchdog=WATCHDOG_SLEEP_SECONDS; msg(log_file, MSG_FUNC": Wrong WATCHDOG update frequency in <%s>. " "Default value is taken: %ld sec\n", MOUNT_DEFAULT_FILE_CONFIG,watchdog); } #endif ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 4: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// #ifdef MICROTRACKING /* checks if all parameters are OK */ if ( !err && /* keys_found==ncfg && */ (microtracking<0 || microtracking>1)) { microtracking=MONIT_DEFAULT_MICROTRACKING; msg(log_file, MSG_FUNC": Wrong MICROTRACKING flag in <%s>. " "Default value is taken: %d\n", MOUNT_DEFAULT_FILE_CONFIG,microtracking); } #endif ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 5: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// #ifdef AUTOCALIBRATION /* checks if all parameters are OK */ if ( !err && /* keys_found==ncfg && */ (autocalib<0 || autocalib>1)) { autocalib=MONIT_DEFAULT_AUTOCALIB; msg(log_file, MSG_FUNC": Wrong AUTOCALIB flag in <%s>. " "Default value is taken: %d\n", MOUNT_DEFAULT_FILE_CONFIG,autocalib); } #endif ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 6: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /* checks input arguments: no_calib == skip calib(0)/calib(adc) in main()/do_init() functions */ #ifdef STANDALONE for(i=1;i0) { arg=str2str(arg,argv[i]); arg=str2lowercase(arg); #endif // override: // option->init_calib_flag and/or option->init_stop_flag // if instructed to do so... if (arg!=NULL && strlen(arg)>0) { if (strcmp(arg,"no_calibration")==0 || strcmp(arg,"nocalibration")==0 || strcmp(arg,"no_calib")==0 || strcmp(arg,"nocalib")==0 || strcmp(arg,"no_cal")==0 || strcmp(arg,"nocal")==0 || strcmp(arg,"skip_calibration")==0 || strcmp(arg,"skipcalibration")==0 || strcmp(arg,"skip_calib")==0 || strcmp(arg,"skipcalib")==0 || strcmp(arg,"skip_cal")==0 || strcmp(arg,"skipcal")==0 || strcmp(arg,"without_calibration")==0 || strcmp(arg,"withoutcalibration")==0 || strcmp(arg,"without_calib")==0 || strcmp(arg,"withoutcalib")==0 || strcmp(arg,"without_cal")==0 || strcmp(arg,"withoutcal")==0 ) option->init_calib_flag=0; if (strcmp(arg,"stop")==0 || strcmp(arg,"stopall")==0 || strcmp(arg,"stop_all")==0 || strcmp(arg,"stopmotors")==0 || strcmp(arg,"stop_motors")==0 || strcmp(arg,"stopallmotors")==0 || strcmp(arg,"stop_all_motors")==0 || strcmp(arg,"allstop")==0 || strcmp(arg,"all_stop")==0 || strcmp(arg,"withstop")==0 || strcmp(arg,"with_stop")==0 || strcmp(arg,"halt")==0 || strcmp(arg,"arret")==0 ) option->init_stop_flag=1; } // end of if(arg!=NULL ... #ifdef STANDALONE if(arg) free(arg); } // end of if(argv[i]... } // end of for(i=1... loop #endif #ifndef STANDALONE printf(MSG_FUNC": arg=%p, arg=|%s|\n",arg,arg);fflush(0); #endif ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 7: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /* loads database of observation sites */ if ( !err && (loc_file=fopen(MOUNT_DEFAULT_FILE_LOCATIONS_DB,"rt"))==NULL ) { err=ERROR_RESULT_CONFIG; msg(log_file,MSG_FUNC": Can't open site database file <%s>\n", MOUNT_DEFAULT_FILE_LOCATIONS_DB); } ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 8: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// if (!err) { /* stores CODE for comparison */ char *cfg_site_code=NULL; cfg_site_code=make_message(site_code); /* search the database */ /* upon success 'site_code' string will be updated */ if( load_site_from_database(loc_file, cfg_site_code, loc_table, nloc)!=0 ) { err=ERROR_RESULT_CONFIG; msg(log_file,MSG_FUNC": Observation site %3s not found in database\n", cfg_site_code); } if(cfg_site_code) free(cfg_site_code); } ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 9: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// if (loc_file!=NULL) fclose(loc_file); ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 10: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// // is RS232 file descriptor pointer equal to NULL ? if (!err) { if(fd==NULL) { msg(log_file, MSG_FUNC": Input pointer to " #ifdef SIMULATION "simulated" #endif " RS232 file descriptor is NULL !!!\n"); err=ERROR_RESULT_FATAL; } } if (!err) { // port for communication // sprintf(port,"%s",port_name); msg(log_file,MSG_FUNC": Setting port to: %s\n", option->rs232_portname); // communication speed msg(log_file,MSG_FUNC": Setting baudrate to: %ld\n", option->rs232_baudrate); // observation site msg(log_file,MSG_FUNC": Setting observation site to: %s\n" "CODE=%s\n" "LONGITUDE=%.5f deg East\n" "LATITUDE=%.5f deg North\n" "ALTITUDE=%.0f meters a.s.l.\n", site_comment, site_code, longitude, latitude, altitude); ///////////////////////////////// establishing communication #ifdef SIMULATION *fd = 1; // file descriptor for SIMULATION is defined here for(mot=0;mot<2;mot++) { msg(log_file, "main:motor-%d: BEFORE_START_SIMUL: ptr=%p\n" " FULL_STEP: gear=%lf\n" " POT: pol=%d, gear=%lf\n" " ENCODER: pol=%d, gear=%lf\n", mot, &TMCL_SIMUL_geom, // TMCL_SIMUL_geom.fs_polarity[mot], TMCL_SIMUL_geom.fs_gear[mot], TMCL_SIMUL_geom.pot_polarity[mot], TMCL_SIMUL_geom.pot_gear[mot], TMCL_SIMUL_geom.enc_polarity[mot], TMCL_SIMUL_geom.enc_gear[mot] ); } TMCL_SIMUL_start(/*&TMCL_SIMUL_geom*/); for(mot=0;mot<2;mot++) { msg(log_file, "main:motor-%d: AFTER_START_SIMUL: ptr=%p\n" " FULL_STEP: gear=%lf\n" " POT: pol=%d, gear=%lf\n" " ENCODER: pol=%d, gear=%lf\n", mot, &TMCL_SIMUL_geom, // TMCL_SIMUL_geom.fs_polarity[mot], TMCL_SIMUL_geom.fs_gear[mot], TMCL_SIMUL_geom.pot_polarity[mot], TMCL_SIMUL_geom.pot_gear[mot], TMCL_SIMUL_geom.enc_polarity[mot], TMCL_SIMUL_geom.enc_gear[mot] ); } #else if( (err=reopen_serial_port(option->rs232_portname, &(option->rs232_baudrate),fd))!=0 ) { msg(log_file,MSG_FUNC": Can't establish RS-232 connection\n"); } else { time_t t=time(NULL); msg(log_file,MSG_FUNC": RS-232 port successfully opened at: %s\n", ctime(&t)); } #endif #ifdef WATCHDOG /* if(watchdog) */ /* { */ /* starts watchdog daemon */ WATCH_start(fd,&calib); /* } */ #endif } /* end of if(!err)... */ ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 11: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /* if required perform complete motor stop before */ /* proceeding any further */ if(!err && option->init_stop_flag) { msg(log_file,MSG_FUNC": Performing complete motor stop...\n"); for(mot=0;mot<2;mot++) if( mst(fd,mot)!=0 ) { status[mot]=MOT_STAT_ERROR; err=ERROR_RESULT_IO; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,MSG_FUNC":motor-%d: Stop failed.\n",mot); #endif } else { status[mot]=MOT_STAT_STOPPED; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, MSG_FUNC":motor-%d: Motor is stopped.\n",mot); #endif } if(!err) msg(log_file,MSG_FUNC": All motors are stopped.\n"); else msg(log_file,MSG_FUNC": Can't stop all motors!\n"); } // end of if(!err && ... ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 12: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// /////////////////////////////// disables HOME switch /////////////////////////////// enables LEFT and RIGHT switches if(!err) { for(mot=0;mot<2;mot++) if(disable_HOME_enable_AUTOSTOP(fd,mot,NULL)==0) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC":motor-%d: " "HOME disabled, LEFT and RIGHT enabled\n",mot); #endif } else { msg(log_file, MSG_FUNC":motor-%d: Can't initialize limit switches\n",mot); err=ERROR_RESULT_IO; } } ////////////////////////////////////////// ////////////////////////////////////////// // #ifdef DEBUG msg(log_file,MSG_FUNC": BREAKPOINT 13: err=%d\n",err); if(!err && logging>MESSAGE_LEVEL+1) { msg(log_file,MSG_FUNC": " "Default calibration data:\n"); print_calibration_data(&calib); } /* for(mot=0;mot<2;mot++) */ /* msg(log_file,MSG_FUNC": " */ /* "Calibration data for motor-%d:\n" */ /* " XL=%-10ld XMIN=%-10ld XHL=%-10ld XHR=%-10ld" */ /* " XMAX=%-10ld XR=%-10ld\n" */ /* "ADCL=%-10ld ADCMIN=%-10ld ADCHL=%-10ld ADCHR=%-10ld" */ /* " ADCMAX=%-10ld ADCR=%-10ld\n", */ /* mot, */ /* calib.XL[mot], */ /* calib.XMIN[mot], */ /* calib.XHL[mot], */ /* calib.XHR[mot], */ /* calib.XMAX[mot], */ /* calib.XR[mot], */ /* calib.ADCL[mot], */ /* calib.ADCMIN[mot], */ /* calib.ADCHL[mot], */ /* calib.ADCHR[mot], */ /* calib.ADCMAX[mot], */ /* calib.ADCR[mot]); */ #endif // ////////////////////////////////////////// ////////////////////////////////////////// // tries to load previous calibration data from file calib.full_flag[MOT_A]=0; calib.full_flag[MOT_D]=0; calib.needcalib_flag[MOT_A]=0; // "calib 0" not required by default calib.needcalib_flag[MOT_D]=0; // "calib 0" not required by default if (!err) { if( load_calibration_data(MOUNT_DEFAULT_FILE_LAST_FULL_CALIB)!=0) { msg(log_file, MSG_FUNC": Can't read calibration data from file <%s>!\n", MOUNT_DEFAULT_FILE_LAST_FULL_CALIB); calib.needcalib_flag[MOT_A]=1; // "calib 1" is required calib.needcalib_flag[MOT_D]=1; // "calib 1" is required } else { msg(log_file, MSG_FUNC": Calibration data succesfully loaded from file <%s>\n", MOUNT_DEFAULT_FILE_LAST_FULL_CALIB); calib.full_flag[MOT_A]=1; calib.full_flag[MOT_D]=1; } // end of if( (err=... // now update TCALIB structure using // GEAR_RATIO, HOME_OFFSET, MOTOR_POLARITY // from CFG_OPTION structure... calib.gear_ratio[MOT_A]=option->motor_gear_ratio[MOT_A]; calib.gear_ratio[MOT_D]=option->motor_gear_ratio[MOT_D]; calib.home_offset[MOT_A]=option->motor_home_offset[MOT_A]; calib.home_offset[MOT_D]=option->motor_home_offset[MOT_D]; calib.motor_polarity[MOT_A]=option->motor_polarity[MOT_A]; calib.motor_polarity[MOT_D]=option->motor_polarity[MOT_D]; } // end of if(!err)... /* keys_found = 0; */ /* calib.full_flag[MOT_A]=0; */ /* calib.full_flag[MOT_D]=0; */ /* calib.needcalib_flag[MOT_A]=0; // "calib 0" not required by default */ /* calib.needcalib_flag[MOT_D]=0; // "calib 0" not required by default */ /* if (!err && */ /* (cal_file = fopen(MOUNT_DEFAULT_FILE_LAST_FULL_CALIB,"rt"))!=NULL ) */ /* { */ /* /\* loads calibration parameters from file *\/ */ /* for(i=0;i0 ) keys_found++; */ /* }; */ /* fclose(cal_file); */ /* /\* checks if all parameters have been read *\/ */ /* if ( keys_found " */ /* "(%d out of %d is OK)\n", */ /* MOUNT_DEFAULT_FILE_LAST_FULL_CALIB,keys_found,ncal); */ /* err=ERROR_RESULT_CONFIG; */ /* } */ /* else */ /* { */ /* msg(log_file, */ /* MSG_FUNC": Calibration data succesfully loaded from file <%s>\n", */ /* MOUNT_DEFAULT_FILE_LAST_FULL_CALIB); */ /* // now cross-check GEAR_RATIO and HOME_OFFSET */ /* // if differ */ /* calib.full_flag[MOT_A]=1; */ /* calib.full_flag[MOT_D]=1; */ /* } /\* end of if(keys_found:\n", MOUNT_DEFAULT_FILE_LAST_FULL_CALIB); print_calibration_data(&calib); } /* if(logging>MESSAGE_LEVEL) { */ /* for(mot=0;mot<2;mot++) */ /* msg(log_file,MSG_FUNC": " */ /* "Calibration data for motor-%d:\n" */ /* " XL=%-10ld XMIN=%-10ld XHL=%-10ld XHR=%-10ld" */ /* " XMAX=%-10ld XR=%-10ld\n" */ /* "ADCL=%-10ld ADCMIN=%-10ld ADCHL=%-10ld ADCHR=%-10ld" */ /* " ADCMAX=%-10ld ADCR=%-10ld\n", */ /* mot, */ /* calib.XL[mot], */ /* calib.XMIN[mot], */ /* calib.XHL[mot], */ /* calib.XHR[mot], */ /* calib.XMAX[mot], */ /* calib.XR[mot], */ /* calib.ADCL[mot], */ /* calib.ADCMIN[mot], */ /* calib.ADCHL[mot], */ /* calib.ADCHR[mot], */ /* calib.ADCMAX[mot], */ /* calib.ADCR[mot]); */ /* } */ #ifdef DEBUG msg(log_file, MSG_FUNC": BREAKPOINT 14: err=%d\n",err); fflush(log_file); #endif // ////////////////////////////////////////// ////////////////////////////////////////// // sets default tracking speed // (because GEAR_RATIO and/or LATITUDE might have been changed) if(!err) { if ( (err=calc_default_track_speed(mot_speed,&calib,latitude))==0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC": " "Default tracking parameters restored succesfully.\n"); #endif } else { err=ERROR_RESULT_CONFIG; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC": " "Can't set default tracking speed!\n"); #endif } /* end of if( (err=... */ } /* end of if (!err)... */ ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 15: err=%d\n",err); fflush(log_file); // ////////////////////////////////////////// ////////////////////////////////////////// //////////////////////////////////// gets status if (!err) { if(get_status(fd,ts,&calib,2) == 0) { /* in the case of serious discrepancies or errors * "calib 0" must be called */ if( ts->motor_status[MOT_A]==MOT_STAT_SLIDE || ts->motor_status[MOT_D]==MOT_STAT_SLIDE || ts->motor_status[MOT_A]==MOT_STAT_ERROR || ts->motor_status[MOT_D]==MOT_STAT_ERROR ) { calib.needcalib_flag[MOT_A]=1; // "calib 0" must be called calib.needcalib_flag[MOT_D]=1; // "calib 0" must be called msg(log_file,MSG_FUNC": Calibration has to be performed first!\n"); } } else { err=ERROR_RESULT_IO; msg(log_file,MSG_FUNC": Can't get mount's status!\n"); } } ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 16: err=%d\n",err); fflush(log_file); // ////////////////////////////////////////// ////////////////////////////////////////// // tries to load saved parameters (position, tracking speed) if(!err) { if (compare_last_position(fd,&calib)==0) { calib.needcalib_flag[MOT_A]=0; // no calibration is needed calib.needcalib_flag[MOT_D]=0; // no calibration is needed msg(log_file, MSG_FUNC": Position has not been changed since last session.\n"); } else { calib.needcalib_flag[MOT_A]=1; // "calib 0" must be called calib.needcalib_flag[MOT_D]=1; // "calib 0" must be called msg(log_file, MSG_FUNC": Calibration has to be performed first!\n"); } } ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 17: err=%d\n",err); // ////////////////////////////////////////// ////////////////////////////////////////// // performs calibration when needed /* #ifdef _HAS_CALIB_ON_INIT_ */ if(!err && option->init_calib_flag) { if(!err && (calib.needcalib_flag[MOT_A] || calib.needcalib_flag[MOT_D] )) { /* loads default motor parameters */ if( /* (err=sio(fd,TEST_MODE_GATE,TMCL_DOUT_BANK,0)) == 0 && */ (err=mot_init(fd,MOT_A,speed_mode,&calib)) == 0 && (err=mot_init(fd,MOT_D,speed_mode,&calib)) == 0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC": Default motor parameters loaded successfully.\n"); #endif } else { err=ERROR_RESULT_IO; msg(log_file,MSG_FUNC": Can't set default motor parameters!\n"); } /* performs calibration "calib 0" */ if(!err && (err=do_calib(fd,"0",0))!=0 ) { msg(log_file,MSG_FUNC": Precise calibration failed!\n"); } #ifdef DEBUG if(!err && logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC": Precise calibration performed successfully.\n"); #endif } /* end of if(!err && ... */ /* #endif // end of _HAS_CALIB_ON_INIT_ */ #ifdef AUTOCALIBRATION // on error tries to perform coarse calibration from potentiometers #ifdef SIMULATION if(err) // don't care about good serial port file descriptor #else if(err && *fd>0) // require good serial port file descriptor #endif { if((err=do_calib_astro(fd,"adc",0))!=0) { msg(log_file,MSG_FUNC": Coarse calibration failed!\n"); } else { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, MSG_FUNC": Coarse calibration performed successfully.\n"); #endif } } /* end of if(err) */ #endif } /* end of if(!err && option->init_calib_flag... */ ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 18: err=%d\n",err); // ////////////////////////////////////////// ////////////////////////////////////////// #ifdef STANDALONE #ifdef WATCHDOG if(watchdog) { // In STANDALONE mode informs WATCHDOG about result of // this initialization WATCH_lastcmd->cmd_end_timestamp=time(NULL); WATCH_lastcmd->cmd_run_flag=0; WATCH_lastcmd->cmd_result=err; // updates TWATCH structure WATCH_lastcmd->ra = ts->ra; WATCH_lastcmd->ha = ts->ha; WATCH_lastcmd->dec = ts->dec; WATCH_lastcmd->az = ts->az; WATCH_lastcmd->h = ts->h; WATCH_lastcmd->timestamp_coo = ts->timestamp_coo; WATCH_lastcmd->timestamp = ts->timestamp; for(mot=0;mot<2;mot++) { WATCH_lastcmd->FS_pos[mot] = ts->pos[mot]*pow(2,-ts->us[mot]); WATCH_lastcmd->ADC_pos[mot] = ts->adc_pos[mot]; WATCH_lastcmd->motor_status[mot]= ts->motor_status[mot]; WATCH_lastcmd->motor_status_coo[mot]= ts->motor_status_coo[mot]; WATCH_lastcmd->LEFTHOME_switch[mot]= ts->lim_l[mot]; WATCH_lastcmd->RIGHT_switch[mot]= ts->lim_r[mot]; } // do we need precise calibration ? for(WATCH_lastcmd->needcalib=0,mot=0;mot<2;mot++) if(WATCH_lastcmd->needcalib!=1) { if(calib.needcalib_flag[mot]==2) WATCH_lastcmd->needcalib=2; // coarse calibration OK if(calib.needcalib_flag[mot]==1) WATCH_lastcmd->needcalib=1; // coarse calibration failed } // informs WATCHDOG that command has been executed // and access to the mount is free while(semaphore_value(&WATCHCOMMAND_turn)>0) semaphore_down(&WATCHCOMMAND_turn); // wakes up WATCHDOG from sleep mode // and forces it to update status file while(semaphore_value(&WATCHSLEEP_turn)>0) semaphore_down(&WATCHSLEEP_turn); } #endif #endif ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 19: err=%d\n",err); // ////////////////////////////////////////// ////////////////////////////////////////// if(err) { #ifdef SIMULATION msg(log_file, MSG_FUNC": Before destroying simulator thread.\n"); TMCL_SIMUL_destroy(); msg(log_file, MSG_FUNC": After destroying simulator thread.\n"); #else // closes serial port (require good serial port file descriptor) if(*fd>0) { if( close_serial(fd)!=0 ) msg(log_file, MSG_FUNC": Serial port close ERROR\n"); } #endif #ifdef WATCHDOG msg(log_file, MSG_FUNC": Before destroying watchdog thread.\n"); WATCH_destroy(); msg(log_file, MSG_FUNC": After destroying watchdog thread.\n"); #endif t=time(NULL); msg(log_file, MSG_FUNC": Stopped due to critical errors at: %s", ctime(&t)); // closes log file if (log_file!=NULL) { if(fflush(log_file)!=0) msg(log_file, MSG_FUNC": Logfile syncing ERROR\n"); fclose(log_file); } logging=0; mount_initialized=0; #ifdef STANDALONE exit(err); #else //msg_filename(kn_log_name, MSG_FUNC": END (ERROR)\n"); printf(MSG_FUNC": END (ERROR=%d)\n",err);fflush(0); return(err); #endif } ////////////////////////////////////////// ////////////////////////////////////////// // msg(log_file,MSG_FUNC": BREAKPOINT 20: err=%d\n",err); // ////////////////////////////////////////// ////////////////////////////////////////// #if !defined(SIMULATION) && defined(DEBUG) print_serial_port_performance(log_file); #endif // assumes mount was intialized at this point - MC - 26 March 2005 mount_initialized=1; /* continues MAIN function in STANDALONE mode * ends DO_INIT function in CORBA mode */ #ifndef STANDALONE //msg_filename(kn_log_name, MSG_FUNC": END (OK)\n"); printf(MSG_FUNC": END (OK)\n");fflush(0); return(0); //kn } //kn #ifndef STANDALONE #undef MSG_FUNC #define MSG_FUNC "execute_command" #endif /************************************************************ * EXECUTE_COMMAND in CORBA mode ************************************************************/ int execute_command( const_buf ) //kn const char *const_buf; //kn { //kn int *fd=&fd_; //mc: pointer to RS232 port file descriptor defined elsewhere extern int mount_initialized; //mc - 26 March 2005 int i,j,found,icmd,err,speed; //kn char *buf=NULL, *tok=NULL, *arg=NULL; //kn time_t t; //kn #ifdef WATCHDOG //mc time_t watch_t0; //mc int mot; #endif //mc int err1; #ifdef AUTOCALIBRATION //---------------------------------------- AUTOMATIC CALIBRATION #ifdef _HAS_DO_ASTROMETRY_ time_t tauto; #endif #endif //-------------------------------------------------------- AUTOMATIC CALIBRATION // printf(MSG_FUNC": checkpoint 1\n"); // mc // makes a local copy of 'cont_buf' printf(MSG_FUNC": const_buf=|%s|, buf=|%s|\n",const_buf, buf);fflush(0); buf=str2str(buf,const_buf); printf(MSG_FUNC": STR2STR: const_buf=|%s|, buf=|%s|\n",const_buf, buf);fflush(0); printf(MSG_FUNC": mount_initialized=%d\n",mount_initialized);fflush(0); tcp->ha = 0.; tcp->dec = 0.; tcp->max_tracktime = -1; #endif // mc err=0; //#ifndef STANDALONE // msg_filename(kn_log_name,MSG_FUNC": BEGIN of execute_command\n"); //#endif /* waits for a command in STANDALONE mode (part of MAIN) * executes specified command in CORBA mode (part of EXECUTE_COMMAND) */ #ifdef STANDALONE #ifdef WATCHDOG //-------------------------------------- WATCHDOG // checks status if (mount_initialized) { err1=get_status(fd,ts,&calib,1); // silent mode goto UPDATE_WATCHDOG_FIRST_TIME; } #endif //----------------------------------------------- WATCHDOG printf("\n");fflush(0); ///////////////////////////////// entering main loop ///////////////////////////////// waiting for a command while(1){ if(buf) { free(buf); buf=NULL; // this line is important! } buf = readline ("monit> "); // read from a command line ///////////////////////////////// ignores empty commands buf = str2lowercase(buf); // convert letters to a lower case buf = filter_comments(buf); // ignore commented lines or comments at the end of line if( buf == NULL || strlen(buf) < 1 )continue; #else // PIMAN mode: if( buf ){ printf(MSG_FUNC": buf=|%s|\n",buf);fflush(0); // msg_filename(kn_log_name,MSG_FUNC": buff!=NULL , buf=|%s|\n",buf); }else{ printf(MSG_FUNC": buf=NULL\n");fflush(0); // msg_filename(kn_log_name,MSG_FUNC": execute_command buf=NULL\n"); } ///////////////////////////////// ignores empty commands buf = str2lowercase(buf); // convert letters to a lower case printf(MSG_FUNC": STR2LOWERCASE: const_buf=|%s|, buf=|%s|\n",const_buf, buf);fflush(0); //msg_filename(kn_log_name,MSG_FUNC": after str2lowercase buf=%s\n",buf); buf = filter_comments(buf); // ignore commented lines or comments at the end of line printf(MSG_FUNC": FILETER_COMMENTS: const_buf=|%s|, buf=|%s|\n",const_buf, buf);fflush(0); //msg_filename(kn_log_name,MSG_FUNC": after filter_comments\n"); if( buf == NULL || strlen(buf) < 1 ) { if(buf) free(buf); buf=NULL; printf(MSG_FUNC": buf is an empty string! Will ignore this command.\n");fflush(0); return(0); } //msg_filename(kn_log_name,MSG_FUNC": execute_command checkpoint 2\n"); //printf(MSG_FUNC": buf=%p is not an empty string\n",buf);fflush(0); #endif t=time(NULL); if (logging>=MESSAGE_LEVEL) { msg(log_file,MSG_FUNC": %-040s at: %s",buf,ctime(&t)); } //#ifndef STANDALONE //msg_filename(kn_log_name,MSG_FUNC": execute_command checkpoint 3\n"); //printf(MSG_FUNC": checkpoint 3 (printed command, time & date)\n");fflush(0); //#endif #ifdef STANDALONE add_history(buf); #endif //#ifndef STANDALONE // msg_filename(kn_log_name,MSG_FUNC": execute_command checkpoint 4\n"); // printf(MSG_FUNC": checkpoint 4 (about to enter command search loop)\n");fflush(0); //#endif ///////////////////////////////// examines input string buffer tok = strtok(buf," ,"); for(i=0, found=0; i0 && cmd_table[i].name[j]!=NULL && strlen(cmd_table[i].name[j])==strlen(tok) && strncmp(cmd_table[i].name[j],tok,strlen(cmd_table[i].name[j])) == 0 && cmd_table[i].cmd!=NULL ) { found++; icmd = i; //printf(MSG_FUNC": checkpoint 7 (command i=%d, synonim j=%d, found=%d\n",i,j,found);fflush(0); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,MSG_FUNC": Command found in database: command=|%s|, " "cmd_number=%d found=%d\n", tok, icmd, found); //printf(MSG_FUNC": Command found in database: command=|%s|, " // "cmd_number=%d, found=%d\n", // tok, // icmd, // found);fflush(0); #endif } /* end of if(tok!=NULL... */ } /* end of for(j... */ } /* end of for(i... */ //#ifndef STANDALONE // msg_filename(kn_log_name, MSG_FUNC": executes command when found=1\n"); // printf(MSG_FUNC": executes command when found=1\n");fflush(0); //#endif //////////////////////////////// executes command when found=1 if(found<=0) { err=ERROR_RESULT_SYNTAX; if (logging>=MESSAGE_LEVEL) msg(log_file, MSG_FUNC": ERROR: unknown command\n"); //printf(MSG_FUNC": ERROR: unknown command\n");fflush(0); } if(found>1) { err=ERROR_RESULT_SYNTAX; if (logging>=MESSAGE_LEVEL) msg(log_file, MSG_FUNC": ERROR: ambiguous command\n"); //printf(MSG_FUNC": ERROR: ambiguous command\n");fflush(0); } if(found==1) { printf(MSG_FUNC": Command = |%s|\n",cmd_table[icmd].name[0]);fflush(0); arg = strtok(NULL,"\n"); printf(MSG_FUNC": Command arguments: arg=%p, arg=|%s|\n",arg,arg);fflush(0); //printf(MSG_FUNC": Before WATCHDOG update...\n");fflush(0); #ifdef WATCHDOG //---------------------------------------------- WATCHDOG /* if(watchdog) */ /* { */ // informs WATCHDOG that new command will be executed semaphore_up(&WATCHCOMMAND_turn); // informs WATCHDOG about new command WATCH_lastcmd->cmd_start_timestamp=t; sprintf(WATCH_lastcmd->cmd_args,"%s",cmd_table[icmd].name[0]); if(arg!=NULL) { strcat(WATCH_lastcmd->cmd_args," "); strncat(WATCH_lastcmd->cmd_args, arg, maxim(0, WATCHDOG_ARGS_LENGTH-1- strlen(arg)-strlen(WATCH_lastcmd->cmd_args))); } WATCH_lastcmd->cmd_run_flag=1; WATCH_lastcmd->cmd_end_timestamp=0; WATCH_lastcmd->cmd_result=ERROR_RESULT_OK; // do we need precise calibration ? for(WATCH_lastcmd->needcalib=0,mot=0;mot<2;mot++) if(WATCH_lastcmd->needcalib!=1) { if(calib.needcalib_flag[mot]==2) WATCH_lastcmd->needcalib=2; // coarse calibration OK if(calib.needcalib_flag[mot]==1) WATCH_lastcmd->needcalib=1; // coarse calibration failed } #ifdef DEBUG if(logging>MESSAGE_LEVEL+7) msg(log_file, MSG_FUNC": Watchdog semaphores before unlock: " "cmd=%d / sleep=%d / lock=%d\n", WATCHCOMMAND_turn, WATCHSLEEP_turn, WATCHLOCK_turn); #endif watch_t0=time(NULL); // waits until WATCHDOG finishes accessing the mount while(semaphore_value(&WATCHLOCK_turn)>0) { if( time(NULL)-watch_t0 > WATCHDOG_LOCK_TIMEOUT ) { #ifdef DEBUG // if(logging>MESSAGE_LEVEL+3) msg(log_file, MSG_FUNC": WATCHDOG is holding new command " "for more than %ld sec!\n", WATCHDOG_LOCK_TIMEOUT); #endif // setting WATCHLOCK semaphore to 0 while(semaphore_value(&WATCHLOCK_turn)>0) semaphore_down(&WATCHLOCK_turn); #ifdef DEBUG if(logging>MESSAGE_LEVEL+3) msg(log_file, MSG_FUNC": Setting WATCHLOCK_turn=%d\n", WATCHLOCK_turn); #endif break; } }; // wakes up WATCHDOG from sleep mode // and forces it to update status file while(semaphore_value(&WATCHSLEEP_turn)>0) semaphore_down(&WATCHSLEEP_turn); #ifdef DEBUG if(logging>MESSAGE_LEVEL+7) msg(log_file, MSG_FUNC": Watchdog semaphores before command: " "cmd=%d / sleep=%d / lock=%d\n", WATCHCOMMAND_turn, WATCHSLEEP_turn, WATCHLOCK_turn); #endif /* } */ #endif //----------------------------------------------- WATCHDOG //printf(MSG_FUNC": After WATCHDOG update...\n"); //printf(MSG_FUNC": mount_initialized=%d\n",mount_initialized); //#ifndef STANDALONE //msg_filename(kn_log_name, MSG_FUNC": updates stopping time\n"); //#endif // updates stopping time for(i=0;i<2;i++) { #ifndef STANDALONE //msg_filename(kn_log_name,MSG_FUNC": before gap: " // "updates stopping time i = %d\n",i); #endif if(mount_initialized && gap(fd,TMCL_ACTUAL_SPEED,i,&speed)==0) { #ifndef STANDALONE //msg_filename(kn_log_name, MSG_FUNC // ": updates stopping time i = %d\n",i); #endif #ifdef DEBUG if(logging>MESSAGE_LEVEL+3) msg(log_file,MSG_FUNC ": calling update_stop_timestamp() before command.\n"); #endif // updates stopping time, first update_stop_timestamp(i,time(NULL),speed); } } /* end of for(i=0...) loop */ //#ifndef STANDALONE //msg_filename(kn_log_name, MSG_FUNC": BEFORE execute new command\n"); //#endif printf(MSG_FUNC": Before EXECUTING COMMAND...\n");fflush(0); // executes new command // (unless command=do_init in CORBA mode mount has to be initialized first!) printf(MSG_FUNC": Pointer to command function icmd=%d: cmd_table[icmd].cmd=%p\n", icmd, cmd_table[icmd].cmd);fflush(0); printf(MSG_FUNC": Code of command icmd=%d: cmd_table[icmd].code=%d (MONIT_CODE_INIT=%d)\n", icmd, cmd_table[icmd].code, MONIT_CODE_INIT);fflush(0); if (cmd_table[icmd].cmd!=NULL) { if(!mount_initialized && cmd_table[icmd].code!=MONIT_CODE_INIT) { err=ERROR_RESULT_FATAL; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,MSG_FUNC ": Mount has to be initialized first!\n"); // printf(MSG_FUNC": ERROR: Mount has to be initialized first!\n"); #endif //#ifndef STANDALONE //msg_filename(kn_log_name, // MSG_FUNC": Mount is not initialized !!!\n"); //#endif } else { err = cmd_table[icmd].cmd(fd,arg,motor); } } #ifndef STANDALONE // msg_filename(kn_log_name, MSG_FUNC": AFTER execute new command\n"); printf(MSG_FUNC": AFTER execute new command err=%d\n",err);fflush(0); #endif if(err != 0) { if(logging>=MESSAGE_LEVEL) msg(log_file,MSG_FUNC": ERROR: command returned error %d\n",err); } // updates stopping time for(i=0;i<2;i++) if(mount_initialized && gap(fd,TMCL_ACTUAL_SPEED,i,&speed)==0) { #ifdef DEBUG if(logging>MESSAGE_LEVEL+3) msg(log_file,MSG_FUNC ": calling update_stop_timestamp() after command.\n"); #endif // updates stopping time, first update_stop_timestamp(i,time(NULL),speed); } // checks status (prints coordinates) if (mount_initialized) // added by MC - 26 March 2005 { switch( cmd_table[icmd].code ) { case MONIT_CODE_STAT: case MONIT_CODE_HELP: case MONIT_CODE_HA: case MONIT_CODE_RA: case MONIT_CODE_DEC: case MONIT_CODE_AZ: case MONIT_CODE_HEIGHT: case MONIT_CODE_COO: case MONIT_CODE_GOTO: case MONIT_CODE_GOTOREL: case MONIT_CODE_ASTRO: #ifdef SIMULATION case MONIT_CODE_SLIDE: #endif err1=get_status(fd,ts,&calib,0); // silent mode break; default: err1=get_status(fd,ts,&calib,1); // verbose mode }; #ifdef AUTOCALIBRATION //------------------------------- AUTOMATIC CALIBRATION #ifdef _HAS_DO_ASTROMETRY_ if(autocalib && err1==0 && (//ts->motor_status[MOT_A]==MOT_STAT_ERROR || ts->motor_status[MOT_A]==MOT_STAT_SLIDE || //ts->motor_status[MOT_D]==MOT_STAT_ERROR || ts->motor_status[MOT_D]==MOT_STAT_SLIDE )) { tauto=time(NULL); msg(log_file, "\n" "ALERT: Slide detected in RA or DEC after " "last command at: %ld sec = %s" " Trying autocorrection...\n\n", tauto,ctime(&tauto)); if (do_calib_astro(fd,"ADC",0)==0) { msg(log_file,MSG_FUNC ": Calibration from encoders/potentiometers OK.\n"); } else { msg(log_file, MSG_FUNC ": Calibrartion from encoders/potentiometers failed!\n"); } } #endif #endif //----------------------------------------------- AUTOMATIC CALIBRATION } /* end of if (mount_initialized)...*/ //#ifndef STANDALONE //msg_filename(kn_log_name, MSG_FUNC": Before watchdog notification\n"); //#endif #ifdef WATCHDOG //-------------------------------------- WATCHDOG #ifdef STANDALONE UPDATE_WATCHDOG_FIRST_TIME:; #endif /* if(watchdog || cmd_table[icmd].code==MONIT_CODE_WATCHDOG ) */ /* { */ // informs WATCHDOG about result of the last command WATCH_lastcmd->cmd_end_timestamp=time(NULL); WATCH_lastcmd->cmd_result=err; WATCH_lastcmd->cmd_run_flag=0; // updates TWATCH structure WATCH_lastcmd->ra = ts->ra; WATCH_lastcmd->ha = ts->ha; WATCH_lastcmd->dec = ts->dec; WATCH_lastcmd->az = ts->az; WATCH_lastcmd->h = ts->h; WATCH_lastcmd->timestamp_coo = ts->timestamp_coo; WATCH_lastcmd->timestamp = ts->timestamp; for(mot=0;mot<2;mot++) { WATCH_lastcmd->FS_pos[mot] = ts->pos[mot]*pow(2,-ts->us[mot]); WATCH_lastcmd->ADC_pos[mot] = ts->adc_pos[mot]; WATCH_lastcmd->motor_status[mot]= ts->motor_status[mot]; WATCH_lastcmd->LEFTHOME_switch[mot]= ts->lim_l[mot]; WATCH_lastcmd->RIGHT_switch[mot]= ts->lim_r[mot]; } // do we need precise calibration ? for(WATCH_lastcmd->needcalib=0,mot=0;mot<2;mot++) if(WATCH_lastcmd->needcalib!=1) { if(calib.needcalib_flag[mot]==2) WATCH_lastcmd->needcalib=2; // coarse calibration OK if(calib.needcalib_flag[mot]==1) WATCH_lastcmd->needcalib=1; // coarse calibration failed } // wakes up WATCHDOG from sleep mode // and forces it to update status file while(semaphore_value(&WATCHSLEEP_turn)>0) semaphore_down(&WATCHSLEEP_turn); // informs WATCHDOG that command has been executed // and access to the mount is free while(semaphore_value(&WATCHCOMMAND_turn)>0) semaphore_down(&WATCHCOMMAND_turn); #ifdef DEBUG if(logging>MESSAGE_LEVEL+7) msg(log_file, MSG_FUNC": Watchdog semaphores after command: " "cmd=%d / sleep=%d / lock=%d\n", WATCHCOMMAND_turn, WATCHSLEEP_turn, WATCHLOCK_turn); /* } /\* end of if(watchdog)...*\/ */ #endif #endif //------------------------------------------------------- WATCHDOG } /* end of if(found==1)...*/ if(err) msg(log_file,MSG_FUNC": ERROR\n"); // always warn about errors #ifdef STANDALONE } /* end of while(1) loop... */ #endif /* here is the end of MAIN function in STANDALONE mode * here is the end of EXECUTE_COMMAND in CORBA mode */ #ifndef STANDALONE if(buf) { free(buf); buf=NULL; } //msg_filename(kn_log_name, MSG_FUNC": END\n"); printf(MSG_FUNC": END, err=%d\n",err);fflush(0); #else if(buf) { free(buf); buf=NULL; } #endif return(err); } #ifndef STANDALONE /************************************************************ * GET MOUNT STATUS in CORBA mode only ************************************************************/ int get_mount_status( const_buf, p_mountStatus, p_chkPosition, p_astroPosition ) //kn const char *const_buf; //kn struct TSTAT *p_mountStatus; //kn struct TCHKPOS *p_chkPosition; //kn struct TASTRO *p_astroPosition; //kn { //kn int err; //kn //msg_filename(kn_log_name, "get_mount_status: BEGIN\n"); printf("get_mount_status: BEGIN: const_buf=%p |%s|, p_mountStatus=%p, p_chkPosition=%p, p_astroPosition=%p\n", const_buf, const_buf, p_mountStatus, p_chkPosition, p_astroPosition);fflush(0); tcp->dec = 0.; tcp->max_tracktime = -1; //////////// some commands may need an updated ASTROMETRY structure //////////// prior to their execution if (p_astroPosition!=NULL) memcpy(ta,p_astroPosition,sizeof(struct TASTRO)); //kn //////////// executes command string specified by const_buf //////////// some commands may update STATUS, POSITION CHECK and ASTROMETRY structures //////////// at the end of their execution err=execute_command( const_buf ); //////////// returns current STATUS, POSITION CHECK and ASTROMETRY structures if (p_mountStatus!=NULL) memcpy(p_mountStatus,ts,sizeof(struct TSTAT)); //kn if (p_chkPosition!=NULL) memcpy(p_chkPosition,tcp,sizeof(struct TCHKPOS)); //kn if (p_astroPosition!=NULL) memcpy(p_astroPosition,ta,sizeof(struct TASTRO)); //kn //////////// always warn about errors if(err) msg(log_file,"get_mount_status: ERROR\n"); #ifndef STANDALONE //msg_filename(kn_log_name, "get_mount_status: END\n"); printf("get_mount_status: END: err=%d, p_mountStatus=%p, p_chkPosition=%p, p_astroPosition=%p\n", err, p_mountStatus, p_chkPosition, p_astroPosition);fflush(0); #endif return(err); } #endif /******************************************************** ******************************************************** * * FUNCTIONS DEFINED BELOW ARE COMMON FOR STANDALONE AND * FOR CORBA MODE * ******************************************************** ******************************************************** */ /********************************************************* * help *************************************************** *********************************************************/ int do_help(fd,arg,mot) int *fd,mot; const char *arg; { // static int code=MONIT_CODE_HELP; int i,j,icmd,found; long range[2]; char *tok; char *argcopy=NULL; // makes a local copy of 'arg' // printf("do_help: INITIAL: arg=|%s|, argcopy=|%s|\n",arg, argcopy); argcopy=str2str(argcopy,arg); // printf("do_help: ARGCOPY: arg=|%s|, argcopy=|%s|\n",arg, argcopy); argcopy=str2lowercase(argcopy); // printf("do_help: LOWERCASE: arg=|%s|, argcopy=|%s|\n",arg, argcopy); STEP0:; if ( argcopy==NULL || strlen(argcopy)==0 || (tok=strtok(argcopy," ,"))==NULL || strlen(tok)<=0) { char *cmd_name[ncmd]; int sort_index[ncmd]; for(i=0;i0) { if (i%3==0) msg(log_file,"\n"); } msg(log_file," %-20s",cmd_name[sort_index[i]]); } msg(log_file,"\n\n"); if(argcopy)free(argcopy); return(0); } else { /* prints help for specific command only */ for(i=0, found=0; i0) found=1; // there is an extra argument else found=0; // no extra arguments // check if 2nd argument is valid // if yes, print allowed range for a given parameter if(found==1) { for(i=0;i0) { if (i%3==0) msg(log_file,"\n"); } msg(log_file," %-20s",axis_par_name[axis_par_sort_index[i]]); } msg(log_file, "\n\nGlobal parameters:\n"); for(i=0;i0) { if (i%3==0) msg(log_file,"\n"); } msg(log_file," %-20s",glob_par_name[glob_par_sort_index[i]]); } msg(log_file, "\n\n%s\n", cmd_table[icmd].details); } // end of if(found==0)... } // end of if(cmd_table[icmd].code!=... for(j=0, found=0;j<8;j++) if(cmd_table[icmd].name[j]!=NULL) found++; if(found>1) { msg(log_file, "NOTE: The following commands are equivalent to each other:"); for(j=0, found=0;j<8;j++) if(cmd_table[icmd].name[j]!=NULL) { if(found==0) msg(log_file, "\n"); else msg(log_file, ", "); found++; msg(log_file, "%s", cmd_table[icmd].name[j]); } msg(log_file,"\n"); } msg(log_file,"\n"); } else // ambiguous command or no arguments { if(argcopy) free(argcopy); argcopy=NULL; goto STEP0; /* lists available commands */ } /* end of if(found==0)... */ } if(argcopy)free(argcopy); return(0); } /***************************************************** * motor (SHOULD BE USED FOR DEBUGGING ONLY!) *****************************************************/ int do_motor(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_MOTOR; int m,err; char *argcopy=NULL; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_motor: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); if( argcopy!=NULL && strlen(argcopy)>0 ) { m=-1; if( strcmp(argcopy,"ra")==0 || strcmp(argcopy,"ha")==0 ) { motor=MOT_A; m=motor; } if( strcmp(argcopy,"dec")==0 || strcmp(argcopy,"d")==0 ) { motor=MOT_D; m=motor; } if(m==-1) { if (sscanf(argcopy,"%d",&m)==1 && (m==MOT_A || m==MOT_D) ) motor=m; else { err=ERROR_RESULT_SYNTAX; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_motor: Wrong motor number: %s\n",argcopy); #endif } } } switch(motor) { case MOT_A: msg(log_file,"Current motor = %d (%s)\n",motor, "Right ascension / Hour angle"); break; case MOT_D: msg(log_file,"Current motor = %d (%s)\n",motor, "Declination"); break; default: err=ERROR_RESULT_CHECK; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_motor: Current motor number is wrong: %d\n",motor); #endif }; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_motor: Ended abnormally " "(wrong motor)\n"); else msg(log_file,"do_motor: Ended normally\n"); } #endif if(argcopy)free(argcopy); return(err); } /********************************************************* * set local baudrate ******************************** *********************************************************/ /* int do_baudrate(fd,arg,motor) */ /* int *fd,motor; */ /* char *arg; */ /* { */ /* char port[100]; */ /* int baudrate; */ /* close(*fd); */ /* if(arg == NULL) return(-1); */ /* baudrate = atoi(arg); */ /* if(baudrate != 9600 && baudrate != 14400 && baudrate != 19200 && */ /* baudrate != 28800 && baudrate != 38400 && baudrate != 57600 && */ /* baudrate != 76800 && baudrate != 115200 ) return(-1); */ /* sprintf(port,"%s",port_name); */ /* if ( (*fd = init_serial(port,baudrate,O_RDWR)) < 0) return(-1); */ /* return(0); */ /* } */ /*********************************************************** * store parameters ******************************************* ***********************************************************/ /* int do_store(fd,arg,motor) */ /* int *fd,motor; */ /* char *arg; */ /* { */ /* u_char opcode; */ /* int i,err,found,itmcl; */ /* int value=0, type=0; */ /* char *tok; */ /* opcode = TMCL_STAP; */ /* tok = strtok(arg," ,"); */ /* if(tok == NULL) return(-3); */ /* for(i=0,found=0; i 0){ */ /* printf(" %s\n",tmcl_table[i].name); */ /* } */ /* itmcl = i; */ /* type = tmcl_table[i].type; */ /* found++; */ /* } */ /* } */ /* if(found > 1) return(-1); */ /* tok = strtok(NULL," ,"); */ /* if(tok == NULL) return(-5); */ /* value = atoi(tok); */ /* err=sap(fd,type,motor,value); */ /* err=stap(fd,type,motor,value); */ /* if(err == 0)printf("stap OK\n"); */ /* else printf("stap error: %d\n",err); */ /* return(err); */ /* } */ /*********************************************************** * set parameters (SHOULD BE USED FOR DEBUGGING ONLY!) ***********************************************************/ int do_set(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_SET; u_char opcode; int i,err,found,itmcl; int value=0, type=0; int bank = 0; char *tok; char *argcopy=NULL; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set: Started...\n"); #endif opcode = TMCL_SAP; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok = strtok(argcopy," ,"); if(tok == NULL) return(ERROR_RESULT_SYNTAX); for(i=0,found=0; i 0) msg(log_file," %s\n",tmcl_table[i].name); itmcl = i; type = tmcl_table[i].type; found++; } } if(found > 1) err=ERROR_RESULT_SYNTAX; // ambiguous command if (found == 0) { for(i=0,found=0; i 0) msg(log_file," %s\n",glob_table[i].name); itmcl = i; type = glob_table[i].type; found++; } } if(found != 1) err=ERROR_RESULT_SYNTAX; // ambiguous parameter opcode = TMCL_SGP; } tok = strtok(NULL," ,"); if(tok == NULL) { err=ERROR_RESULT_SYNTAX; // no value given } if(!err) { value = atoi(tok); if(opcode == TMCL_SAP) err=sap(fd,type,motor,value); else err=sgp(fd,type,bank ,value); if(err) err=ERROR_RESULT_IO; } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_set: Ended abnormally " "(SAP/SGP/ambiguity error)\n"); else msg(log_file,"do_set: Ended normally\n"); } #endif return(err); } /**************************************************** * calibrate ***************************************** *****************************************************/ int do_calib(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_CALIB; int err,iter,typ,found; /* time_t timestamp; */ char c[COMMENT_SIZE]="\0"; char *tok; char *argcopy=NULL; /* int hemisphere=(latitude>=0 ? 1 : -1); */ int motor_flag[2]={1,1}; char argument[COMMENT_SIZE]="encoder"; // default argument for do_calib_astro() // extern struct CALIB calib; // extern double t_home, d_home; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_calib: Started... arg=|%s|\n",arg); #endif iter=0; // iteration number found=0; // correct argument has been found typ=-1; // calibration mode is not set yet // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok = strtok(argcopy," ,"); if( tok == NULL ) err=0; // empty arguments else // non-empty arguments { // than looks for other text arguments (fast,full,test,random...) if(!found) { if( strcmp(tok,"fast")==0 ) { found=1; // use calibrate() function typ=0; // fast calibration from limit switches } else if( strcmp(tok,"fast:0")==0 || strcmp(tok,"fast:ha")==0 || strcmp(tok,"fast:ra")==0 ) { found=1; // use calibrate() function typ=0; // fast calibration from limit switches motor_flag[MOT_A]=1; motor_flag[MOT_D]=0; // skip declination sprintf(argument,"encoder:ha"); // skip declination } else if( strcmp(tok,"fast:1")==0 || strcmp(tok,"fast:dec")==0 || strcmp(tok,"fast:d")==0 ) { found=1; // use calibrate() function typ=0; // fast calibration from limit switches motor_flag[MOT_A]=0; // skip hour angle motor_flag[MOT_D]=1; sprintf(argument,"encoder:dec"); // skip hour angle } else if( strcmp(tok,"full")==0 ) { found=1; // use calibrate() function typ=1; // full calibration from limit switches } else if( strcmp(tok,"full:0")==0 || strcmp(tok,"full:ha")==0 || strcmp(tok,"full:ra")==0 ) { found=1; // use calibrate() function typ=1; // full calibration from limit switches motor_flag[MOT_A]=1; motor_flag[MOT_D]=0; // skip declination sprintf(argument,"encoder:ha"); // skip declination } else if( strcmp(tok,"full:1")==0 || strcmp(tok,"full:dec")==0 || strcmp(tok,"full:d")==0 ) { found=1; // use calibrate() function typ=1; // full calibration from limit switches motor_flag[MOT_A]=0; // skip hour angle motor_flag[MOT_D]=1; sprintf(argument,"encoder:dec"); // skip hour angle } else if( strcmp(tok,"test")==0 || strcmp(tok,"tst")==0 ) { found=1; // use calibrate() function typ=2; // fast calibration + testing correlation between motor steps and ADC } else if( strcmp(tok,"random")==0 || strcmp(tok,"random_test")==0 || strcmp(tok,"random_tst")==0 || strcmp(tok,"rnd")==0 || strcmp(tok,"rnd_test")==0 || strcmp(tok,"rnd_tst")==0 || strcmp(tok,"test_random")==0 || strcmp(tok,"test_rnd")==0 || strcmp(tok,"tst_random")==0 || strcmp(tok,"tst_rnd")==0 ) { found=1; // use calibrate() function typ=3; // fast calibration + testing correlation between motor steps and ADC // using randomized positions } } // finally looks for other numeric arguments (1..3) if( !found && sscanf(tok,"%d",&typ)==1 && typ >= 0 && typ <= 3) { found = 1; // use calibrate() function } // check mode=4 separately (i.e. calibration from encoders/potentiometers) if( (!found && (strcmp(tok,"adc")==0 || strcmp(tok,"potentiometer")==0 || strcmp(tok,"pot")==0 || strcmp(tok,"encoder")==0 || (sscanf(tok,"%d",&typ)==1 && typ==4))) || (found && (typ==0 || typ==2 || typ==3 ) && (option->calib_encoder_is_precise[MOT_A] && // when both encoders are precise option->calib_encoder_is_precise[MOT_D] )) ) // avoid looking for HOME switch { if(typ!=0 && typ!=2 && typ!=3) typ=4; found=2; // use calibrate_astro() function } else if (!found && (strcmp(tok,"adc:0")==0 || strcmp(tok,"potentiometer:0")==0 || strcmp(tok,"pot:0")==0 || strcmp(tok,"encoder:0")==0 || strcmp(tok,"adc:ha")==0 || strcmp(tok,"potentiometer:ha")==0 || strcmp(tok,"pot:ha")==0 || strcmp(tok,"encoder:ha")==0 || strcmp(tok,"adc:ra")==0 || strcmp(tok,"potentiometer:ra")==0 || strcmp(tok,"pot:ra")==0 || strcmp(tok,"encoder:ra")==0 )) { typ=4; found=2; // use calibrate_astro() function sprintf(argument,"encoder:ha"); // skip declination motor_flag[MOT_A]=1; motor_flag[MOT_D]=0; // skip declination } else if (!found && (strcmp(tok,"adc:1")==0 || strcmp(tok,"potentiometer:1")==0 || strcmp(tok,"pot:1")==0 || strcmp(tok,"encoder:1")==0 || strcmp(tok,"adc:dec")==0 || strcmp(tok,"potentiometer:dec")==0 || strcmp(tok,"pot:dec")==0 || strcmp(tok,"encoder:dec")==0 || strcmp(tok,"adc:d")==0 || strcmp(tok,"potentiometer:d")==0 || strcmp(tok,"pot:d")==0 || strcmp(tok,"encoder:d")==0 )) { typ=4; found=2; // use calibrate_astro() function sprintf(argument,"encoder:dec"); // skip hour angle motor_flag[MOT_A]=0; // skip hour angle motor_flag[MOT_D]=1; } if(found==2) { // use calibrate_astro() function if( (err=do_calib_astro(fd,argument,0))!=0) { sprintf(c,"do_calib_astro:adc"); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: " "Calibration from encoders/potentiometers failed!\n"); } else { if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: " "Calibration from encoders/potentiometers OK.\n"); #endif } if( typ==0 || typ==4 ) goto SKIP; // displays final calibration results and exits else found=1; // continue with calibrate() when typ=2 or typ=3 (test modes) } if (found==1 && typ>=0 && typ<=3 ) { // use calibrate() function do { iter++; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib:iter=%d: " "Starting calibration mode=%d\n",iter,typ); #endif // reduce speed after first failure if(iter>1) { if (do_set_speed(fd,"half",0)==0) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: Calibration will be performed at" "a reduced speed.\n"); } else { if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: Can't reduce mount speed!\n"); } #endif } if ( (err=calibrate(fd,typ,&calib,motor_flag))==0 ) break; #ifdef DEBUG else { if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib:iter=%d: Calibration failed!\n",iter); } #endif } while( (typ==0 || typ==1) && iter< MONIT_CALIB_MAXRETRY ); if(err) { msg(log_file, "do_calib: Calibration mode=%d failed %d time(s)!\n" " Getting position from encoders/potentiometers.\n", typ, iter); if( (err=do_calib_astro(fd,argument,0))!=0) { sprintf(c,"calibrate + do_calib_astro:adc"); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: " "Calibration from encoders/potentiometers failed!\n"); #endif } else { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: " "Calibration from encoders/potentiometers OK.\n"); #endif } } else { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file, "do_calib: " "Calibration mode=%d OK.\n",typ); #endif } } else { err=ERROR_RESULT_CHECK; sprintf(c,"wrong mode"); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib: Wrong mode=%d\n",typ); #endif } /* end of if(!found... */ } /* end of if(tok==NULL)... */ SKIP:; if(!err) { print_calibration_data(&calib); /* timestamp=time((time_t*)NULL); */ /* msg(log_file, */ /* "Calibration data at: %s\n" */ /* "HA (RA) axis (motor-%d):\n" */ /* " Full steps per HA revolution %11.7le\n" */ /* " Microstep parameter %d (1:%d)\n" */ /* " POSITION: MICROSTEPS: ENCODER: HA[deg] @ DEC=0:\n" */ /* " LEFT mechanical limit %-8ld %-5ld %-9.5lf\n" */ /* " LEFT limit switch %-8ld %-5ld %-9.5lf\n" */ /* " HOME reference switch (L->R) %-8ld %-5ld %-9.5lf\n" */ /* " HOME reference switch (R->L) %-8ld %-5ld %-9.5lf\n" */ /* " RIGHT limit switch %-8ld %-5ld %-9.5lf\n" */ /* " RIGHT mechanical limit %-8ld %-5ld %-9.5lf\n\n" */ /* "DEC axis (motor-%d):\n" */ /* " Full steps per DEC revolution %11.7le\n" */ /* " Microstep parameter %d (1:%d)\n" */ /* " POSITION: MICROSTEPS: ENCODER: DEC[deg] @ HA=0:\n" */ /* " LEFT mechanical limit %-8ld %-5ld %-9.5lf\n" */ /* " LEFT limit switch %-8ld %-5ld %-9.5lf\n" */ /* " HOME reference switch (L->R) %-8ld %-5ld %-9.5lf\n" */ /* " HOME reference switch (R->L) %-8ld %-5ld %-9.5lf\n" */ /* " RIGHT limit switch %-8ld %-5ld %-9.5lf\n" */ /* " RIGHT mechanical limit %-8ld %-5ld %-9.5lf\n\n", */ /* ctime(×tamp), */ /* MOT_A, */ /* calib.gear_ratio[MOT_A], */ /* calib.microstep[MOT_A],(int)pow(2,calib.microstep[MOT_A]), */ /* calib.XL[MOT_A], calib.ADCL[MOT_A], */ /* (double)(calib.XL[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* calib.XMIN[MOT_A], calib.ADCMIN[MOT_A], */ /* (double)(calib.XMIN[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* calib.XHL[MOT_A], calib.ADCHL[MOT_A], */ /* (double)(calib.XHL[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* calib.XHR[MOT_A], calib.ADCHR[MOT_A], */ /* (double)(calib.XHR[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* calib.XMAX[MOT_A], calib.ADCMAX[MOT_A], */ /* (double)(calib.XMAX[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* calib.XR[MOT_A], calib.ADCR[MOT_A], */ /* (double)(calib.XR[MOT_A]*calib.motor_polarity[MOT_A]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_A]/pow(2,calib.microstep[MOT_A]) /\*+ t_home*\/ + calib.home_offset[MOT_A], */ /* MOT_D, */ /* calib.gear_ratio[MOT_D], */ /* calib.microstep[MOT_D],(int)pow(2,calib.microstep[MOT_D]), */ /* calib.XL[MOT_D], calib.ADCL[MOT_D], */ /* (double)(calib.XL[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D], */ /* calib.XMIN[MOT_D], calib.ADCMIN[MOT_D], */ /* (double)(calib.XMIN[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D], */ /* calib.XHL[MOT_D], calib.ADCHL[MOT_D], */ /* (double)(calib.XHL[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D], */ /* calib.XHR[MOT_D], calib.ADCHR[MOT_D], */ /* (double)(calib.XHR[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D], */ /* calib.XMAX[MOT_D], calib.ADCMAX[MOT_D], */ /* (double)(calib.XMAX[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D], */ /* calib.XR[MOT_D], calib.ADCR[MOT_D], */ /* (double)(calib.XR[MOT_D]*calib.motor_polarity[MOT_D]*hemisphere*360.0)/ */ /* calib.gear_ratio[MOT_D]/pow(2,calib.microstep[MOT_D]) /\*+ d_home*\/ + calib.home_offset[MOT_D] */ /* ); */ } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if(!err) msg(log_file, "do_calib: Ended normally\n"); else msg(log_file, "do_calib: Ended abnormally (%s)\n",c); } #endif return(err); } /***************************************************** * gets coordinates ***************************** *****************************************************/ int do_get_coo(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_COO; int err; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_get_coo: Started...\n"); #endif // calls do_set_coo() with arg="" err=do_set_coo(fd,NULL,motor); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if(!err) msg(log_file, "do_get_coo: Ended normally\n"); else msg(log_file, "do_get_coo: Ended abnormally (do_set_coo)\n"); } #endif return(err); } /////////////////////////////////////////////////////// TEST - START /* #if !defined(_TESTAUTOGUIDE_) && defined(SIMULATION) */ /* #define _TESTAUTOGUIDE_ */ /* #endif */ /////////////////////////////////////////////////////// TEST - END #ifdef _HAS_DO_ASTROMETRY_ /***************************************************** * gets coordinates ***************************** *****************************************************/ int do_calib_astro(fd,arg,mot) int *fd,mot; const char *arg; { // static int code=MONIT_CODE_ASTRO; int /*motor,track_us[2],track_speed[2],track_pdiv[2],*/ err,err_delayed_tracking_stopped,adc_flag,force_flag, hemisphere=(latitude>=0 ? 1 : -1); long adc[2],pos[2],timestamp; double st,ha,ra,dec,az,h; #if defined(SIMULATION) && defined(FALSE_ASTROMETRY_STUDY) double simulated_astrometry_offset[2]={0,0}; int simulated_astrometry_flag=0; #endif #ifdef SIMULATION /* double factor; */ int us[2]; double XH[2],XL[2],XR[2],XMIN[2],XMAX[2]; extern TMCL_SIMUL_GEOMETRY TMCL_SIMUL_geom; #endif char c[COMMENT_SIZE]="\0"; // extern struct TSTAT *ts; // extern struct TASTRO *ta; extern struct CALIB calib; char *tok; char *argcopy=NULL; int motor_flag[2]={1,1}; err=0; err_delayed_tracking_stopped=0; // when mount is neither tracking nor stopped #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_calib_astro: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok = strtok(argcopy," ,"); adc_flag=0; force_flag=0; // In REAL-TIME, STANDALONE always use encoders/potentiometers #ifndef SIMULATION #ifdef STANDALONE adc_flag=1; #endif #endif /* In SIMULATION always reset TASTRO_FLAG of global TASTRO structure 'ta'. * Since in SIMULATION mode 'ta' is filled only inside do_calib_astro() * this prevents erroneous behaviour after calling * 'astro FORCE' followed by 'astro'. */ #ifdef SIMULATION ta->track_flag=-1; #endif if( adc_flag==0 && tok!=NULL && strlen(tok)>0 ) { if(strcmp(tok,"adc")==0 || strcmp(tok,"potentiometer")==0 || strcmp(tok,"pot")==0 || strcmp(tok,"encoder")==0 ) { /* switching to "astrometry" from encoder/potentiometer data */ adc_flag=1; } if(strcmp(tok,"adc:ha")==0 || strcmp(tok,"potentiometer:ha")==0 || strcmp(tok,"pot:ha")==0 || strcmp(tok,"encoder:ha")==0 || strcmp(tok,"adc:ra")==0 || strcmp(tok,"potentiometer:ra")==0 || strcmp(tok,"pot:ra")==0 || strcmp(tok,"encoder:ra")==0 || strcmp(tok,"adc:0")==0 || strcmp(tok,"potentiometer:0")==0 || strcmp(tok,"pot:0")==0 || strcmp(tok,"encoder:0")==0 ) { /* switching to "astrometry" from encoder/potentiometer data */ adc_flag=1; motor_flag[MOT_A]=1; motor_flag[MOT_D]=0; // skip declination } if(strcmp(tok,"adc:dec")==0 || strcmp(tok,"potentiometer:dec")==0 || strcmp(tok,"pot:dec")==0 || strcmp(tok,"encoder:dec")==0 || strcmp(tok,"adc:d")==0 || strcmp(tok,"potentiometer:d")==0 || strcmp(tok,"pot:d")==0 || strcmp(tok,"encoder:d")==0 || strcmp(tok,"adc:1")==0 || strcmp(tok,"potentiometer:1")==0 || strcmp(tok,"pot:1")==0 || strcmp(tok,"encoder:1")==0 ) { /* switching to "astrometry" from encoder/potentiometer data */ adc_flag=1; motor_flag[MOT_A]=0; // skip hour angle motor_flag[MOT_D]=1; } #if defined(SIMULATION) && defined(FALSE_ASTROMETRY_STUDY) if(strcmp(tok,"false")==0) { simulated_astrometry_flag=1; simulated_astrometry_offset[MOT_A]=50.0; simulated_astrometry_offset[MOT_D]=-50.0; } #endif } #ifdef DEBUG if(adc_flag==1 && logging>=MESSAGE_LEVEL) msg(log_file,"do_calib_astro: " "ADC mode => getting position from encoders/potentiometers.\n"); #endif /* suppress integrity check when either: * 1. FORCE argument was given, or * 2. ta->track_flag=2 in TASTRO structure. */ if( adc_flag==0 && tok!=NULL && strlen(tok)>0) { if( strcmp(tok,"force")==0 ) force_flag=1; } if( ta->track_flag==2 ) force_flag=1; #ifdef DEBUG if(force_flag==1 && logging>=MESSAGE_LEVEL) msg(log_file,"do_calib_astro: " "FORCE mode => integrity check disabled.\n"); #endif // gets current status, quiet mode if(!err && (err=get_status(fd,ts,&calib,0))!=0 ) { if(force_flag==0) { err=ERROR_RESULT_IO; sprintf(c,"get_status:initial"); } #ifdef DEBUG else if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: Can't get initial status " "(will try to proceed anyway).\n"); #endif } /* In case of force_flag==0 (i.e. integrity checking enabled) * only (TRACKING,TRACKING), (TRACKING, STOPPED) or (STOPPED,STOPPED) * statuses are allowed. Otherwise 'astro' command won't proceed. */ if(force_flag==1) { ta->track_flag=2; // don't bother about tracking/stopped // status in the FORCED mode! } else { if(check_tracking(ts)) /* // Loads tracking paramters for cross-checking */ /* for(motor=0;motor<2;motor++) */ /* { */ /* track_us[motor]=(int)mot_speed[motor][MOT_TRACK_SPEED] */ /* [MOT_SPEED_INDEX_MICROSTEP].val; */ /* track_speed[motor]=(int)mot_speed[motor][MOT_TRACK_SPEED] */ /* [MOT_SPEED_INDEX_MAX_SPEED].val; // includes polarity */ /* track_pdiv[motor]=(int)mot_speed[motor][MOT_TRACK_SPEED] */ /* [MOT_SPEED_INDEX_PULSE_DIV].val; */ /* } */ /* // Verifies status */ /* if( ((ts->vel[MOT_A]==0 && track_speed[MOT_A]==0) || */ /* (ts->target_vel[MOT_A]==track_speed[MOT_A] && */ /* ts->target_vel[MOT_A]==ts->vel[MOT_A] && */ /* ts->pdiv[MOT_A]==track_pdiv[MOT_A] && */ /* ts->us[MOT_A]==track_us[MOT_A] )) && */ /* ((ts->vel[MOT_D]==0 && track_speed[MOT_D]==0) || */ /* (ts->target_vel[MOT_D]==track_speed[MOT_D] && */ /* ts->target_vel[MOT_D]==ts->vel[MOT_D] && */ /* ts->pdiv[MOT_D]==track_pdiv[MOT_D] && */ /* ts->us[MOT_D]==track_us[MOT_D] )) */ /* ) */ { /* Current speed parameters match the pre-set tracking * speed parameters => we are in a tracking mode */ #ifdef SIMULATION // PIMAN or STANDALONE, SIMULATION ta->track_flag=1; #else #ifdef STANDALONE // STANDALONE, REAL-TIME: ta->track_flag=1; #else // PIMAN, REAL-TIME: if(adc_flag==1) ta->track_flag=1; // modify ta->track_flag // only if ADC/ENCODER/POTENTIOMETER mode was requested; // use external TASTRO structure otherwise #endif #endif #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: Tracking is turned ON\n"); #endif } else { // verifies (STOPPED,STOPPED) status by hand, // since SLIDE can mask STOPPED/TRACKING/BUSY flag if( ts->vel[MOT_A]==0 && ts->vel[MOT_D]==0 ) { #ifdef SIMULATION // PIMAN or STANDALONE, SIMULATION: ta->track_flag=0; #else #ifdef STANDALONE // STANDALONE, REAL-TIME: ta->track_flag=0; #else // PIMAN, REAL-TIME: if(adc_flag==1) ta->track_flag=0;// only modify ta->track_flag // if ADC mode was requested; // otherwise use information // from external TASTRO structure #endif #endif #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: Both motors are stopped\n"); #endif } else { if(force_flag==0) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: " "Not in STOPPED/TRACKING mode " "(switching to FORCE mode).\n"); #endif ta->track_flag=2; // don't bother about tracking/stopped // status in the FORCED mode! force_flag=1; err_delayed_tracking_stopped=ERROR_RESULT_CHECK; } #ifdef DEBUG else if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: " "Not in STOPPED/TRACKING mode " "(will try to proceed anyway).\n"); #endif } } } switch(adc_flag) { case 0: #ifdef SIMULATION ///////////////////////////////////////////////////// //// SIMULATED ASTROMETRY - BEGIN //// ///////////////////////////////////////////////////// // // calculates "true" astrometry position // in SIMUALTED mode (STANDALONE/PIMAN) // for(mot=0;mot<2;mot++) if(!err) { if ( (err=TMCL_SIMUL_get_internal_val(mot, TMCL_ACTUAL_POSITION, &pos[mot]))==0 && (err=TMCL_SIMUL_get_internal_val(mot, TMCL_MICROSTEP, &us[mot]))==0 && (err=TMCL_SIMUL_get_internal_geometry_val (mot, TMCL_SIMUL_internal_geom_type_FS, TMCL_SIMUL_internal_geom_pos_HOME,&XH[mot]))==0 && (err=TMCL_SIMUL_get_internal_geometry_val (mot, TMCL_SIMUL_internal_geom_type_FS, TMCL_SIMUL_internal_geom_pos_RIGHT,&XR[mot]))==0 && (err=TMCL_SIMUL_get_internal_geometry_val (mot, TMCL_SIMUL_internal_geom_type_FS, TMCL_SIMUL_internal_geom_pos_LEFT,&XL[mot]))==0 && (err=TMCL_SIMUL_get_internal_geometry_val (mot, TMCL_SIMUL_internal_geom_type_FS, TMCL_SIMUL_internal_geom_pos_MIN,&XMIN[mot]))==0 && (err=TMCL_SIMUL_get_internal_geometry_val (mot, TMCL_SIMUL_internal_geom_type_FS, TMCL_SIMUL_internal_geom_pos_MAX,&XMAX[mot]))==0 ) { } else { err=ERROR_RESULT_IO; sprintf(c,"get_internal:motor-%d",mot); break; } } if(!err) { timestamp = time(NULL); st = get_ST_2args(longitude,timestamp); // time in hours // checks limit LEFT and RIGHT border for(mot=0;mot<2;mot++) { /* // converts calibration microstepping */ /* // into current microstepping */ /* factor = pow(2.0,us[mot]/\*-TMCL_SIMUL_calib.microstep[mot]*\/); */ if( pos[mot]>=(long)(XR[mot]*microsteps[us[mot]])) pos[mot]=minim(pos[mot], (long)(microsteps[us[mot]]*XMAX[mot])); if( pos[mot]<=(long)(XL[mot]*microsteps[us[mot]])) pos[mot]=maxim(pos[mot], (long)(microsteps[us[mot]]*XMIN[mot])); } // calculates true coordinates ha= ((double)pos[MOT_A]/microsteps[us[MOT_A]]-XH[MOT_A]) / TMCL_SIMUL_geom.fs_gear[MOT_A] * calib.motor_polarity[MOT_A] /* * TMCL_SIMUL_geom.fs_polarity[MOT_A]*/ * hemisphere * 360. + TMCL_SIMUL_geom.offset_home[MOT_A]; dec= ((double)pos[MOT_D]/microsteps[us[MOT_D]]-XH[MOT_D]) / TMCL_SIMUL_geom.fs_gear[MOT_D] * calib.motor_polarity[MOT_D] /* * TMCL_SIMUL_geom.fs_polarity[MOT_D]*/ * hemisphere * 360. + TMCL_SIMUL_geom.offset_home[MOT_D]; /* normalizes DEC to [-180deg, 180deg] convention */ while (dec>180.0) dec -= 360.0; while (dec<=-180.0) dec += 360.0; /* normalizes DEC to [-90deg, 90deg] convention */ if(dec>90.) { dec = 180. - dec; ha += 180.; } if(dec<=-90.) { dec = -180.- dec; ha += 180.; } /* normalizes HA to [0, 360deg] convention */ while (ha>=360.) ha -= 360.; while (ha<0.) ha += 360.; ra=(st/24.)*360.-ha; // [deg] while(ra < 0) ra += 360.; while(ra >= 360.)ra -= 360.; // updates TASTRO structure ta->ra = ra; ta->dec = dec; ta->timestamp = timestamp; /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL) { */ msg(log_file, "Simulated astrometry: " "TIMESTAMP=%ld sec, RA=%9.5lf deg, " "HA=%9.5lf deg, DEC=%9.5lf deg\n", ts->timestamp,ta->ra,ha,ta->dec); /* } */ /* #endif */ } /////////////////////////////////////////////////////// TEST - START #ifdef _TESTAUTOGUIDE_ // if tracking is ON then wait a 10 seconds // in order to test tracking extrapolation // inside calibrate_astro() if (ta->track_flag==1) { msg(log_file,"do_calib_astro: Waiting for 10 sec...\n"); msleep(10000000); msg(log_file,"do_calib_astro: Proceeding to calibrate_astro()\n"); } #endif /////////////////////////////////////////////////////// TEST - END ///////////////////////////////////////////////////// //// SIMULATED ASTROMETRY - END //// ///////////////////////////////////////////////////// #endif break; case 1: // calculates "true" astrometry position in REAL-TIME STANDALONE mode // from potentiometers/encoders for(mot=0;mot<2;mot++) if(!err) { /* if ( gio(fd,mot_pot_channel[mot], */ /* TMCL_AIN_BANK,&adc[mot])!=0 ) */ if ( read_absolute_encoder(fd,mot,&adc[mot])!=0 ) { err=ERROR_RESULT_IO; sprintf(c,"encoder:motor-%d",mot); break; } } if(!err) { timestamp = time(NULL); st = get_ST_2args(longitude,timestamp); // time in hours // calculates coordinates calc_position_from_encoder_counts(adc,timestamp,&calib, &ha,&dec,&ra,&az,&h); /* pos[MOT_A] = (double)(adc[MOT_A]+0.5- */ /* 0.5*(calib.ADCHR[MOT_A]+calib.ADCHL[MOT_A]))/ */ /* (double)(calib.ADCMAX[MOT_A]-calib.ADCMIN[MOT_A])* */ /* (calib.XMAX[MOT_A]-calib.XMIN[MOT_A]); */ /* pos[MOT_D] = (double)(adc[MOT_D]+0.5- */ /* 0.5*(calib.ADCHR[MOT_D]+calib.ADCHL[MOT_D]))/ */ /* (double)(calib.ADCMAX[MOT_D]-calib.ADCMIN[MOT_D])* */ /* (calib.XMAX[MOT_D]-calib.XMIN[MOT_D]); */ /* ha= pos[MOT_A]/(calib.gear_ratio[MOT_A]* */ /* microsteps[calib.microstep[MOT_A]]* */ /* calib.motor_polarity[MOT_A]*hemisphere)*360. */ /* /\*+ t_home*\/ + calib.home_offset[MOT_A]; */ /* dec = pos[MOT_D]/(calib.gear_ratio[MOT_D]* */ /* microsteps[calib.microstep[MOT_D]]* */ /* calib.motor_polarity[MOT_D]*hemisphere)*360. */ /* /\*+ d_home*\/ + calib.home_offset[MOT_D]; */ /* /\* normalizes DEC to [-180deg, 180deg] convention *\/ */ /* while (dec>180.0) dec -= 360.0; */ /* while (dec<=-180.0) dec += 360.0; */ /* /\* normalizes DEC to [-90deg, 90deg] convention *\/ */ /* if(dec>90.) { dec = 180. - dec; ha += 180.; } */ /* if(dec<=-90.) { dec = -180.- dec; ha += 180.; } */ /* /\* normalizes HA to [0, 360deg] convention *\/ */ /* while (ha>=360.) ha -= 360.; */ /* while (ha<0.) ha += 360.; */ /* ra=(st/24.)*360.-ha; // [deg] */ /* while(ra < 0) ra += 360.; */ /* while(ra >= 360.)ra -= 360.; */ #ifdef DEBUG if(logging>MESSAGE_LEVEL) { for (mot=0;mot<2;mot++) pos[mot] = calc_microsteps_from_encoder_counts(mot, calib.microstep[mot], adc[mot], &calib); msg(log_file, "do_calib_astro: Position from potentiometers/encoders:\n" " HA=%9.5lf deg (adc=%ld, " "pos=%ld, us=%d)\n" " DEC=%9.5lf deg (adc=%ld, " "pos=%ld, us=%d)\n", ha,adc[MOT_A],pos[MOT_A], calib.microstep[MOT_A], dec,adc[MOT_D],pos[MOT_D], calib.microstep[MOT_D]); } #endif // updates TASTRO structure ta->ra = ra; ta->dec = dec; ta->timestamp = timestamp; /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL) { */ msg(log_file, "Simulated astrometry: " "TIMESTAMP=%ld sec, RA=%9.5lf deg, " "HA=%9.5lf deg, DEC=%9.5lf deg\n", ts->timestamp,ta->ra,ha,ta->dec); /* } */ /* #endif */ } /* end of if(!err)... */ break; default: sprintf(c,"wrong adc_flag=%d",adc_flag); err=ERROR_RESULT_CHECK; }; /* end of switch(adc_flag..*/ #if !defined(SIMULATION) && !defined(STANDALONE) /* #if defined(DEBUG) && !defined(SIMULATION) && !defined(STANDALONE) */ /* if(logging>MESSAGE_LEVEL) { */ // calculate HOUR ANGLE which is not included TASTRO structure st = get_ST_2args(longitude,ts->timestamp); // time in hours ha=(st/24.)*360.-ra; // [deg] // normalizes HA to [0, 360deg] convention while (ha>=360.) ha -= 360.; while (ha<0.) ha += 360.; msg(log_file, "External astrometry: " "TIMESTAMP=%ld sec, RA=%9.5lf deg, " "HA=%9.5lf deg, DEC=%9.5lf deg\n", ts->timestamp,ta->ra,ha,ta->dec); /* } */ #endif #if defined(SIMULATION) && defined(FALSE_ASTROMETRY_STUDY) if(simulated_astrometry_flag) { st = get_ST_2args(longitude,ts->timestamp); // time in hours ha = (st/24.)*360. - ta->ra + simulated_astrometry_offset[MOT_A]; dec = ta->dec + simulated_astrometry_offset[MOT_D]; /* normalizes DEC to [-180deg, 180deg] convention */ while (dec>180.0) dec -= 360.0; while (dec<=-180.0) dec += 360.0; /* normalizes DEC to [-90deg, 90deg] convention */ if(dec>90.) { dec = 180. - dec; ha += 180.; } if(dec<=-90.) { dec = -180.- dec; ha += 180.; } /* normalizes HA to [0, 360deg] convention */ while (ha>=360.) ha -= 360.; while (ha<0.) ha += 360.; ra=(st/24.)*360.-ha; // [deg] while(ra < 0) ra += 360.; while(ra >= 360.)ra -= 360.; // updates TASTRO structure ta->ra = ra; ta->dec = dec; msg(log_file, "FALSE astrometry passed to calibrate_astro(): " "TIMESTAMP=%ld sec, RA=%9.5lf deg, " "HA=%9.5lf deg, DEC=%9.5lf deg\n", ts->timestamp,ta->ra,ha,ta->dec); } #endif /* The actual motor step adjustment will be done * by calibrate_astro() function */ if (!err && (err=calibrate_astro(fd,ta,&calib,motor_flag))!=0 ) { sprintf(c,"calibrate_astro"); } if(err_delayed_tracking_stopped) { if(!err) sprintf(c,"not STOPPED/TRACKING"); else strcat(c," + not STOPPED/TRACKING"); err=err_delayed_tracking_stopped; } /* The "ADC" mode can not replace precise calibration from limit switches * or precise astrometry when precision of the encoders/potentiometers * is not sufficient; * in such a case set calib.needcalib_flag[]=2 regardless of the result * returned by calibrate_astro() */ if( adc_flag==1 ) for(mot=0;mot<2;mot++) if (motor_flag[mot]) { if(!err) { if(option->calib_encoder_is_precise[mot]) calib.needcalib_flag[mot]=0; // precise calibration OK else calib.needcalib_flag[mot]=2; // coarse calibration OK } else calib.needcalib_flag[mot]=1; // calibration failed } // get current status, verbose mode if(!err && (err=get_status(fd,ts,&calib,1))!=0) { if(force_flag==0) { err=ERROR_RESULT_IO; sprintf(c,"get_status:final"); } #ifdef DEBUG else if(logging>MESSAGE_LEVEL) msg(log_file,"do_calib_astro: Can't get final status " "(will try to proceed anyway).\n"); #endif } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if(!err) msg(log_file, "do_calib_astro: Ended normally\n"); else msg(log_file, "do_calib_astro: Ended abnormally (%s)\n",c); } #endif return(err); } #endif /***************************************************** * gets program version ******************************* *****************************************************/ int do_get_version(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_VER; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_get_version: Started...\n"); #endif msg(log_file, _MONIT_SESSION_TYPE_ " TRINAMIC TMCM-300 session\n" _MONIT_BUILD_VERSION_"\n"); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, "do_get_version: Ended normally\n"); #endif return(0); } /***************************************************** * stop motor (SHOULD BE USED FOR DEBUGGING ONLY!) *****************************************************/ int do_stop(fd,arg,motor) int *fd,motor; const char *arg; { extern int status[2]; // static int code=MONIT_CODE_STOP; int err=0; int val,val2; char *tok; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_stop: Started...\n"); if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop: motor=%d arg=|%s|\n", motor,arg); #endif err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); if(tok == NULL || strlen(tok) == 0) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop: stopping current motor: %d\n",motor); val=motor; // do_motor() command is implemented in DEBUG mode // threfore variable 'motor' can be changed by user #else err=ERROR_RESULT_SYNTAX; // if not in DEBUG mode then skip STOP command // because 'motor' command is not implemented #endif } else { val=-1; // probe first argument if( strcmp(tok,"ra")==0 || strcmp(tok,"ha")==0 ) { val=MOT_A; } if( strcmp(tok,"dec")==0 || strcmp(tok,"d")==0 ) { val=MOT_D; } if( (val==-1 && sscanf(tok,"%d",&val)!=1) || val<0 || val>1) { err=ERROR_RESULT_SYNTAX; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop: wrong motor number: %s\n",tok); #endif } // probe second argument tok=strtok(NULL," ,"); if(tok!=NULL && strlen(tok)>0) { val2=-1; if( strcmp(tok,"ra")==0 || strcmp(tok,"ha")==0 ) { val2=MOT_A; } if( strcmp(tok,"dec")==0 || strcmp(tok,"d")==0 ) { val2=MOT_D; } if( (val2==-1 && sscanf(tok,"%d",&val2)!=1) || val2<0 || val2>1) { err=ERROR_RESULT_SYNTAX; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop: wrong motor number: %s\n",tok); #endif } if( (val==0 && val2==1) || (val==1 && val2==0) ) val=10; } } /* end of if ( tok==NULL ... */ if(!err && (val==0 || val==1 || val==10)) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) { if(val!=10) msg(log_file,"do_stop: stopping motor %d\n",val); else msg(log_file,"do_stop: stopping both motors.\n"); } #endif if(val==10) for(val=0;val<2;val++) { if( mst(fd,val) != 0 ) { err=ERROR_RESULT_IO; status[val]=MOT_STAT_ERROR; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop:motor-%d: MST error\n",val); #endif } else status[val]=MOT_STAT_STOPPED; } else { if( mst(fd,val) != 0 ) { err=ERROR_RESULT_IO; status[val]=MOT_STAT_ERROR; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_stop:motor-%d: MST error\n",val); #endif } else status[val]=MOT_STAT_STOPPED; } } /* end if(!err... */ if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if(!err) msg(log_file, "do_stop: Ended normally\n"); else msg(log_file, "do_stop: Ended abnormally (mst/ambiguity error)\n"); } #endif return(err); } /***************************************************** * move to coordinates *****************************************************/ int do_set_coo(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_GOTO; /* long timeout=480000000; // 8 min */ long timeout=120000000; // 2 min for FAST speed parameters char *tok1,*tok2; // argument string double arg1,arg2; // argument value; int narg,found,err; //kn struct TSTAT ts_,*ts=&ts_; // status structure int (*func)(); // pointer to a function to be called double ha,dec,az,h; // coordinates char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; // extern struct CALIB calib; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_coo: Started...\n"); #endif /* msg(log_file,"BEFORE STR2STR: arg=|%s| argcopy=|%s|\n", */ /* arg,argcopy); */ // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); /* msg(log_file,"AFTER STR2STR: arg=|%s| argcopy=|%s|\n", */ /* arg,argcopy); */ // if some arguments exist, performs syntax checking if( argcopy==NULL || (argcopy!=NULL && strlen(argcopy)>0) ) { // stores old coordinates into 'ts' variable of TSTAT type err=get_status(fd,ts,&calib,0); // prints no information sprintf(c,"get_status verb=0"); // checks arguments if( !err ) { narg=0; tok1 = strtok(argcopy," ,"); if( tok1!=NULL && strlen(tok1)>0 ) narg=1; tok2=strtok(NULL," ,"); if( narg==1 && tok2!=NULL && strlen(tok2)>0 ) narg=2; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_set_coo: arg1=|%s| arg2=|%s| narg=%d\n", tok1,tok2,narg); #endif found=0; switch(narg) { case 0:break; case 2: // Syntax (1): goto // Syntax (2): goto ra= d[ec]= if( ( sscanf(tok1,"%lf",&arg1)==1 && sscanf(tok2,"%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ) ) { found=1; func=set_RA_DEC; // arg1=RA, arg2=DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_RA_DEC " "RA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (4): goto ha= d[ec]= if( !found && (( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ))) { found=1; func=set_HA_DEC; // arg1=HA, arg2=DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (7): goto az= h[eight]= if( !found && (( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"height=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"height=%lf",&arg2)==1 ) || ( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"h=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"h=%lf",&arg2)==1 ))) { // gets new (AZ,H) az = arg1; h = arg2; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1=ha; // HA arg2=dec; // DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } break; case 1: // Syntax (3): goto ra= if( !found && sscanf(tok1,"ra=%lf",&arg1)==1 ) { found=1; func=set_RA_DEC; // arg1=RA arg2=ts->dec; // DEC (old value) #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_RA_DEC " "RA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (5): goto ha= if( !found && sscanf(tok1,"ha=%lf",&arg1)==1 ) { found=1; func=set_HA_DEC; arg1=arg1; // HA arg2=ts->dec; // DEC (old value) #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (6): goto d[ec]= if( !found && ( sscanf(tok1,"dec=%lf",&arg2)==1 || sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; func=set_HA_DEC; arg1=ts->ha; // HA (old value) // arg2=DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (8): goto az= if( !found && sscanf(tok1,"az=%lf",&arg1)==1 ) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old HEIGHT corresponding to old (HA,DEC) h = asin( sin(dec/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(dec/180.*M_PI)*cos(latitude/180.*M_PI)* cos(ha/180.*M_PI) )*180./M_PI; // gets new AZIMUTH az = arg1; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1=ha; // HA arg2=dec; // DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (9): goto h[eight]= if( !found && ( sscanf(tok1,"height=%lf",&arg2)==1 || sscanf(tok1,"h=%lf",&arg2)==1 )) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old AZ corresponding to old (HA,DEC) az = atan2( sin(ha/180.*M_PI), sin(latitude/180.*M_PI)*cos(ha/180.*M_PI)- tan(dec/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; // gets new HEIGHT h = arg2; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1=ha; // HA arg2=dec; // DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } }; /* end of switch(narg) */ // if everything is OK, starts moving if (narg>0) { // wrong syntax if(!found) { err=-1; sprintf(c,"wrong syntax"); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo: Wrong syntax: |%s|\n", arg); #endif } // good syntax else { // checks speed_mode range and // updates timeout switch(speed_mode) { case MOT_FAST_SPEED: break; // do not change timeout case MOT_MEDIUM_SPEED: timeout*=2; // two times longer timeout break; default: // wrong speed mode err=-1; sprintf(c,"wrong speed mode"); }; if(!err) { if ( (err=func(fd,arg1,arg2,timeout,&calib))!=0 ) sprintf(c,"set_HA_DEC/set_RA_DEC"); } } } /* end of if(narg>0).... */ } /* end of if(!err)... */ } /* end of if(arg!=NULL...*/ // finally prints coordinates on screen if (!err) { err = get_status(fd,ts,&calib,1); // only prints the coordinates sprintf(c,"get_status verb=1"); } if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_set_coo: Ended abnormally (%s)\n",c); else msg(log_file,"do_set_coo: Ended normally\n"); } #endif return(err); } /***************************************************** * move to relative coordinates *****************************************************/ int do_set_coo_relative(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_GOTOREL; long timeout=480000000; // 8 min char *tok1,*tok2; // argument string double arg1,arg2; // argument value; int narg,found,err; //kn struct TSTAT ts_,*ts=&ts_; // status structure int (*func)(); // pointer to a function to be called double ha,dec,az,h; // coordinates char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; // extern struct CALIB calib; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_coo_relative: Started...\n"); #endif err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // if some arguments exist, performs syntax checking if( argcopy==NULL || (argcopy!=NULL && strlen(argcopy)>0) ) { // stores old coordinates into 'ts' variable of TSTAT type err=get_status(fd,ts,&calib,0); // prints no information sprintf(c,"get_status verb=0"); // checks arguments if( !err ) { narg=0; tok1 = strtok(argcopy," ,"); if( tok1!=NULL && strlen(tok1)>0 ) narg=1; tok2=strtok(NULL," ,"); if( narg==1 && tok2!=NULL && strlen(tok2)>0 ) narg=2; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_set_coo_relative: arg1=|%s| arg2=|%s| narg=%d\n", tok1,tok2,narg); #endif found=0; switch(narg) { case 0:break; case 2: // Syntax (1): goto // Syntax (2): goto ra= d[ec]= if( ( sscanf(tok1,"%lf",&arg1)==1 && sscanf(tok2,"%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ) ) { found=1; func=set_RA_DEC; arg1 += ts->ra; // adds old position arg2 += ts->dec; // adds old position // arg1 = new RA // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_RA_DEC " "RA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (4): goto ha= d[ec]= if( !found && (( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ))) { found=1; func=set_HA_DEC; arg1 += ts->ha; // adds old position arg2 += ts->dec; // adds old position // arg1 = new HA // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (7): goto az= h[eight]= if( !found && (( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"height=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"height=%lf",&arg2)==1 ) || ( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"h=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"h=%lf",&arg2)==1 ))) { // gets new (AZ,H) az = ts->az + arg1; // adds old position h = ts->h + arg2; // adds old position // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1 = ha; // arg1 = new HA arg2 = dec; // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } break; case 1: // Syntax (3): goto ra= if( !found && sscanf(tok1,"ra=%lf",&arg1)==1 ) { found=1; func=set_RA_DEC; arg1 += ts->ra; // adds old position // arg1 = new RA arg2=ts->dec; // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_RA_DEC " "RA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (5): goto ha= if( !found && sscanf(tok1,"ha=%lf",&arg1)==1 ) { found=1; func=set_HA_DEC; arg1 += ts->ha; // add old position // arg1 = new HA arg2 = ts->dec; // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (6): goto d[ec]= if( !found && ( sscanf(tok1,"dec=%lf",&arg2)==1 || sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; func=set_HA_DEC; arg1 = ts->ha; // arg1 = new HA arg2 += ts->dec; // adds old position // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (8): goto az= if( !found && sscanf(tok1,"az=%lf",&arg1)==1 ) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old HEIGHT corresponding to old (HA,DEC) h = asin( sin(dec/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(dec/180.*M_PI)*cos(latitude/180.*M_PI)* cos(ha/180.*M_PI) )*180./M_PI; // gets new AZIMUTH az = ts->az + arg1; // adds old position // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1=ha; // arg1 = new HA arg2=dec; // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (9): goto h[eight]= if( !found && ( sscanf(tok1,"height=%lf",&arg2)==1 || sscanf(tok1,"h=%lf",&arg2)==1 )) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old AZ corresponding to old (HA,DEC) az = atan2( sin(ha/180.*M_PI), sin(latitude/180.*M_PI)*cos(ha/180.*M_PI)- tan(dec/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; // gets new HEIGHT h = ts->h + arg2; // adds old position // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; func=set_HA_DEC; arg1=ha; // arg1 = new HA arg2=dec; // arg2 = new DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: FUNC=set_HA_DEC " "HA=%9.5lf deg DEC=%9.5lf deg\n", arg1,arg2); #endif } }; /* end of switch(narg) */ // if everything is OK, starts moving if (narg>0) { // wrong syntax if(!found) { err=-1; sprintf(c,"wrong syntax"); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_set_coo_relative: Wrong syntax: |%s|\n", arg); #endif } // good syntax else { err = func(fd,arg1,arg2,timeout,&calib); sprintf(c,"set_HA_DEC/set_RA_DEC"); } } /* end of if(narg>0).... */ } /* end of if(!err)... */ } /* end of if(arg!=NULL...*/ // finally prints coordinates on screen if (!err) { err = get_status(fd,ts,&calib,1); // only prints the coordinates sprintf(c,"get_status verb=1"); } if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_set_coo_relative: Ended abnormally (%s)\n",c); else msg(log_file,"do_set_coo_relative: Ended normally\n"); } #endif return(err); } /***************************************************** * check if coordinates are within mount's range *****************************************************/ int do_check_coo(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CHK_GOTO; char *tok1,*tok2; // argument string double arg1,arg2; // argument value; int narg,found,err; //kn struct TSTAT ts_,*ts=&ts_; // status structure double st,ha,dec,az,h; // coordinates long max_tracktime; // maximal allowed tracking time [sec] after // moving to a hypothetical position char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; // extern struct CALIB calib; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_check_coo: Started...\n"); #endif err=0; max_tracktime=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // if some arguments exist, performs syntax checking if( argcopy==NULL ) { // prints coordinates and updates 'ts' variable of TSTAT type err=get_status(fd,ts,&calib,0); sprintf(c,"get_status verb=0"); } if (argcopy!=NULL && strlen(argcopy)>0) { // do not print coordinates on screen err = get_status(fd,ts,&calib,0); sprintf(c,"get_status verb=0"); if (!err) { narg=0; st=get_ST_2args(longitude,ts->timestamp); // time in hours tok1 = strtok(argcopy," ,"); if( tok1!=NULL && strlen(tok1)>0 ) narg=1; tok2=strtok(NULL," ,"); if( narg==1 && tok2!=NULL && strlen(tok2)>0 ) narg=2; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_check_coo: arg1=|%s| arg2=|%s| narg=%d\n", tok1,tok2,narg); #endif found=0; switch(narg) { case 0:break; case 2: // Syntax (1): goto // Syntax (2): goto ra= d[ec]= if( ( sscanf(tok1,"%lf",&arg1)==1 && sscanf(tok2,"%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ) ) { found=1; ha=(st/24.)*360.-arg1; // HA [deg] dec=arg2; // DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (4): goto ha= d[ec]= if( !found && (( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 ))) { found=1; ha=arg1; // HA dec=arg2; // DEC #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (7): goto az= h[eight]= if( !found && (( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"height=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"height=%lf",&arg2)==1 ) || ( sscanf(tok1,"az=%lf",&arg1)==1 && sscanf(tok2,"h=%lf",&arg2)==1 ) || ( sscanf(tok2,"az=%lf",&arg1)==1 && sscanf(tok1,"h=%lf",&arg2)==1 ))) { found=1; // gets new (AZ,H) az = arg1; h = arg2; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } break; case 1: // Syntax (3): goto ra= if( !found && sscanf(tok1,"ra=%lf",&arg1)==1 ) { found=1; ha=(st/24.)*360.-arg1; // HA [deg] dec=ts->dec; // DEC (old value) #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (5): goto ha= if( !found && sscanf(tok1,"ha=%lf",&arg1)==1 ) { found=1; dec=ts->dec; // DEC (old value) ha=arg1; // HA #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (6): goto d[ec]= if( !found && ( sscanf(tok1,"dec=%lf",&arg2)==1 || sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; ha=ts->ha; // HA (old value) dec=arg2; #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (8): goto az= if( !found && sscanf(tok1,"az=%lf",&arg1)==1 ) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old HEIGHT corresponding to old (HA,DEC) h = asin( sin(dec/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(dec/180.*M_PI)*cos(latitude/180.*M_PI)* cos(ha/180.*M_PI) )*180./M_PI; // gets new AZIMUTH az = arg1; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) ) *180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } // Syntax (9): goto h[eight]= if( !found && ( sscanf(tok1,"height=%lf",&arg2)==1 || sscanf(tok1,"h=%lf",&arg2)==1 )) { // gets old HA, DEC ha=ts->ha; dec=ts->dec; // calculates old AZ corresponding to old (HA,DEC) az = atan2( sin(ha/180.*M_PI), sin(latitude/180.*M_PI)*cos(ha/180.*M_PI)- tan(dec/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; // gets new HEIGHT h = arg2; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )* 180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; found=1; #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: " "HA=%9.5lf deg DEC=%9.5lf deg\n", ha,dec); #endif } }; /* end of switch(narg) */ // if everything is OK, starts moving if (narg>0) { // wrong syntax if(!found) { err=-1; sprintf(c,"wrong syntax"); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_check_coo: Wrong syntax: |%s|\n", arg); #endif } // good syntax else { max_tracktime = check_HA_DEC(ha,dec,&calib,tcp); /* tcp->ha = arg1; */ /* tcp->dec = arg2; */ /* tcp->max_tracktime = max_tracktime; */ if(max_tracktime>0) { msg(log_file, "Position is within mount's range.\n" "Maximal tracking time would be %ld sec.\n", max_tracktime); } else { msg(log_file,"Position is out of mount's range.\n"); sprintf(c,"check_HA_DEC"); } } } /* end of if(narg>0).... */ } /* end of if (!err)... */ } /* end of if(arg!=NULL...*/ if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_check_coo: Ended abnormally (%s)\n",c); else msg(log_file,"do_check_coo: Ended normally\n"); } #endif return(err); } /***************************************************************** * move telescope to absolute HA (t) position ********************* *****************************************************************/ int do_set_ha(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_HA; char *tok; int err; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_ha: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // forwards argument directly to do_set_coo() adding suitable prefix tok=strtok(argcopy," ,"); if(tok) snprintf(c,COMMENT_SIZE,"ha=%s",tok); // writes no more than COMMENT_SIZE err=do_set_coo(fd,c,motor); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_ha: Ended abnormally (do_set_coo error)\n"); else msg(log_file, "do_set_ha: Ended normally\n"); } #endif return(err); } /***************************************************************** * move telescope to absolute DEC (d) position ******************* *****************************************************************/ int do_set_dec(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_DEC; char *tok; int err; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_dec: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // forwards argument directly to do_set_coo() adding suitable prefix tok=strtok(argcopy," ,"); if(tok) snprintf(c,COMMENT_SIZE,"d=%s",tok); // writes no more than COMMENT_SIZE err=do_set_coo(fd,c,motor); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_dec: Ended abnormally (do_set_coo error)\n"); else msg(log_file, "do_set_dec: Ended normally\n"); } #endif return(err); } /***************************************************************** * move telescope to absolute RA (a) position ******************** *****************************************************************/ int do_set_ra(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_RA; char *tok; int err; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_ra: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // forwards argument directly to do_set_coo() adding suitable prefix tok=strtok(argcopy," ,"); if(tok) snprintf(c,COMMENT_SIZE,"ra=%s",tok); // writes no more than COMMENT_SIZE err=do_set_coo(fd,c,motor); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_ra: Ended abnormally (do_set_coo error)\n"); else msg(log_file, "do_set_ra: Ended normally\n"); } #endif return(err); } /***************************************************** * move to horizontal coordinate AZIMUTH (astronomical) *****************************************************/ int do_set_az(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_AZ; char *tok; int err; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_az: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // forwards argument directly to do_set_coo() adding suitable prefix tok=strtok(argcopy," ,"); if(tok) snprintf(c,COMMENT_SIZE,"az=%s",tok); // writes no more than COMMENT_SIZE err=do_set_coo(fd,c,motor); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_az: Ended abnormally (do_set_coo error)\n"); else msg(log_file, "do_set_az: Ended normally\n"); } #endif return(err); } /***************************************************** * move to horizontal coordinate HEIGHT *****************************************************/ int do_set_h(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_HEIGHT; char *tok; int err; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_h: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // forwards argument directly to do_set_coo() adding suitable prefix tok=strtok(argcopy," ,"); if(tok) snprintf(c,COMMENT_SIZE,"h=%s",tok); // writes no more than COMMENT_SIZE err=do_set_coo(fd,c,motor); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_h: Ended abnormally (do_set_coo error)\n"); else msg(log_file, "do_set_h: Ended normally\n"); } #endif return(err); } /***************************************************** * goes to a parking position *****************************************************/ int do_park(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_PARK; int maxiter,count,ipos,err,mot,us[2],motor_flag[2]; long adc[2],pos[2]; double az,h,ha,dec,x,factor; long twait_8min=480000000; // microseconds static int last_err=0,last_logging; char c[COMMENT_SIZE]="\0",strnum[2]; extern int status[2]; // extern struct CALIB calib; err=0; // increases verbose level if previous result gave ERROR if(last_err) { last_logging = logging; logging = maxim(MESSAGE_LEVEL_ON_ERROR,logging); } else last_logging=logging; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_park: Started...\n"); if(logging>MESSAGE_LEVEL) msg(log_file,"do_park: Random: maxiter=%d, " "AZ range={%lf,%lf}, " "H range={%lf,%lf}\n" " Failsafe: AZ=%lf, H=%lf\n" " Precision=%d\n", option->dopark_maxiter, option->dopark_minazimuth,option->dopark_maxazimuth, option->dopark_minheight,option->dopark_maxheight, option->dopark_az_safe,option->dopark_h_safe, option->dopark_precision); #endif // sets speed parameters /* if ((err=mot_speed_par(fd,MOT_A, MOT_FAST_SPEED,&calib)) == 0 && */ /* (err=mot_speed_par(fd,MOT_D, MOT_FAST_SPEED,&calib)) == 0 && */ if ((err=mot_speed_par(fd,MOT_A, speed_mode,&calib)) == 0 && (err=mot_speed_par(fd,MOT_D, speed_mode,&calib)) == 0 && (err=gap(fd,TMCL_MICROSTEP,MOT_A,&us[MOT_A])) == 0 && (err=gap(fd,TMCL_MICROSTEP,MOT_D,&us[MOT_D])) == 0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_park: speed parameters set\n"); #endif } else { err=ERROR_RESULT_IO; sprintf(c,"mot_speed_par/GAP:MICROSTEP"); } // calculates (random) target position (below the horizon) count=0; rand_seed((unsigned int)time(NULL)); maxiter = maxim(2, option->dopark_maxiter); if (!err) while(countdopark_az_safe; h = option->dopark_h_safe; } else { if(count==maxiter-1) { az = option->dopark_az_safe+180.0; h = option->dopark_h_safe; } else { // random azimuth and height az = option->dopark_minazimuth + (option->dopark_maxazimuth-option->dopark_minazimuth) * rando(); h = option->dopark_minheight + (option->dopark_maxheight-option->dopark_minheight) * rando(); } } // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )*180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; #ifdef DEBUG if(logging>MESSAGE_LEVEL/*+1*/) msg(log_file,"do_park: iter=%03ld: err=%d: " "(HA,DEC)=(%9.5lf,%9.5lf) (AZ,H)=(%9.5lf,%9.5lf)\n", count,err,ha,dec,az,h); #endif // check position availability if(!err) { if (check_HA_DEC(ha,dec,&calib,tcp)>0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_park: iter=%d: err=%d: " "primary and/or secondary position is/are " "within mount's range\n", count,err); #endif for(ipos=0;ipos<2;ipos++) if (tcp->tracktime[ipos]>0) { err=0; pos[MOT_A] = (long)(tcp->ha_pos[ipos]*pow(2,us[MOT_A])); pos[MOT_D] = (long)(tcp->dec_pos[ipos]*pow(2,us[MOT_D])); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_park: iter=%d: err=%d: ipos=%d: " "position is within mount's range\n", count,err,ipos); #endif // checks minimal distance to LEFT/RIGHT limit switches for(mot=0;mot<2;mot++) { x = pos[mot]*pow(2.0,-us[mot]); // full-steps factor = pow(2.0,-calib.microstep[mot]); if( (x-calib.XMIN[mot]*factor)/ calib.gear_ratio[mot]*360.0 < option->dopark_switch_clearance || (calib.XMAX[mot]*factor-x)/ calib.gear_ratio[mot]*360.0 < option->dopark_switch_clearance ) { err=ERROR_RESULT_CHECK; sprintf(c,"too close to the limit switch"); #ifdef DEBUG if(logging>MESSAGE_LEVEL/*+1*/) msg(log_file,"do_park:motor-%d: iter=%d: err=%d: " "position is too close to one of the limit " "switches\n",mot,count,err); #endif break; // exits for(mot...) loop } /* end of if( (x-calib...) */ } /* end of for(mot...) */ if(!err) break; // exits for(ipos...) loop } /* end of for(ipos...) if(tcp->...) */ if(!err) break; // exits while(count...) loop } else { err=ERROR_RESULT_POSITION; sprintf(c,"out of range"); } /* end of if(check_HA_DEC..) */ } /*end of if(!err)... */ } /* end of while(count...) loop */ if(!err) for(mot=0;mot<2;mot++) { motor_flag[mot]=1; adc[mot]=(double)( 0.5*(calib.ADCHL[mot]+calib.ADCHR[mot])+ pos[mot]*pow(2,-us[mot]+calib.microstep[mot])* (calib.ADCMAX[mot]-calib.ADCMIN[mot])/ (calib.XMAX[mot]-calib.XMIN[mot]) ); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_park:motor-%d: counts=%ld ADC=%ld\n", mot,pos[mot],adc[mot]); #endif } /* end of if(!err)... */ // speed_mode range check // timeout update if(!err) switch(speed_mode) { case MOT_FAST_SPEED: break; // do not change timeout case MOT_MEDIUM_SPEED: twait_8min*=2; // two times longer break; default: err=ERROR_RESULT_CHECK; sprintf(c,"wrong speed mode"); }; // goes to a park position using ADC counts instead of motor counts; // this prevents mismatch due to slide if(!err) { // find_adc() with precision 0 means that only coarse // positioning will be done (FASTER!) if( (err=find_adc(fd,motor_flag,adc,twait_8min, option->dopark_precision,&calib))==0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_park: park position reached\n"); #endif } else { sprintf(c,"find_adc"); } } /* end of if(!err).. */ if(err) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_park: stopping motors, getting status\n"); #endif for(mot=0;mot<2;mot++) if( mst(fd,mot)!=0 ) { status[mot]=MOT_STAT_ERROR; sprintf(strnum,"%1d",mot); strcat(c," + MST:motor-"); strcat(c,strnum); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, "do_park:motor-%d: EMERGENCY STOP FAILED !!!\n",mot); #endif } else { status[mot]=MOT_STAT_STOPPED; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, "do_park:motor-%d: EMERGENCY STOP COMPLETED\n",mot); #endif } if( get_status(fd,ts,&calib,2) !=0 ) { strcat(c," + get_status"); } } #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_park: Ended abnormally (%s)\n",c); else msg(log_file, "do_park: Ended normally\n"); } #endif // stores command result last_err = err; // restores verbose level logging = last_logging; return(err); } /***************************************************** * goes to the Zenith position *****************************************************/ int do_zenith(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_ZENITH; int ipos,err,mot,us[2],motor_flag[2]; long adc[2],pos[2]; double az,h,ha,dec,x,factor; long twait_8min=480000000; // microseconds static int last_err=0,last_logging; char c[COMMENT_SIZE]="\0",strnum[2]; extern int status[2]; // extern struct CALIB calib; err=0; // increases verbose level if previous result gave ERROR if(last_err) { last_logging = logging; logging = maxim(MESSAGE_LEVEL_ON_ERROR,logging); } else last_logging=logging; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_zenith: Started...\n"); #endif // sets speed parameters /* if ((err=mot_speed_par(fd,MOT_A, MOT_FAST_SPEED,&calib)) == 0 && */ /* (err=mot_speed_par(fd,MOT_D, MOT_FAST_SPEED,&calib)) == 0 && */ if ((err=mot_speed_par(fd,MOT_A, speed_mode,&calib)) == 0 && (err=mot_speed_par(fd,MOT_D, speed_mode,&calib)) == 0 && (err=gap(fd,TMCL_MICROSTEP,MOT_A,&us[MOT_A])) == 0 && (err=gap(fd,TMCL_MICROSTEP,MOT_D,&us[MOT_D])) == 0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_zenith: speed parameters set\n"); #endif } else { err=ERROR_RESULT_IO; sprintf(c,"mot_speed_par/GAP:MICROSTEP"); } // calculates (random) target position (Zenith) az = 0.0; h = 90.0; // converts (AZ,H) to (HA,DEC) ha = atan2( sin(az/180.*M_PI), sin(latitude/180.*M_PI)*cos(az/180.*M_PI)- tan(-h/180.*M_PI)*cos(latitude/180.*M_PI) )*180./M_PI; dec = -asin( sin(-h/180.*M_PI)*sin(latitude/180.*M_PI)+ cos(-h/180.*M_PI)*cos(latitude/180.*M_PI)* cos(az/180.*M_PI) )*180./M_PI; /* normalizes DEC to [-180deg, 180deg] convention */ while (dec>180.0) dec -= 360.0; while (dec<=-180.0) dec += 360.0; /* normalizes DEC to [-90deg, 90deg] convention */ if(dec>90.) { dec = 180. - dec; ha += 180.; } if(dec<=-90.) { dec = -180.- dec; ha += 180.; } /* normalizes HA to [-180deg, 180deg] convention */ while (ha > 180. ) ha -= 360.; while (ha <= -180. ) ha += 360.; #ifdef DEBUG if(logging>MESSAGE_LEVEL/*+1*/) msg(log_file,"do_zenith: err=%d: " "(HA,DEC)=(%9.5lf,%9.5lf) (AZ,H)=(%9.5lf,%9.5lf)\n", err,ha,dec,az,h); #endif // checking position availability if (!err) { if(check_HA_DEC(ha,dec,&calib,tcp)>0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_zenith: err=%d: " "primary and/or secondary position is/are within mount's range\n", err); #endif for(ipos=0;ipos<2;ipos++) if (tcp->tracktime[ipos]>0) { err=0; pos[MOT_A] = (long)(tcp->ha_pos[ipos]*pow(2,us[MOT_A])); pos[MOT_D] = (long)(tcp->dec_pos[ipos]*pow(2,us[MOT_D])); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_zenith: err=%d: ipos=%d: " "position is within mount's range\n", err,ipos); #endif // checks minimal distance to LEFT/RIGHT limit switches for(mot=0;mot<2;mot++) { x = pos[mot]*pow(2.0,-us[mot]); // full-steps factor = pow(2.0,-calib.microstep[mot]); if( (x-calib.XMIN[mot]*factor)/ calib.gear_ratio[mot]*360.0 < option->dozenith_switch_clearance || (calib.XMAX[mot]*factor-x)/ calib.gear_ratio[mot]*360.0 < option->dozenith_switch_clearance ) { err=ERROR_RESULT_CHECK; sprintf(c,"too close to limit switch"); #ifdef DEBUG if(logging>MESSAGE_LEVEL/*+1*/) msg(log_file,"do_zenith:motor-%d: err=%d: " "position is too close to one of the limit " "switches\n",mot,err); #endif break; // exits for(mot...) loop } /* end of if( (x-calib...) */ } /* end of for(mot...) */ if(!err) break; // exits for(ipos...) loop } /* end of for(ipos...) if(tcp->...) */ } else { err=ERROR_RESULT_POSITION; sprintf(c,"out of range"); } /* end of if(check_HA_DEC..) */ } /* end of if(!err)... */ if(!err) for(mot=0;mot<2;mot++) { motor_flag[mot]=1; adc[mot]=(double)( 0.5*(calib.ADCHL[mot]+calib.ADCHR[mot])+ pos[mot]*pow(2,-us[mot]+calib.microstep[mot])* (calib.ADCMAX[mot]-calib.ADCMIN[mot])/ (calib.XMAX[mot]-calib.XMIN[mot]) ); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_zenith:motor-%d: counts=%ld ADC=%ld\n", mot,pos[mot],adc[mot]); #endif } /* end of if(!err)... */ // speed_mode range check // timeout update if(!err) switch(speed_mode) { case MOT_FAST_SPEED: break; // do not change timeout case MOT_MEDIUM_SPEED: twait_8min*=2; // two times longer break; default: err=ERROR_RESULT_CHECK; sprintf(c,"wrong speed mode"); }; // goes to the Zenith position using ADC counts instead of motor counts; // this prevents mismatch due to slide if(!err) { // find_adc() with precision 0 means that only coarse // positioning will be done (FASTER!) if( (err=find_adc(fd,motor_flag,adc,twait_8min, option->dozenith_precision,&calib))==0 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_zenith: Zenith position reached\n"); #endif } else { sprintf(c,"find_adc"); } } /* end of if(!err).. */ if(err) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_zenith: stopping motors, getting status\n"); #endif for(mot=0;mot<2;mot++) if( mst(fd,mot)!=0 ) { status[mot]=MOT_STAT_ERROR; sprintf(strnum,"%1d",mot); strcat(c," + MST:motor-"); strcat(c,strnum); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, "do_zenith:motor-%d: EMERGENCY STOP FAILED !!!\n",mot); #endif } else { status[mot]=MOT_STAT_STOPPED; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file, "do_zenith:motor-%d: EMERGENCY STOP COMPLETED\n",mot); #endif } if( get_status(fd,ts,&calib,2) !=0 ) { strcat(c," + get_status"); } } #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_zenith: Ended abnormally (%s)\n",c); else msg(log_file, "do_zenith: Ended normally\n"); } #endif // stores command result last_err = err; // restores verbose level logging = last_logging; return(err); } /***************************************************** * observation site parameters *****************************************************/ int do_site(fd,arg,motor) int *fd,motor; const char *arg; { //static int code=MONIT_CODE_SITE; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_site: Started...\n"); #endif msg(log_file, "Current observation site:\n" "NAME = %s\n" "CODE = %s\n" "LONGITUDE = %.5f deg %s\n" "LATITUDE = %.5f deg %s\n" "HEMISPHERE = %s\n" "ALTITUDE = %.0f meters (%.0f feet) a.s.l.\n", site_comment, site_code, fabs(longitude), ( signum(longitude)>=0 ? "E" : "W" ), fabs(latitude), ( signum(latitude)>=0 ? "N" : "S" ), (signum(latitude)>=0 ? "Northern" : "Southern"), altitude /* meters */ , altitude * 100.0/2.54/12.0 /* feet */ ); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) msg(log_file, "do_site: Ended normally\n"); #endif return(0); } /***************************************************** * sets moving stategy *****************************************************/ int do_set_strategy(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_STRATEGY; int s,err; char *tok; char *argcopy=NULL; char *str_msg=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_strategy: Started...\n"); #endif err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); if( tok!=NULL ) { if( sscanf(tok,"%d",&s)==1 && ( s==MONIT_STRATEGY_FASTEST || s==MONIT_STRATEGY_LONGEST )) strategy=s; else { err=-1; if(strcmp(tok,"fast")==0 || strcmp(tok,"fastest")==0 || strcmp(tok,"speed")==0 ) { err=0; strategy=MONIT_STRATEGY_FASTEST; } if(strcmp(tok,"long")==0 || strcmp(tok,"longest")==0 || strcmp(tok,"track")==0 || strcmp(tok,"tracking")==0 ) { err=0; strategy=MONIT_STRATEGY_LONGEST; } } if (err) msg(log_file, "do_set_strategy: Wrong mode=%s\n",tok); } switch(strategy) { case MONIT_STRATEGY_FASTEST: str_msg=make_message("FASTEST movement"); break; case MONIT_STRATEGY_LONGEST: str_msg=make_message("LONGEST tracking"); break; default: str_msg=make_message("UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; }; msg(log_file,"Strategy = %s\n",str_msg); free(str_msg); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_strategy: Ended abnormally (wrong mode)\n"); else msg(log_file, "do_set_strategy: Ended normally\n"); } #endif return(err); } /***************************************************** * setting verbose mode *****************************************************/ int do_verb(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_VERB; int l; if ((arg != NULL) && (strlen(arg)>0)) if (sscanf(arg,"%d",&l)==1 && l>=0 ) logging=l; msg(log_file,"Verbose level: %d\n",logging); return(0); } /***************************************************** * sets autoguiding parameter *****************************************************/ int do_set_autoguide(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_AUTOGUIDE; int l,err; char *tok; char *argcopy=NULL; char *str_msg=NULL; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); err=0; if ( tok!=NULL ) { err=ERROR_RESULT_SYNTAX; if (sscanf(tok,"%d",&l)==1 && (l==0 || l==1) ) { autoguiding=l; err=0; } else if ( strcmp(tok,"on")==0 ) { autoguiding=1; err=0; } else if ( strcmp(tok,"off")==0 ) { autoguiding=0; err=0; } } switch( autoguiding ) { case 0: str_msg=make_message("OFF"); break; case 1: str_msg=make_message("ON"); break; default: str_msg=make_message("UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; }; msg(log_file,"Tracking autoguide mode: %s\n",str_msg); free(str_msg); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_autoguide: Ended abnormally (wrong mode)\n"); else msg(log_file, "do_set_autoguide: Ended normally\n"); } #endif return(err); } #ifdef MICROTRACKING /***************************************************** * sets microtracking parameter *****************************************************/ int do_set_microtracking(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_MICROTRACKING; int l,err; char *tok; char *argcopy=NULL; char *str_msg=NULL; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); err=0; if ( tok!=NULL ) { err=ERROR_RESULT_SYNTAX; if (sscanf(tok,"%d",&l)==1 && (l==0 || l==1) ) { microtracking=l; err=0; } else if ( strcmp(tok,"on")==0 ) { microtracking=1; err=0; } else if ( strcmp(tok,"off")==0 ) { microtracking=0; err=0; } } switch( microtracking ) { case 0: str_msg=make_message("OFF"); break; case 1: str_msg=make_message("ON"); break; default: str_msg=make_message("UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; }; msg(log_file,"Microtracking mode: %s\n",str_msg); free(str_msg); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_microtracking: Ended abnormally (wrong mode)\n"); else msg(log_file, "do_set_microtracking: Ended normally\n"); } #endif return(err); } #endif #ifdef AUTOCALIBRATION /***************************************************** * setting autocalibration mode *****************************************************/ int do_set_autocalib(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_AUTOCALIB; int l,err; char *tok; char *argcopy=NULL; char *str_msg=NULL; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); err=0; if ( tok!=NULL ) { err=ERROR_RESULT_SYNTAX; if (sscanf(tok,"%d",&l)==1 && (l==0 || l==1) ) { autocalib=l; err=0; } else if ( strcmp(tok,"on")==0 ) { autocalib=1; err=0; } else if ( strcmp(tok,"off")==0 ) { autocalib=0; err=0; } } switch( autocalib ) { case 0: str_msg=make_message("OFF"); break; case 1: str_msg=make_message("ON"); break; default: str_msg=make_message("UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; }; msg(log_file,"Autocalibration mode: %s\n",str_msg); free(str_msg); if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_autocalib: Ended abnormally (wrong mode)\n"); else msg(log_file, "do_set_autocalib: Ended normally\n"); } #endif return(err); } #endif #ifdef WATCHDOG /***************************************************** * setting watchdog frequency *****************************************************/ int do_set_watchdog(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_WATCHDOG; int err; long l; char *tok; static long last_watchdog=WATCHDOG_SLEEP_SECONDS; char *argcopy=NULL; char *str_msg=NULL; // stores last non-zero value if(watchdog>0) last_watchdog=watchdog; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); err=0; if (tok!=NULL) { err=ERROR_RESULT_SYNTAX; if ((sscanf(tok,"%ld",&l)==1 || sscanf(tok,"period=%ld",&l)==1 ) && l>=0 ) { watchdog=l; err=0; } if ( strcmp(tok,"on")==0 ) { watchdog=last_watchdog; err=0; } if ( strcmp(tok,"off")==0 ) { watchdog=0; err=0; } } switch( watchdog ) { case 0: str_msg=make_message("OFF"); break; default: if(watchdog>0) { str_msg=make_message("ON, updates every %ld sec",watchdog); } else { str_msg=make_message("UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; } break; }; msg(log_file,"Watchdog process: %s\n",str_msg); free(str_msg); // stores last non-zero value if(watchdog>0) last_watchdog=watchdog; if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file, "do_set_watchdog: Ended abnormally (wrong mode)\n"); else msg(log_file, "do_set_watchdog: Ended normally\n"); } #endif return(err); } #endif /* /\***************************************************** */ /* * serial port initialization */ /* *****************************************************\/ */ /* int do_port(fd,arg,motor) */ /* int *fd,motor; */ /* const char *arg; */ /* { */ /* // static int code=MONIT_CODE_PORT; */ /* return(0); */ /* } */ /***************************************************** * performs random movement every 10 seconds *****************************************************/ int do_flats(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_FLATS; long timestamp,timeout; // ,t,told,tstart; /* long pos[2],range[2],current[2]; */ /* long twait_1sec = 1000000; // microseconds */ /* long twait_2sec = 2000000; // microseconds */ /* long twait_3sec = 3000000; // microseconds */ /* long twait_4sec = 4000000; // microseconds */ /* long twait_4800msec= 4800000; // microseconds */ /* long twait_5sec = 5000000; // microseconds */ /* long twait_10sec = 10000000;// microseconds */ /* long twait_50msec = 50000; // microseconds */ /* long twait_200msec = 200000; // microseconds */ /* long twait_1min = 60000000;// microseconds */ /* long twait_2min = 120000000; // microseconds */ char *tok1,*tok2,*tok3,*tok4; // argument string pointetrs double arg1,arg2,arg3,arg4; // argument value; int narg,found,err; // mot,err1,target_speed,at_target,next,hemisphere=sign(latitude); long modulo=MONIT_FLATS_TIME_MODULO, residue=MONIT_FLATS_TIME_RESIDUE; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; //extern int status[2]; //extern struct CALIB calib; //extern struct TSTAT *ts; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_flats: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // if some arguments exist, performs syntax checking if( argcopy==NULL || (argcopy!=NULL && strlen(argcopy)>0) ) { // checks arguments narg=0; tok1 = strtok(argcopy," ,"); if( tok1!=NULL && strlen(tok1)>0 ) narg=1; tok2=strtok(NULL," ,"); if( narg==1 && tok2!=NULL && strlen(tok2)>0 ) narg=2; tok3=strtok(NULL," ,"); if( narg==2 && tok3!=NULL && strlen(tok3)>0 ) narg=3; tok4=strtok(NULL," ,"); if( narg==3 && tok4!=NULL && strlen(tok4)>0 ) narg=4; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_flats: arg1=|%s| arg2=|%s| " "arg3=|%s| arg4=|%s| narg=%d\n", tok1,tok2,tok3,tok4,narg); #endif if(narg>0) { // stores old coordinates into 'ts' variable of TSTAT type // prints no information if ( (err=get_status(fd,ts,&calib,0))!=0 ) sprintf(c,"get_status verb=0"); else #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_flats: initial position " "HA=%-9.5lf deg, DEC=%-9.5lf deg\n", ts->ha,ts->dec); #endif } /* end of if(narg>0)... */ found=0; if(!err) switch(narg) { case 0: err=-1; sprintf(c,"no parameters given"); break; case 4: // Syntax (1): flats at= dt= // modulo= residue= if( (( (sscanf(tok1,"at=%lf", &arg1)==1 && sscanf(tok2,"dt=%lf", &arg2)==1 ) || (sscanf(tok2,"at=%lf", &arg1)==1 && sscanf(tok1,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok3,"modulo=%lf", &arg3)==1 && sscanf(tok4,"residue=%lf",&arg4)==1 ) || (sscanf(tok4,"modulo=%lf", &arg3)==1 && sscanf(tok3,"residue=%lf",&arg4)==1 ) )) || (( (sscanf(tok2,"at=%lf", &arg1)==1 && sscanf(tok3,"dt=%lf", &arg2)==1 ) || (sscanf(tok3,"at=%lf", &arg1)==1 && sscanf(tok2,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok1,"modulo=%lf", &arg3)==1 && sscanf(tok4,"residue=%lf",&arg4)==1 ) || (sscanf(tok4,"modulo=%lf", &arg3)==1 && sscanf(tok1,"residue=%lf",&arg4)==1 ) )) || (( (sscanf(tok1,"at=%lf", &arg1)==1 && sscanf(tok4,"dt=%lf", &arg2)==1 ) || (sscanf(tok4,"at=%lf", &arg1)==1 && sscanf(tok1,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok3,"residue=%lf",&arg4)==1 ) || (sscanf(tok3,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 ) )) || (( (sscanf(tok1,"at=%lf", &arg1)==1 && sscanf(tok3,"dt=%lf", &arg2)==1 ) || (sscanf(tok3,"at=%lf", &arg1)==1 && sscanf(tok1,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok4,"residue=%lf",&arg4)==1 ) || (sscanf(tok4,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 ) )) || (( (sscanf(tok3,"at=%lf", &arg1)==1 && sscanf(tok4,"dt=%lf", &arg2)==1 ) || (sscanf(tok4,"at=%lf", &arg1)==1 && sscanf(tok3,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok1,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 ) || (sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok1,"residue=%lf",&arg4)==1 ) )) || (( (sscanf(tok2,"at=%lf", &arg1)==1 && sscanf(tok4,"dt=%lf", &arg2)==1 ) || (sscanf(tok4,"at=%lf", &arg1)==1 && sscanf(tok2,"dt=%lf", &arg2)==1 ) ) && ( (sscanf(tok1,"modulo=%lf", &arg3)==1 && sscanf(tok3,"residue=%lf",&arg4)==1 ) || (sscanf(tok3,"modulo=%lf", &arg3)==1 && sscanf(tok1,"residue=%lf",&arg4)==1 ) )) ) { found=1; // arg1=TIMESTAMP, arg2=DURATION, arg3=MODULO, arg4=RESIDUE timestamp=(long)arg1; timeout=(long)arg2; modulo=(long)arg3; // must be non-zero! residue=(long)arg4; // must be within 0...(modulo-1) } break; case 3: // Syntax (2): flats dt= // modulo= residue= if( ( sscanf(tok1,"dt=%lf", &arg2)==1 && ((sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok3,"residue=%lf",&arg4)==1 ) || (sscanf(tok3,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 )) ) || ( sscanf(tok2,"dt=%lf", &arg2)==1 && ((sscanf(tok1,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 ) || (sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok1,"residue=%lf",&arg4)==1 )) ) || ( sscanf(tok3,"dt=%lf", &arg2)==1 && ((sscanf(tok1,"modulo=%lf", &arg3)==1 && sscanf(tok2,"residue=%lf",&arg4)==1 ) || (sscanf(tok2,"modulo=%lf", &arg3)==1 && sscanf(tok1,"residue=%lf",&arg4)==1 )) ) ) { found=1; // arg2=DURATION, arg3=MODULO, arg4=RESIDUE timestamp=ts->timestamp; timeout=(long)arg2; modulo=(long)arg3; // must be non-zero! residue=(long)arg4; // must be within 0...(modulo-1) } break; case 2: // Syntax (3): flats // Syntax (4): flats at= dt= if( ( sscanf(tok1,"%lf",&arg1)==1 && sscanf(tok2,"%lf",&arg2)==1 ) || ( sscanf(tok1,"at=%lf",&arg1)==1 && sscanf(tok2,"dt=%lf",&arg2)==1 ) || ( sscanf(tok2,"at=%lf",&arg1)==1 && sscanf(tok1,"dt=%lf",&arg2)==1 ) ) { found=1; // arg1=TIMESTAMP, arg2=DURATION timestamp=(long)arg1; timeout=(long)arg2; } break; case 1: // Syntax (5): flats [dt=] if( !found && ( sscanf(tok1,"dt=%lf",&arg1)==1 || sscanf(tok1,"%lf",&arg1)==1 ) ) { found=1; // arg1=DURATION timestamp=ts->timestamp; timeout=(long)arg1; } }; /* end of switch(narg) */ // if everything is OK, starts moving if (!err && narg>0) { // wrong syntax if(!found) { err=-1; sprintf(c,"wrong syntax"); } // good syntax else { err = flat_frames(fd,timestamp,timeout,modulo,residue, &calib,ts); /* tstart=ts->timestamp; */ /* // for convenience timestamp=0 means that */ /* // the movement will be started NOW */ /* if(timestamp==0) timestamp=tstart; */ /* // checks timeout expiration */ /* if(timestamp+timeout<=tstart) */ /* { */ /* err=-2; */ /* sprintf(c,"timeout occured before start"); */ /* } */ /* // checks validity of MODULO and RESIDUE */ /* if( modulo==0 && residue==0 ) */ /* { */ /* modulo = MONIT_FLATS_TIME_MODULO; */ /* residue = MONIT_FLATS_TIME_RESIDUE; */ /* } */ /* if( !err && modulo<=0 && residue!=0 ) */ /* { */ /* err=-3; */ /* sprintf(c,"wrong parameter modulo=%ld",modulo); */ /* } */ /* if( !err && modulo!=0 && (residue<0 || residue>=modulo) ) */ /* { */ /* err=-4; */ /* sprintf(c,"wrong parameter residue=%ld " */ /* "for modulo=%ld",residue,modulo); */ /* } */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL+1) */ /* msg(log_file, */ /* "do_flats: TIMESTAMP=%ld sec (since 1970 UTC), " */ /* "DURATION=%ld sec, " */ /* "MODULO=%ld sec, " */ /* "RESIDUE=%ld sec\n", */ /* timestamp,timeout,modulo,residue); */ /* #endif */ /* // calculates amplitude for DEC movements */ /* range[MOT_D]=(double)( */ /* MONIT_FLATS_D_MAXANGLE/360.0* */ /* calib.gear_ratio[MOT_D]* */ /* pow(2,MOTOR_DEFAULT_DEC_FLATS_MICROSTEP)); */ /* // calculates target speed for tracking */ /* target_speed = (double)(calib.motor_polarity[MOT_A]* */ /* hemisphere* */ /* MOTOR_DEFAULT_HA_TRACK_MAX_SPEED* */ /* pow(2.,MOTOR_DEFAULT_HA_FLATS_MICROSTEP+ */ /* MOTOR_DEFAULT_HA_FLATS_PULSE_DIV- */ /* MOTOR_DEFAULT_HA_TRACK_MICROSTEP- */ /* MOTOR_DEFAULT_HA_TRACK_PULSE_DIV)); */ /* if(fabs(target_speed)>2047) */ /* { */ /* target_speed=0; */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL+1) */ /* msg(log_file,"do_flats: Tracking is not possible. " */ /* "Check: us, p_div, vmax for FLATS !!!\n"); */ /* #endif */ /* } */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL+1) */ /* msg(log_file,"do_flats: track_speed=%ld\n", */ /* target_speed); */ /* #endif */ /* // sets initial parameters */ /* if(!err)for(mot=0;mot<2;mot++) */ /* { */ /* if(!err && */ /* (err=mot_speed_par(fd, mot, MOT_FLATS_SPEED,&calib))==0 && */ /* (err=gap(fd,TMCL_ACTUAL_POSITION,mot, */ /* ¤t[mot]))==0 && */ /* (err=sap(fd,TMCL_REF_DISABLE,mot,1))==0 && */ /* (err=sap(fd,TMCL_LEFT_LIMIT_DISABLE,mot,0))==0 && */ /* (err=sap(fd,TMCL_RIGHT_LIMIT_DISABLE,mot,0))==0 && */ /* (err=sap(fd,TMCL_LIMIT_DISABLE,mot,0)) ==0 && */ /* (err=sap(fd,TMCL_SOFT_STOP,mot,1)) ==0 && */ /* (err=sio(fd,TEST_MODE_GATE, */ /* TMCL_DOUT_BANK,0)) ==0 && */ /* (err=sio(fd,mot_home_gate_channel[mot], */ /* TMCL_DOUT_BANK,0)) ==0 && */ /* (err=sap(fd,TMCL_RIGHT_NOT_LEFT,mot,0))==0 ) */ /* { */ /* pos[mot]=current[mot]; // needed for DEC movement */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL) */ /* msg(log_file, */ /* "do_flats:motor-%d: " */ /* "initialization completed\n",mot); */ /* #endif */ /* } */ /* else */ /* { */ /* sprintf(c,"mot_speed_par/GAP/SAP/SIO error"); */ /* } */ /* } */ /* // waits for start */ /* if(!err && */ /* tstartMESSAGE_LEVEL && t%5==0 && t!=told) */ /* msg(log_file, */ /* "do_flats: t=%ld sec, " */ /* "waiting for start at timestamp=%ld sec\n", */ /* t,timestamp); */ /* #endif */ /* told=t; */ /* } */ /* while(tMESSAGE_LEVEL) */ /* msg(log_file, */ /* "do_flats: tracking started...\n"); */ /* #endif */ /* } */ /* else */ /* { */ /* sprintf(c,"rot/mrot_sync error"); */ /* #ifdef DEBUG */ /* if( logging>MESSAGE_LEVEL) */ /* msg(log_file, */ /* "do_flats: tracking not set !\n"); */ /* #endif */ /* } */ /* } /\* end of if(!err)... *\/ */ /* // starts timeout loop */ /* t=time(NULL); // current timestamp */ /* told=t; */ /* while(!err && */ /* tt) */ /* { */ /* t=time(NULL); // current timestamp */ /* usleep(twait_50msec); */ /* if( t % modulo == residue ) */ /* { */ /* next=1; */ /* break; */ /* } */ /* #ifdef DEBUG */ /* if( logging>MESSAGE_LEVEL && t!=told ) */ /* msg(log_file, */ /* "do_flats: t=%ld sec, " */ /* "waiting for next move...\n", */ /* t); */ /* #endif */ /* told=t; */ /* } */ /* if(next) */ /* { */ /* // new target for DEC */ /* pos[MOT_D] += range[MOT_D]; */ /* // - moving in DEC */ /* if( !err ) */ /* { */ /* if( (err=mot_abs(fd,MOT_D,pos[MOT_D]))==0 && */ /* (err=move_sync(fd,MOT_D, */ /* twait_4800msec))==0 && */ /* (err=gap(fd,TMCL_AT_TARGET_POSITION,MOT_D, */ /* &at_target))==0 && */ /* at_target==1 ) */ /* { */ /* #ifdef DEBUG */ /* if( logging>MESSAGE_LEVEL+1) */ /* msg(log_file, */ /* "do_flats:motor-%d: " */ /* "target pos=%ld reached\n", */ /* MOT_D,pos[MOT_D]); */ /* #endif */ /* } */ /* else */ /* { */ /* if(err) sprintf(c,"mot_abs/move_sync/GAP error"); */ /* else if(!at_target) */ /* { */ /* sprintf(c,"at_target=0"); */ /* err=-1; // prevents further movenents */ /* } */ /* #ifdef DEBUG */ /* if( logging>MESSAGE_LEVEL+1) */ /* msg(log_file, */ /* "do_flats:motor-%d: " */ /* "target pos=%ld not reached !\n", */ /* MOT_D,pos[MOT_D]); */ /* #endif */ /* } */ /* } /\* end of if(!err)... *\/ */ /* } /\* end of if(next)... *\/ */ /* } /\* end of while() loop *\/ */ /* // going to initial position */ /* if( !err ) */ /* { */ /* if((err=mot_speed_par(fd, MOT_A, speed_mode,&calib))==0 && */ /* (err=mot_speed_par(fd, MOT_D, speed_mode,&calib))==0 && */ /* (err=mot_abs(fd,MOT_A,ts->pos[MOT_A]))==0 && */ /* (err=mot_abs(fd,MOT_D,ts->pos[MOT_D]))==0 && */ /* (err=move_sync(fd,MOT_A,twait_2min)) && */ /* (err=move_sync(fd,MOT_D,twait_2min)) ) */ /* { */ /* #ifdef DEBUG */ /* if( logging>MESSAGE_LEVEL) */ /* for(mot=0;mot<2;mot++) */ /* msg(log_file, */ /* "do_flats:motor-%d: " */ /* "initial pos=%ld restored successfully\n", */ /* mot,ts->pos[mot]); */ /* #endif */ /* } */ /* else */ /* { */ /* sprintf(c,"mot_abs/move_sync error"); */ /* } */ /* } /\* end of if(!err)... *\/ */ /* // on error: stops the motors */ /* if (err) for(mot=0;mot<2;mot++) */ /* { */ /* if( (err1=mst(fd,mot))==0 ) */ /* status[mot]=MOT_STAT_STOPPED; */ /* else */ /* { */ /* status[mot]=MOT_STAT_ERROR; */ /* sprintf(c,"MST error"); */ /* } */ /* } /\* end of if(err)... *\/ */ } /* end of if(!found)... */ } /* end of if(!err && narg>0).... */ } /* end of if(arg==NULL... */ if(argcopy)free(argcopy); /* // finally prints coordinates on screen */ /* if (!err) */ /* { */ /* if( (err=get_status(fd,ts,&calib,1))!=0) // only prints the coordinates */ /* sprintf(c,"get_status verb=1"); */ /* } */ #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_flats: Ended abnormally (%s)\n",c); else msg(log_file,"do_flats: Ended normally\n"); } #endif return(err); } #ifdef SIMULATION /***************************************************** * dump curent state to a file ************************ *****************************************************/ int do_dump_to_file(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_DUMP; int err; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_dump_to_file: Started...\n"); #endif err=TMCL_SIMUL_dump_to_file(); if(!err) { #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_dump_to_file: Ended normally...\n"); #endif } else { #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_dump_to_file: Ended abnormally " "(TMCL_SIMUL_dump_to_file)\n"); #endif } return(err); } #endif #ifdef SIMULATION /***************************************************** * sets hardware HOME position *********************** *****************************************************/ int do_home_position(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_HOME; int err; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_home_position: Started...\n"); #endif if( (err=TMCL_SIMUL_force_home_position(MOT_A))==0 && (err=TMCL_SIMUL_force_home_position(MOT_D))==0 ) { calib.needcalib_flag[MOT_A]=0; calib.needcalib_flag[MOT_D]=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_home_position: Ended normally...\n"); #endif } else { #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_home_position: Ended abnormally " "(TMCL_SIMUL_force_HOME_position)\n"); #endif } return(err); } #endif /***************************************************** * quit monitor ******************************** *****************************************************/ int do_quit(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_QUIT; time_t t; int err,mot; extern int status[2]; // extern struct CALIB calib; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_quit: Started...\n"); #endif // always stops the motors for(mot=0;mot<2;mot++) if ( mst(fd,mot)!=0 ) { status[mot]=MOT_STAT_ERROR; msg(log_file,"do_quit:motor-%d: Motor stop ERROR\n",mot); } else status[mot]=MOT_STAT_STOPPED; if(!err) { if( (err=save_last_status(fd,&calib))!=0 ) { msg(log_file,"do_quit: Saving last position ERROR\n"); } } #ifdef SIMULATION // dumps simulator's state to a file if (TMCL_SIMUL_dump_to_file()!=0) { #ifdef DEBUG msg(log_file,"do_quit: Mount's state dump ERROR\n"); #endif } // exits simulator TMCL_SIMUL_destroy(); #endif t=time(NULL); #ifndef SIMULATION #ifdef DEBUG print_serial_port_performance(log_file); #endif // closes serial port if( close_serial(fd)!=0 ) msg(log_file, "do_quit: Serial port close ERROR\n"); /* if (*fd>=0) */ /* { */ /* if(close(*fd)!=0) */ /* msg(log_file, "do_quit: Serial port close ERROR\n"); */ /* } */ #endif msg(log_file, "\n" "do_quit: " _MONIT_SESSION_TYPE_ " TRINAMIC TMCM-300 session ended at: %s",ctime(&t)); msg(log_file, " "_MONIT_BUILD_VERSION_"\n"); #ifdef WATCHDOG // closes watchdog daemon WATCH_destroy(); #endif // closes log file if (log_file!=NULL) { if(fflush(log_file)!=0) msg(log_file, "do_quit: Logfile syncing ERROR\n"); fclose(log_file); } logging=0; mount_initialized=0; // always finish the current process by exit(0) exit(0); } /***************************************************** * pause monitor ******************************** *****************************************************/ int do_pause(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_PAUSE; time_t t; int mot,err; extern int status[2]; // extern struct CALIB calib; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_pause: Started...\n"); #endif // always stops the motors for(mot=0;mot<2;mot++) if ( mst(fd,mot)!=0 ) { err=ERROR_RESULT_IO; status[mot]=MOT_STAT_ERROR; msg(log_file,"do_pause:motor-%d: Motor stop ERROR\n",mot); } else status[mot]=MOT_STAT_STOPPED; if(!err) { if( (err=save_last_status(fd,&calib))!=0 ) { msg(log_file,"do_pause: Saving last position ERROR\n"); } } #ifdef SIMULATION // dumps current simulator state to a file if (TMCL_SIMUL_dump_to_file()!=0) { #ifdef DEBUG msg(log_file,"do_quit: Mount's state dump ERROR\n"); #endif } // exits simulator TMCL_SIMUL_destroy(); #endif t=time(NULL); #ifndef SIMULATION #ifdef DEBUG print_serial_port_performance(log_file); #endif // closes serial port if( close_serial(fd)!=0 ) msg(log_file, "do_pause: Serial port close ERROR\n"); /* if (*fd>=0) */ /* { */ /* if(close(*fd)!=0) */ /* msg(log_file, "do_pause: Serial port close ERROR\n"); */ /* } */ #endif msg(log_file, "\n" "do_pause: " _MONIT_SESSION_TYPE_ " TRINAMIC TMCM-300 session ended at: %s",ctime(&t)); msg(log_file, " "_MONIT_BUILD_VERSION_"\n"); #ifdef WATCHDOG // closes watchdog daemon WATCH_destroy(); #endif // closes log file if (log_file!=NULL) { if(fflush(log_file)!=0) msg(log_file, "do_pause: Logfile syncing ERROR\n"); fclose(log_file); } logging=0; mount_initialized=0; #ifdef STANDALONE exit(0); #else return(0); #endif } /***************************************************************** * get parameters (SHOULD BE USED FOR DEBUGGING ONLY!) *****************************************************************/ int do_get(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_GET; int i,err,get_all=0; long value=0; char *tok; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_get: Started...\n"); #endif err=0; value =0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); if( argcopy == NULL || strlen(argcopy)==0) { get_all = 1; } else { tok = strtok(argcopy, " ,"); } while (get_all || (get_all==0 && tok!= NULL)) { for(i=0; iMESSAGE_LEVEL) msg(log_file,"do_get: error while reading GAP parameter type=%d\n",tmcl_table[i].type); #endif err=ERROR_RESULT_IO; } else msg(log_file, "%4d %20s = %ld\n", tmcl_table[i].type,tmcl_table[i].name,value); } #ifndef SIMULATION for(i=0; iMESSAGE_LEVEL) msg(log_file,"do_get: error while reading GGP parameter type=%d\n",glob_table[i].type); #endif err=ERROR_RESULT_IO; } else msg(log_file, "%4d %20s = %ld\n", glob_table[i].type,glob_table[i].name,value); } #endif get_all = 0; tok = strtok(NULL," ,"); } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_get: Ended abnormally " "(GAP/GGP)\n"); else msg(log_file,"do_get: Ended normally\n"); } #endif return(err); } /*********************************************************** * set digital outputs (SHOULD BE USED FOR DEBUGGING ONLY!) ***********************************************************/ int do_dout(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_DOUT; u_char opcode; int err=0; long value=0; int channel=0; char *tok; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_dout: Started...\n"); #endif opcode = TMCL_SIO; err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_dout: arg=|%s|\n",arg); #endif tok=strtok(argcopy," ,"); if(tok==NULL) // no parameters given { for(channel=0;channel<8;channel++) { if (gio(fd,channel,TMCL_DOUT_BANK,&value)==0) msg(log_file,"DIGITAL OUT channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"DIGITAL OUT channel=%d ERROR!!!\n", channel); } } } else // some parameters given { if ( sscanf(tok,"%d",&channel)==1 && channel>=0 && channel<8) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_dout: channel=%d tok=|%s|\n",channel,tok); #endif tok=strtok(NULL," ,"); if( tok!=NULL ) { if( sscanf(tok,"%ld",&value)==1 && (value==0 || value==1)) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_dout: value=%ld tok=|%s|\n",value,tok); #endif if (sio(fd,channel,TMCL_DOUT_BANK,value)==0) msg(log_file,"DIGITAL OUT channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"DIGITAL OUT channel=%d ERROR!!!\n", channel); } } else { err=ERROR_RESULT_SYNTAX; msg(log_file,"do_dout: Wrong value: %s\n",tok); } } else { if (gio(fd,channel,TMCL_DOUT_BANK,&value)==0) msg(log_file,"DIGITAL OUT channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"DIGITAL OUT channel=%d ERROR!!!\n", channel); } } } else { err=ERROR_RESULT_SYNTAX; msg(log_file,"do_dout: Wrong channnel: %s\n",tok); } } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_dout: Ended abnormally " "(GIO/SIO/wrong channel/wrong value)\n"); else msg(log_file,"do_dout: Ended normally\n"); } #endif return(err); } /*********************************************************** * get analog inputs (SHOULD BE USED FOR DEBUGGING ONLY!) ***********************************************************/ int do_ain(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_AIN; u_char opcode; int err=0; long value=0; int channel=0; char *tok; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_ain: Started...\n"); #endif opcode = TMCL_GIO; err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_ain: arg=|%s|\n",arg); #endif tok=strtok(argcopy," ,"); if( tok==NULL ) // no parameters given { for(channel=0;channel<8;channel++) { if (gio(fd,channel,TMCL_AIN_BANK,&value)==0) msg(log_file,"ANALOG IN channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"ANALOG IN channel=%d ERROR!!!\n", channel); } } } else // some parameters given { if( sscanf(tok,"%d",&channel)==1 && channel>=0 && channel<8) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_ain: channel=%d tok=|%s|\n",channel,tok); #endif if (gio(fd,channel,TMCL_AIN_BANK,&value)==0) msg(log_file,"ANALOG IN channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"ANALOG IN channel=%d ERROR!!!\n", channel); } } else { err=ERROR_RESULT_SYNTAX; msg(log_file,"do_ain: Wrong channel: %s\n",tok); } } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_ain: Ended abnormally " "(GIO/SIO/wrong channel)\n"); else msg(log_file,"do_ain: Ended normally\n"); } #endif return(err); } /*********************************************************** * get digital inputs (SHOULD BE USED FOR DEBUGGING ONLY!) ***********************************************************/ int do_din(fd,arg,motor) int *fd,motor; const char *arg; { // static int code=MONIT_CODE_DIN; u_char opcode; int err=0; long value=0; int channel=0; char *tok; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_din: Started...\n"); #endif opcode = TMCL_GIO; err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); #ifdef DEBUG if(logging>MESSAGE_LEVEL)msg(log_file,"do_din: arg=|%s|\n",arg); #endif tok=strtok(argcopy," ,"); if( tok==NULL ) // no parameters given { for(channel=0;channel<8;channel++) { if( gio(fd,channel,TMCL_DIN_BANK,&value)==0) msg(log_file,"DIGITAL IN channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"DIGITAL IN channel=%d ERROR!!!\n", channel); } } } else // some parameters given { if( sscanf(tok,"%d",&channel)==1 && channel>=0 && channel<8 ) { #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_din: channel=%d tok=|%s|\n",channel,tok); #endif if (gio(fd,channel,TMCL_DIN_BANK,&value)==0) msg(log_file,"DIGITAL IN channel=%d value=%ld\n", channel,value); else { err=ERROR_RESULT_IO; msg(log_file,"DIGITAL IN channel=%d ERROR!!!\n", channel); } } else { err=ERROR_RESULT_SYNTAX; msg(log_file,"do_din: Wrong channel: %s\n",tok); } } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_din: Ended abnormally " "(GIO/SIO/wrong channel)\n"); else msg(log_file,"do_din: Ended normally\n"); } #endif return(err); } /***************************************************************** * tracking ON/OFF *********************************************** *****************************************************************/ int do_tracking(fd,arg,dummy) int *fd,dummy; const char *arg; { char *tok; // static int code=MONIT_CODE_TRACK; int err, // err1, val=-1; // val=-1 --> only query about current tracking mode // val=0 --> stop tracking // val=1 --> start tracking // val=2 --> start tracking using default parameters char *argcopy=NULL; // extern struct CALIB calib; /* int mot,track_us[2],track_speed[2],track_pdiv[2],ispeed,track_verify; */ #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_tracking: Started...\n"); #endif err=0; // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); // if no arguments are given then just query about current tracking status if( tok!=NULL ) { // checks first non-numeric value if( sscanf(tok,"%d",&val)!=1 ) { val=-1; if(strcmp(tok,"default")==0 ) { // Request to set default tracking parameters for HA and DEC val=2; } if( strcmp(tok,"on")==0 ) val=1; if( strcmp(tok,"off")==0 ) val=0; } /* // Setting default tracking parameters for HA and DEC */ /* if( val==2 ) */ /* { */ /* // update all tracking speeds (tracking and microtracking) */ /* if( (err1=calc_default_track_speed(mot_speed,&calib,latitude))==0 ) { */ /* val=1; */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL) */ /* msg(log_file, */ /* "do_tracking: " */ /* "Default tracking parameters restored succesfully.\n"); */ /* #endif */ /* } else { */ /* err=err1; // keep track of the first error occured */ /* val=-1; */ /* #ifdef DEBUG */ /* if(logging>MESSAGE_LEVEL) */ /* msg(log_file, */ /* "do_tracking: " */ /* "Cannot set default tracking speed!\n"); */ /* #endif */ /* } /\* end of if(err1=... *\/ */ /* } /\* end of if(val==2)... *\/ */ if(val>=0 && val<=2) { err=tracking(fd, val, &calib); } else { err=ERROR_RESULT_SYNTAX; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_tracking: Wrong mode: %s\n",tok); #endif } } if(!err) { if(get_status(fd,ts,&calib,0)!=0) { err=ERROR_RESULT_IO; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_tracking: Can't read motor parameters\n"); #endif } else { // Prints message if(check_tracking(ts)) msg(log_file,"Tracking ON\n"); else msg(log_file,"Tracking OFF\n"); } } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_tracking: Ended abnormally " "(tracking/get_status/wrong mode)\n"); else msg(log_file,"do_tracking: Ended normally\n"); } #endif return(err); } /***************************************************************** * sets maximal speed ********************************************* *****************************************************************/ int do_set_speed(fd,arg,dummy) int *fd,dummy; const char *arg; { char *tok; // static int code=MONIT_CODE_SPEED; int err=-1,val=-1; char c[COMMENT_SIZE]="\0"; // temporary character array char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_set_speed: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); // if no arguments are given queries current speed mode if( tok!=NULL ) { if( sscanf(tok,"%d",&val)==1 ) { switch(val) { case 0: val=MOT_FAST_SPEED; break; case 1: val=MOT_MEDIUM_SPEED; break; default: val=-1; }; } else { val=-1; if(strcmp(tok,"fast")==0 || strcmp(tok,"fastest")==0 || strcmp(tok,"max")==0 || strcmp(tok,"maximal")==0 ) val=MOT_FAST_SPEED; if(strcmp(tok,"half")==0 || strcmp(tok,"slow")==0 || strcmp(tok,"slowest")==0 || strcmp(tok,"medium")==0 || strcmp(tok,"min")==0 || strcmp(tok,"minimal")==0 ) val=MOT_MEDIUM_SPEED; } if(val==MOT_FAST_SPEED || val==MOT_MEDIUM_SPEED) { speed_mode=val; err=0; } else { err=ERROR_RESULT_SYNTAX; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_set_speed: Wrong mode=%s\n",tok); #endif } } else err=0; switch(speed_mode) { case MOT_FAST_SPEED: sprintf(c,"FASTEST speed and acceleration (fast movement)"); break; case MOT_MEDIUM_SPEED: sprintf(c,"HALF of the fastest speed and acceleration (safe movement)"); break; default: sprintf(c,"UNKNOWN!!!"); err=ERROR_RESULT_SYNTAX; }; msg(log_file,"Speed = %s\n",c); if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_set_speed: Ended abnormally " "(wrong mode)\n"); else msg(log_file,"do_set_speed: Ended normally\n"); } #endif return(err); } #ifdef SIMULATION /***************************************************** * generate slide (SHOULD BE USED FOR DEBUGGING ONLY!) *****************************************************/ int do_slide(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_SLIDE; char *tok1,*tok2; // argument string double arg1,arg2; // argument value; int narg,found,err; char c[COMMENT_SIZE]="\0"; // temporary character array double deg_slide_offset[2]={0,0}; char *argcopy=NULL; extern double latitude; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_slide: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); // if some arguments exist, performs syntax checking if( argcopy==NULL || (argcopy!=NULL && strlen(argcopy)>0) ) { // checks arguments if(!err) { narg=0; tok1 = strtok(argcopy," ,"); if( tok1!=NULL && strlen(tok1)>0 ) narg=1; tok2=strtok(NULL," ,"); if( narg==1 && tok2!=NULL && strlen(tok2)>0 ) narg=2; #ifdef DEBUG if(logging>MESSAGE_LEVEL) msg(log_file,"do_slide: arg1=|%s| arg2=|%s| narg=%d\n", tok1,tok2,narg); #endif found=0; switch(narg) { case 0:break; case 2: // Syntax (1): slide // Syntax (2): slide ra= d[ec]= if( ( sscanf(tok1,"%lf",&arg1)==1 && sscanf(tok2,"%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ra=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ra=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; arg1 *= -1; // RIGHT ASCENSION has opposite sign // Delta_HA = arg1, Delta_DEC = arg2 #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: " "Delta_HA=%9.5lf deg Delta_DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (4): slide ha= d[ec]= if( ( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"dec=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"dec=%lf",&arg2)==1 ) || ( sscanf(tok1,"ha=%lf",&arg1)==1 && sscanf(tok2,"d=%lf",&arg2)==1 ) || ( sscanf(tok2,"ha=%lf",&arg1)==1 && sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; // Delta_HA = arg1, Delta_DEC = arg2 #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: " "Delta_HA=%9.5lf deg Delta_DEC=%9.5lf deg\n", arg1,arg2); #endif } break; case 1: // Syntax (5): slide ha= if( !found && sscanf(tok1,"ha=%lf",&arg1)==1 ) { found=1; arg2=0.0; // Delta_HA = arg1, Delta_DEC = 0 #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: " "Delta_HA=%9.5lf deg Delta_DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (3): slide ra= if( !found && sscanf(tok1,"ra=%lf",&arg1)==1 ) { found=1; arg1 *= -1; // RIGHT ASCENSION has opposite sign arg2 = 0.0; // Delta_HA = arg1, Delta_DEC = 0 #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: " "Delta_HA=%9.5lf deg Delta_DEC=%9.5lf deg\n", arg1,arg2); #endif } // Syntax (6): slide d[ec]= if( !found && ( sscanf(tok1,"dec=%lf",&arg2)==1 || sscanf(tok1,"d=%lf",&arg2)==1 )) { found=1; arg1=0.0; // Delta_HA = 0, Delta_DEC = arg2 #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: " "Delta_HA=%9.5lf deg Delta_DEC=%9.5lf deg\n", arg1,arg2); #endif } }; /* end of switch(narg) */ // if everything is OK, starts shifting if (narg>0) { // wrong syntax if(!found) { err=ERROR_RESULT_SYNTAX; sprintf(c,"wrong syntax"); #ifdef DEBUG if(logging>MESSAGE_LEVEL+1) msg(log_file,"do_slide: Wrong syntax: |%s|\n", arg); #endif } // good syntax else { // gets old coordinates into 'ts' variable of TSTAT type if (get_status(fd,ts,&calib,1)!=0) { err=ERROR_RESULT_IO; sprintf(c,"get_status:before"); } // sets internal shift in degrees deg_slide_offset[MOT_A] = calib.motor_polarity[MOT_A]*arg1; deg_slide_offset[MOT_D] = calib.motor_polarity[MOT_D]*arg2; msg(log_file, "Deliberately generated shifts:\n" " Delta_HA = %9.5lf deg\n" " Delta_DEC = %9.5lf deg\n", arg1, arg2); if (TMCL_SIMUL_generate_slide_in_deg(deg_slide_offset, latitude)!=0) { err=ERROR_RESULT_IO; sprintf(c,"TMCL_SIMUL_generate_slide_in_deg"); } } } /* end of if(narg>0).... */ } /* end of if(!err)... */ } /* end of if(arg!=NULL...*/ // finally prints coordinates on screen if (!err) { if (get_status(fd,ts,&calib,1)!=0) err=ERROR_RESULT_IO; sprintf(c,"get_status:after"); } if(argcopy)free(argcopy); #ifdef DEBUG if (logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_slide: Ended abnormally (%s)\n",c); else msg(log_file,"do_slide: Ended normally\n"); } #endif return(err); } #endif /***************************************************** * get status: position, etc. *****************************************************/ int do_status(fd,arg,dummy) int *fd,dummy; const char *arg; { // extern struct CALIB calib; // static int code=MONIT_CODE_STAT; int err; //kn static struct TSTAT ts; err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_status: Started...\n"); #endif if(get_status(fd,ts,&calib,2)!=0) err=ERROR_RESULT_IO; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (err) msg(log_file,"do_status: Ended abnormally " "(get_status error)\n"); else msg(log_file,"do_status: Ended normally\n"); } #endif return(err); } #if !defined(SIMULATION) && defined(STANDALONE) && defined(RS232_ERROR_STUDY) /***************************************************************** * disconnects momentarily RS-232 port after some delay *****************************************************************/ int do_rs232_disconnect(fd,arg,dummy) int *fd,dummy; const char *arg; { char *tok; // static int code=MONIT_CODE_RS232_DISCONNECT; int err=0; long val=0; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_rs232_disconnect: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); rs232_error_timestamp=time(NULL); // if no arguments are given get current time if( tok!=NULL ) { if( sscanf(tok,"%ld",&val)==1 && val>0 ) rs232_error_timestamp+=val; } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { msg(log_file,"do_rs232_disconnect: Ended normally. " "Momentary RS-232 failure scheduled at: %s", ctime(&rs232_error_timestamp)); } #endif rs232_error_flag=1; return(err); } /***************************************************************** * disconnects permanently RS-232 port after some delay *****************************************************************/ int do_rs232_block(fd,arg,dummy) int *fd,dummy; const char *arg; { char *tok; // static int code=MONIT_CODE_RS232_BLOCK; int err=0; long val=0; char *argcopy=NULL; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_rs232_block: Started...\n"); #endif // makes a local copy of 'arg' argcopy=str2str(argcopy,arg); argcopy=str2lowercase(argcopy); tok=strtok(argcopy," ,"); rs232_error_timestamp=time(NULL); // if no arguments are given get current time if( tok!=NULL ) { if( sscanf(tok,"%ld",&val)==1 && val>0 ) rs232_error_timestamp+=val; } if(argcopy)free(argcopy); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { msg(log_file,"do_rs232_block: Ended normally. " "Permanent RS-232 failure scheduled at: %s", ctime(&rs232_error_timestamp)); } #endif rs232_error_flag=2; return(err); } /***************************************************************** *re-connects RS-232 port *****************************************************************/ int do_rs232_connect(fd,arg,dummy) int *fd,dummy; const char *arg; { // static int code=MONIT_CODE_RS232_CONNECT; int err=0; #ifdef DEBUG if(logging>=MESSAGE_LEVEL) msg(log_file,"do_rs232_connect: Started...\n"); #endif rs232_error_flag=0; rs232_error_timestamp=0; strcpy(option->rs232_portname,rs232_error_goodport); msg(log_file, "do_rs232_connect: Trying to reconnect RS-232: " "port=%s baudrate=%ld, fd=%p\n", option->rs232_portname, option->rs232_baudrate, fd); err=reopen_serial_port(option->rs232_portname, &(option->rs232_baudrate),fd); #ifdef DEBUG if(logging>=MESSAGE_LEVEL) { if (!err) msg(log_file,"do_rs232_connect: Ended normally. " "RS-232 connection re-established.\n"); else msg(log_file,"do_rs232_connect: Ended abnormally. " "Could not re-establish RS-232 conection !!!\n"); } #endif return(err); } #endif #undef MESSAGE_LEVEL #undef _GNU_SOURCE