Added menu option for bed leveling.

This commit is contained in:
Edward Patel 2015-03-15 23:18:11 +01:00
parent 0e51e53813
commit 8005d22c81
8 changed files with 192 additions and 17 deletions

View file

@ -384,8 +384,9 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
#define MESH_MAX_X (X_MAX_POS - MESH_MIN_X) #define MESH_MAX_X (X_MAX_POS - MESH_MIN_X)
#define MESH_MIN_Y 10 #define MESH_MIN_Y 10
#define MESH_MAX_Y (Y_MAX_POS - MESH_MIN_Y) #define MESH_MAX_Y (Y_MAX_POS - MESH_MIN_Y)
#define MESH_NUM_X_POINTS 4 #define MESH_NUM_X_POINTS 3
#define MESH_NUM_Y_POINTS 3 #define MESH_NUM_Y_POINTS 3
#define MESH_HOME_SEARCH_Z 4 // Z after Home, bed somewhere below but above 0.0
#endif // MESH_BED_LEVELING #endif // MESH_BED_LEVELING
//=========================================================================== //===========================================================================

View file

@ -20,6 +20,10 @@
* max_e_jerk * max_e_jerk
* add_homing (x3) * add_homing (x3)
* *
* Mesh bed leveling:
* active
* z_values[][]
*
* DELTA: * DELTA:
* endstop_adj (x3) * endstop_adj (x3)
* delta_radius * delta_radius
@ -69,6 +73,10 @@
#include "ultralcd.h" #include "ultralcd.h"
#include "ConfigurationStore.h" #include "ConfigurationStore.h"
#if defined(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#endif // MESH_BED_LEVELING
void _EEPROM_writeData(int &pos, uint8_t* value, uint8_t size) { void _EEPROM_writeData(int &pos, uint8_t* value, uint8_t size) {
uint8_t c; uint8_t c;
while(size--) { while(size--) {
@ -128,6 +136,11 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, max_e_jerk); EEPROM_WRITE_VAR(i, max_e_jerk);
EEPROM_WRITE_VAR(i, add_homing); EEPROM_WRITE_VAR(i, add_homing);
#if defined(MESH_BED_LEVELING)
EEPROM_WRITE_VAR(i, mbl.active);
EEPROM_WRITE_VAR(i, mbl.z_values);
#endif // MESH_BED_LEVELING
#ifdef DELTA #ifdef DELTA
EEPROM_WRITE_VAR(i, endstop_adj); // 3 floats EEPROM_WRITE_VAR(i, endstop_adj); // 3 floats
EEPROM_WRITE_VAR(i, delta_radius); // 1 float EEPROM_WRITE_VAR(i, delta_radius); // 1 float
@ -250,7 +263,7 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, max_feedrate); EEPROM_READ_VAR(i, max_feedrate);
EEPROM_READ_VAR(i, max_acceleration_units_per_sq_second); EEPROM_READ_VAR(i, max_acceleration_units_per_sq_second);
// steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner) // steps per sq second need to be updated to agree with the units per sq second (as they are what is used in the planner)
reset_acceleration_rates(); reset_acceleration_rates();
EEPROM_READ_VAR(i, acceleration); EEPROM_READ_VAR(i, acceleration);
@ -264,6 +277,11 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, max_e_jerk); EEPROM_READ_VAR(i, max_e_jerk);
EEPROM_READ_VAR(i, add_homing); EEPROM_READ_VAR(i, add_homing);
#if defined(MESH_BED_LEVELING)
EEPROM_READ_VAR(i, mbl.active);
EEPROM_READ_VAR(i, mbl.z_values);
#endif // MESH_BED_LEVELING
#ifdef DELTA #ifdef DELTA
EEPROM_READ_VAR(i, endstop_adj); // 3 floats EEPROM_READ_VAR(i, endstop_adj); // 3 floats
EEPROM_READ_VAR(i, delta_radius); // 1 float EEPROM_READ_VAR(i, delta_radius); // 1 float
@ -392,6 +410,10 @@ void Config_ResetDefault() {
max_e_jerk = DEFAULT_EJERK; max_e_jerk = DEFAULT_EJERK;
add_homing[X_AXIS] = add_homing[Y_AXIS] = add_homing[Z_AXIS] = 0; add_homing[X_AXIS] = add_homing[Y_AXIS] = add_homing[Z_AXIS] = 0;
#if defined(MESH_BED_LEVELING)
mbl.active = 0;
#endif // MESH_BED_LEVELING
#ifdef DELTA #ifdef DELTA
endstop_adj[X_AXIS] = endstop_adj[Y_AXIS] = endstop_adj[Z_AXIS] = 0; endstop_adj[X_AXIS] = endstop_adj[Y_AXIS] = endstop_adj[Z_AXIS] = 0;
delta_radius = DELTA_RADIUS; delta_radius = DELTA_RADIUS;

View file

@ -1566,6 +1566,11 @@ inline void gcode_G28() {
plan_bed_level_matrix.set_to_identity(); //Reset the plane ("erase" all leveling data) plan_bed_level_matrix.set_to_identity(); //Reset the plane ("erase" all leveling data)
#endif #endif
#if defined(MESH_BED_LEVELING)
uint8_t mbl_was_active = mbl.active;
mbl.active = 0;
#endif // MESH_BED_LEVELING
saved_feedrate = feedrate; saved_feedrate = feedrate;
saved_feedmultiply = feedmultiply; saved_feedmultiply = feedmultiply;
feedmultiply = 100; feedmultiply = 100;
@ -1780,6 +1785,23 @@ inline void gcode_G28() {
enable_endstops(false); enable_endstops(false);
#endif #endif
#if defined(MESH_BED_LEVELING)
if (mbl_was_active) {
current_position[X_AXIS] = mbl.get_x(0);
current_position[Y_AXIS] = mbl.get_y(0);
destination[X_AXIS] = current_position[X_AXIS];
destination[Y_AXIS] = current_position[Y_AXIS];
destination[Z_AXIS] = current_position[Z_AXIS];
destination[E_AXIS] = current_position[E_AXIS];
feedrate = homing_feedrate[X_AXIS];
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate, active_extruder);
st_synchronize();
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
mbl.active = 1;
}
#endif
feedrate = saved_feedrate; feedrate = saved_feedrate;
feedmultiply = saved_feedmultiply; feedmultiply = saved_feedmultiply;
previous_millis_cmd = millis(); previous_millis_cmd = millis();
@ -4998,6 +5020,13 @@ void calculate_delta(float cartesian[3])
// This function is used to split lines on mesh borders so each segment is only part of one mesh area // This function is used to split lines on mesh borders so each segment is only part of one mesh area
void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, uint8_t x_splits=0xff, uint8_t y_splits=0xff) void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, uint8_t x_splits=0xff, uint8_t y_splits=0xff)
{ {
if (!mbl.active) {
plan_buffer_line(x, y, z, e, feed_rate, extruder);
for(int8_t i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i];
}
return;
}
int pix = mbl.select_x_index(current_position[X_AXIS]); int pix = mbl.select_x_index(current_position[X_AXIS]);
int piy = mbl.select_y_index(current_position[Y_AXIS]); int piy = mbl.select_y_index(current_position[Y_AXIS]);
int ix = mbl.select_x_index(x); int ix = mbl.select_x_index(x);
@ -5012,7 +5041,13 @@ void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed
float ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist; float ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist; float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
x_splits ^= 1 << ix; x_splits ^= 1 << ix;
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[E_AXIS] = ne;
mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[E_AXIS] = e;
mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits);
return; return;
} else if (ix < pix && (x_splits)&(1<<pix)) { } else if (ix < pix && (x_splits)&(1<<pix)) {
@ -5021,7 +5056,13 @@ void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed
float ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist; float ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist; float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
x_splits ^= 1 << pix; x_splits ^= 1 << pix;
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[E_AXIS] = ne;
mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[E_AXIS] = e;
mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits);
return; return;
} else if (iy > piy && (y_splits)&(1<<iy)) { } else if (iy > piy && (y_splits)&(1<<iy)) {
@ -5030,7 +5071,13 @@ void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed
float nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist; float nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist; float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
y_splits ^= 1 << iy; y_splits ^= 1 << iy;
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[E_AXIS] = ne;
mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[E_AXIS] = e;
mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits);
return; return;
} else if (iy < piy && (y_splits)&(1<<piy)) { } else if (iy < piy && (y_splits)&(1<<piy)) {
@ -5039,11 +5086,17 @@ void mesh_plan_buffer_line(float x, float y, float z, const float &e, float feed
float nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist; float nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist; float ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
y_splits ^= 1 << piy; y_splits ^= 1 << piy;
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[E_AXIS] = ne;
mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(nx, ny, z, ne, feed_rate, extruder, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[E_AXIS] = e;
mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits); mesh_plan_buffer_line(x, y, z, e, feed_rate, extruder, x_splits, y_splits);
return; return;
} }
plan_buffer_line(x, y, z, e, feedrate, extruder); plan_buffer_line(x, y, z, e, feed_rate, extruder);
for(int8_t i=0; i < NUM_AXIS; i++) { for(int8_t i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i]; current_position[i] = destination[i];
} }

View file

@ -95,6 +95,9 @@
#ifndef MSG_MOVE_AXIS #ifndef MSG_MOVE_AXIS
#define MSG_MOVE_AXIS "Move axis" #define MSG_MOVE_AXIS "Move axis"
#endif #endif
#ifndef MSG_LEVEL_BED
#define MSG_LEVEL_BED "Level bed"
#endif
#ifndef MSG_MOVE_X #ifndef MSG_MOVE_X
#define MSG_MOVE_X "Move X" #define MSG_MOVE_X "Move X"
#endif #endif

View file

@ -4,4 +4,17 @@
mesh_bed_leveling mbl; mesh_bed_leveling mbl;
mesh_bed_leveling::mesh_bed_leveling() {
reset();
}
void mesh_bed_leveling::reset() {
for (int y=0; y<MESH_NUM_Y_POINTS; y++) {
for (int x=0; x<MESH_NUM_X_POINTS; x++) {
z_values[y][x] = 0;
}
}
active = 0;
}
#endif // MESH_BED_LEVELING #endif // MESH_BED_LEVELING

View file

@ -7,20 +7,12 @@
class mesh_bed_leveling { class mesh_bed_leveling {
public: public:
uint8_t active;
float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS]; float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS];
mesh_bed_leveling() { mesh_bed_leveling();
reset();
}
void reset() { void reset();
for (int y=0; y<MESH_NUM_Y_POINTS; y++) {
for (int x=0; x<MESH_NUM_X_POINTS; x++) {
z_values[y][x] = 0;
}
}
}
float get_x(int i) { return MESH_MIN_X + MESH_X_DIST*i; } float get_x(int i) { return MESH_MIN_X + MESH_X_DIST*i; }
float get_y(int i) { return MESH_MIN_Y + MESH_Y_DIST*i; } float get_y(int i) { return MESH_MIN_Y + MESH_Y_DIST*i; }

View file

@ -553,7 +553,9 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa
} }
#if defined(MESH_BED_LEVELING) #if defined(MESH_BED_LEVELING)
z += mbl.get_z(x, y); if (mbl.active) {
z += mbl.get_z(x, y);
}
#endif // MESH_BED_LEVELING #endif // MESH_BED_LEVELING
#ifdef ENABLE_AUTO_BED_LEVELING #ifdef ENABLE_AUTO_BED_LEVELING
@ -1095,7 +1097,9 @@ void plan_set_position(const float &x, const float &y, const float &z, const flo
#if defined(ENABLE_AUTO_BED_LEVELING) #if defined(ENABLE_AUTO_BED_LEVELING)
apply_rotation_xyz(plan_bed_level_matrix, x, y, z); apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#elif defined(MESH_BED_LEVELING) #elif defined(MESH_BED_LEVELING)
z += mbl.get_z(x, y); if (mbl.active) {
z += mbl.get_z(x, y);
}
#endif // ENABLE_AUTO_BED_LEVELING #endif // ENABLE_AUTO_BED_LEVELING
position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);

View file

@ -68,6 +68,13 @@ static void lcd_sdcard_menu();
static void lcd_delta_calibrate_menu(); static void lcd_delta_calibrate_menu();
#endif // DELTA_CALIBRATION_MENU #endif // DELTA_CALIBRATION_MENU
#if defined(MANUAL_BED_LEVELING)
#include "mesh_bed_leveling.h"
static void _lcd_level_bed();
static void _lcd_level_bed_homing();
static void lcd_level_bed();
#endif // MANUAL_BED_LEVELING
static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
/* Different types of actions that can be used in menu items. */ /* Different types of actions that can be used in menu items. */
@ -616,6 +623,10 @@ static void lcd_prepare_menu() {
#endif #endif
MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu); MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu);
#if defined(MANUAL_BED_LEVELING)
MENU_ITEM(submenu, MSG_LEVEL_BED, lcd_level_bed);
#endif
END_MENU(); END_MENU();
} }
@ -1326,7 +1337,12 @@ void lcd_update() {
#endif #endif
#ifdef ULTIPANEL #ifdef ULTIPANEL
if (currentMenu != lcd_status_screen && millis() > timeoutToStatus) { if (currentMenu != lcd_status_screen &&
#if defined(MANUAL_BED_LEVELING)
currentMenu != _lcd_level_bed &&
currentMenu != _lcd_level_bed_homing &&
#endif // MANUAL_BED_LEVELING
millis() > timeoutToStatus) {
lcd_return_to_status(); lcd_return_to_status();
lcdDrawUpdate = 2; lcdDrawUpdate = 2;
} }
@ -1745,4 +1761,75 @@ char *ftostr52(const float &x)
return conv; return conv;
} }
#if defined(MANUAL_BED_LEVELING)
static int _lcd_level_bed_position;
static void _lcd_level_bed()
{
if (encoderPosition != 0) {
refresh_cmd_timeout();
current_position[Z_AXIS] += float((int)encoderPosition) * 0.05;
if (min_software_endstops && current_position[Z_AXIS] < Z_MIN_POS) current_position[Z_AXIS] = Z_MIN_POS;
if (max_software_endstops && current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
encoderPosition = 0;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS]/60, active_extruder);
lcdDrawUpdate = 1;
}
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR("Z"), ftostr32(current_position[Z_AXIS]));
static bool debounce_click = false;
if (LCD_CLICKED) {
if (!debounce_click) {
debounce_click = true;
int ix = _lcd_level_bed_position % MESH_NUM_X_POINTS;
int iy = _lcd_level_bed_position / MESH_NUM_X_POINTS;
mbl.set_z(ix, iy, current_position[Z_AXIS]);
_lcd_level_bed_position++;
if (_lcd_level_bed_position == MESH_NUM_X_POINTS*MESH_NUM_Y_POINTS) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
mbl.active = 1;
enquecommands_P(PSTR("G28"));
lcd_return_to_status();
} else {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
ix = _lcd_level_bed_position % MESH_NUM_X_POINTS;
iy = _lcd_level_bed_position / MESH_NUM_X_POINTS;
if (iy&1) { // Zig zag
ix = (MESH_NUM_X_POINTS - 1) - ix;
}
current_position[X_AXIS] = mbl.get_x(ix);
current_position[Y_AXIS] = mbl.get_y(iy);
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
lcdDrawUpdate = 1;
}
}
} else {
debounce_click = false;
}
}
static void _lcd_level_bed_homing()
{
if (axis_known_position[X_AXIS] &&
axis_known_position[Y_AXIS] &&
axis_known_position[Z_AXIS]) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
current_position[X_AXIS] = MESH_MIN_X;
current_position[Y_AXIS] = MESH_MIN_Y;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[X_AXIS]/60, active_extruder);
_lcd_level_bed_position = 0;
lcd_goto_menu(_lcd_level_bed);
}
}
static void lcd_level_bed()
{
axis_known_position[X_AXIS] = false;
axis_known_position[Y_AXIS] = false;
axis_known_position[Z_AXIS] = false;
mbl.reset();
enquecommands_P(PSTR("G28"));
lcd_goto_menu(_lcd_level_bed_homing);
}
#endif // MANUAL_BED_LEVELING
#endif //ULTRA_LCD #endif //ULTRA_LCD