Skip to content

Commit

Permalink
G34 automatic point assignment (#16473)
Browse files Browse the repository at this point in the history
  • Loading branch information
InsanityAutomation authored Feb 1, 2020
1 parent 90b6324 commit e58d1bf
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 105 deletions.
53 changes: 36 additions & 17 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,35 +668,54 @@
*/
//#define Z_STEPPER_AUTO_ALIGN
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
// Define probe X and Y positions for Z1, Z2 [, Z3]
#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }
// Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
// If not defined, probe limits will be used.
// Override with 'M422 S<index> X<pos> Y<pos>'
//#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }

/**
* Orientation for the automatically-calculated probe positions.
* Override Z stepper align points with 'M422 S<index> X<pos> Y<pos>'
*
* 2 Steppers: (0) (1)
* | | 2 |
* | 1 2 | |
* | | 1 |
*
* 3 Steppers: (0) (1) (2) (3)
* | 3 | 1 | 2 1 | 2 |
* | | 3 | | 3 |
* | 1 2 | 2 | 3 | 1 |
*
* 4 Steppers: (0) (1) (2) (3)
* | 4 3 | 1 4 | 2 1 | 3 2 |
* | | | | |
* | 1 2 | 2 3 | 3 4 | 4 1 |
*
*/
#ifndef Z_STEPPER_ALIGN_XY
//#define Z_STEPPERS_ORIENTATION 0
#endif

// Provide Z stepper positions for more rapid convergence in bed alignment.
// Currently requires triple stepper drivers.
// Requires triple stepper drivers (i.e., set NUM_Z_STEPPER_DRIVERS to 3)
//#define Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
// Define Stepper XY positions for Z1, Z2, Z3 corresponding to
// the Z screw positions in the bed carriage.
// Define one position per Z stepper in stepper driver order.
#define Z_STEPPER_ALIGN_STEPPER_XY { { 210.7, 102.5 }, { 152.6, 220.0 }, { 94.5, 102.5 } }
#else
// Amplification factor. Used to scale the correction step up or down.
// In case the stepper (spindle) position is further out than the test point.
// Use a value > 1. NOTE: This may cause instability
#define Z_STEPPER_ALIGN_AMP 1.0
// Amplification factor. Used to scale the correction step up or down in case
// the stepper (spindle) position is farther out than the test point.
#define Z_STEPPER_ALIGN_AMP 1.0 // Use a value > 1.0 NOTE: This may cause instability!
#endif

// Set number of iterations to align
#define Z_STEPPER_ALIGN_ITERATIONS 3

// Enable to restore leveling setup after operation
#define RESTORE_LEVELING_AFTER_G34
// On a 300mm bed a 5% grade would give a misalignment of ~1.5cm
#define G34_MAX_GRADE 5 // (%) Maximum incline G34 will handle

// Stop criterion. If the accuracy is better than this stop iterating early
#define Z_STEPPER_ALIGN_ACC 0.02
#define G34_MAX_GRADE 5 // (%) Maximum incline that G34 will handle
#define Z_STEPPER_ALIGN_ITERATIONS 5 // Number of iterations to apply during alignment
#define Z_STEPPER_ALIGN_ACC 0.02 // Stop iterating early if the accuracy is better than this
#define RESTORE_LEVELING_AFTER_G34 // Restore leveling after G34 is done?
#endif

// @section motion
Expand Down
137 changes: 137 additions & 0 deletions Marlin/src/feature/z_stepper_align.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* feature/z_stepper_align.cpp
*/

#include "../inc/MarlinConfigPre.h"

#if ENABLED(Z_STEPPER_AUTO_ALIGN)

#include "z_stepper_align.h"
#include "../module/probe.h"

ZStepperAlign z_stepper_align;

xy_pos_t ZStepperAlign::xy[NUM_Z_STEPPER_DRIVERS];

#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
xy_pos_t ZStepperAlign::stepper_xy[NUM_Z_STEPPER_DRIVERS];
#endif

void ZStepperAlign::reset_to_default() {
#ifdef Z_STEPPER_ALIGN_XY

constexpr xy_pos_t xy_init[] = Z_STEPPER_ALIGN_XY;
static_assert(COUNT(xy_init) == NUM_Z_STEPPER_DRIVERS,
"Z_STEPPER_ALIGN_XY requires "
#if NUM_Z_STEPPER_DRIVERS == 4
"four {X,Y} entries (Z, Z2, Z3, and Z4)."
#elif NUM_Z_STEPPER_DRIVERS == 3
"three {X,Y} entries (Z, Z2, and Z3)."
#else
"two {X,Y} entries (Z and Z2)."
#endif
);

constexpr xyz_pos_t dpo = NOZZLE_TO_PROBE_OFFSET;

#define LTEST(N) (xy_init[N].x >= _MAX(X_MIN_BED + MIN_PROBE_EDGE_LEFT, X_MIN_POS + dpo.x) - 0.00001f)
#define RTEST(N) (xy_init[N].x <= _MIN(X_MAX_BED - MIN_PROBE_EDGE_RIGHT, X_MAX_POS + dpo.x) + 0.00001f)
#define FTEST(N) (xy_init[N].y >= _MAX(Y_MIN_BED + MIN_PROBE_EDGE_FRONT, Y_MIN_POS + dpo.y) - 0.00001f)
#define BTEST(N) (xy_init[N].y <= _MIN(Y_MAX_BED - MIN_PROBE_EDGE_BACK, Y_MAX_POS + dpo.y) + 0.00001f)

static_assert(LTEST(0) && RTEST(0), "The 1st Z_STEPPER_ALIGN_XY X is unreachable with the default probe X offset.");
static_assert(FTEST(0) && BTEST(0), "The 1st Z_STEPPER_ALIGN_XY Y is unreachable with the default probe Y offset.");
static_assert(LTEST(1) && RTEST(1), "The 2nd Z_STEPPER_ALIGN_XY X is unreachable with the default probe X offset.");
static_assert(FTEST(1) && BTEST(1), "The 2nd Z_STEPPER_ALIGN_XY Y is unreachable with the default probe Y offset.");
#if NUM_Z_STEPPER_DRIVERS >= 3
static_assert(LTEST(2) && RTEST(2), "The 3rd Z_STEPPER_ALIGN_XY X is unreachable with the default probe X offset.");
static_assert(FTEST(2) && BTEST(2), "The 3rd Z_STEPPER_ALIGN_XY Y is unreachable with the default probe Y offset.");
#if NUM_Z_STEPPER_DRIVERS >= 4
static_assert(LTEST(3) && RTEST(3), "The 4th Z_STEPPER_ALIGN_XY X is unreachable with the default probe X offset.");
static_assert(FTEST(3) && BTEST(3), "The 4th Z_STEPPER_ALIGN_XY Y is unreachable with the default probe Y offset.");
#endif
#endif

#else // !defined(Z_STEPPER_ALIGN_XY)

const xy_pos_t xy_init[] = {
#if NUM_Z_STEPPER_DRIVERS >= 3 // First probe point...
#if !Z_STEPPERS_ORIENTATION
{ probe.min_x(), probe.min_y() }, // SW
#elif Z_STEPPERS_ORIENTATION == 1
{ probe.min_x(), probe.max_y() }, // NW
#elif Z_STEPPERS_ORIENTATION == 2
{ probe.max_x(), probe.max_y() }, // NE
#elif Z_STEPPERS_ORIENTATION == 3
{ probe.max_x(), probe.min_y() }, // SE
#else
#error "Z_STEPPERS_ORIENTATION must be from 0 to 3 (first point SW, NW, NE, SE)."
#endif
#if NUM_Z_STEPPER_DRIVERS == 4 // 3 more points...
#if !Z_STEPPERS_ORIENTATION
{ probe.min_x(), probe.max_y() }, { probe.max_x(), probe.max_y() }, { probe.max_x(), probe.min_y() } // SW
#elif Z_STEPPERS_ORIENTATION == 1
{ probe.max_x(), probe.max_y() }, { probe.max_x(), probe.min_y() }, { probe.min_x(), probe.min_y() } // NW
#elif Z_STEPPERS_ORIENTATION == 2
{ probe.max_x(), probe.min_y() }, { probe.min_x(), probe.min_y() }, { probe.min_x(), probe.max_y() } // NE
#elif Z_STEPPERS_ORIENTATION == 3
{ probe.min_x(), probe.min_y() }, { probe.min_x(), probe.max_y() }, { probe.max_x(), probe.max_y() } // SE
#endif
#elif !Z_STEPPERS_ORIENTATION // or 2 more points...
{ probe.max_x(), probe.min_y() }, { X_CENTER, probe.max_y() } // SW
#elif Z_STEPPERS_ORIENTATION == 1
{ probe.min_x(), probe.min_y() }, { probe.max_x(), Y_CENTER } // NW
#elif Z_STEPPERS_ORIENTATION == 2
{ probe.min_x(), probe.max_y() }, { X_CENTER, probe.min_y() } // NE
#elif Z_STEPPERS_ORIENTATION == 3
{ probe.max_x(), probe.max_y() }, { probe.min_x(), Y_CENTER } // SE
#endif
#elif Z_STEPPERS_ORIENTATION
{ X_CENTER, probe.min_y() }, { X_CENTER, probe.max_y() }
#else
{ probe.min_x(), Y_CENTER }, { probe.max_x(), Y_CENTER }
#endif
};

#endif // !defined(Z_STEPPER_ALIGN_XY)

COPY(xy, xy_init);

#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
constexpr xy_pos_t stepper_xy_init[] = Z_STEPPER_ALIGN_STEPPER_XY;
static_assert(
COUNT(stepper_xy_init) == NUM_Z_STEPPER_DRIVERS,
"Z_STEPPER_ALIGN_STEPPER_XY requires "
#if NUM_Z_STEPPER_DRIVERS == 4
"four {X,Y} entries (Z, Z2, Z3, and Z4)."
#elif NUM_Z_STEPPER_DRIVERS == 3
"three {X,Y} entries (Z, Z2, and Z3)."
#endif
);
COPY(stepper_xy, stepper_xy_init);
#endif
}

#endif // Z_STEPPER_AUTO_ALIGN
41 changes: 41 additions & 0 deletions Marlin/src/feature/z_stepper_align.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once

/**
* feature/z_stepper_align.h
*/

#include "../inc/MarlinConfig.h"

class ZStepperAlign {
public:
static xy_pos_t xy[NUM_Z_STEPPER_DRIVERS];

#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
static xy_pos_t stepper_xy[NUM_Z_STEPPER_DRIVERS];
#endif

static void reset_to_default();
};

extern ZStepperAlign z_stepper_align;
2 changes: 1 addition & 1 deletion Marlin/src/gcode/bedlevel/G26.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ void GcodeSuite::G26() {
if (location.valid()) {
const xy_pos_t circle = _GET_MESH_POS(location.pos);

// If this mesh location is outside the printable_radius, skip it.
// If this mesh location is outside the printable radius, skip it.
if (!position_is_reachable(circle)) continue;

// Determine where to start and end the circle,
Expand Down
Loading

0 comments on commit e58d1bf

Please sign in to comment.