Пример #1
0
uint8_t cm_set_feed_rate(double feed_rate)
{
	if (gm.inverse_feed_rate_mode == true) {
		gm.inverse_feed_rate = feed_rate; // minutes per motion for this block only
	} else {
		gm.feed_rate = _to_millimeters(feed_rate);
	}
	return (TG_OK);
}
Пример #2
0
uint8_t cm_set_origin_offsets(double offset[], double flag[])	// G92
{
	gm.origin_offset_mode = true;
	for (uint8_t i=0; i<AXES; i++) {
		if (flag[i] > EPSILON) {	 	// behaves according to NIST 3.5.18
			gm.origin_offset[i] = gm.position[i] - cfg.offset[gm.coord_system][i] 
								  - _to_millimeters(offset[i]);
		}
	}
	return (TG_OK);
}
Пример #3
0
void cm_set_target(double target[], double flag[])
{ 
	uint8_t i;
	double length;
	double tmp = 0;

	// process XYZABC for lower modes
	for (i=X; i<=Z; i++) {
		if ((flag[i] < EPSILON) || (cfg.a[i].axis_mode == AXIS_DISABLED)) {
			continue;
		} else if ((cfg.a[i].axis_mode == AXIS_STANDARD) || (cfg.a[i].axis_mode == AXIS_INHIBITED)) {
			if (gm.distance_mode == ABSOLUTE_MODE) {
				gm.target[i] = cm_get_coord_offset(i) + _to_millimeters(target[i]);
			} else {
				gm.target[i] += _to_millimeters(target[i]);
			}
//		} else if (i<A) {
//			printf_P(stderr,PSTR("%c axis using unsupported axis mode"), cfg_get_configuration_group_char(i));
		}
	}
	// FYI: The ABC loop below relies on the XYZ loop having been run first
	for (i=A; i<=C; i++) {
		// skip axis if not flagged for update or its disabled
		if ((flag[i] < EPSILON) || (cfg.a[i].axis_mode == AXIS_DISABLED)) {
			continue;

		} else if ((cfg.a[i].axis_mode == AXIS_STANDARD) || (cfg.a[i].axis_mode == AXIS_INHIBITED)) {
			tmp = target[i];	// no mm conversion - it's in degrees

		} else if ((cfg.a[i].axis_mode == AXIS_RADIUS) && (flag[i] > EPSILON)) {
			tmp = _to_millimeters(target[i]) * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_X) && (flag[X] > EPSILON)) {
			tmp = (target[X] - gm.position[X]) * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_Y) && (flag[Y] > EPSILON)) {
			tmp = (target[Y] - gm.position[Y]) * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_Z) && (flag[Z] > EPSILON)) {
			tmp = (target[Z] - gm.position[Z]) * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_XY) && 
			((flag[X] > EPSILON) || (flag[Y] > EPSILON))) {
			length = sqrt(square(target[X] - gm.position[X]) + 
						  square(target[Y] - gm.position[Y]));
			tmp = length * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_XZ) && 
			((flag[X] > EPSILON) || (flag[Z] > EPSILON))) {
			length = sqrt(square(target[X] - gm.position[X]) + 
						  square(target[Z] - gm.position[Z]));
			tmp = length * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_YZ) && 
			((flag[Y] > EPSILON) || (flag[Z] > EPSILON))) {
			length = sqrt(square(target[Y] - gm.position[Y]) + 
						  square(target[Z] - gm.position[Z]));
			tmp = length * 360 / (2 * M_PI * cfg.a[i].radius);

		} else if ((cfg.a[i].axis_mode == AXIS_SLAVE_XYZ) && 
			((flag[X] > EPSILON) || (flag[Y] > EPSILON) || (flag[Z] > EPSILON))) {
			length = sqrt(square(target[X] - gm.position[X]) + 
						  square(target[Y] - gm.position[Y]) +
						  square(target[Z] - gm.position[Z]));
			tmp = length * 360 / (2 * M_PI * cfg.a[i].radius);
		}
		if (gm.distance_mode == ABSOLUTE_MODE) {
			gm.target[i] = tmp;
		} else {
			gm.target[i] += tmp;
		}
	}
}
Пример #4
0
void cm_set_arc_radius(double r) 
{ 
	gm.arc_radius = _to_millimeters(r);
}
Пример #5
0
void cm_set_arc_offset(double i, double j, double k)
{ 
	gm.arc_offset[0] = _to_millimeters(i);
	gm.arc_offset[1] = _to_millimeters(j);
	gm.arc_offset[2] = _to_millimeters(k);
}
Пример #6
0
/*
 * cm_arc_feed() - canonical machine entry point for arc
 *
 * Generates an arc by queueing line segments to the move buffer. The arc is
 * approximated by generating a large number of tiny, linear segments.
 */
stat_t cm_arc_feed(float target[], float flags[],// arc endpoints
				   float i, float j, float k, 	 // raw arc offsets
				   float radius, 				 // non-zero radius implies radius mode
				   uint8_t motion_mode)			 // defined motion mode
{
	// trap zero feed rate condition
	if ((cm.gm.feed_rate_mode != INVERSE_TIME_MODE) && (fp_ZERO(cm.gm.feed_rate))) {
		return (STAT_GCODE_FEEDRATE_NOT_SPECIFIED);
	}

	// Trap conditions where no arc movement will occur, but the system is still in
	// arc motion mode - this is not an error. This can happen when a F word or M
	// word is by itself.(The tests below are organized for execution efficiency)
	if ( fp_ZERO(i) && fp_ZERO(j) && fp_ZERO(k) && fp_ZERO(radius) ) {
		if ( fp_ZERO((flags[AXIS_X] + flags[AXIS_Y] + flags[AXIS_Z] +
					  flags[AXIS_A] + flags[AXIS_B] + flags[AXIS_C]))) {
			return (STAT_OK);
		}
	}

	// set values in the Gcode model state & copy it (linenum was already captured)
	cm_set_model_target(target, flags);
	cm.gm.motion_mode = motion_mode;
	cm_set_work_offsets(&cm.gm);					// capture the fully resolved offsets to gm
	memcpy(&arc.gm, &cm.gm, sizeof(GCodeState_t));	// copy GCode context to arc singleton - some will be overwritten to run segments

	// populate the arc control singleton
	copy_vector(arc.position, cm.gmx.position);		// set initial arc position from gcode model
	arc.radius = _to_millimeters(radius);			// set arc radius or zero
	arc.offset[0] = _to_millimeters(i);				// copy offsets with conversion to canonical form (mm)
	arc.offset[1] = _to_millimeters(j);
	arc.offset[2] = _to_millimeters(k);

	// Set the arc plane for the current G17/G18/G19 setting
	// Plane axis 0 and 1 are the arc plane, 2 is the linear axis normal to the arc plane
	if (cm.gm.select_plane == CANON_PLANE_XY) {	// G17 - the vast majority of arcs are in the G17 (XY) plane
		arc.plane_axis_0 = AXIS_X;
		arc.plane_axis_1 = AXIS_Y;
		arc.linear_axis  = AXIS_Z;
	} else if (cm.gm.select_plane == CANON_PLANE_XZ) {	// G18
		arc.plane_axis_0 = AXIS_X;
		arc.plane_axis_1 = AXIS_Z;
		arc.linear_axis  = AXIS_Y;
	} else if (cm.gm.select_plane == CANON_PLANE_YZ) {	// G19
		arc.plane_axis_0 = AXIS_Y;
		arc.plane_axis_1 = AXIS_Z;
		arc.linear_axis  = AXIS_X;
	}

	// compute arc runtime values and prep for execution by the callback
	ritorno(_compute_arc());

	// test arc soft limits
	stat_t status = _test_arc_soft_limits();
	if (status != STAT_OK) {
		cm.gm.motion_mode = MOTION_MODE_CANCEL_MOTION_MODE;
		copy_vector(cm.gm.target, cm.gmx.position);		// reset model position
		return (cm_soft_alarm(status));
	}

	cm_cycle_start();						// if not already started
	arc.run_state = MOVE_RUN;				// enable arc to be run from the callback
	cm_finalize_move();
	return (STAT_OK);
}
Пример #7
0
/*
 * cm_arc_feed() - canonical machine entry point for arc
 *
 * Generates an arc by queuing line segments to the move buffer. The arc is
 * approximated by generating a large number of tiny, linear arc_segments.
 */
stat_t cm_arc_feed(float target[], float flags[],       // arc endpoints
				   float i, float j, float k,           // raw arc offsets
				   float radius,                        // non-zero radius implies radius mode
				   uint8_t motion_mode)                 // defined motion mode
{
	////////////////////////////////////////////////////
	// Set axis plane and trap arc specification errors

	// trap missing feed rate
	if ((cm.gm.feed_rate_mode != INVERSE_TIME_MODE) && (fp_ZERO(cm.gm.feed_rate))) {
    	return (STAT_GCODE_FEEDRATE_NOT_SPECIFIED);
	}

    // set radius mode flag and do simple test(s)
	bool radius_f = fp_NOT_ZERO(cm.gf.arc_radius);			    // set true if radius arc
    if ((radius_f) && (cm.gn.arc_radius < MIN_ARC_RADIUS)) {    // radius value must be + and > minimum radius
        return (STAT_ARC_RADIUS_OUT_OF_TOLERANCE);
    }

    // setup some flags
	bool target_x = fp_NOT_ZERO(flags[AXIS_X]);	                // set true if X axis has been specified
	bool target_y = fp_NOT_ZERO(flags[AXIS_Y]);
	bool target_z = fp_NOT_ZERO(flags[AXIS_Z]);

    bool offset_i = fp_NOT_ZERO(cm.gf.arc_offset[0]);	        // set true if offset I has been specified
    bool offset_j = fp_NOT_ZERO(cm.gf.arc_offset[1]);           // J
    bool offset_k = fp_NOT_ZERO(cm.gf.arc_offset[2]);           // K

	// Set the arc plane for the current G17/G18/G19 setting and test arc specification
	// Plane axis 0 and 1 are the arc plane, the linear axis is normal to the arc plane.
	if (cm.gm.select_plane == CANON_PLANE_XY) {	// G17 - the vast majority of arcs are in the G17 (XY) plane
    	arc.plane_axis_0 = AXIS_X;
    	arc.plane_axis_1 = AXIS_Y;
    	arc.linear_axis  = AXIS_Z;
        if (radius_f) {
            if (!(target_x || target_y)) {                      // must have at least one endpoint specified
        	    return (STAT_ARC_AXIS_MISSING_FOR_SELECTED_PLANE);
            }
        } else { // center format arc tests
            if (offset_k) { // it's OK to be missing either or both i and j, but error if k is present
        	    return (STAT_ARC_SPECIFICATION_ERROR);
            }
        }

    } else if (cm.gm.select_plane == CANON_PLANE_XZ) {	// G18
    	arc.plane_axis_0 = AXIS_X;
    	arc.plane_axis_1 = AXIS_Z;
    	arc.linear_axis  = AXIS_Y;
        if (radius_f) {
            if (!(target_x || target_z))
                return (STAT_ARC_AXIS_MISSING_FOR_SELECTED_PLANE);
        } else {
            if (offset_j)
                return (STAT_ARC_SPECIFICATION_ERROR);
        }

    } else if (cm.gm.select_plane == CANON_PLANE_YZ) {	// G19
    	arc.plane_axis_0 = AXIS_Y;
    	arc.plane_axis_1 = AXIS_Z;
    	arc.linear_axis  = AXIS_X;
        if (radius_f) {
            if (!(target_y || target_z))
                return (STAT_ARC_AXIS_MISSING_FOR_SELECTED_PLANE);
        } else {
            if (offset_i)
                return (STAT_ARC_SPECIFICATION_ERROR);
        }
	}

	// set values in the Gcode model state & copy it (linenum was already captured)
	cm_set_model_target(target, flags);

    // in radius mode it's an error for start == end
    if(radius_f) {
        if ((fp_EQ(cm.gmx.position[AXIS_X], cm.gm.target[AXIS_X])) &&
            (fp_EQ(cm.gmx.position[AXIS_Y], cm.gm.target[AXIS_Y])) &&
            (fp_EQ(cm.gmx.position[AXIS_Z], cm.gm.target[AXIS_Z]))) {
            return (STAT_ARC_ENDPOINT_IS_STARTING_POINT);
        }
    }

    // now get down to the rest of the work setting up the arc for execution
	cm.gm.motion_mode = motion_mode;
	cm_set_work_offsets(&cm.gm);					// capture the fully resolved offsets to gm
	memcpy(&arc.gm, &cm.gm, sizeof(GCodeState_t));	// copy GCode context to arc singleton - some will be overwritten to run segments
	copy_vector(arc.position, cm.gmx.position);		// set initial arc position from gcode model

	arc.radius = _to_millimeters(radius);			// set arc radius or zero

	arc.offset[0] = _to_millimeters(i);				// copy offsets with conversion to canonical form (mm)
	arc.offset[1] = _to_millimeters(j);
	arc.offset[2] = _to_millimeters(k);

	arc.rotations = floor(fabs(cm.gn.parameter));   // P must be a positive integer - force it if not

	// determine if this is a full circle arc. Evaluates true if no target is set
	arc.full_circle = (fp_ZERO(flags[arc.plane_axis_0]) & fp_ZERO(flags[arc.plane_axis_1]));

	// compute arc runtime values
	ritorno(_compute_arc());

	if (fp_ZERO(arc.length)) {
        return (STAT_MINIMUM_LENGTH_MOVE);          // trap zero length arcs that _compute_arc can throw
    }

/*	// test arc soft limits
	stat_t status = _test_arc_soft_limits();
	if (status != STAT_OK) {
    	cm.gm.motion_mode = MOTION_MODE_CANCEL_MOTION_MODE;
    	copy_vector(cm.gm.target, cm.gmx.position);		// reset model position
    	return (cm_soft_alarm(status));
	}
*/
	cm_cycle_start();						// if not already started
	arc.run_state = MOVE_RUN;				// enable arc to be run from the callback
	cm_finalize_move();
	return (STAT_OK);
}