G34 automatic point assignment (#16473)
This commit is contained in:
parent
90b6324563
commit
e58d1bf974
6 changed files with 298 additions and 105 deletions
|
@ -668,11 +668,37 @@
|
||||||
*/
|
*/
|
||||||
//#define Z_STEPPER_AUTO_ALIGN
|
//#define Z_STEPPER_AUTO_ALIGN
|
||||||
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
// Define probe X and Y positions for Z1, Z2 [, Z3]
|
// Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
|
||||||
#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }
|
// 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.
|
// 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
|
//#define Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS
|
||||||
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
// Define Stepper XY positions for Z1, Z2, Z3 corresponding to
|
// Define Stepper XY positions for Z1, Z2, Z3 corresponding to
|
||||||
|
@ -680,23 +706,16 @@
|
||||||
// Define one position per Z stepper in stepper driver order.
|
// 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 } }
|
#define Z_STEPPER_ALIGN_STEPPER_XY { { 210.7, 102.5 }, { 152.6, 220.0 }, { 94.5, 102.5 } }
|
||||||
#else
|
#else
|
||||||
// Amplification factor. Used to scale the correction step up or down.
|
// Amplification factor. Used to scale the correction step up or down in case
|
||||||
// In case the stepper (spindle) position is further out than the test point.
|
// the stepper (spindle) position is farther out than the test point.
|
||||||
// Use a value > 1. NOTE: This may cause instability
|
#define Z_STEPPER_ALIGN_AMP 1.0 // Use a value > 1.0 NOTE: This may cause instability!
|
||||||
#define Z_STEPPER_ALIGN_AMP 1.0
|
|
||||||
#endif
|
#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
|
// On a 300mm bed a 5% grade would give a misalignment of ~1.5cm
|
||||||
#define G34_MAX_GRADE 5 // (%) Maximum incline G34 will handle
|
#define G34_MAX_GRADE 5 // (%) Maximum incline that G34 will handle
|
||||||
|
#define Z_STEPPER_ALIGN_ITERATIONS 5 // Number of iterations to apply during alignment
|
||||||
// Stop criterion. If the accuracy is better than this stop iterating early
|
#define Z_STEPPER_ALIGN_ACC 0.02 // Stop iterating early if the accuracy is better than this
|
||||||
#define Z_STEPPER_ALIGN_ACC 0.02
|
#define RESTORE_LEVELING_AFTER_G34 // Restore leveling after G34 is done?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// @section motion
|
// @section motion
|
||||||
|
|
137
Marlin/src/feature/z_stepper_align.cpp
Normal file
137
Marlin/src/feature/z_stepper_align.cpp
Normal file
|
@ -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
Marlin/src/feature/z_stepper_align.h
Normal file
41
Marlin/src/feature/z_stepper_align.h
Normal file
|
@ -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;
|
|
@ -707,7 +707,7 @@ void GcodeSuite::G26() {
|
||||||
if (location.valid()) {
|
if (location.valid()) {
|
||||||
const xy_pos_t circle = _GET_MESH_POS(location.pos);
|
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;
|
if (!position_is_reachable(circle)) continue;
|
||||||
|
|
||||||
// Determine where to start and end the circle,
|
// Determine where to start and end the circle,
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
|
||||||
|
#include "../../feature/z_stepper_align.h"
|
||||||
|
|
||||||
#include "../gcode.h"
|
#include "../gcode.h"
|
||||||
#include "../../module/planner.h"
|
#include "../../module/planner.h"
|
||||||
#include "../../module/stepper.h"
|
#include "../../module/stepper.h"
|
||||||
|
@ -45,68 +47,6 @@
|
||||||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||||
#include "../../core/debug_out.h"
|
#include "../../core/debug_out.h"
|
||||||
|
|
||||||
//
|
|
||||||
// Sanity check G34 / M422 settings
|
|
||||||
//
|
|
||||||
constexpr xy_pos_t test_z_stepper_align_xy[] = Z_STEPPER_ALIGN_XY;
|
|
||||||
|
|
||||||
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
|
||||||
|
|
||||||
static_assert(COUNT(test_z_stepper_align_xy) >= NUM_Z_STEPPER_DRIVERS,
|
|
||||||
"Z_STEPPER_ALIGN_XY requires at least three {X,Y} entries (Z, Z2, Z3, ...)."
|
|
||||||
);
|
|
||||||
|
|
||||||
constexpr float test_z_stepper_align_stepper_xy[][XY] = Z_STEPPER_ALIGN_STEPPER_XY;
|
|
||||||
static_assert(
|
|
||||||
COUNT(test_z_stepper_align_stepper_xy) == NUM_Z_STEPPER_DRIVERS,
|
|
||||||
"Z_STEPPER_ALIGN_STEPPER_XY requires three {X,Y} entries (one per Z stepper)."
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static_assert(COUNT(test_z_stepper_align_xy) == NUM_Z_STEPPER_DRIVERS,
|
|
||||||
#if NUM_Z_STEPPER_DRIVERS == 4
|
|
||||||
"Z_STEPPER_ALIGN_XY requires four {X,Y} entries (Z, Z2, Z3, and Z4)."
|
|
||||||
#elif NUM_Z_STEPPER_DRIVERS == 3
|
|
||||||
"Z_STEPPER_ALIGN_XY requires three {X,Y} entries (Z, Z2, and Z3)."
|
|
||||||
#else
|
|
||||||
"Z_STEPPER_ALIGN_XY requires two {X,Y} entries (Z and Z2)."
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
constexpr xyz_pos_t dpo = NOZZLE_TO_PROBE_OFFSET;
|
|
||||||
|
|
||||||
#define LTEST(N) (test_z_stepper_align_xy[N].x >= _MAX(X_MIN_BED + MIN_PROBE_EDGE_LEFT, X_MIN_POS + dpo.x) - 0.00001f)
|
|
||||||
#define RTEST(N) (test_z_stepper_align_xy[N].x <= _MIN(X_MAX_BED - MIN_PROBE_EDGE_RIGHT, X_MAX_POS + dpo.x) + 0.00001f)
|
|
||||||
#define FTEST(N) (test_z_stepper_align_xy[N].y >= _MAX(Y_MIN_BED + MIN_PROBE_EDGE_FRONT, Y_MIN_POS + dpo.y) - 0.00001f)
|
|
||||||
#define BTEST(N) (test_z_stepper_align_xy[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
|
|
||||||
|
|
||||||
//
|
|
||||||
// G34 / M422 shared data
|
|
||||||
//
|
|
||||||
static xy_pos_t z_stepper_align_pos[] = Z_STEPPER_ALIGN_XY;
|
|
||||||
|
|
||||||
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
|
||||||
static xy_pos_t z_stepper_align_stepper_pos[] = Z_STEPPER_ALIGN_STEPPER_XY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define G34_PROBE_COUNT COUNT(z_stepper_align_pos)
|
|
||||||
|
|
||||||
inline void set_all_z_lock(const bool lock) {
|
inline void set_all_z_lock(const bool lock) {
|
||||||
stepper.set_z_lock(lock);
|
stepper.set_z_lock(lock);
|
||||||
stepper.set_z2_lock(lock);
|
stepper.set_z2_lock(lock);
|
||||||
|
@ -201,11 +141,11 @@ void GcodeSuite::G34() {
|
||||||
// iteration this will be re-calculated based on the actual bed position
|
// iteration this will be re-calculated based on the actual bed position
|
||||||
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * (
|
float z_probe = Z_BASIC_CLEARANCE + (G34_MAX_GRADE) * 0.01f * (
|
||||||
#if NUM_Z_STEPPER_DRIVERS == 3
|
#if NUM_Z_STEPPER_DRIVERS == 3
|
||||||
SQRT(_MAX(HYPOT2(z_stepper_align_pos[0].x - z_stepper_align_pos[0].y, z_stepper_align_pos[1].x - z_stepper_align_pos[1].y),
|
SQRT(_MAX(HYPOT2(z_stepper_align.xy[0].x - z_stepper_align.xy[0].y, z_stepper_align.xy[1].x - z_stepper_align.xy[1].y),
|
||||||
HYPOT2(z_stepper_align_pos[1].x - z_stepper_align_pos[1].y, z_stepper_align_pos[2].x - z_stepper_align_pos[2].y),
|
HYPOT2(z_stepper_align.xy[1].x - z_stepper_align.xy[1].y, z_stepper_align.xy[2].x - z_stepper_align.xy[2].y),
|
||||||
HYPOT2(z_stepper_align_pos[2].x - z_stepper_align_pos[2].y, z_stepper_align_pos[0].x - z_stepper_align_pos[0].y)))
|
HYPOT2(z_stepper_align.xy[2].x - z_stepper_align.xy[2].y, z_stepper_align.xy[0].x - z_stepper_align.xy[0].y)))
|
||||||
#else
|
#else
|
||||||
HYPOT(z_stepper_align_pos[0].x - z_stepper_align_pos[0].y, z_stepper_align_pos[1].x - z_stepper_align_pos[1].y)
|
HYPOT(z_stepper_align.xy[0].x - z_stepper_align.xy[0].y, z_stepper_align.xy[1].x - z_stepper_align.xy[1].y)
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -216,31 +156,39 @@ void GcodeSuite::G34() {
|
||||||
current_position.z -= z_probe * 0.5f;
|
current_position.z -= z_probe * 0.5f;
|
||||||
|
|
||||||
float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N(NUM_Z_STEPPER_DRIVERS, 10000.0f, 10000.0f, 10000.0f),
|
float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N(NUM_Z_STEPPER_DRIVERS, 10000.0f, 10000.0f, 10000.0f),
|
||||||
z_measured[G34_PROBE_COUNT] = { 0 },
|
z_measured[NUM_Z_STEPPER_DRIVERS] = { 0 },
|
||||||
z_maxdiff = 0.0f,
|
z_maxdiff = 0.0f,
|
||||||
amplification = z_auto_align_amplification;
|
amplification = z_auto_align_amplification;
|
||||||
|
|
||||||
uint8_t iteration;
|
uint8_t iteration;
|
||||||
bool err_break = false;
|
bool err_break = false;
|
||||||
|
|
||||||
|
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
|
bool adjustment_reverse = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (iteration = 0; iteration < z_auto_align_iterations; ++iteration) {
|
for (iteration = 0; iteration < z_auto_align_iterations; ++iteration) {
|
||||||
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> probing all positions.");
|
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> probing all positions.");
|
||||||
|
|
||||||
SERIAL_ECHOLNPAIR("\nITERATION: ", int(iteration + 1));
|
SERIAL_ECHOLNPAIR("\nITERATION: ", int(iteration + 1));
|
||||||
|
|
||||||
// Initialize minimum value
|
// Initialize minimum value
|
||||||
float z_measured_min = 100000.0f,
|
float z_measured_min = 100000.0f,
|
||||||
z_measured_max = -100000.0f;
|
z_measured_max = -100000.0f;
|
||||||
|
|
||||||
// Probe all positions (one per Z-Stepper)
|
// Probe all positions (one per Z-Stepper)
|
||||||
for (uint8_t i = 0; i < G34_PROBE_COUNT; ++i) {
|
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i) {
|
||||||
// iteration odd/even --> downward / upward stepper sequence
|
// iteration odd/even --> downward / upward stepper sequence
|
||||||
const uint8_t iprobe = (iteration & 1) ? G34_PROBE_COUNT - 1 - i : i;
|
const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPER_DRIVERS - 1 - i : i;
|
||||||
|
|
||||||
// Safe clearance even on an incline
|
// Safe clearance even on an incline
|
||||||
if (iteration == 0 || i > 0) do_blocking_move_to_z(z_probe);
|
if (iteration == 0 || i > 0) do_blocking_move_to_z(z_probe);
|
||||||
|
|
||||||
|
if (DEBUGGING(LEVELING))
|
||||||
|
DEBUG_ECHOLNPAIR_P(PSTR("Probing X"), z_stepper_align.xy[iprobe].x, SP_Y_STR, z_stepper_align.xy[iprobe].y);
|
||||||
|
|
||||||
// Probe a Z height for each stepper.
|
// Probe a Z height for each stepper.
|
||||||
const float z_probed_height = probe.probe_at_point(z_stepper_align_pos[iprobe], raise_after, 0, true);
|
const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true);
|
||||||
if (isnan(z_probed_height)) {
|
if (isnan(z_probed_height)) {
|
||||||
SERIAL_ECHOLNPGM("Probing failed.");
|
SERIAL_ECHOLNPGM("Probing failed.");
|
||||||
err_break = true;
|
err_break = true;
|
||||||
|
@ -279,15 +227,15 @@ void GcodeSuite::G34() {
|
||||||
// This allows the actual adjustment logic to be shared by both algorithms.
|
// This allows the actual adjustment logic to be shared by both algorithms.
|
||||||
linear_fit_data lfd;
|
linear_fit_data lfd;
|
||||||
incremental_LSF_reset(&lfd);
|
incremental_LSF_reset(&lfd);
|
||||||
for (uint8_t i = 0; i < G34_PROBE_COUNT; ++i) {
|
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i) {
|
||||||
SERIAL_ECHOLNPAIR("PROBEPT_", int(i + 1), ": ", z_measured[i]);
|
SERIAL_ECHOLNPAIR("PROBEPT_", i + '1', ": ", z_measured[i]);
|
||||||
incremental_LSF(&lfd, z_stepper_align_pos[i], z_measured[i]);
|
incremental_LSF(&lfd, z_stepper_align.xy[i], z_measured[i]);
|
||||||
}
|
}
|
||||||
finish_incremental_LSF(&lfd);
|
finish_incremental_LSF(&lfd);
|
||||||
|
|
||||||
z_measured_min = 100000.0f;
|
z_measured_min = 100000.0f;
|
||||||
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i) {
|
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i) {
|
||||||
z_measured[i] = -(lfd.A * z_stepper_align_stepper_pos[i].x + lfd.B * z_stepper_align_stepper_pos[i].y);
|
z_measured[i] = -(lfd.A * z_stepper_align.stepper_xy[i].x + lfd.B * z_stepper_align.stepper_xy[i].y);
|
||||||
z_measured_min = _MIN(z_measured_min, z_measured[i]);
|
z_measured_min = _MIN(z_measured_min, z_measured[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,8 +257,8 @@ void GcodeSuite::G34() {
|
||||||
// Correct the individual stepper offsets
|
// Correct the individual stepper offsets
|
||||||
for (uint8_t zstepper = 0; zstepper < NUM_Z_STEPPER_DRIVERS; ++zstepper) {
|
for (uint8_t zstepper = 0; zstepper < NUM_Z_STEPPER_DRIVERS; ++zstepper) {
|
||||||
// Calculate current stepper move
|
// Calculate current stepper move
|
||||||
const float z_align_move = z_measured[zstepper] - z_measured_min,
|
float z_align_move = z_measured[zstepper] - z_measured_min;
|
||||||
z_align_abs = ABS(z_align_move);
|
const float z_align_abs = ABS(z_align_move);
|
||||||
|
|
||||||
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
// Optimize one iteration's correction based on the first measurements
|
// Optimize one iteration's correction based on the first measurements
|
||||||
|
@ -318,10 +266,14 @@ void GcodeSuite::G34() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check for less accuracy compared to last move
|
// Check for less accuracy compared to last move
|
||||||
if (last_z_align_move[zstepper] < z_align_abs - 1.0) {
|
if (last_z_align_move[zstepper] < z_align_abs * 0.7f) {
|
||||||
SERIAL_ECHOLNPGM("Decreasing accuracy detected.");
|
SERIAL_ECHOLNPGM("Decreasing accuracy detected.");
|
||||||
err_break = true;
|
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
break;
|
adjustment_reverse = !adjustment_reverse;
|
||||||
|
#else
|
||||||
|
err_break = true;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the alignment for the next iteration
|
// Remember the alignment for the next iteration
|
||||||
|
@ -342,6 +294,13 @@ void GcodeSuite::G34() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DISABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
|
// Decreasing accuracy was detected so move was inverted.
|
||||||
|
// Will match reversed Z steppers on dual steppers. Triple will need more work to map.
|
||||||
|
if (adjustment_reverse)
|
||||||
|
z_align_move = -z_align_move;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Do a move to correct part of the misalignment for the current stepper
|
// Do a move to correct part of the misalignment for the current stepper
|
||||||
do_blocking_move_to_z(amplification * z_align_move + current_position.z);
|
do_blocking_move_to_z(amplification * z_align_move + current_position.z);
|
||||||
} // for (zstepper)
|
} // for (zstepper)
|
||||||
|
@ -406,12 +365,13 @@ void GcodeSuite::G34() {
|
||||||
* Y<pos> : Y position to set (Unchanged if omitted)
|
* Y<pos> : Y position to set (Unchanged if omitted)
|
||||||
*/
|
*/
|
||||||
void GcodeSuite::M422() {
|
void GcodeSuite::M422() {
|
||||||
|
|
||||||
if (!parser.seen_any()) {
|
if (!parser.seen_any()) {
|
||||||
for (uint8_t i = 0; i < G34_PROBE_COUNT; ++i)
|
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i)
|
||||||
SERIAL_ECHOLNPAIR_P(PSTR("M422 S"), i + 1, SP_X_STR, z_stepper_align_pos[i].x, SP_Y_STR, z_stepper_align_pos[i].y);
|
SERIAL_ECHOLNPAIR_P(PSTR("M422 S"), i + '1', SP_X_STR, z_stepper_align.xy[i].x, SP_Y_STR, z_stepper_align.xy[i].y);
|
||||||
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i)
|
for (uint8_t i = 0; i < NUM_Z_STEPPER_DRIVERS; ++i)
|
||||||
SERIAL_ECHOLNPAIR_P(PSTR("M422 W"), i + 1, SP_X_STR, z_stepper_align_stepper_pos[i].x, SP_Y_STR, z_stepper_align_stepper_pos[i].y);
|
SERIAL_ECHOLNPAIR_P(PSTR("M422 W"), i + '1', SP_X_STR, z_stepper_align.stepper_xy[i].x, SP_Y_STR, z_stepper_align.stepper_xy[i].y);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -427,9 +387,9 @@ void GcodeSuite::M422() {
|
||||||
|
|
||||||
xy_pos_t *pos_dest = (
|
xy_pos_t *pos_dest = (
|
||||||
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
!is_probe_point ? z_stepper_align_stepper_pos :
|
!is_probe_point ? z_stepper_align.stepper_xy :
|
||||||
#endif
|
#endif
|
||||||
z_stepper_align_pos
|
z_stepper_align.xy
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!is_probe_point
|
if (!is_probe_point
|
||||||
|
@ -451,7 +411,7 @@ void GcodeSuite::M422() {
|
||||||
int8_t position_index;
|
int8_t position_index;
|
||||||
if (is_probe_point) {
|
if (is_probe_point) {
|
||||||
position_index = parser.intval('S') - 1;
|
position_index = parser.intval('S') - 1;
|
||||||
if (!WITHIN(position_index, 0, int8_t(G34_PROBE_COUNT) - 1)) {
|
if (!WITHIN(position_index, 0, int8_t(NUM_Z_STEPPER_DRIVERS) - 1)) {
|
||||||
SERIAL_ECHOLNPGM("?(S) Z-ProbePosition index invalid.");
|
SERIAL_ECHOLNPGM("?(S) Z-ProbePosition index invalid.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Change EEPROM version if the structure changes
|
// Change EEPROM version if the structure changes
|
||||||
#define EEPROM_VERSION "V75"
|
#define EEPROM_VERSION "V76"
|
||||||
#define EEPROM_OFFSET 100
|
#define EEPROM_OFFSET 100
|
||||||
|
|
||||||
// Check the integrity of data offsets.
|
// Check the integrity of data offsets.
|
||||||
|
@ -66,6 +66,10 @@
|
||||||
#include "../feature/bedlevel/bedlevel.h"
|
#include "../feature/bedlevel/bedlevel.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
#include "../feature/z_stepper_align.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(EXTENSIBLE_UI)
|
#if ENABLED(EXTENSIBLE_UI)
|
||||||
#include "../lcd/extensible_ui/ui_api.h"
|
#include "../lcd/extensible_ui/ui_api.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -251,6 +255,16 @@ typedef struct SettingsDataStruct {
|
||||||
z4_endstop_adj; // M666 (S4) Z
|
z4_endstop_adj; // M666 (S4) Z
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Z_STEPPER_AUTO_ALIGN, Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS
|
||||||
|
//
|
||||||
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
xy_pos_t z_stepper_align_xy[NUM_Z_STEPPER_DRIVERS]; // M422 S X Y
|
||||||
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
|
xy_pos_t z_stepper_align_stepper_xy[NUM_Z_STEPPER_DRIVERS]; // M422 W X Y
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// ULTIPANEL
|
// ULTIPANEL
|
||||||
//
|
//
|
||||||
|
@ -801,6 +815,13 @@ void MarlinSettings::postprocess() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
EEPROM_WRITE(z_stepper_align.xy);
|
||||||
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
|
EEPROM_WRITE(z_stepper_align.stepper_xy);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// LCD Preheat settings
|
// LCD Preheat settings
|
||||||
//
|
//
|
||||||
|
@ -1669,6 +1690,13 @@ void MarlinSettings::postprocess() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
EEPROM_READ(z_stepper_align.xy);
|
||||||
|
#if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||||
|
EEPROM_READ(z_stepper_align.stepper_xy);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// LCD Preheat settings
|
// LCD Preheat settings
|
||||||
//
|
//
|
||||||
|
@ -2473,6 +2501,14 @@ void MarlinSettings::reset() {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Z Stepper Auto-alignment points
|
||||||
|
//
|
||||||
|
|
||||||
|
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
|
||||||
|
z_stepper_align.reset_to_default();
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Servo Angles
|
// Servo Angles
|
||||||
//
|
//
|
||||||
|
|
Reference in a new issue