mirror of
https://github.com/MarlinFirmware/Marlin.git
synced 2026-03-05 09:34:47 -07:00
Merge 19f0f07d76 into b553c0e62a
This commit is contained in:
commit
d7d3ffd6ad
16 changed files with 528 additions and 137 deletions
|
|
@ -1120,7 +1120,7 @@
|
|||
//#define ASSISTED_TRAMMING
|
||||
#if ENABLED(ASSISTED_TRAMMING)
|
||||
|
||||
// Define from 3 to 9 points to probe.
|
||||
// Define from 3 to 9 points to probe. Overwritten by "DYNAMIC_MARGINS" if "DYNAMIC_TRAMMING" is enabled.
|
||||
#define TRAMMING_POINT_XY { { 20, 20 }, { 180, 20 }, { 180, 180 }, { 20, 180 } }
|
||||
|
||||
// Define position names for probe points.
|
||||
|
|
@ -2530,12 +2530,34 @@
|
|||
* should the probe position be modified with M851XY then the
|
||||
* probe points will follow. This prevents any change from causing
|
||||
* the probe to be unable to reach any points.
|
||||
*
|
||||
* If you enable DYNAMIC_MARGINS PROBING_MARGINs are changeable without recompilation.
|
||||
* They are then bedlevel.margin_l, bedlevel.margin_r, bedlevel.margin_f, bedlevel.margin_b
|
||||
* and can be overwritten with "M421 L50 R50 F50 B50" for a 50mm margin around the bed
|
||||
* and saved to the EEPROM on runtime. Default values underneath.
|
||||
* Setting manually via gcode respects probe_offsets and the min and max positions
|
||||
* and recalculates if a too low value is set so the probed area is valid.
|
||||
*
|
||||
* DYNAMIC_MARGINS can be also enabled to be used for the ASSISTED_TRAMMING points with
|
||||
* #define DYNAMIC_TRAMMING
|
||||
*
|
||||
*/
|
||||
#if PROBE_SELECTED && !IS_KINEMATIC
|
||||
//#define PROBING_MARGIN_LEFT PROBING_MARGIN
|
||||
//#define PROBING_MARGIN_RIGHT PROBING_MARGIN
|
||||
//#define PROBING_MARGIN_FRONT PROBING_MARGIN
|
||||
//#define PROBING_MARGIN_BACK PROBING_MARGIN
|
||||
//#define DYNAMIC_MARGINS
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
#if ENABLED(ASSISTED_TRAMMING)
|
||||
//#define DYNAMIC_TRAMMING
|
||||
#endif
|
||||
#define PROBING_MARGIN_LEFT 45
|
||||
#define PROBING_MARGIN_RIGHT 45
|
||||
#define PROBING_MARGIN_FRONT 45
|
||||
#define PROBING_MARGIN_BACK 45
|
||||
#else
|
||||
#define PROBING_MARGIN_LEFT PROBING_MARGIN
|
||||
#define PROBING_MARGIN_RIGHT PROBING_MARGIN
|
||||
#define PROBING_MARGIN_FRONT PROBING_MARGIN
|
||||
#define PROBING_MARGIN_BACK PROBING_MARGIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ xy_float_t LevelingBilinear::grid_factor;
|
|||
bed_mesh_t LevelingBilinear::z_values;
|
||||
xy_pos_t LevelingBilinear::cached_rel;
|
||||
xy_int8_t LevelingBilinear::cached_g;
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
int16_t LevelingBilinear::margin_l, LevelingBilinear::margin_r, LevelingBilinear::margin_f, LevelingBilinear::margin_b;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Extrapolate a single point from its neighbors
|
||||
|
|
|
|||
|
|
@ -22,11 +22,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
#include "../../../feature/bedlevel/bedlevel.h"
|
||||
#endif
|
||||
|
||||
class LevelingBilinear {
|
||||
public:
|
||||
static bed_mesh_t z_values;
|
||||
static xy_pos_t grid_spacing, grid_start;
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static int16_t margin_l, margin_r, margin_f, margin_b;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static xy_float_t grid_factor;
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt
|
|||
*/
|
||||
bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
|
||||
// Find closest grid intersection
|
||||
const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
|
||||
const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
|
||||
const uint8_t grid_x = LROUND(constrain(float(pos.x - (TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X))) / (TERN(DYNAMIC_MARGINS, bedlevel.get_mesh_x_dist(), MESH_X_DIST)), 0, (GRID_MAX_POINTS_X) - 1));
|
||||
const uint8_t grid_y = LROUND(constrain(float(pos.y - (TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y))) / (TERN(DYNAMIC_MARGINS, bedlevel.get_mesh_y_dist(), MESH_Y_DIST)), 0, (GRID_MAX_POINTS_Y) - 1));
|
||||
return search_from(grid_x, grid_y, func, data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,22 +64,26 @@ void unified_bed_leveling::report_state() {
|
|||
int8_t unified_bed_leveling::storage_slot;
|
||||
|
||||
float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
int16_t unified_bed_leveling::margin_l, unified_bed_leveling::margin_r, unified_bed_leveling::margin_f, unified_bed_leveling::margin_b;
|
||||
#endif
|
||||
|
||||
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
|
||||
|
||||
const float
|
||||
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
|
||||
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
|
||||
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
|
||||
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
|
||||
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
|
||||
),
|
||||
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
|
||||
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
|
||||
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
|
||||
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
|
||||
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
|
||||
);
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
const float
|
||||
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
|
||||
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
|
||||
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
|
||||
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
|
||||
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
|
||||
),
|
||||
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
|
||||
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
|
||||
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
|
||||
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
|
||||
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
|
||||
);
|
||||
#endif
|
||||
|
||||
volatile int16_t unified_bed_leveling::encoder_diff;
|
||||
|
||||
|
|
@ -173,8 +177,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
|
|||
SERIAL_ECHOPGM("\nBed Topography Report");
|
||||
if (human) {
|
||||
SERIAL_ECHOLNPGM(":\n");
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
|
||||
serial_echo_xy(4, (TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X)), (TERN(DYNAMIC_MARGINS, (Y_BED_SIZE - unified_bed_leveling::margin_f), MESH_MAX_Y)));
|
||||
serial_echo_xy(twixt, (TERN(DYNAMIC_MARGINS, (X_BED_SIZE - unified_bed_leveling::margin_r), MESH_MAX_X)), (TERN(DYNAMIC_MARGINS, (Y_BED_SIZE - unified_bed_leveling::margin_f), MESH_MAX_Y)));
|
||||
SERIAL_EOL();
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
}
|
||||
|
|
@ -231,8 +235,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
|
|||
if (human) {
|
||||
serial_echo_column_labels(eachsp - 2);
|
||||
SERIAL_EOL();
|
||||
serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
|
||||
serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
|
||||
serial_echo_xy(4, (TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X)), (TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_Y)));
|
||||
serial_echo_xy(twixt, (TERN(DYNAMIC_MARGINS, (X_BED_SIZE - unified_bed_leveling::margin_r), MESH_MAX_X)), (TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_Y)));
|
||||
SERIAL_EOL();
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
#include "../../../core/debug_out.h"
|
||||
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
class unified_bed_leveling;
|
||||
extern unified_bed_leveling bedlevel;
|
||||
#endif
|
||||
#define UBL_VERSION "1.01"
|
||||
#define UBL_OK false
|
||||
#define UBL_ERR true
|
||||
|
|
@ -37,9 +41,10 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP, CLOSEST };
|
|||
// External references
|
||||
|
||||
struct mesh_index_pair;
|
||||
|
||||
#define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
|
||||
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
#define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
|
||||
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
|
||||
#endif
|
||||
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
||||
|
|
@ -110,14 +115,20 @@ public:
|
|||
static void smart_fill_wlsf(const float ) __O2; // O2 gives smaller code than Os on A2560
|
||||
|
||||
static int8_t storage_slot;
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
typedef float bed_mesh_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
||||
static int16_t margin_l, margin_r, margin_f, margin_b;
|
||||
#endif
|
||||
|
||||
static bed_mesh_t z_values;
|
||||
#if ENABLED(OPTIMIZED_MESH_STORAGE)
|
||||
static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
|
||||
static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
|
||||
#endif
|
||||
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
|
||||
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
|
||||
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
|
||||
#endif
|
||||
|
||||
#if HAS_MARLINUI_MENU
|
||||
static bool lcd_map_control;
|
||||
|
|
@ -133,12 +144,12 @@ public:
|
|||
FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float z) { z_values[px][py] = z; }
|
||||
|
||||
static int8_t cell_index_x_raw(const float x) {
|
||||
return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST));
|
||||
return FLOOR((x - (TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X))) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST)));
|
||||
}
|
||||
|
||||
static int8_t cell_index_y_raw(const float y) {
|
||||
return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST));
|
||||
}
|
||||
return FLOOR((y - (TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y))) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)));
|
||||
}
|
||||
|
||||
static bool cell_index_x_valid(const float x) {
|
||||
return WITHIN(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1);
|
||||
|
|
@ -162,11 +173,11 @@ public:
|
|||
static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
|
||||
|
||||
static int8_t closest_x_index(const float x) {
|
||||
const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
|
||||
const int8_t px = (x - (TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X)) + (TERN(DYNAMIC_MARGINS, get_mesh_x_dist(), MESH_X_DIST)) * 0.5) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST));
|
||||
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
|
||||
}
|
||||
static int8_t closest_y_index(const float y) {
|
||||
const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
|
||||
const int8_t py = (y - (TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y)) + (TERN(DYNAMIC_MARGINS, get_mesh_y_dist(), MESH_Y_DIST)) * 0.5) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST));
|
||||
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
|
||||
}
|
||||
static xy_int8_t closest_indexes(const xy_pos_t &xy) {
|
||||
|
|
@ -214,7 +225,7 @@ public:
|
|||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
|
||||
const float xratio = (rx0 - get_mesh_x(x1_i)) * RECIPROCAL(MESH_X_DIST),
|
||||
const float xratio = (rx0 - get_mesh_x(x1_i)) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST)),
|
||||
z1 = z_values[x1_i][yi];
|
||||
|
||||
return z1 + xratio * (z_values[_MIN(x1_i, (GRID_MAX_POINTS_X) - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
|
||||
|
|
@ -237,7 +248,7 @@ public:
|
|||
return _UBL_OUTER_Z_RAISE;
|
||||
}
|
||||
|
||||
const float yratio = (ry0 - get_mesh_y(y1_i)) * RECIPROCAL(MESH_Y_DIST),
|
||||
const float yratio = (ry0 - get_mesh_y(y1_i)) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)),
|
||||
z1 = z_values[xi][y1_i];
|
||||
|
||||
return z1 + yratio * (z_values[xi][_MIN(y1_i, (GRID_MAX_POINTS_Y) - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
|
||||
|
|
@ -259,12 +270,12 @@ public:
|
|||
* UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned.
|
||||
*/
|
||||
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH
|
||||
if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y))
|
||||
if (!WITHIN(rx0, TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X), TERN(DYNAMIC_MARGINS, X_BED_SIZE - bedlevel.margin_r, MESH_MAX_X)) || !WITHIN(ry0, TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y), TERN(DYNAMIC_MARGINS, Y_BED_SIZE - bedlevel.margin_b, MESH_MAX_Y)))
|
||||
return UBL_Z_RAISE_WHEN_OFF_MESH;
|
||||
#endif
|
||||
|
||||
const uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1;
|
||||
const float x0 = get_mesh_x(cx), x1 = get_mesh_x(cx + 1),
|
||||
IF_DISABLED(DYNAMIC_MARGINS, const) uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1;
|
||||
IF_DISABLED(DYNAMIC_MARGINS, const) float x0 = get_mesh_x(cx), x1 = get_mesh_x(cx + 1),
|
||||
z1 = calc_z0(rx0, x0, z_values[cx][cy], x1, z_values[mx][cy]),
|
||||
z2 = calc_z0(rx0, x0, z_values[cx][my], x1, z_values[mx][my]);
|
||||
float z0 = calc_z0(ry0, get_mesh_y(cy), z1, get_mesh_y(cy + 1), z2);
|
||||
|
|
@ -286,13 +297,28 @@ public:
|
|||
static float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
|
||||
|
||||
static constexpr float get_z_offset() { return 0.0f; }
|
||||
|
||||
static float get_mesh_x(const uint8_t i) {
|
||||
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
|
||||
}
|
||||
static float get_mesh_y(const uint8_t i) {
|
||||
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
|
||||
}
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
static float get_mesh_x(const uint8_t i) {
|
||||
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
|
||||
}
|
||||
static float get_mesh_y(const uint8_t i) {
|
||||
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
|
||||
}
|
||||
#endif
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static float get_mesh_x(const uint8_t i) {
|
||||
return bedlevel.margin_l + i * get_mesh_x_dist();
|
||||
}
|
||||
static float get_mesh_y(const uint8_t i) {
|
||||
return bedlevel.margin_f + i * get_mesh_y_dist();
|
||||
}
|
||||
static float get_mesh_x_dist() {
|
||||
return float((X_BED_SIZE - bedlevel.margin_r) - bedlevel.margin_l) / (GRID_MAX_POINTS_X - 1);
|
||||
}
|
||||
static float get_mesh_y_dist() {
|
||||
return float((Y_BED_SIZE - bedlevel.margin_b) - bedlevel.margin_f) / (GRID_MAX_POINTS_Y - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UBL_SEGMENTED
|
||||
static bool line_to_destination_segmented(const feedRate_t scaled_fr_mm_s);
|
||||
|
|
@ -307,7 +333,9 @@ public:
|
|||
|
||||
}; // class unified_bed_leveling
|
||||
|
||||
extern unified_bed_leveling bedlevel;
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
extern unified_bed_leveling bedlevel;
|
||||
#endif
|
||||
|
||||
// Prevent debugging propagating to other files
|
||||
#include "../../../core/debug_out.h"
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ void unified_bed_leveling::G29() {
|
|||
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
|
||||
restore_ubl_active_state();
|
||||
#if ENABLED(UBL_G29_J_RECENTER)
|
||||
motion.blocking_move_xy(0.5f * ((MESH_MIN_X) + (MESH_MAX_X)), 0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y)));
|
||||
motion.blocking_move_xy(0.5f * ((TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X)) + (TERN(DYNAMIC_MARGINS, X_BED_SIZE - bedlevel.margin_r, MESH_MAX_X))), 0.5f * ((TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y)) + (TERN(DYNAMIC_MARGINS, Y_BED_SIZE - bedlevel.margin_b, MESH_MAX_Y))));
|
||||
#endif
|
||||
motion.report_position();
|
||||
SET_PROBE_DEPLOYED(true);
|
||||
|
|
@ -828,8 +828,8 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) {
|
|||
probe.move_z_after_probing();
|
||||
|
||||
motion.blocking_move_xy(
|
||||
constrain(nearby.x - probe.offset_xy.x, MESH_MIN_X, MESH_MAX_X),
|
||||
constrain(nearby.y - probe.offset_xy.y, MESH_MIN_Y, MESH_MAX_Y)
|
||||
constrain(TERN(DYNAMIC_MARGINS, nearby.x, nearby.x - probe.offset_xy.x), TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X), (TERN(DYNAMIC_MARGINS, (X_BED_SIZE - bedlevel.margin_r), MESH_MAX_X))),
|
||||
constrain(TERN(DYNAMIC_MARGINS, nearby.y, nearby.y - probe.offset_xy.y), TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y), (TERN(DYNAMIC_MARGINS, (Y_BED_SIZE - bedlevel.margin_b), MESH_MAX_Y)))
|
||||
);
|
||||
|
||||
restore_ubl_active_state();
|
||||
|
|
@ -895,8 +895,8 @@ void set_message_with_feedback(FSTR_P const fstr) {
|
|||
|
||||
motion.blocking_move(
|
||||
xyz_pos_t({
|
||||
0.5f * ((MESH_MIN_X) + (MESH_MAX_X)),
|
||||
0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y)),
|
||||
0.5f * ((TERN(DYNAMIC_MARGINS, (X_BED_SIZE - unified_bed_leveling::margin_r), MESH_MAX_X)) - TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X)),
|
||||
0.5f * ((TERN(DYNAMIC_MARGINS, (Y_BED_SIZE - unified_bed_leveling::margin_b), MESH_MAX_Y)) - TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_f, MESH_MIN_Y)),
|
||||
MANUAL_PROBE_START_Z
|
||||
#ifdef SAFE_BED_LEVELING_START_I
|
||||
, SAFE_BED_LEVELING_START_I
|
||||
|
|
@ -1392,7 +1392,7 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh
|
|||
float best_so_far = 99999.99f;
|
||||
|
||||
GRID_LOOP(i, j) {
|
||||
if ( type == CLOSEST || type == (isnan(z_values[i][j]) ? INVALID : REAL)
|
||||
if (type == CLOSEST || type == (isnan(z_values[i][j]) ? INVALID : REAL)
|
||||
|| (type == SET_IN_BITMAP && !done_flags->marked(i, j))
|
||||
) {
|
||||
// Found a Mesh Point of the specified type!
|
||||
|
|
@ -1535,10 +1535,10 @@ void unified_bed_leveling::smart_fill_mesh() {
|
|||
#ifndef G29J_MESH_TILT_MARGIN
|
||||
#define G29J_MESH_TILT_MARGIN 0
|
||||
#endif
|
||||
const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_X, probe.min_x()),
|
||||
x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_X, probe.max_x()),
|
||||
y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_Y, probe.min_y()),
|
||||
y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_Y, probe.max_y()),
|
||||
const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X), probe.min_x()),
|
||||
x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), TERN(DYNAMIC_MARGINS, (X_BED_SIZE - unified_bed_leveling::margin_r), MESH_MAX_X), probe.max_x()),
|
||||
y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_f, MESH_MIN_Y), probe.min_y()),
|
||||
y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), TERN(DYNAMIC_MARGINS, (Y_BED_SIZE - unified_bed_leveling::margin_b), MESH_MAX_Y), probe.max_y()),
|
||||
dx = (x_max - x_min) / (param.J_grid_size - 1),
|
||||
dy = (y_max - y_min) / (param.J_grid_size - 1);
|
||||
|
||||
|
|
@ -1696,7 +1696,7 @@ void unified_bed_leveling::smart_fill_mesh() {
|
|||
|
||||
SERIAL_ECHOPGM("Extrapolating mesh...");
|
||||
|
||||
const float weight_scaled = weight_factor * _MAX(MESH_X_DIST, MESH_Y_DIST);
|
||||
const float weight_scaled = weight_factor * _MAX(TERN(DYNAMIC_MARGINS, unified_bed_leveling::get_mesh_x_dist(), MESH_X_DIST), TERN(DYNAMIC_MARGINS, unified_bed_leveling::get_mesh_y_dist(), MESH_Y_DIST));
|
||||
|
||||
GRID_LOOP(jx, jy) if (!isnan(z_values[jx][jy])) SBI(bitmap[jx], jy);
|
||||
|
||||
|
|
@ -1760,14 +1760,14 @@ void unified_bed_leveling::smart_fill_mesh() {
|
|||
SERIAL_ECHOLNPGM("Probe Offset M851 Z", p_float_t(probe.offset.z, 7));
|
||||
#endif
|
||||
|
||||
SERIAL_ECHOLNPGM("MESH_MIN_X " STRINGIFY(MESH_MIN_X) "=", MESH_MIN_X); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MIN_Y " STRINGIFY(MESH_MIN_Y) "=", MESH_MIN_Y); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MAX_X " STRINGIFY(MESH_MAX_X) "=", MESH_MAX_X); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MAX_Y " STRINGIFY(MESH_MAX_Y) "=", MESH_MAX_Y); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_X_DIST ", MESH_X_DIST);
|
||||
SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MIN_X " STRINGIFY(TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X)) "=", TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_l, MESH_MIN_X)); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MIN_Y " STRINGIFY(TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_f, MESH_MIN_Y)) "=", TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_f, MESH_MIN_Y)); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MAX_X " STRINGIFY(TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_r, MESH_MAX_X)) "=", TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_r, MESH_MAX_X)); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_MAX_Y " STRINGIFY(TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_b, MESH_MAX_Y)) "=", TERN(DYNAMIC_MARGINS, unified_bed_leveling::margin_b, MESH_MAX_Y)); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_X_DIST ", TERN(DYNAMIC_MARGINS, unified_bed_leveling::mesh_x_dist(), MESH_X_DIST)); serial_delay(50);
|
||||
SERIAL_ECHOLNPGM("MESH_Y_DIST ", TERN(DYNAMIC_MARGINS, unified_bed_leveling::mesh_y_dist(), MESH_Y_DIST)); serial_delay(50);
|
||||
|
||||
SERIAL_ECHOPGM("X-Axis Mesh Points at: ");
|
||||
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) {
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@
|
|||
#endif
|
||||
|
||||
// The distance is always MESH_X_DIST so multiply by the constant reciprocal.
|
||||
const float xratio = (end.x - get_mesh_x(iend.x)) * RECIPROCAL(MESH_X_DIST),
|
||||
yratio = (end.y - get_mesh_y(iend.y)) * RECIPROCAL(MESH_Y_DIST),
|
||||
const float xratio = (end.x - get_mesh_x(iend.x)) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST));
|
||||
const float yratio = (end.y - get_mesh_y(iend.y)) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)),
|
||||
z1 = z_values[iend.x][iend.y ] + xratio * (z_values[iend.x + 1][iend.y ] - z_values[iend.x][iend.y ]),
|
||||
z2 = z_values[iend.x][iend.y + 1] + xratio * (z_values[iend.x + 1][iend.y + 1] - z_values[iend.x][iend.y + 1]);
|
||||
|
||||
|
|
@ -414,8 +414,8 @@
|
|||
// for mesh inset area.
|
||||
|
||||
xy_int8_t icell = {
|
||||
int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)),
|
||||
int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST))
|
||||
int8_t((raw.x - (TERN(DYNAMIC_MARGINS, bedlevel.margin_l, MESH_MIN_X))) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST))),
|
||||
int8_t((raw.y - (TERN(DYNAMIC_MARGINS, bedlevel.margin_f, MESH_MIN_Y))) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)))
|
||||
};
|
||||
LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
|
||||
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
|
||||
|
|
@ -435,15 +435,15 @@
|
|||
const xy_pos_t pos = { get_mesh_x(icell.x), get_mesh_y(icell.y) };
|
||||
xy_pos_t cell = raw - pos;
|
||||
|
||||
const float z_xmy0 = (z_x1y0 - z_x0y0) * RECIPROCAL(MESH_X_DIST), // z slope per x along y0 (lower left to lower right)
|
||||
z_xmy1 = (z_x1y1 - z_x0y1) * RECIPROCAL(MESH_X_DIST); // z slope per x along y1 (upper left to upper right)
|
||||
const float z_xmy0 = (z_x1y0 - z_x0y0) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST)); // z slope per x along y0 (lower left to lower right)
|
||||
const float z_xmy1 = (z_x1y1 - z_x0y1) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_x_dist()), RECIPROCAL(MESH_X_DIST)); // z slope per x along y1 (upper left to upper right)
|
||||
|
||||
float z_cxy0 = z_x0y0 + z_xmy0 * cell.x; // z height along y0 at cell.x (changes for each cell.x in cell)
|
||||
|
||||
const float z_cxy1 = z_x0y1 + z_xmy1 * cell.x, // z height along y1 at cell.x
|
||||
z_cxyd = z_cxy1 - z_cxy0; // z height difference along cell.x from y0 to y1
|
||||
|
||||
float z_cxym = z_cxyd * RECIPROCAL(MESH_Y_DIST); // z slope per y along cell.x from pos.y to y1 (changes for each cell.x in cell)
|
||||
float z_cxym = z_cxyd * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)); // z slope per y along cell.x from pos.y to y1 (changes for each cell.x in cell)
|
||||
|
||||
// float z_cxcy = z_cxy0 + z_cxym * cell.y; // interpolated mesh z height along cell.x at cell.y (do inside the segment loop)
|
||||
|
||||
|
|
@ -451,8 +451,8 @@
|
|||
// and the z_cxym slope will change, both as a function of cell.x within the cell, and
|
||||
// each change by a constant for fixed segment lengths.
|
||||
|
||||
const float z_sxy0 = z_xmy0 * diff.x, // per-segment adjustment to z_cxy0
|
||||
z_sxym = (z_xmy1 - z_xmy0) * RECIPROCAL(MESH_Y_DIST) * diff.x; // per-segment adjustment to z_cxym
|
||||
const float z_sxy0 = z_xmy0 * diff.x; // per-segment adjustment to z_cxy0
|
||||
const float z_sxym = (z_xmy1 - z_xmy0) * TERN(DYNAMIC_MARGINS, RECIPROCAL(get_mesh_y_dist()), RECIPROCAL(MESH_Y_DIST)) * diff.x; // per-segment adjustment to z_cxym
|
||||
|
||||
for (;;) { // for all segments within this mesh cell
|
||||
|
||||
|
|
@ -471,7 +471,7 @@
|
|||
raw += diff;
|
||||
cell += diff;
|
||||
|
||||
if (!WITHIN(cell.x, 0, MESH_X_DIST) || !WITHIN(cell.y, 0, MESH_Y_DIST)) // done within this cell, break to next
|
||||
if (!WITHIN(cell.x, 0, TERN(DYNAMIC_MARGINS, get_mesh_x_dist(), MESH_X_DIST)) || !WITHIN(cell.y, 0, TERN(DYNAMIC_MARGINS, get_mesh_y_dist(), MESH_Y_DIST))) // done within this cell, break to next
|
||||
break;
|
||||
|
||||
// Next segment still within same mesh cell, adjust the per-segment
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
#include "../core/debug_out.h"
|
||||
|
||||
#if ALL(DYNAMIC_MARGINS, DYNAMIC_TRAMMING)
|
||||
xy_pos_t tramming_points[] = TRAMMING_POINT_XY;
|
||||
#endif
|
||||
#define _TRAM_NAME_DEF(N) PGMSTR(point_name_##N, TRAMMING_POINT_NAME_##N);
|
||||
#define _TRAM_NAME_ITEM(N) point_name_##N
|
||||
REPEAT_1(_NR_TRAM_NAMES, _TRAM_NAME_DEF)
|
||||
|
|
|
|||
|
|
@ -35,9 +35,13 @@ static_assert(
|
|||
"TRAMMING_SCREW_THREAD must be M3_CW, M3_CCW, M4_CW, M4_CCW, M5_CW, or M5_CCW."
|
||||
);
|
||||
|
||||
constexpr xy_pos_t tramming_points[] = TRAMMING_POINT_XY;
|
||||
|
||||
#define G35_PROBE_COUNT COUNT(tramming_points)
|
||||
#if ALL(DYNAMIC_MARGINS, DYNAMIC_TRAMMING)
|
||||
#define G35_PROBE_COUNT 4
|
||||
extern xy_pos_t tramming_points[];
|
||||
#else
|
||||
#define G35_PROBE_COUNT COUNT(tramming_points)
|
||||
constexpr xy_pos_t tramming_points[] = TRAMMING_POINT_XY;
|
||||
#endif
|
||||
static_assert(WITHIN(G35_PROBE_COUNT, 3, 9), "TRAMMING_POINT_XY requires between 3 and 9 XY positions.");
|
||||
|
||||
#ifdef TRAMMING_POINT_NAME_9
|
||||
|
|
@ -63,9 +67,11 @@ static_assert(_NR_TRAM_NAMES >= G35_PROBE_COUNT, "Define enough TRAMMING_POINT_N
|
|||
#define _TRAM_NAME_PTR(N) point_name_##N[]
|
||||
extern const char REPLIST_1(_NR_TRAM_NAMES, _TRAM_NAME_PTR);
|
||||
|
||||
#define _CHECK_TRAM_POINT(N) static_assert(Probe::build_time::can_reach(tramming_points[N]), "TRAMMING_POINT_XY point " STRINGIFY(N) " is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.");
|
||||
REPEAT(_NR_TRAM_NAMES, _CHECK_TRAM_POINT)
|
||||
#undef _CHECK_TRAM_POINT
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
#define _CHECK_TRAM_POINT(N) static_assert(Probe::build_time::can_reach(tramming_points[N]), "TRAMMING_POINT_XY point " STRINGIFY(N) " is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.");
|
||||
REPEAT(_NR_TRAM_NAMES, _CHECK_TRAM_POINT)
|
||||
#undef _CHECK_TRAM_POINT
|
||||
#endif
|
||||
|
||||
extern PGM_P const tramming_point_name[];
|
||||
|
||||
|
|
@ -74,3 +80,7 @@ extern PGM_P const tramming_point_name[];
|
|||
#else
|
||||
inline void move_to_tramming_wait_pos() {}
|
||||
#endif
|
||||
|
||||
#if ALL(DYNAMIC_MARGINS, DYNAMIC_TRAMMING)
|
||||
void updateTrammingPoints();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,6 +41,18 @@
|
|||
//
|
||||
|
||||
#include "../../feature/tramming.h"
|
||||
#if ALL(DYNAMIC_MARGINS, DYNAMIC_TRAMMING)
|
||||
void updateTrammingPoints() {
|
||||
tramming_points[0].x = bedlevel.margin_l;
|
||||
tramming_points[0].y = bedlevel.margin_f;
|
||||
tramming_points[1].x = X_BED_SIZE - bedlevel.margin_r;
|
||||
tramming_points[1].y = bedlevel.margin_f;
|
||||
tramming_points[2].x = bedlevel.margin_l;
|
||||
tramming_points[2].y = Y_BED_SIZE - bedlevel.margin_b;
|
||||
tramming_points[3].x = X_BED_SIZE - bedlevel.margin_r;
|
||||
tramming_points[3].y = Y_BED_SIZE - bedlevel.margin_b;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* G35: Read bed corners to help adjust bed screws
|
||||
|
|
@ -60,6 +72,10 @@ void GcodeSuite::G35() {
|
|||
|
||||
if (DEBUGGING(LEVELING)) log_machine_info();
|
||||
|
||||
#if ALL(DYNAMIC_MARGINS, DYNAMIC_TRAMMING)
|
||||
updateTrammingPoints();
|
||||
#endif
|
||||
|
||||
float z_measured[G35_PROBE_COUNT] = { 0 };
|
||||
|
||||
const uint8_t screw_thread = parser.byteval('S', TRAMMING_SCREW_THREAD);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../feature/bedlevel/bedlevel.h"
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
#include "../../../module/probe.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../../../lcd/extui/ui_api.h"
|
||||
|
|
@ -45,12 +48,28 @@
|
|||
* - If I is omitted, set the entire row
|
||||
* - If J is omitted, set the entire column
|
||||
* - If both I and J are omitted, set all
|
||||
*
|
||||
* M421: Set one or more PROBING_MARGINS if ENABLED(DYNAMIC_MARGINS) in mm
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* - set single margin (l):
|
||||
* M421 L10
|
||||
* - set multiple margins (lf):
|
||||
* M421 L10 F10
|
||||
* - set all margins to one value (lrfb):
|
||||
* M421 L50 R50 F50 B50
|
||||
* - recalculate all min margins based on probe offsets and reachable area (lrfb):
|
||||
* M421 L0 R0 F0 B0
|
||||
* - reset margins to the defaults
|
||||
* M421 D
|
||||
*
|
||||
*/
|
||||
void GcodeSuite::M421() {
|
||||
int8_t ix = parser.intval('I', -1), iy = parser.intval('J', -1);
|
||||
const bool hasZ = parser.seenval('Z'),
|
||||
hasQ = !hasZ && parser.seenval('Q');
|
||||
|
||||
bool did_something = false;
|
||||
if (hasZ || hasQ) {
|
||||
if (WITHIN(ix, -1, GRID_MAX_POINTS_X - 1) && WITHIN(iy, -1, GRID_MAX_POINTS_Y - 1)) {
|
||||
const float zval = parser.value_linear_units();
|
||||
|
|
@ -63,12 +82,94 @@ void GcodeSuite::M421() {
|
|||
}
|
||||
}
|
||||
bedlevel.refresh_bed_level();
|
||||
did_something = true;
|
||||
}
|
||||
else
|
||||
else {
|
||||
SERIAL_ERROR_MSG(STR_ERR_MESH_XY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
auto safe_margin = [](int user_val, int min_required, const char axis_char) {
|
||||
const int m = constrain(user_val, 0, 1000);
|
||||
if (m < min_required) {
|
||||
#if DISABLED(MARLIN_SMALL_BUILD)
|
||||
SERIAL_ECHOPGM(" ! ");
|
||||
SERIAL_CHAR(axis_char);
|
||||
SERIAL_ECHOPGM(" margin too small (");
|
||||
SERIAL_ECHO(m);
|
||||
SERIAL_ECHOPGM(" < ");
|
||||
SERIAL_ECHO(min_required);
|
||||
SERIAL_ECHOPGM("). ");
|
||||
SERIAL_CHAR(axis_char);
|
||||
SERIAL_ECHOPGM(" set to: ");
|
||||
SERIAL_ECHOLN(min_required);
|
||||
#endif
|
||||
return min_required;
|
||||
}
|
||||
return m;
|
||||
};
|
||||
if (parser.seen('D')) {
|
||||
// 'D' with no value resets all margins
|
||||
bedlevel.margin_l = PROBING_MARGIN_LEFT;
|
||||
bedlevel.margin_f = PROBING_MARGIN_RIGHT;
|
||||
bedlevel.margin_r = PROBING_MARGIN_FRONT;
|
||||
bedlevel.margin_b = PROBING_MARGIN_BACK;
|
||||
#if DISABLED(MARLIN_SMALL_BUILD)
|
||||
SERIAL_ECHOPGM(" Margins reset: L");
|
||||
SERIAL_ECHO(bedlevel.margin_l);
|
||||
SERIAL_ECHOPGM(" R");
|
||||
SERIAL_ECHO(bedlevel.margin_r);
|
||||
SERIAL_ECHOPGM(" F");
|
||||
SERIAL_ECHO(bedlevel.margin_f);
|
||||
SERIAL_ECHOPGM(" B");
|
||||
SERIAL_ECHO(bedlevel.margin_b);
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('L')) {
|
||||
// Left margin: X_MIN_POS + probe_offset must reach >= 0, but min 10
|
||||
bedlevel.margin_l = safe_margin(parser.value_int(), constrain(((TERN(HAS_HOME_OFFSET, motion.home_offset.x, X_MIN_POS) - ceilf(fabs(probe.offset_xy.x))) <= 0 ? 10 : (TERN(HAS_HOME_OFFSET, motion.home_offset.x, X_MIN_POS) - ceilf(fabs(probe.offset_xy.x)))), 10, X_BED_SIZE), 'L');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('F')) {
|
||||
// Front margin: Y_MIN_POS + probe_offset must reach >= 0, but min 10
|
||||
bedlevel.margin_f = safe_margin(parser.value_int(), constrain(((TERN(HAS_HOME_OFFSET, motion.home_offset.y, Y_MIN_POS) - ceilf(fabs(probe.offset_xy.y))) <= 0 ? 10 : (TERN(HAS_HOME_OFFSET, motion.home_offset.y, Y_MIN_POS) - ceilf(fabs(probe.offset_xy.y)))), 10, Y_BED_SIZE), 'F');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('R')) {
|
||||
// Right margin: The probe must not exceed X_BED_SIZE, but min 10
|
||||
bedlevel.margin_r = safe_margin(parser.value_int(), constrain(_MAX(10, X_BED_SIZE - (X_MAX_POS - ceilf(fabs(probe.offset_xy.x)))), 10, X_BED_SIZE), 'R');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('B')) {
|
||||
bedlevel.margin_b = safe_margin(parser.value_int(), constrain(_MAX(10, Y_BED_SIZE - (Y_MAX_POS - ceilf(fabs(probe.offset_xy.y)))), 10, Y_BED_SIZE), 'B');
|
||||
did_something = true;
|
||||
}
|
||||
#endif
|
||||
if (!did_something) {
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
M421_report();
|
||||
#else
|
||||
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
|
||||
}
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
void GcodeSuite::M421_report(const bool forReplay/*=true*/) {
|
||||
TERN_(MARLIN_SMALL_BUILD, return);
|
||||
report_heading_etc(forReplay, F("Dynamic Margins"));
|
||||
SERIAL_ECHOPGM(" M421 L");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_l));
|
||||
SERIAL_ECHOPGM(" R");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_r));
|
||||
SERIAL_ECHOPGM(" F");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_f));
|
||||
SERIAL_ECHOPGM(" B");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_b));
|
||||
SERIAL_ECHOLNPGM(" ; Margins in mm");
|
||||
}
|
||||
#endif // DYNAMIC_MARGINS
|
||||
|
||||
#endif // AUTO_BED_LEVELING_BILINEAR
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
#include "../../gcode.h"
|
||||
#include "../../../feature/bedlevel/bedlevel.h"
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
#include "../../../module/probe.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../../../lcd/extui/ui_api.h"
|
||||
|
|
@ -44,6 +47,22 @@
|
|||
* M421 I<xindex> J<yindex> N : Set the Mesh Point IJ to NAN (not set)
|
||||
* M421 C Z<linear> : Set the closest Mesh Point to the Z value
|
||||
* M421 C Q<offset> : Add the Q value to the closest Mesh Point
|
||||
*
|
||||
* M421: Set one or more PROBING_MARGINS if ENABLED(DYNAMIC_MARGINS) in mm
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* - set single margin (l):
|
||||
* M421 L10
|
||||
* - set multiple margins (lf):
|
||||
* M421 L10 F10
|
||||
* - set all margins to one value (lrfb):
|
||||
* M421 L50 R50 F50 B50
|
||||
* - recalculate all min margins based on probe offsets and reachable area (lrfb):
|
||||
* M421 L0 R0 F0 B0
|
||||
* - reset margins to the defaults
|
||||
* M421 D
|
||||
*
|
||||
*/
|
||||
void GcodeSuite::M421() {
|
||||
xy_int8_t ij = { int8_t(parser.intval('I', -1)), int8_t(parser.intval('J', -1)) };
|
||||
|
|
@ -54,20 +73,109 @@ void GcodeSuite::M421() {
|
|||
hasZ = parser.seen('Z'),
|
||||
hasQ = !hasZ && parser.seen('Q');
|
||||
|
||||
const bool mesh_command = hasZ || hasQ || hasN;
|
||||
if (hasC) ij = bedlevel.find_closest_mesh_point_of_type(CLOSEST, motion.position);
|
||||
|
||||
// Test for bad parameter combinations
|
||||
if (int(hasC) + int(hasI && hasJ) != 1 || !(hasZ || hasQ || hasN))
|
||||
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
|
||||
|
||||
// Test for I J out of range
|
||||
else if (!WITHIN(ij.x, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(ij.y, 0, GRID_MAX_POINTS_Y - 1))
|
||||
SERIAL_ERROR_MSG(STR_ERR_MESH_XY);
|
||||
else {
|
||||
float &zval = bedlevel.z_values[ij.x][ij.y]; // Altering this Mesh Point
|
||||
zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0); // N=NAN, Z=NEWVAL, or Q=ADDVAL
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval)); // Ping ExtUI in case it's showing the mesh
|
||||
bool did_something = false;
|
||||
// Mesh point modification
|
||||
if (mesh_command) {
|
||||
// Bad parameter combination: Must have exactly one of (C or both I+J)
|
||||
if (int(hasC) + int(hasI && hasJ) != 1) {
|
||||
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
|
||||
return;
|
||||
}
|
||||
// Test for I J out of range
|
||||
if (!WITHIN(ij.x, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(ij.y, 0, GRID_MAX_POINTS_Y - 1)) {
|
||||
SERIAL_ERROR_MSG(STR_ERR_MESH_XY);
|
||||
return;
|
||||
}
|
||||
// Apply Z/Q/N value
|
||||
float &zval = bedlevel.z_values[ij.x][ij.y];
|
||||
zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0);
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval));
|
||||
did_something = true;
|
||||
}
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
auto safe_margin = [](int user_val, int min_required, const char axis_char) {
|
||||
const int m = constrain(user_val, 0, 1000);
|
||||
if (m < min_required) {
|
||||
#if DISABLED(MARLIN_SMALL_BUILD)
|
||||
SERIAL_ECHOPGM(" ! ");
|
||||
SERIAL_CHAR(axis_char);
|
||||
SERIAL_ECHOPGM(" margin too small (");
|
||||
SERIAL_ECHO(m);
|
||||
SERIAL_ECHOPGM(" < ");
|
||||
SERIAL_ECHO(min_required);
|
||||
SERIAL_ECHOPGM("). ");
|
||||
SERIAL_CHAR(axis_char);
|
||||
SERIAL_ECHOPGM(" set to: ");
|
||||
SERIAL_ECHOLN(min_required);
|
||||
#endif
|
||||
return min_required;
|
||||
}
|
||||
return m;
|
||||
};
|
||||
if (parser.seen('D')) {
|
||||
// 'D' with no value resets all margins
|
||||
bedlevel.margin_l = PROBING_MARGIN_LEFT;
|
||||
bedlevel.margin_f = PROBING_MARGIN_RIGHT;
|
||||
bedlevel.margin_r = PROBING_MARGIN_FRONT;
|
||||
bedlevel.margin_b = PROBING_MARGIN_BACK;
|
||||
#if DISABLED(MARLIN_SMALL_BUILD)
|
||||
SERIAL_ECHOPGM(" Margins reset: L");
|
||||
SERIAL_ECHO(bedlevel.margin_l);
|
||||
SERIAL_ECHOPGM(" R");
|
||||
SERIAL_ECHO(bedlevel.margin_r);
|
||||
SERIAL_ECHOPGM(" F");
|
||||
SERIAL_ECHO(bedlevel.margin_f);
|
||||
SERIAL_ECHOPGM(" B");
|
||||
SERIAL_ECHO(bedlevel.margin_b);
|
||||
SERIAL_EOL();
|
||||
#endif
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('L')) {
|
||||
// Left margin: X_MIN_POS + probe_offset must reach >= 0, but min 10
|
||||
bedlevel.margin_l = safe_margin(parser.value_int(), constrain(_MAX(10, TERN(HAS_HOME_OFFSET, motion.home_offset.x, X_MIN_POS) - ceilf(fabs(probe.offset_xy.x))), 10, X_BED_SIZE), 'L');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('F')) {
|
||||
// Front margin: Y_MIN_POS + probe_offset must reach >= 0, but min 10
|
||||
bedlevel.margin_f = safe_margin(parser.value_int(), constrain(_MAX(10, TERN(HAS_HOME_OFFSET, motion.home_offset.y, Y_MIN_POS) - ceilf(fabs(probe.offset_xy.y))), 10, Y_BED_SIZE), 'F');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('R')) {
|
||||
// Right margin: The probe must not exceed X_BED_SIZE, but min 10
|
||||
bedlevel.margin_r = safe_margin(parser.value_int(), constrain(_MAX(10, X_BED_SIZE - (X_MAX_POS - ceilf(fabs(probe.offset_xy.x)))), 10, X_BED_SIZE), 'R');
|
||||
did_something = true;
|
||||
}
|
||||
if (parser.seen('B')) {
|
||||
// Back margin: The probe must not exceed Y_BED_SIZE, but min 10
|
||||
bedlevel.margin_b = safe_margin(parser.value_int(), constrain(_MAX(10, Y_BED_SIZE - (Y_MAX_POS - ceilf(fabs(probe.offset_xy.y)))), 10, Y_BED_SIZE), 'B');
|
||||
did_something = true;
|
||||
}
|
||||
#endif
|
||||
if (!did_something) {
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
M421_report();
|
||||
#else
|
||||
SERIAL_ERROR_MSG(STR_ERR_M421_PARAMETERS);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
void GcodeSuite::M421_report(const bool forReplay/*=true*/) {
|
||||
TERN_(MARLIN_SMALL_BUILD, return);
|
||||
report_heading_etc(forReplay, F("Dynamic Margins"));
|
||||
SERIAL_ECHOPGM(" M421 L");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_l));
|
||||
SERIAL_ECHOPGM(" R");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_r));
|
||||
SERIAL_ECHOPGM(" F");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_f));
|
||||
SERIAL_ECHOPGM(" B");
|
||||
SERIAL_ECHO(LINEAR_UNIT(bedlevel.margin_b));
|
||||
SERIAL_ECHOLNPGM(" ; Margins in mm");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,9 @@ private:
|
|||
static void M420();
|
||||
static void M420_report(const bool forReplay=true);
|
||||
static void M421();
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static void M421_report(const bool forReplay=true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(BACKLASH_GCODE)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,17 @@
|
|||
#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
|
||||
#include "../core/debug_out.h"
|
||||
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
||||
#include "../feature/bedlevel/abl/bbl.h"
|
||||
extern LevelingBilinear bedlevel;
|
||||
#endif
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
#include "../feature/bedlevel/ubl/ubl.h"
|
||||
extern unified_bed_leveling bedlevel;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
enum ProbePtRaise : uint8_t {
|
||||
PROBE_PT_NONE, // No raise or stow after run_z_probe
|
||||
|
|
@ -111,18 +122,33 @@ public:
|
|||
// Note: This won't work on SCARA since the probe offset rotates with the arm.
|
||||
static bool can_reach(const float rx, const float ry, const bool probe_relative=true) {
|
||||
if (probe_relative) {
|
||||
return motion.can_reach(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& motion.can_reach(rx, ry, PROBING_MARGIN); // Can the probe also go near there?
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
return motion.can_reach(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& motion.can_reach(rx, ry, bedlevel.margin_l); // Can the probe also go near there?
|
||||
#else
|
||||
return motion.can_reach(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go?
|
||||
&& motion.can_reach(rx, ry, PROBING_MARGIN); // Can the probe also go near there?
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
return motion.can_reach(rx, ry)
|
||||
&& motion.can_reach(rx + offset_xy.x, ry + offset_xy.y, PROBING_MARGIN);
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
return motion.can_reach(rx, ry)
|
||||
&& motion.can_reach(rx + offset_xy.x, ry + offset_xy.y, bedlevel.margin_r);
|
||||
#else
|
||||
return motion.can_reach(rx, ry)
|
||||
&& motion.can_reach(rx + offset_xy.x, ry + offset_xy.y, PROBING_MARGIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
static bool can_reach(const float rx, const float ry, const bool=true) {
|
||||
return motion.can_reach(rx, ry)
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
return motion.can_reach(rx, ry)
|
||||
&& motion.can_reach(rx, ry, bedlevel.margin_l);
|
||||
#else
|
||||
return motion.can_reach(rx, ry)
|
||||
&& motion.can_reach(rx, ry, PROBING_MARGIN);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -249,9 +275,15 @@ public:
|
|||
|
||||
#if HAS_BED_PROBE || HAS_LEVELING
|
||||
#if IS_KINEMATIC
|
||||
static constexpr float probe_radius(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y));
|
||||
}
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static float probe_radius(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return float(PRINTABLE_RADIUS) - _MAX(bedlevel.margin_l, HYPOT(probe_offset_xy.x, probe_offset_xy.y));
|
||||
}
|
||||
#else
|
||||
static constexpr float probe_radius(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -263,30 +295,58 @@ public:
|
|||
* close it can get the RIGHT edge of the bed (unless the nozzle is able move
|
||||
* far enough past the right edge).
|
||||
*/
|
||||
static constexpr float _min_x(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((X_MIN_BED) + (PROBING_MARGIN_LEFT), (X_MIN_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_x(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((X_MAX_BED) - (PROBING_MARGIN_RIGHT), (X_MAX_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _min_y(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((Y_MIN_BED) + (PROBING_MARGIN_FRONT), (Y_MIN_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_y(const xy_pos_t &probe_offset_xy=offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((Y_MAX_BED) - (PROBING_MARGIN_BACK), (Y_MAX_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
#if DISABLED(DYNAMIC_MARGINS)
|
||||
static constexpr float _min_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) - (float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y))),
|
||||
_MAX((X_MIN_BED) + PROBING_MARGIN_LEFT, (X_MIN_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) + (float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y))),
|
||||
_MIN((X_MAX_BED) - PROBING_MARGIN_RIGHT, (X_MAX_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static constexpr float _min_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) - (float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y))),
|
||||
_MAX((Y_MIN_BED) + PROBING_MARGIN_FRONT, (Y_MIN_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
static constexpr float _max_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) + (float(PRINTABLE_RADIUS) - _MAX(PROBING_MARGIN, HYPOT(probe_offset_xy.x, probe_offset_xy.y))),
|
||||
_MIN((Y_MAX_BED) - PROBING_MARGIN_BACK, (Y_MAX_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static float _min_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((X_MIN_BED) + bedlevel.margin_l, (X_MIN_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static float _max_x(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(X_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((X_MAX_BED) - bedlevel.margin_r, (X_MAX_POS) + probe_offset_xy.x)
|
||||
);
|
||||
}
|
||||
static float _min_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) - probe_radius(probe_offset_xy),
|
||||
_MAX((Y_MIN_BED) + bedlevel.margin_f, (Y_MIN_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
static float _max_y(const xy_pos_t &probe_offset_xy = offset_xy) {
|
||||
return TERN(IS_KINEMATIC,
|
||||
(Y_CENTER) + probe_radius(probe_offset_xy),
|
||||
_MIN((Y_MAX_BED) - bedlevel.margin_b, (Y_MAX_POS) + probe_offset_xy.y)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
static float min_x() { return _min_x() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - motion.home_offset.x)); }
|
||||
static float max_x() { return _max_x() TERN_(NOZZLE_AS_PROBE, TERN_(HAS_HOME_OFFSET, - motion.home_offset.x)); }
|
||||
|
|
@ -295,6 +355,10 @@ public:
|
|||
|
||||
// constexpr helpers used in build-time static_asserts, relying on default probe offsets.
|
||||
class build_time {
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
static xyz_pos_t default_probe_xyz_offset;
|
||||
static xy_pos_t default_probe_xy_offset;
|
||||
#else
|
||||
static constexpr xyz_pos_t default_probe_xyz_offset = xyz_pos_t(
|
||||
#if HAS_BED_PROBE
|
||||
NOZZLE_TO_PROBE_OFFSET
|
||||
|
|
@ -302,10 +366,12 @@ public:
|
|||
{ 0 }
|
||||
#endif
|
||||
);
|
||||
static constexpr xy_pos_t default_probe_xy_offset = xy_pos_t({ default_probe_xyz_offset.x, default_probe_xyz_offset.y });
|
||||
static constexpr xy_pos_t default_probe_xy_offset = xy_pos_t({ default_probe_xyz_offset.x, default_probe_xyz_offset.y });
|
||||
#endif
|
||||
|
||||
public:
|
||||
static constexpr bool can_reach(float x, float y) {
|
||||
|
||||
TERN(DYNAMIC_MARGINS, static, static constexpr) bool can_reach(float x, float y) {
|
||||
#if IS_KINEMATIC
|
||||
return HYPOT2(x, y) <= sq(probe_radius(default_probe_xy_offset));
|
||||
#else
|
||||
|
|
@ -314,7 +380,7 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
static constexpr bool can_reach(const xy_pos_t &point) { return can_reach(point.x, point.y); }
|
||||
TERN(DYNAMIC_MARGINS, static, static constexpr) bool can_reach(const xy_pos_t &point) { return can_reach(point.x, point.y); }
|
||||
};
|
||||
|
||||
#if NEEDS_THREE_PROBE_POINTS
|
||||
|
|
@ -336,9 +402,9 @@ public:
|
|||
points[1] = xy_float_t({ (X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120 });
|
||||
points[2] = xy_float_t({ (X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240 });
|
||||
#elif ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
points[0] = xy_float_t({ _MAX(float(MESH_MIN_X), min_x()), _MAX(float(MESH_MIN_Y), min_y()) });
|
||||
points[1] = xy_float_t({ _MIN(float(MESH_MAX_X), max_x()), _MAX(float(MESH_MIN_Y), min_y()) });
|
||||
points[2] = xy_float_t({ (_MAX(float(MESH_MIN_X), min_x()) + _MIN(float(MESH_MAX_X), max_x())) / 2, _MIN(float(MESH_MAX_Y), max_y()) });
|
||||
points[0] = xy_float_t({ _MAX(TERN(DYNAMIC_MARGINS, float(bedlevel.margin_l), float(MESH_MIN_X)), min_x()), _MAX(TERN(DYNAMIC_MARGINS, float(bedlevel.margin_r), float(MESH_MIN_Y)), min_y()) });
|
||||
points[1] = xy_float_t({ _MIN(TERN(DYNAMIC_MARGINS, float(X_BED_SIZE - bedlevel.margin_l), float(MESH_MAX_X)), max_x()), _MAX(TERN(DYNAMIC_MARGINS, float(bedlevel.margin_r), float(MESH_MIN_Y)), min_y()) });
|
||||
points[2] = xy_float_t({ (_MAX(TERN(DYNAMIC_MARGINS, float(bedlevel.margin_l), float(MESH_MIN_X)), min_x()) + _MIN(TERN(DYNAMIC_MARGINS, float(X_BED_SIZE - bedlevel.margin_r), float(MESH_MAX_X)), max_x())) / 2, _MIN(TERN(DYNAMIC_MARGINS, float(Y_BED_SIZE - bedlevel.margin_f), float(MESH_MAX_Y)), max_y()) });
|
||||
#else
|
||||
points[0] = xy_float_t({ min_x(), min_y() });
|
||||
points[1] = xy_float_t({ max_x(), min_y() });
|
||||
|
|
|
|||
|
|
@ -300,6 +300,9 @@ typedef struct SettingsDataStruct {
|
|||
uint8_t grid_max_x, grid_max_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
|
||||
uint16_t grid_check; // Hash to check against X/Y
|
||||
xy_pos_t bilinear_grid_spacing, bilinear_start; // G29 L F
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
int16_t margin_l, margin_r, margin_f, margin_b;
|
||||
#endif
|
||||
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
||||
bed_mesh_t z_values; // G29
|
||||
#else
|
||||
|
|
@ -1113,6 +1116,12 @@ void MarlinSettings::postprocess() {
|
|||
dummyf = 0;
|
||||
for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummyf);
|
||||
#endif
|
||||
#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL) && ENABLED(DYNAMIC_MARGINS)
|
||||
EEPROM_WRITE(bedlevel.margin_l);
|
||||
EEPROM_WRITE(bedlevel.margin_r);
|
||||
EEPROM_WRITE(bedlevel.margin_f);
|
||||
EEPROM_WRITE(bedlevel.margin_b);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -2180,6 +2189,12 @@ void MarlinSettings::postprocess() {
|
|||
else // EEPROM data is stale
|
||||
#endif // AUTO_BED_LEVELING_BILINEAR
|
||||
{
|
||||
#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL) && ENABLED(DYNAMIC_MARGINS)
|
||||
EEPROM_READ(bedlevel.margin_l);
|
||||
EEPROM_READ(bedlevel.margin_r);
|
||||
EEPROM_READ(bedlevel.margin_f);
|
||||
EEPROM_READ(bedlevel.margin_b);
|
||||
#endif
|
||||
// Skip past disabled (or stale) Bilinear Grid data
|
||||
for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_READ(dummyf);
|
||||
}
|
||||
|
|
@ -3439,6 +3454,8 @@ void MarlinSettings::reset() {
|
|||
|
||||
TERN_(DWIN_CREALITY_LCD_JYERSUI, jyersDWIN.resetSettings());
|
||||
|
||||
TERN_(DYNAMIC_MARGINS, { bedlevel.margin_l = PROBING_MARGIN_LEFT; bedlevel.margin_f = PROBING_MARGIN_FRONT; bedlevel.margin_r = PROBING_MARGIN_RIGHT; bedlevel.margin_b = PROBING_MARGIN_BACK; });
|
||||
|
||||
//
|
||||
// Case Light Brightness
|
||||
//
|
||||
|
|
@ -3941,6 +3958,10 @@ void MarlinSettings::reset() {
|
|||
|
||||
gcode.M420_report(forReplay);
|
||||
|
||||
#if ENABLED(DYNAMIC_MARGINS)
|
||||
gcode.M421_report(forReplay);
|
||||
#endif
|
||||
|
||||
#if ENABLED(MESH_BED_LEVELING)
|
||||
|
||||
if (leveling_is_valid()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue