/* ************************************************************** */ /* * Module CM6K * This module contains I/O functions for the Compumotor model * 6K indexer. * * Zachary Wolf * 4/4/06 */ /* ************************************************************** */ /* INCLUDES */ #include #include #include #include #include "cm6k.h" /* ************************************************************** */ /* PRIVATE FUNCTIONS */ int cm6k_open_dev(int rs232_dev_addr); void cm6k_close_dev(int dev_ID); int cm6k_out(int dev_ID, char *buf); int cm6k_in(int dev_ID, char* buf); int cm6k_check_dev_open(int dev_ID); int cm6k_read_error_status(int dev_ID); void cm6k_get_num_mot_steps_per_rev(int axis, long int* num_steps_per_rev); void cm6k_get_num_enc_steps_per_rev(int axis, long int* num_steps_per_rev); void cm6k_message(char* msg); void cm6k_error(char* msg); /* ************************************************************** */ /* PRIVATE DEVICE TABLE */ /* * This table allows several devices of the same type to be * used in the system. * dev_addr, contains the addresses of opened devices * dev_count, contains the number of devices open of this type */ static int dev_addr[CM6K_MAX_NUM_DEV + 1]; static int dev_count; /* ************************************************************** */ /* PRIVATE GLOBAL VARIABLES */ /* * com_port, port number for I/O * cmd, buffer for RS232 I/O strings * msg, buffer for message strings to Standard I/O */ static int com_port; static char cmd[CM6K_MAX_CMD + 1]; static char msg[CM6K_MAX_CMD + 1]; /* ************************************************************** */ /* PUBLIC FUNCTIONS */ /* ************************************************************** */ /* * cm6k_init * This function opens the device, queries for ID, and * initializes the device to a known state. * * Input: * rs232_com_port, RS232 com port the device is connected to (1 to 32) * rs232_dev_addr, RS232 address of the device (00 to 99, 00 is reserved) * * Output: * ID, identifier for future references to the device * * Zachary Wolf * 4/4/06 */ void cm6k_init(int rs232_com_port, int rs232_dev_addr, int* ID) { /* Declare variables */ int dev_ID; int err; int axis; long int num_steps_per_rev; /* Message */ cm6k_message(""); cm6k_message("Initializing the CM6K..."); /* Check input parameters */ if (rs232_com_port < 1 || rs232_com_port > 32) { Fmt(msg, "%s 99) { Fmt(msg, "%s CM6K_MAX_NUM_DEV) { Fmt(msg, "%s CM6K_NUM_AXES) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s 99999999) { Fmt(msg, "%s*%iD%i", &reply_axis, &steps_taken); /* Debug */ //printf("cmd = %s\n", cmd); //printf("steps_requested = %i, steps_taken = %i\n", dis_steps, steps_taken); /* Make sure the proper number of steps were taken */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } if (steps_taken != dis_steps) { cm6k_error("The wrong number of steps were taken"); return; } /* Done */ return; } /* ************************************************************** */ /* * cm6k_start_rel_move * This function starts a move of the motor. It moves the * specified number of revolutions with the specified acceleration * and velocity. * * Input: * dev_ID, device identifier * axis, axis number to move (1 to 4) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * dis, distance (rev), can be + or - * * Zachary Wolf * 4/4/06 */ void cm6k_start_rel_move(int dev_ID, int axis, double acc, double vel, double dis) { /* Declare variables */ long int num_steps_per_rev; int dev_open; long int dis_steps; /* Convert distance in revolutions to distance in steps */ cm6k_get_num_mot_steps_per_rev(axis, &num_steps_per_rev); dis_steps = dis * num_steps_per_rev; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s 99999999) { Fmt(msg, "%s CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s 99999999) { Fmt(msg, "%s%i:%i", &reply_axis, &steps_taken); /* Debug */ //printf("cmd = %s\n", cmd); //printf("steps_requested = %i, steps_taken = %i\n", dis_steps, steps_taken); /* Make sure the proper number of steps were taken */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } if (steps_taken != dis_steps) { cm6k_error("The wrong number of steps were taken"); return; } /* Done */ return; } /* ************************************************************** */ /* * cm6k_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 * 4/4/06 */ void cm6k_abs_move(int dev_ID, int axis, double acc, double vel, double pos) { /* Declare variables */ long int num_steps_per_rev; int dev_open; long int pos_steps; long int fin_pos; int reply_axis; /* Convert position in revolutions to position in steps */ cm6k_get_num_mot_steps_per_rev(axis, &num_steps_per_rev); pos_steps = pos * num_steps_per_rev; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 99.) { Fmt(msg, "%s 99999999) { Fmt(msg, "%s%i:%i", &reply_axis, &fin_pos); /* Debug */ //printf("cmd = %s\n", cmd); //printf("position_requested = %i, final_position = %i\n", pos_steps, fin_pos); /* Make sure the proper position was achieved */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } if (fin_pos != pos_steps) { cm6k_error("The wrong number of steps were taken"); return; } /* Done */ return; } /* ************************************************************** */ /* * cm6k_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 4) * acc, acceleration (rev/sec/sec) * vel, velocity (rev/sec) * * Zachary Wolf * 4/4/06 */ void cm6k_go_home(int dev_ID, int axis, double acc, double vel) { /* Declare variables */ int dev_open; int reply_axis; long int fin_pos; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s 999.999) { Fmt(msg, "%s 20.) { Fmt(msg, "%s%i:%i", &reply_axis, &fin_pos); /* Debug */ //printf("cmd = %s\n", cmd); //printf("position_requested = %i, final_position = %i\n", pos_steps, fin_pos); /* Check */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } /* Done */ return; } /* ************************************************************** */ /* * cm6k_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 (rev), can be + or - * * Zachary Wolf * 4/4/06 */ void cm6k_get_mot_position(int dev_ID, int axis, double* pos) { /* Declare variables */ int dev_open; long int pos_steps; long int num_steps_per_rev; int reply_axis; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s%i:%i", &reply_axis, &pos_steps); /* Check */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } /* Convert the position in steps to position in revolutions */ cm6k_get_num_mot_steps_per_rev(axis, &num_steps_per_rev); *pos = (double) pos_steps / (double) num_steps_per_rev; /* Done */ return; } /* ************************************************************** */ /* * cm6k_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 * 4/4/06 */ void cm6k_get_enc_position(int dev_ID, int axis, double* pos) { /* Declare variables */ int dev_open; long int pos_steps; long int num_steps_per_rev; int reply_axis; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s%i:%i", &reply_axis, &pos_steps); /* Check */ if (reply_axis != axis) { cm6k_error("The wrong axis number was returned"); return; } /* Convert the position in steps to position in revolutions */ /* Four encoder transitions make one step */ cm6k_get_num_enc_steps_per_rev(axis, &num_steps_per_rev); *pos = (double) pos_steps / (double)4 / (double) num_steps_per_rev; /* Done */ return; } /* ************************************************************** */ /* * cm6k_zero * This function sets the indexer position counter to zero. * * Input: * dev_ID, device identifier * axis, axis number (1 to 4) * * Zachary Wolf * 8/25/98 */ void cm6k_zero(int dev_ID, int axis) { /* Declare variables */ int err; int dev_open; /* Check input parameters */ if (dev_ID < 1 || dev_ID > CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 4) { Fmt(msg, "%s CM6K_MAX_NUM_DEV) { Fmt(msg, "%s 99) { Fmt(msg, "%s%s[t-]", buf); /* Already done */ /* Return the string in buf */ strcpy(buf, in_buf); /* Done */ return 0; } /* ************************************************************** */ /* * cm6k_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 * 2/23/02 */ int cm6k_check_dev_open(int dev_ID) { /* See if the device address has a positive value */ if (dev_addr[dev_ID] > 0) { return 1; /* Open */ } else { return 0; /* Not open */ } } /* ************************************************************** */ /* * cm6k_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 * 4/4/06 */ int cm6k_read_error_status(int dev_ID) { /* Declare variables */ int axis; int reply_axis; char status[CM6K_MAX_CMD]; /* Request the controller status */ for (axis = 1; axis <= 4; axis++) { Fmt(cmd, "%s<%i[w1]R", axis); cm6k_out(dev_ID, cmd); //cm6k_hold_until_ready_to_reply(dev_ID); cm6k_in(dev_ID, cmd); Scan(cmd, "%s>%i:%s", &reply_axis, status); if (strcmp(status, "*S") == 0 || strcmp(status, "*C") == 0) { cm6k_error("Controller error"); return -1; } } /* Done */ return 0; } /* ************************************************************** */ /* * cm6k_get_num_mot_steps_per_rev * This function gets the motor's number of steps per revolution. * * Input: * axis, axis number (1 to 8) * * Output: * num_steps_per_rev, number of steps per revolution * * Zachary Wolf * 4/4/06 */ void cm6k_get_num_mot_steps_per_rev(int axis, long int* num_steps_per_rev) { /* Determine the number of steps per revolutuon */ if (axis == 1) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS1; else if (axis == 2) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS1; else if (axis == 3) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS3; else if (axis == 4) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS4; else if (axis == 5) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS5; else if (axis == 6) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS6; else if (axis == 7) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS7; else if (axis == 8) *num_steps_per_rev = CM6K_NUM_MOT_STEPS_PER_REV_AXIS8; else cm6k_error("Unknown axis number"); /* Done */ return; } /* ************************************************************** */ /* * cm6k_get_num_enc_steps_per_rev * This function gets the encoder's number of steps per revolution. * * Input: * axis, axis number (1 to 4) * * Output: * num_steps_per_rev, number of steps per revolution * * Zachary Wolf * 4/4/06 */ void cm6k_get_num_enc_steps_per_rev(int axis, long int* num_steps_per_rev) { /* Determine the number of steps per revolutuon */ if (axis == 1) *num_steps_per_rev = CM6K_NUM_ENC_STEPS_PER_REV_AXIS1; else if (axis == 2) *num_steps_per_rev = CM6K_NUM_ENC_STEPS_PER_REV_AXIS1; else if (axis == 3) *num_steps_per_rev = CM6K_NUM_ENC_STEPS_PER_REV_AXIS3; else if (axis == 4) *num_steps_per_rev = CM6K_NUM_ENC_STEPS_PER_REV_AXIS4; else cm6k_error("Unknown axis number"); /* Done */ return; } /* ************************************************************** */ /* * cm6k_message * This function handles messages about the CM6K. * * Input: * message, string to display in standard I/O * * Zachary Wolf * 4/4/06 */ void cm6k_message(char* message) { /* Print the message */ printf("%s\n", message); /* Done */ return; } /* ************************************************************** */ /* * cm6k_error * This function handles error messages for the CM6K. * * Input: * message, string to display in standard I/O * * Zachary Wolf * 4/4/06 */ void cm6k_error(char* message) { /* Declare variables */ char buf[80]; /* Notify the operator of the error */ printf("\nCM6K ERROR: %s\n", message); Beep(); Delay(.5); Beep(); /* Terminate the program if the operator desires */ printf("Press ENTER to continue.\nPress any key then ENTER to terminate program.\n"); fgets(buf, 80, stdin); if (buf[0] == '\n') return; else exit(0); }