Updated M48 friendly for DELTA

Partial implementation with reference to MarlinFirmware/Marlin#3011
This commit is contained in:
Scott Lahteine 2016-02-27 20:49:49 -08:00
parent 09ef955191
commit 68085ca855
2 changed files with 126 additions and 110 deletions

View file

@ -3642,6 +3642,7 @@ inline void gcode_M42() {
* V = Verbose level (0-4, default=1) * V = Verbose level (0-4, default=1)
* E = Engage Z probe for each reading * E = Engage Z probe for each reading
* L = Number of legs of movement before probe * L = Number of legs of movement before probe
* S = Schizoid (Or Star if you prefer)
* *
* This function assumes the bed has been homed. Specifically, that a G28 command * This function assumes the bed has been homed. Specifically, that a G28 command
* as been issued prior to invoking the M48 Z probe repeatability measurement function. * as been issued prior to invoking the M48 Z probe repeatability measurement function.
@ -3651,7 +3652,7 @@ inline void gcode_M42() {
inline void gcode_M48() { inline void gcode_M48() {
double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50]; double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50];
uint8_t verbose_level = 1, n_samples = 10, n_legs = 0; uint8_t verbose_level = 1, n_samples = 10, n_legs = 0, schizoid_flag = 0;
if (code_seen('V')) { if (code_seen('V')) {
verbose_level = code_value_short(); verbose_level = code_value_short();
@ -3672,50 +3673,57 @@ inline void gcode_M42() {
} }
} }
double X_current = st_get_axis_position_mm(X_AXIS), float X_current = current_position[X_AXIS],
Y_current = st_get_axis_position_mm(Y_AXIS), Y_current = current_position[Y_AXIS],
Z_current = st_get_axis_position_mm(Z_AXIS), Z_current = current_position[Z_AXIS],
E_current = st_get_axis_position_mm(E_AXIS), X_probe_location = X_current + X_PROBE_OFFSET_FROM_EXTRUDER,
X_probe_location = X_current, Y_probe_location = Y_current, Y_probe_location = Y_current + Y_PROBE_OFFSET_FROM_EXTRUDER,
Z_start_location = Z_current + Z_RAISE_BEFORE_PROBING; Z_start_location = Z_current + Z_RAISE_BEFORE_PROBING;
bool deploy_probe_for_each_reading = code_seen('E'); bool deploy_probe_for_each_reading = code_seen('E');
if (code_seen('X')) { if (code_seen('X')) {
X_probe_location = code_value() - (X_PROBE_OFFSET_FROM_EXTRUDER); X_probe_location = code_value();
if (X_probe_location < X_MIN_POS || X_probe_location > X_MAX_POS) { #if DISABLED(DELTA)
out_of_range_error(PSTR("X")); if (X_probe_location < MIN_PROBE_X || X_probe_location > MAX_PROBE_X) {
return; out_of_range_error(PSTR("X"));
} return;
}
#endif
} }
if (code_seen('Y')) { if (code_seen('Y')) {
Y_probe_location = code_value() - Y_PROBE_OFFSET_FROM_EXTRUDER; Y_probe_location = code_value();
if (Y_probe_location < Y_MIN_POS || Y_probe_location > Y_MAX_POS) { #if DISABLED(DELTA)
out_of_range_error(PSTR("Y")); if (Y_probe_location < MIN_PROBE_Y || Y_probe_location > MAX_PROBE_Y) {
return; out_of_range_error(PSTR("Y"));
} return;
}
#endif
} }
if (code_seen('L')) { #if ENABLED(DELTA)
if (sqrt(X_probe_location * X_probe_location + Y_probe_location * Y_probe_location) > DELTA_PROBEABLE_RADIUS) {
SERIAL_PROTOCOLPGM("? (X,Y) location outside of probeable radius.\n");
return;
}
#endif
bool seen_L = code_seen('L');
if (seen_L) {
n_legs = code_value_short(); n_legs = code_value_short();
if (n_legs == 1) n_legs = 2;
if (n_legs < 0 || n_legs > 15) { if (n_legs < 0 || n_legs > 15) {
SERIAL_PROTOCOLPGM("?Number of legs in movement not plausible (0-15).\n"); SERIAL_PROTOCOLPGM("?Number of legs in movement not plausible (0-15).\n");
return; return;
} }
if (n_legs == 1) n_legs = 2;
} }
// if (code_seen('S')) {
// Do all the preliminary setup work. First raise the Z probe. schizoid_flag++;
// if (!seen_L) n_legs = 7;
}
st_synchronize();
plan_bed_level_matrix.set_to_identity();
plan_buffer_line(X_current, Y_current, Z_start_location, E_current, homing_feedrate[Z_AXIS] / 60, active_extruder);
st_synchronize();
//
// Now get everything to the specified probe point So we can safely do a probe to // Now get everything to the specified probe point So we can safely do a probe to
// get us close to the bed. If the Z-Axis is far from the bed, we don't want to // get us close to the bed. If the Z-Axis is far from the bed, we don't want to
// use that as a starting point for each probe. // use that as a starting point for each probe.
@ -3723,90 +3731,112 @@ inline void gcode_M42() {
if (verbose_level > 2) if (verbose_level > 2)
SERIAL_PROTOCOLPGM("Positioning the probe...\n"); SERIAL_PROTOCOLPGM("Positioning the probe...\n");
plan_buffer_line(X_probe_location, Y_probe_location, Z_start_location, #if ENABLED(DELTA)
E_current, reset_bed_level(); // we don't do bed level correction in M48 because we want the raw data when we probe
homing_feedrate[X_AXIS] / 60, #else
active_extruder); plan_bed_level_matrix.set_to_identity(); // we don't do bed level correction in M48 because we wantthe raw data when we probe
st_synchronize(); #endif
current_position[X_AXIS] = X_current = st_get_axis_position_mm(X_AXIS); if (Z_start_location < Z_RAISE_BEFORE_PROBING * 2.0)
current_position[Y_AXIS] = Y_current = st_get_axis_position_mm(Y_AXIS); do_blocking_move_to_z(Z_start_location);
current_position[Z_AXIS] = Z_current = st_get_axis_position_mm(Z_AXIS);
current_position[E_AXIS] = E_current = st_get_axis_position_mm(E_AXIS); do_blocking_move_to_xy(X_probe_location - X_PROBE_OFFSET_FROM_EXTRUDER, Y_probe_location - Y_PROBE_OFFSET_FROM_EXTRUDER);
// //
// OK, do the initial probe to get us close to the bed. // OK, do the initial probe to get us close to the bed.
// Then retrace the right amount and use that in subsequent probes // Then retrace the right amount and use that in subsequent probes
// //
deploy_z_probe();
setup_for_endstop_move(); setup_for_endstop_move();
run_z_probe();
Z_current = current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS); probe_pt(X_probe_location, Y_probe_location, Z_RAISE_BEFORE_PROBING,
Z_start_location = Z_current + Z_RAISE_BEFORE_PROBING; deploy_probe_for_each_reading ? ProbeDeployAndStow : ProbeDeploy,
verbose_level);
plan_buffer_line(X_probe_location, Y_probe_location, Z_start_location, raise_z_after_probing();
E_current,
homing_feedrate[X_AXIS] / 60,
active_extruder);
st_synchronize();
Z_current = current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS);
if (deploy_probe_for_each_reading) stow_z_probe();
for (uint8_t n = 0; n < n_samples; n++) { for (uint8_t n = 0; n < n_samples; n++) {
// Make sure we are at the probe location randomSeed(millis());
do_blocking_move_to(X_probe_location, Y_probe_location, Z_start_location); // this also updates current_position delay(500);
if (n_legs) { if (n_legs) {
millis_t ms = millis(); float radius, angle = random(0.0, 360.0);
double radius = ms % ((X_MAX_LENGTH) / 4), // limit how far out to go int dir = (random(0, 10) > 5.0) ? -1 : 1; // clockwise or counter clockwise
theta = RADIANS(ms % 360L);
float dir = (ms & 0x0001) ? 1 : -1; // clockwise or counter clockwise
//SERIAL_ECHOPAIR("starting radius: ",radius); radius = random(
//SERIAL_ECHOPAIR(" theta: ",theta); #if ENABLED(DELTA)
//SERIAL_ECHOPAIR(" direction: ",dir); DELTA_PROBEABLE_RADIUS / 8, DELTA_PROBEABLE_RADIUS / 3
//SERIAL_EOL; #else
5, X_MAX_LENGTH / 8
#endif
);
if (verbose_level > 3) {
SERIAL_ECHOPAIR("Starting radius: ", radius);
SERIAL_ECHOPAIR(" angle: ", angle);
delay(100);
if (dir > 0)
SERIAL_ECHO(" Direction: Counter Clockwise \n");
else
SERIAL_ECHO(" Direction: Clockwise \n");
delay(100);
}
for (uint8_t l = 0; l < n_legs - 1; l++) { for (uint8_t l = 0; l < n_legs - 1; l++) {
ms = millis(); double delta_angle;
theta += RADIANS(dir * (ms % 20L)); if (schizoid_flag)
radius += (ms % 10L) - 5L; delta_angle = dir * 2.0 * 72.0; // The points of a 5 point star are 72 degrees apart. We need to
if (radius < 0.0) radius = -radius; // skip a point and go to the next one on the star.
else
X_current = X_probe_location + cos(theta) * radius; delta_angle = dir * (float) random(25, 45); // If we do this line, we are just trying to move further
X_current = constrain(X_current, X_MIN_POS, X_MAX_POS); // around the circle.
Y_current = Y_probe_location + sin(theta) * radius; angle += delta_angle;
Y_current = constrain(Y_current, Y_MIN_POS, Y_MAX_POS); while (angle > 360.0) // We probably do not need to keep the angle between 0 and 2*PI, but the
angle -= 360.0; // Arduino documentation says the trig functions should not be given values
while (angle < 0.0) // outside of this range. It looks like they behave correctly with
angle += 360.0; // numbers outside of the range, but just to be safe we clamp them.
X_current = X_probe_location - X_PROBE_OFFSET_FROM_EXTRUDER + cos(RADIANS(angle)) * radius;
Y_current = Y_probe_location - Y_PROBE_OFFSET_FROM_EXTRUDER + sin(RADIANS(angle)) * radius;
#if DISABLED(DELTA)
X_current = constrain(X_current, X_MIN_POS, X_MAX_POS);
Y_current = constrain(Y_current, Y_MIN_POS, Y_MAX_POS);
#else
// If we have gone out too far, we can do a simple fix and scale the numbers
// back in closer to the origin.
while (sqrt(X_current * X_current + Y_current * Y_current) > DELTA_PROBEABLE_RADIUS) {
X_current /= 1.25;
Y_current /= 1.25;
if (verbose_level > 3) {
SERIAL_ECHOPAIR("Pulling point towards center:", X_current);
SERIAL_ECHOPAIR(", ", Y_current);
SERIAL_EOL;
delay(50);
}
}
#endif
if (verbose_level > 3) { if (verbose_level > 3) {
SERIAL_PROTOCOL("Going to:");
SERIAL_ECHOPAIR("x: ", X_current); SERIAL_ECHOPAIR("x: ", X_current);
SERIAL_ECHOPAIR("y: ", Y_current); SERIAL_ECHOPAIR("y: ", Y_current);
SERIAL_ECHOPAIR(" z: ", current_position[Z_AXIS]);
SERIAL_EOL; SERIAL_EOL;
delay(55);
} }
do_blocking_move_to_xy(X_current, Y_current);
do_blocking_move_to(X_current, Y_current, Z_current); // this also updates current_position
} // n_legs loop } // n_legs loop
// Go back to the probe location
do_blocking_move_to(X_probe_location, Y_probe_location, Z_start_location); // this also updates current_position
} // n_legs } // n_legs
if (deploy_probe_for_each_reading) { // We don't really have to do this move, but if we don't we can see a funny shift in the Z Height
deploy_z_probe(); // Because the user might not have the Z_RAISE_BEFORE_PROBING height identical to the
delay(1000); // Z_RAISE_BETWEEN_PROBING height. This gets us back to the probe location at the same height that
// we have been running around the circle at.
do_blocking_move_to_xy(X_probe_location - X_PROBE_OFFSET_FROM_EXTRUDER, Y_probe_location - Y_PROBE_OFFSET_FROM_EXTRUDER);
if (deploy_probe_for_each_reading)
sample_set[n] = probe_pt(X_probe_location, Y_probe_location, Z_RAISE_BEFORE_PROBING, ProbeDeployAndStow, verbose_level);
else {
if (n == n_samples - 1)
sample_set[n] = probe_pt(X_probe_location, Y_probe_location, Z_RAISE_BEFORE_PROBING, ProbeStow, verbose_level); else
sample_set[n] = probe_pt(X_probe_location, Y_probe_location, Z_RAISE_BEFORE_PROBING, ProbeStay, verbose_level);
} }
setup_for_endstop_move();
run_z_probe();
sample_set[n] = current_position[Z_AXIS];
// //
// Get the current mean for the data points we have so far // Get the current mean for the data points we have so far
// //
@ -3824,13 +3854,13 @@ inline void gcode_M42() {
sum += ss * ss; sum += ss * ss;
} }
sigma = sqrt(sum / (n + 1)); sigma = sqrt(sum / (n + 1));
if (verbose_level > 1) { if (verbose_level > 1) {
SERIAL_PROTOCOL(n + 1); SERIAL_PROTOCOL(n + 1);
SERIAL_PROTOCOLPGM(" of "); SERIAL_PROTOCOLPGM(" of ");
SERIAL_PROTOCOL((int)n_samples); SERIAL_PROTOCOL((int)n_samples);
SERIAL_PROTOCOLPGM(" z: "); SERIAL_PROTOCOLPGM(" z: ");
SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6); SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6);
delay(50);
if (verbose_level > 2) { if (verbose_level > 2) {
SERIAL_PROTOCOLPGM(" mean: "); SERIAL_PROTOCOLPGM(" mean: ");
SERIAL_PROTOCOL_F(mean, 6); SERIAL_PROTOCOL_F(mean, 6);
@ -3838,36 +3868,26 @@ inline void gcode_M42() {
SERIAL_PROTOCOL_F(sigma, 6); SERIAL_PROTOCOL_F(sigma, 6);
} }
} }
if (verbose_level > 0) SERIAL_EOL; if (verbose_level > 0) SERIAL_EOL;
delay(50);
do_blocking_move_to_z(current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS);
} // End of probe loop code
plan_buffer_line(X_probe_location, Y_probe_location, Z_start_location, current_position[E_AXIS], homing_feedrate[Z_AXIS] / 60, active_extruder); // raise_z_after_probing();
st_synchronize();
// Stow between
if (deploy_probe_for_each_reading) {
stow_z_probe();
delay(1000);
}
}
// Stow after
if (!deploy_probe_for_each_reading) {
stow_z_probe();
delay(1000);
}
clean_up_after_endstop_move();
if (verbose_level > 0) { if (verbose_level > 0) {
SERIAL_PROTOCOLPGM("Mean: "); SERIAL_PROTOCOLPGM("Mean: ");
SERIAL_PROTOCOL_F(mean, 6); SERIAL_PROTOCOL_F(mean, 6);
SERIAL_EOL; SERIAL_EOL;
delay(25);
} }
SERIAL_PROTOCOLPGM("Standard Deviation: "); SERIAL_PROTOCOLPGM("Standard Deviation: ");
SERIAL_PROTOCOL_F(sigma, 6); SERIAL_PROTOCOL_F(sigma, 6);
SERIAL_EOL; SERIAL_EOL; SERIAL_EOL; SERIAL_EOL;
delay(25);
clean_up_after_endstop_move();
} }
#endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST

View file

@ -231,10 +231,6 @@
#error You cannot use Z_PROBE_SLED with DELTA. #error You cannot use Z_PROBE_SLED with DELTA.
#endif #endif
#if ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST)
#error Z_MIN_PROBE_REPEATABILITY_TEST is not supported with DELTA yet.
#endif
#endif #endif
#endif #endif