#include /* ************************************************************** */ /* * Module WIRPOS * This module contains functions for automating measurements with * wire position detectors. The detector is moved until its signal * is centered on the wire. A coordinate measuring machine, or some * other device, then locates tooling balls on the detector. This is * used to get the wire position without touching the wire. * * Zachary Wolf * 6/3/05 */ /* ************************************************************** */ /* INCLUDES */ #include #include #include #include #include "wirpos.h" #include "wirposui.h" #include "esp7000.h" #include "hp34970_sw.h" /* ************************************************************** */ /* PRIVATE FUNCTIONS */ void wirpos_message(char* msg); void wirpos_error(char* msg); void wirpos_log_device_type(enum wirpos_device_type_enum device_type); void wirpos_log_move_home(int det_num); void wirpos_log_rel_move(int det_num, double dis); void wirpos_log_abs_move(int det_num, double pos); void wirpos_log_get_pos(int det_num, double pos); void wirpos_log_get_volt(int det_num, double v); void wirpos_log_set_zero_pos(int det_num); /* ************************************************************** */ /* PRIVATE GLOBAL VARIABLES */ static int esp7000_ID; static int wirpos_hp34970_ID; static double nominal_position[WIRPOS_MAX_NUM_WIR_DET]; static char cmd[WIRPOS_MAX_NUM_CHAR]; static char msg[WIRPOS_MAX_NUM_CHAR]; /* ************************************************************** */ /* PRIVATE PARAMETERS */ static char log_file[100]; static struct wirpos_param_struct wirpos_param; /* ************************************************************** */ /* PUBLIC FUNCTIONS */ /* ************************************************************** */ /* * wirpos_init * This function opens the device, queries for ID, and * initializes the device to a known state. * * Zachary Wolf * 6/3/05 */ void wirpos_init(char log_file_in[], struct wirpos_param_struct wirpos_param_in) { /* Declare variables */ int i; /* Save the module parameters */ strcpy(log_file, log_file_in); wirpos_param = wirpos_param_in; /* Initialize the appropriate devices */ if (wirpos_param.device_type == WIRPOS_ESP7000_HP34970) { hp34970_init(wirpos_param.board_addr, wirpos_param.hp34970_addr, &wirpos_hp34970_ID); esp7000_init(wirpos_param.board_addr, wirpos_param.esp7000_addr, &esp7000_ID); } else if (wirpos_param.device_type == WIRPOS_MANUAL_HP34970) { hp34970_init(wirpos_param.board_addr, wirpos_param.hp34970_addr, &wirpos_hp34970_ID); } else if (wirpos_param.device_type == WIRPOS_NONE_NONE); else wirpos_error("Unknown device type."); /* Move each detector to its home position */ if (wirpos_param.device_type != WIRPOS_NONE_NONE) { printf("\nMove detectors to their home position:\n"); for (i = 0; i < wirpos_param.num_wire_det; i++) wirpos_move_home(i); //Turn off power to the active axes for (i = 1; i <= ESP7000_MAX_NUM_AXES; i++) esp7000_deactivate_axis(esp7000_ID, i); } /* Log the device type */ wirpos_log_device_type(wirpos_param.device_type); /* Done */ return; } /* ************************************************************** */ /* * wirpos_manual_move_to_wire * This function requests the operator to move the stages to the position * where the detector is roughly centered on the wire. The DMM monitors * the detector output to aid in moving. * * Input: * det_num, detector number (0, 1, 2, ...) * * Zachary Wolf * 6/3/05 */ void wirpos_manual_move_to_wire(int det_num) { /* Declare variables */ char buf[80]; /* Check input parameters */ if (det_num < 0 || det_num >= wirpos_param.num_wire_det) { Fmt(msg, "%s= wirpos_param.num_wire_det) { Fmt(msg, "%s= wirpos_param.num_wire_det) { Fmt(msg, "%s= wirpos_param.num_wire_det) { Fmt(msg, "%s= wirpos_param.num_wire_det) { Fmt(msg, "%s= wirpos_param.num_wire_det) { Fmt(msg, "%s WIRPOS_SENS * v_det_abs[0]) { found_wire = 1; index_wire = i; } /* If the wire is found, exit early to save time */ if (found_wire == 1 && (i - index_wire) > 3) break; } /* Find the minimum and maximum output voltage */ v_min = v_det_abs[0]; v_min_index = 0; v_max = v_det_abs[0]; for (i = 1; i < num_pos; i++) { if (v_det_abs[i] < v_min) { v_min = v_det_abs[i]; v_min_index = i; } if (v_det_abs[i] > v_max) v_max = v_det_abs[i]; } /* Determine the midpoint voltage level */ v_mid = (v_min + v_max) / 2.; /* Draw a line at the midpoint voltage level */ wirposui_plot_line(0., v_mid, WIRPOS_COARSE_NUM_POS * WIRPOS_COARSE_STEP_SIZE, v_mid); /* Interpolate on the left side, starting from the minimum */ x_left = 0.; for (i = v_min_index; i >= 0; i--) { if (v_det_abs[i] >= v_mid && v_det_abs[i+1] < v_mid) { x_left = x_det[i] + ((v_mid - v_det_abs[i]) / (v_det_abs[i+1] - v_det_abs[i])) * (x_det[i+1] - x_det[i]); break; } } /* Plot the left interpolation point */ wirposui_plot_x_v_thresh(x_left, v_mid); /* Interpolate on the right side */ x_right = 0.; for (i = v_min_index; i < num_pos - 1; i++) { if (v_det_abs[i] <= v_mid && v_det_abs[i+1] > v_mid) { x_right = x_det[i] + ((v_mid - v_det_abs[i]) / (v_det_abs[i+1] - v_det_abs[i])) * (x_det[i+1] - x_det[i]); break; } } /* Plot the right interpolation point */ wirposui_plot_x_v_thresh(x_right, v_mid); /* Average to get the wire position */ *coarse_wire_pos = (x_left + x_right) / 2.; /* Check */ if (found_wire == 0 || x_left == 0. || x_right == 0.) { wirpos_message("wirpos_find_wire_coarse: Could not find wire."); *coarse_wire_pos = 0.; } /* Plot the wire position */ wirposui_plot_x_v_wire(*coarse_wire_pos, v_mid); /* Move to the wire position */ printf("Moving to the coarse wire position...\n"); wirpos_abs_move(det_num, *coarse_wire_pos); /* Done */ return; } /* ************************************************************** */ /* * wirpos_find_wire_fine * This function moves a detector through a small range in evenly * spaced steps starting from a coarse initial estimate of the * wire position. At each step, it measures the detector output * voltage. A final scan is used to get fit information to * determine the wire position. * * Input: * det_num, number of the detector to move (0, 1, 2, ...) * coarse_wire_pos, initial estimate of the wire position (m) * * Output: * fine_wire_pos, wire position (m) * * Zachary Wolf * 7/25/05 */ void wirpos_find_wire_fine(int det_num, double coarse_wire_pos, double* fine_wire_pos) { /* Declare variables */ double x_det_start; double v_det[WIRPOS_FINE_NUM_POS]; double v_det_abs[WIRPOS_FINE_NUM_POS]; double x_det[WIRPOS_FINE_NUM_POS]; int i, j, v_min_index; double v_min, v_max; double v_mid; double x_left, x_right; double v_fit[WIRPOS_FIT_NUM_POS]; double v_fit_abs[WIRPOS_FIT_NUM_POS]; double x_fit[WIRPOS_FIT_NUM_POS]; double z[WIRPOS_FIT_NUM_POS], slope, intercept, mse; double sum; /* Check input parameters */ if (det_num < 0 || det_num >= wirpos_param.num_wire_det) { Fmt(msg, "%s v_max) v_max = v_det_abs[i]; } /* Determine the midpoint voltage level */ v_mid = (v_min + v_max) / 2.; /* Draw a line at the midpoint voltage level */ wirposui_plot_line(x_det_start - WIRPOS_FINE_STEP_SIZE, v_mid, x_det_start + WIRPOS_FINE_NUM_POS * WIRPOS_FINE_STEP_SIZE, v_mid); /* Interpolate on the left side */ x_left = 0.; for (i = v_min_index; i >= 0; i--) { if (v_det_abs[i] >= v_mid && v_det_abs[i+1] < v_mid) { x_left = x_det[i] + ((v_mid - v_det_abs[i]) / (v_det_abs[i+1] - v_det_abs[i])) * (x_det[i+1] - x_det[i]); break; } } /* Move to the initial position of the fit scan on the left side */ x_det_start = x_left - ((WIRPOS_FIT_NUM_POS - 1) * WIRPOS_FIT_STEP_SIZE / 2.) - WIRPOS_FIT_STEP_SIZE; if (x_det_start < 0.) { printf("Problem finding the wire, exiting..."); *fine_wire_pos = 0.; return; } wirpos_abs_move(det_num, x_det_start - 0.000040); wirpos_abs_move(det_num, x_det_start); /* Do a fit scan around x_left */ for (i = 0; i < WIRPOS_FIT_NUM_POS; i++) { /* Do a relative move by the step size */ wirpos_rel_move(det_num, WIRPOS_FIT_STEP_SIZE); /* Measure the detector output voltage */ wirpos_get_volt(det_num, &v_fit[i]); v_fit_abs[i] = fabs(v_fit[i]); /* Get the detector position */ wirpos_get_pos(det_num, &x_fit[i]); /* Plot the measurement */ wirposui_plot_x_v_samp(x_fit[i], v_fit_abs[i]); } /* Fit the scan to find a new measurement of x_left */ LinFit(x_fit, v_fit_abs, WIRPOS_FIT_NUM_POS, z, &slope, &intercept, &mse); x_left = (v_mid - intercept) / slope; /* Plot the left interpolation point */ wirposui_plot_x_v_thresh(x_left, v_mid); /* Interpolate on the right side */ x_right = 0.; for (i = v_min_index; i < WIRPOS_FINE_NUM_POS - 1; i++) { if (v_det_abs[i] <= v_mid && v_det_abs[i+1] > v_mid) { x_right = x_det[i] + ((v_mid - v_det_abs[i]) / (v_det_abs[i+1] - v_det_abs[i])) * (x_det[i+1] - x_det[i]); break; } } /* Move to the initial position of the fit scan on the right side */ x_det_start = x_right - ((WIRPOS_FIT_NUM_POS - 1) * WIRPOS_FIT_STEP_SIZE / 2.) - WIRPOS_FIT_STEP_SIZE; if (x_det_start < 0.) { printf("Problem finding the wire, exiting..."); *fine_wire_pos = 0.; return; } wirpos_abs_move(det_num, x_det_start); /* Do a fit scan around x_right */ for (i = 0; i < WIRPOS_FIT_NUM_POS; i++) { /* Do a relative move by the step size */ wirpos_rel_move(det_num, WIRPOS_FIT_STEP_SIZE); /* Measure the detector output voltage */ wirpos_get_volt(det_num, &v_fit[i]); v_fit_abs[i] = fabs(v_fit[i]); /* Get the detector position */ wirpos_get_pos(det_num, &x_fit[i]); /* Plot the measurement */ wirposui_plot_x_v_samp(x_fit[i], v_fit_abs[i]); } /* Fit the scan to find a new measurement of x_right */ LinFit(x_fit, v_fit_abs, WIRPOS_FIT_NUM_POS, z, &slope, &intercept, &mse); x_right = (v_mid - intercept) / slope; /* Plot the right interpolation point */ wirposui_plot_x_v_thresh(x_right, v_mid); /* Average to get the wire position */ *fine_wire_pos = (x_left + x_right) / 2.; /* Plot the wire position */ wirposui_plot_x_v_wire(*fine_wire_pos, v_mid); /* Move to the wire position */ printf("Moving to the fine wire position...\n"); wirpos_abs_move(det_num, *fine_wire_pos - 0.000050); wirpos_abs_move(det_num, *fine_wire_pos); /* Done */ return; } /* ************************************************************** */ /* * wirpos_find_wire * This function first makes a coarse measurement of the wire position. * It then does a fine measurement to get the final position. * It leaves the detector centered on the wire. * * Input: * det_num, number of the detector to move (0, 1, 2, ...) * * Output: * wire_pos, wire position (m) * * Zachary Wolf * 8/4/05 */ void wirpos_find_wire(int det_num, double* wire_pos) { /* Declare variables */ double coarse_wire_pos; int i=0,done=0; //turn on the axis esp7000_activate_axis(esp7000_ID, det_num+1); //not the best place for it, but it works /* Make an initial coarse measurement of the wire position */ do { i++; wirpos_find_wire_coarse(det_num, &coarse_wire_pos); if(coarse_wire_pos!=0.) done=1; else { printf("\nFailed to find coarse wire position.\n"); if(i