#include /* ************************************************************** */ /* * Module CM6K6 * This module contains I/O functions for the Compumotor model * 6K6 indexer. * * Zachary Wolf * 9/4/02 * Modified for CM6K6 module by Yurii Levashov */ /* ************************************************************** */ /* INCLUDES */ #include #include #include #include #include "cam_movers_dec.h" #include "cm6k6_g.h" /* ************************************************************** */ /* PRIVATE FUNCTIONS */ /* ************************************************************** */ /* PRIVATE DEVICE TABLE */ /* * This table allows several devices of the same type to be * used in the system. * dev_addr, contains the rs232 addresses of opened devices * dev_descr, contains the device descriptors of opened devices * dev_count, contains the number of devices open of this type */ static int dev_addr[CM6K6_MAX_NUM_DEV + 1]; static int dev_descr[CM6K6_MAX_NUM_DEV + 1]; static int dev_count; /* ************************************************************** */ /* PRIVATE GLOBAL VARIABLES */ /* * cmd, buffer for RS232 I/O strings * msg, buffer for message strings to Standard I/O */ static int com_port; static char cmd[CM6K6_MAX_CMD + 1]; static char msg[CM6K6_MAX_CMD + 1]; /* ************************************************************** */ /* PUBLIC FUNCTIONS */ /* ************************************************************** */ /* * cm6k6_init * This function opens the device, queries for ID, and * initializes the device to a known state. * * Input: * rs232_com_port (1-32) * rs232_dev_addr (00-99) (00 is reserved) * * Output: * ID, identifier for future references to the device * * Zachary Wolf * 9/4/02 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_init(int rs232_com_port, int rs232_dev_addr, int* ID) { /* Declare variables */ int dev_ID; int err; int mr; int er; int axis; long int mres[7]; long int eres[7]; long int scale[7]; double acc; int limit; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES *ID = 1; return; #endif /* Check input parameters */ if(rs232_com_port < 1 || rs232_com_port > 32) if(cm6k6_error_handling(rs232_com_port, "RS232_COM_PORT") == 1) return; if(rs232_dev_addr < 0 || rs232_dev_addr > 99) if(cm6k6_error_handling(rs232_dev_addr, "RS232_DEV_ADDR") == 1) return; /* Save the com port number */ com_port = rs232_com_port; /* Open RS232 communications */ err = OpenComConfig(com_port, "", 9600, 0, 8, 1, 512, 512); if (err != 0) if(cm6k6_error_handling(err, "OpenCom") == 1) return; err = FlushInQ(com_port); if (err != 0) if(cm6k6_error_handling(err, "FlushInQ") == 1) return; err = FlushOutQ(com_port); if (err != 0) if(cm6k6_error_handling(err, "FlushOutQ") == 1) return; /* Open the CM6K6 */ dev_ID = cm6k6_open_dev(rs232_dev_addr); if (dev_ID <= 0) if(cm6k6_error_handling(dev_ID, "RS232.Device was not opened") == 1) return; /* Reset */ cm6k6_out(dev_ID, "!RESET"); Delay(5); /* set COM1 for command transmission */ cm6k6_out(dev_ID, "PORT1"); /* Enable communication */ cm6k6_out(dev_ID, "E1"); /* Disable Echo */ cm6k6_out(dev_ID, "ECHO0"); /* set responce field without command itself and error */ // cm6k6_out(dev_ID, "ERRLVL0"); /* Make sure start-up program doesn't execute */ cm6k6_out(dev_ID, "STARTP CLR"); /* Define stepper motor axis types */ // cm6k6_out(dev_ID, "DRIVE000000"); // De-Energize the motor drives cm6k6_out(dev_ID, "AXSDEF000000"); // 0 - for stepper motors /* Define position limits settings */ cm6k6_out(dev_ID, "LS0,0,0,0,0,0"); // Programmable limits disabled // GetCtrlVal(panel_ID, PANEL_LIMITS_DISABLE, &limit); // if(limit == 1) cm6k6_out(dev_ID, "LH0,0,0,0,0,0"); // End-of-travel limits disabled // else // { // err = MessagePopup ("WARNING", // "Please make sure limit switches are connected"); // cm6k6_out(dev_ID, "LH3,3,3,3,3,3"); // End-of-travel limits enabled cm6k6_out(dev_ID, "LIMLVL0"); // Set signal level to low // GetCtrlVal (PANEL, PANEL_NUMERIC_ACCELERATION, &acc); Fmt(cmd, "%s<@LHAD%f", ACC); //Set deceleration value 10 times higher cm6k6_out(dev_ID, cmd); // } /* Disable drive fault checking */ cm6k6_out(dev_ID, "DRFEN000000"); /* Enable error detection */ // cm6k6_out(dev_ID, "ERROR111111"); /* Enable encoder ports */ cm6k6_out(dev_ID, "ENCCNT111111"); // Reference to the encoder position /* Set the motor resolutions and follower scaling in revs*/ for (axis = 1; axis <= 6; axis++) { cm6k6_get_num_mot_steps_per_rev(axis, &mr); mres[axis] = mr; } /* Enable Scaling */ cm6k6_out(dev_ID, "SCALE1"); Fmt(cmd, "%s CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s 9999.9) { Fmt(msg, "%s 99.) { Fmt(msg, "%s%f", &ini_pos); /* Set incremental-preset mode */ Fmt(cmd, "%s<%i[w1]MA0", axis); // Move wrt current position cm6k6_out(dev_ID, cmd); Fmt(cmd, "%s<%i[w1]MC0", axis); //to go a specific distance cm6k6_out(dev_ID, cmd); /* Set the acceleration */ Fmt(cmd, "%s<%i[w1]A%f", axis, acc); cm6k6_out(dev_ID, cmd); /* Set the velocity */ Fmt(cmd, "%s<%i[w1]V%f", axis, vel); cm6k6_out(dev_ID, cmd); /* Set the distance */ Fmt(cmd, "%s<%i[w1]D%f", axis, dis); cm6k6_out(dev_ID, cmd); /* Move*/ if (axis == 1) { Fmt(cmd, "%s%f", &fin_pos); /* Caclulate number of steps taken */ revs_taken = fin_pos - ini_pos; /* Make sure the proper position was achieved */ err = (int) fabs(dis * 100000) - (int) fabs(revs_taken * 100000); if (err != 0) if(cm6k6_error_handling(err, "Positioning") == 1) return -1; /* Check for command errors */ cm6k6_read_error_status(dev_ID); /* Done */ return 0; } /* ************************************************************** */ /* * cm6k6_abs_move * This function moves the motor to the specified location * with the specified acceleration and velocity. * * Input: * dev_ID, device identifier * axis, number of the axis to move (1 to 4) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * pos, position (rev), can be + or - * * Zachary Wolf * 9/4/02 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_abs_move(int dev_ID, int axis, double acc, double vel, double pos) { /* Declare variables */ int dev_open, err; double fin_pos; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES return; #endif /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s%f", &fin_pos); /* Make sure the proper position was achieved */ err = (int) fin_pos - (int) pos; if (err != 0) if(cm6k6_error_handling(err, "Positioning") == 1) return; /* Check for command errors */ cm6k6_read_error_status(dev_ID); /* Done */ return; } /* ************************************************************** */ /* * cm6k6_go_home * This function moves the motor home position. The velocity * and acceleration are specified. * * Input: * dev_ID, device identifier * axis, number of the axis to move (1 to 6) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * * Zachary Wolf * 9/4/02 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_go_home(int dev_ID, int axis, double acc, double vel) { /* Declare variables */ int dev_open, err; long int fin_pos; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES return; #endif /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s%i",&fin_pos); /* Check for command errors */ cm6k6_read_error_status(dev_ID); /* Done */ return; } /* ************************************************************** */ /* * cm6k6_get_mot_position * This function gets the number of revolutions from zero that * the motor is currently at. * * Input: * dev_ID, device identifier * axis, axis number (1 to 4) * * Output: * pos, position (revs), can be + or - * * Zachary Wolf * 9/9/02 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_get_mot_position(int dev_ID, int axis, double* pos) { /* Declare variables */ int dev_open; int err; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES return; #endif /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s%f", pos); /* Check for command errors */ cm6k6_read_error_status(dev_ID); /* Done */ return; } /* ************************************************************** */ /* * cm6k6_get_enc_position * This function gets the number of revolutions from zero that * the encoder is currently at. * * Input: * dev_ID, device identifier * axis, axis number (1 to 4) * * Output: * pos, position (rev), can be + or - * * Zachary Wolf * 9/9/02 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_get_enc_position(int dev_ID, int axis, double* pos) { /* Declare variables */ int dev_open; double cts; long int cts_per_rev; double dum; int err; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES return; #endif /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s%f",&cts); /* convert to position in revs */ dum = cts / cts_per_rev; Fmt(cmd, "%s<%f", dum); Scan(cmd, "%s>%f", pos); /* Check for command errors */ cm6k6_read_error_status(dev_ID); /* Done */ return; } /* ************************************************************** */ /* * cm6k6_follow_move * This function sets up the motor to follow the specified axis * to the specified location * with the specified acceleration and velocity. * * Input: * dev_ID, device identifier * axis, number of the axis to move (1 to 4) * follow, axis to follow (1 to 4) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * pos, position (rev), can be + or - * * Kirsten Hacker * 9-14-04 * Modified by Yurii Levashov 01/26/2005 */ void cm6k6_follow_move (int dev_ID, int master, int follow, double acc, double vel, double dis) { /* Declare variables */ int dev_open; int scale; long int fin_pos; long int steps_taken; /* Exit here if testing without hardware */ #ifdef DUMMY_DEVICES return; #endif /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s CM6K6_NUM_AXIS) { Fmt(msg, "%s CM6K6_MAX_NUM_DEV) { Fmt(msg, "%s%s[t-]", buf); /* Already done */ /* Return the string in buf */ strcpy(buf, in_buf); /* Done */ return 0; } /* ************************************************************** */ /* * cm6k6_check_dev_open * This function checks to see if the specified device is open. * If the device has been opened, a 1 is returned, 0 otherwise. * * Input: * dev_ID, device identifier * * Output: * status, 1 if device is open, 0 otherwise * * Zachary Wolf * 7/27/98 * Modified by Yurii Levashov 01/26/2005 */ int cm6k6_check_dev_open(int dev_ID) { /* See if the device descriptor has a positive value */ if (dev_descr[dev_ID] > 0) { return 1; /* Open */ } else { return 0; /* Not open */ } } /* ************************************************************** */ /* * cm6k6_read_error_status * This function obtains device errors. * The operator is alerted if there is an error. * * Input: * dev_ID, device identifier * * Output: * err, 0 if no errors, -1 otherwise * * Zachary Wolf * 9/9/02 * Modified by Yurii Levashov 01/26/2005 */ int cm6k6_read_error_status(int dev_ID) { /* Declare variables */ int axis; char status[CM6K6_MAX_CMD]; /* Request the controller status */ for (axis = 1; axis <= 4; axis++) { Fmt(cmd, "%s 32) if(cm6k6_error_handling(rs232_com_port, "RS232_COM_PORT") == 1) return; if(rs232_dev_addr < 0 || rs232_dev_addr > 99) if(cm6k6_error_handling(rs232_dev_addr, "RS232_DEV_ADDR") == 1) return; /* Save the com port number */ com_port = rs232_com_port; /* Open RS232 communications */ err = OpenComConfig(com_port, "", 9600, 0, 8, 1, 512, 512); if (err != 0) if(cm6k6_error_handling(err, "OpenCom") == 1) return; err = FlushInQ(com_port); if (err != 0) if(cm6k6_error_handling(err, "FlushInQ") == 1) return; err = FlushOutQ(com_port); if (err != 0) if(cm6k6_error_handling(err, "FlushOutQ") == 1) return; /* Open the CM6K6 */ dev_ID = cm6k6_open_dev(rs232_dev_addr); if (dev_ID <= 0) if(cm6k6_error_handling(dev_ID, "RS232.Device was not opened") == 1) return; /* Reset */ cm6k6_out(dev_ID, "!RESET"); Delay(5); /* set COM1 for command transmission */ cm6k6_out(dev_ID, "PORT1"); /* Enable communication */ cm6k6_out(dev_ID, "E1"); /* Disable Echo */ cm6k6_out(dev_ID, "ECHO0"); /* set responce field without command itself and error */ // cm6k6_out(dev_ID, "ERRLVL0"); /* Make sure start-up program doesn't execute */ cm6k6_out(dev_ID, "STARTP CLR"); /* Define stepper motor axis types */ // cm6k6_out(dev_ID, "DRIVE000000"); // De-Energize the motor drives cm6k6_out(dev_ID, "AXSDEF000000"); // 0 - for stepper motors /* Define position limits settings */ cm6k6_out(dev_ID, "LS0,0,0,0,0,0"); // Programmable limits disabled // GetCtrlVal(panel_ID, PANEL_LIMITS_DISABLE, &limit); // if(limit == 1) cm6k6_out(dev_ID, "LH0,0,0,0,0,0"); // End-of-travel limits disabled // else // { // err = MessagePopup ("WARNING", // "Please make sure limit switches are connected"); // cm6k6_out(dev_ID, "LH3,3,3,3,3,3"); // End-of-travel limits enabled cm6k6_out(dev_ID, "LIMLVL0"); // Set signal level to low // GetCtrlVal (PANEL, PANEL_NUMERIC_ACCELERATION, &acc); Fmt(cmd, "%s<@LHAD%f", ACC * 10); //Set hard limit deceleration value 10 times higher cm6k6_out(dev_ID, cmd); // } // Disable drive fault checking cm6k6_out(dev_ID, "DRFEN000000"); // Enable error detection // cm6k6_out(dev_ID, "ERROR111111"); // Enable encoder ports cm6k6_out(dev_ID, "ENCCNT111111"); // Reference to the encoder position // Set the motor resolutions and follower scaling in revs for (axis = 1; axis <= CM6K6_NUM_AXIS ; axis++) { cm6k6_get_num_mot_steps_per_rev(axis, &mr); mres[axis]=mr; } // Enable Scaling cm6k6_out(dev_ID, "SCALE1"); Fmt(cmd, "%s%f", &ini_pos); // Format the go command if (axis==1) Fmt(msg, "%s<100000"); else if (axis==2) Fmt(msg, "%s<010000"); else if (axis==3) Fmt(msg, "%s<001000"); else if (axis==4) Fmt(msg, "%s<000100"); else if (axis==5) Fmt(msg, "%s<000010"); else if (axis==6) Fmt(msg, "%s<000001"); else cm6k6_error_handling(err, "wrong axis number"); // Energize motor driver Fmt(cmd, "%s%f", &fin_pos); /* Caclulate number of steps taken */ revs_taken = (fin_pos - ini_pos); /* Make sure the proper position was achieved */ err = (int) (fabs(step_size) - fabs(revs_taken)); if (err != 0) if(cm6k6_error_handling(err, "Positioning") == 1) { cm6k6_stop_motor(dev_ID, axis); // De - Energize motor driver cm6k6_out(dev_ID, "DRIVE000000"); return -1; } /* Check for command errors */ // cm6k6_read_error_status(dev_ID); /* Done */ return 0; } /* ************************************************************** */ /* * cm6k6_cam_move_5 * This function moves the motor the specified number of revolutions * with the specified acceleration and velocity. * * Input: * dev_ID, device identifier * axis, number of the axis to move (1 to 6) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * dis, distance (rev), can be + or - * * Zachary Wolf * 9/4/02 * Modified by Yurii Levashov 01/26/2005 * Modified by Michael Levashov 07/02/2007 */ int cm6k6_cam_move_5(int panel, int control[], int dev_ID, double distance[], int led_flag) { /* Declare variables */ int dev_open, err = 0; char st[] = "NOT"; double ini_pos[5]; double fin_pos[5]; double revs_taken; int ID; int i; for(i = 0; i < 5; i++) { // Ask for the initial position Fmt(cmd, "%s<%i[w1]TPC", i + 1); cm6k6_out(dev_ID, cmd); cm6k6_in(dev_ID, cmd); CopyString(cmd,0, cmd,5,20); Scan(cmd, "%s>%f", &ini_pos[i]); // Set the distance for each axis Fmt(cmd, "%s<%i[w1]D%f[p10]", i + 1, distance[i]); // positive step_size moves motor clockwise cm6k6_out(dev_ID, cmd); //turn ON LED's if(led_flag == 1) SetCtrlAttribute (panel, control[i + 5], ATTR_CTRL_VAL, 1); } if(led_flag == 1) DisplayPanel (panel); // Energize motor drivers cm6k6_out(dev_ID, "DRIVE111110"); Delay(2.0); // move 5 motors cm6k6_out(dev_ID,"GO111110"); // Wait until the move is complete err = cm6k6_ifmove_delay (dev_ID, i + 1); Delay(1.0); // De-Energize motor drivers cm6k6_out(dev_ID, "DRIVE000000");; for(i = 0; i < 5; i++) { // Turn OFF LED if(led_flag == 1) SetCtrlAttribute (panel, control[i + 5], ATTR_CTRL_VAL, 0); Delay(1.0); // Ask for the final position Fmt(cmd, "%s<%i[w1]TPC", i + 1); cm6k6_out(dev_ID, cmd); cm6k6_in(dev_ID, cmd); CopyString(cmd,0, cmd,5,20); Scan(cmd, "%s>%f", &fin_pos[i]); // Caclulate number of steps taken revs_taken = (fin_pos[i] - ini_pos[i]); /* Make sure the proper position was achieved */ err = (int) (fabs(distance[i]) - fabs(revs_taken)); if (err != 0) if(cm6k6_error_handling(err, "Positioning") == 1) { cm6k6_stop_motor(dev_ID, i + 1); return -1; } } if(led_flag == 1) DisplayPanel (panel); /* Check for command errors */ // cm6k6_read_error_status(dev_ID); /* Done */ return 0; }