Skip to content

Commit

Permalink
Merge pull request MarlinFirmware#4183 from leptun/mbl_print_area
Browse files Browse the repository at this point in the history
MBL print area
  • Loading branch information
3d-gussner authored Sep 13, 2023
2 parents 0aa380b + ede4cc5 commit 2e70697
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 532 deletions.
3 changes: 1 addition & 2 deletions Firmware/Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include "pins.h"
#include "Timer.h"
#include "mmu2.h"
extern uint8_t mbl_z_probe_nr;

#ifndef AT90USB
#define HardwareSerial_h // trick to disable the standard HWserial
Expand Down Expand Up @@ -236,7 +235,7 @@ enum class HeatingStatus : uint8_t
extern HeatingStatus heating_status;

extern bool fans_check_enabled;
extern float homing_feedrate[];
constexpr float homing_feedrate[] = HOMING_FEEDRATE;
extern uint8_t axis_relative_modes;
extern float feedrate;
extern int feedmultiply;
Expand Down
431 changes: 158 additions & 273 deletions Firmware/Marlin_main.cpp

Large diffs are not rendered by default.

91 changes: 46 additions & 45 deletions Firmware/mesh_bed_calibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,11 +685,11 @@ bool is_bed_z_jitter_data_valid()
// offsets of the Z heiths of the calibration points from the first point are saved as 16bit signed int, scaled to tenths of microns
// if at least one 16bit integer has different value then -1 (0x0FFFF), data are considered valid and function returns true, otherwise it returns false
{
bool data_valid = false;
for (int8_t i = 0; i < 8; ++i) {
if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF) data_valid = true;
if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF)
return true;
}
return data_valid;
return false;
}

static void world2machine_update(const float vec_x[2], const float vec_y[2], const float cntr[2])
Expand Down Expand Up @@ -776,7 +776,7 @@ void world2machine_revert_to_uncorrected()
static inline bool vec_undef(const float v[2])
{
const uint32_t *vx = (const uint32_t*)v;
return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF;
return vx[0] == 0xFFFFFFFF || vx[1] == 0xFFFFFFFF;
}


Expand Down Expand Up @@ -2184,6 +2184,16 @@ inline void scan_bed_induction_sensor_point()

#define MESH_BED_CALIBRATION_SHOW_LCD

float __attribute__((noinline)) BED_X(const uint8_t col)
{
return ((float)col * x_mesh_density + BED_X0);
}

float __attribute__((noinline)) BED_Y(const uint8_t row)
{
return ((float)row * y_mesh_density + BED_Y0);
}

BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask)
{
// Don't let the manage_inactivity() function remove power from the motors.
Expand Down Expand Up @@ -2481,8 +2491,8 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix;
current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
current_position[X_AXIS] = BED_X(ix * 3);
current_position[Y_AXIS] = BED_Y(iy * 3);
go_to_current(homing_feedrate[X_AXIS] / 60);
delay_keep_alive(3000);
}
Expand Down Expand Up @@ -2820,16 +2830,16 @@ void go_home_with_z_lift()
// Go home.
// First move up to a safe height.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
go_to_current(homing_feedrate[Z_AXIS]/60);
go_to_current(homing_feedrate[Z_AXIS] / 60);
// Second move to XY [0, 0].
current_position[X_AXIS] = X_MIN_POS+0.2;
current_position[Y_AXIS] = Y_MIN_POS+0.2;
current_position[X_AXIS] = X_MIN_POS + 0.2;
current_position[Y_AXIS] = Y_MIN_POS + 0.2;
// Clamp to the physical coordinates.
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
go_to_current(homing_feedrate[X_AXIS]/20);
go_to_current((3 * homing_feedrate[X_AXIS]) / 60);
// Third move up to a safe height.
current_position[Z_AXIS] = Z_MIN_POS;
go_to_current(homing_feedrate[Z_AXIS]/60);
go_to_current(homing_feedrate[Z_AXIS] / 60);
}

// Sample the 9 points of the bed and store them into the EEPROM as a reference.
Expand Down Expand Up @@ -2890,8 +2900,8 @@ bool sample_mesh_and_store_reference()
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag
current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
current_position[X_AXIS] = BED_X(ix * 3);
current_position[Y_AXIS] = BED_Y(iy * 3);
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
go_to_current(homing_feedrate[X_AXIS]/60);
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
Expand Down Expand Up @@ -2957,8 +2967,7 @@ bool sample_mesh_and_store_reference()
}
}

mbl.upsample_3x3();
mbl.active = true;
mbl.reset();

go_home_with_z_lift();

Expand Down Expand Up @@ -3010,8 +3019,8 @@ bool scan_bed_induction_points(int8_t verbosity_level)
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix;
float bedX = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
float bedY = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
float bedX = BED_X(ix * 3);
float bedY = BED_Y(iy * 3);
current_position[X_AXIS] = vec_x[0] * bedX + vec_y[0] * bedY + cntr[0];
current_position[Y_AXIS] = vec_x[1] * bedX + vec_y[1] * bedY + cntr[1];
// The calibration points are very close to the min Y.
Expand Down Expand Up @@ -3040,9 +3049,12 @@ bool scan_bed_induction_points(int8_t verbosity_level)
// To replace loading of the babystep correction.
static void shift_z(float delta)
{
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] - delta, current_position[E_AXIS], homing_feedrate[Z_AXIS]/40);
const float curpos_z = current_position[Z_AXIS];
current_position[Z_AXIS] -= delta;
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60);
st_synchronize();
plan_set_z_position(current_position[Z_AXIS]);
current_position[Z_AXIS] = curpos_z;
plan_set_z_position(curpos_z);
}

// Number of baby steps applied
Expand Down Expand Up @@ -3118,20 +3130,19 @@ void mbl_settings_init() {
//magnet elimination: use aaproximate Z-coordinate instead of measured values for points which are near magnets
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION, 1);
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_POINTS_NR, 3);
mbl_z_probe_nr = eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3);
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3);
}

//parameter ix: index of mesh bed leveling point in X-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
//parameter iy: index of mesh bed leveling point in Y-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
//parameter meas_points: number of mesh bed leveling points in one axis; currently designed and tested for values 3 and 7
//parameter zigzag: false if ix is considered 0 on left side of bed and ix rises with rising X coordinate; true if ix is considered 0 on the right side of heatbed for odd iy values (zig zag mesh bed leveling movements)
//function returns true if point is considered valid (typicaly in safe distance from magnet or another object which inflences PINDA measurements)
bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag) {
bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy) {
//"human readable" heatbed plan
//magnet proximity influence Z coordinate measurements significantly (40 - 100 um)
//0 - measurement point is above magnet and Z coordinate can be influenced negatively
//1 - we should be in safe distance from magnets, measurement should be accurate
if ((ix >= meas_points) || (iy >= meas_points)) return false;
if ((ix >= MESH_NUM_X_POINTS) || (iy >= MESH_NUM_Y_POINTS))
return false;

uint8_t valid_points_mask[7] = {
//[X_MAX,Y_MAX]
Expand All @@ -3145,36 +3156,26 @@ bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bo
0b1111111,//0
//[0,0]
};
if (meas_points == 3) {
ix *= 3;
iy *= 3;
}
if (zigzag) {
if ((iy % 2) == 0) return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
else return (valid_points_mask[6 - iy] & (1 << ix));
}
else {
return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
}
return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
}

void mbl_single_point_interpolation(uint8_t x, uint8_t y, uint8_t meas_points) {
void mbl_single_point_interpolation(uint8_t x, uint8_t y) {
//printf_P(PSTR("x = %d; y = %d \n"), x, y);
uint8_t count = 0;
float z = 0;
if (mbl_point_measurement_valid(x, y + 1, meas_points, false)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; }
if (mbl_point_measurement_valid(x, y - 1, meas_points, false)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; }
if (mbl_point_measurement_valid(x + 1, y, meas_points, false)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; }
if (mbl_point_measurement_valid(x - 1, y, meas_points, false)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; }
if (mbl_point_measurement_valid(x, y + 1)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; }
if (mbl_point_measurement_valid(x, y - 1)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; }
if (mbl_point_measurement_valid(x + 1, y)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; }
if (mbl_point_measurement_valid(x - 1, y)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; }
if(count != 0) mbl.z_values[y][x] = z / count; //if we have at least one valid point in surrounding area use average value, otherwise use inaccurately measured Z-coordinate
//printf_P(PSTR("result: Z = %f \n\n"), mbl.z_values[y][x]);
}

void mbl_interpolation(uint8_t meas_points) {
for (uint8_t x = 0; x < meas_points; x++) {
for (uint8_t y = 0; y < meas_points; y++) {
if (!mbl_point_measurement_valid(x, y, meas_points, false)) {
mbl_single_point_interpolation(x, y, meas_points);
void mbl_magnet_elimination() {
for (uint8_t y = 0; y < MESH_NUM_Y_POINTS; y++) {
for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) {
if (!mbl_point_measurement_valid(x, y)) {
mbl_single_point_interpolation(x, y);
}
}
}
Expand Down
20 changes: 15 additions & 5 deletions Firmware/mesh_bed_calibration.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

#endif //not HEATBED_V2

#define BED_X(i, n) ((float)i * (BED_Xn - BED_X0) / (n - 1) + BED_X0)
#define BED_Y(i, n) ((float)i * (BED_Yn - BED_Y0) / (n - 1) + BED_Y0)
constexpr float x_mesh_density = (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1);
constexpr float y_mesh_density = (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1);

// Exact positions of the print head above the bed reference points, in the world coordinates.
// The world coordinates match the machine coordinates only in case, when the machine
Expand Down Expand Up @@ -145,6 +145,17 @@ inline bool world2machine_clamp(float &x, float &y)
machine2world(tmpx, tmpy, x, y);
return clamped;
}

/// @brief For a given column on the mesh calculate the bed X coordinate
/// @param col column index on mesh
/// @return Bed X coordinate
float BED_X(const uint8_t col);

/// @brief For a given row on the mesh calculate the bed Y coordinate
/// @param row row index on mesh
/// @return Bed Y coordinate
float BED_Y(const uint8_t row);

/**
* @brief Bed skew and offest detection result
*
Expand Down Expand Up @@ -203,6 +214,5 @@ extern void count_xyz_details(float (&distanceMin)[2]);
extern bool sample_z();

extern void mbl_settings_init();

extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag);
extern void mbl_interpolation(uint8_t meas_points);
extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy);
extern void mbl_magnet_elimination();
Loading

0 comments on commit 2e70697

Please sign in to comment.