Commit bba4310c authored by Franco (nextime) Lanza's avatar Franco (nextime) Lanza

Merge remote-tracking branch 'upstream/dev' into dev

parents 79e48094 0c0cb1bd
Pipeline #74 skipped
...@@ -128,6 +128,8 @@ ...@@ -128,6 +128,8 @@
* M407 - Displays measured filament diameter * M407 - Displays measured filament diameter
* M408 - Report JSON-style response * M408 - Report JSON-style response
* M410 - Quickstop. Abort all the planned moves * M410 - Quickstop. Abort all the planned moves
* M420 - Enable/Disable Mesh Bed Leveling
* M421 - Set a single Mesh Bed Leveling Z coordinate. M421 X<mm> Y<mm> Z<mm>' or 'M421 I<xindex> J<yindex> Z<mm>
* M428 - Set the home_offset logically based on the current_position * M428 - Set the home_offset logically based on the current_position
* M500 - stores paramters in EEPROM * M500 - stores paramters in EEPROM
* M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). * M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
......
### Version 4.2.84
* Add Mesh Bed Level (MBL)
### Version 4.2.83 ### Version 4.2.83
* Add Cooler and Hot Chamber * Add Cooler and Hot Chamber
* Add Laser Beam PWM and raster base64 * Add Laser Beam PWM and raster base64
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* - Endstop pullup resistors * - Endstop pullup resistors
* - Endstops logic * - Endstops logic
* - Endstops min or max * - Endstops min or max
* - Min Z height for homing
* - Stepper enable logic * - Stepper enable logic
* - Stepper step logic * - Stepper step logic
* - Stepper direction * - Stepper direction
...@@ -104,6 +105,18 @@ ...@@ -104,6 +105,18 @@
/*****************************************************************************************/ /*****************************************************************************************/
/*****************************************************************************************
***************************** MIN Z HEIGHT FOR HOMING **********************************
*****************************************************************************************
* *
* (in mm) Minimal z height before homing (G28) for Z clearance above the bed, clamps, *
* Be sure you have this distance over your Z_MAX_POS in case. *
* *
*****************************************************************************************/
#define MIN_Z_HEIGHT_FOR_HOMING 0
/*****************************************************************************************/
/***************************************************************************************** /*****************************************************************************************
********************************* Stepper enable logic ********************************** ********************************* Stepper enable logic **********************************
***************************************************************************************** *****************************************************************************************
...@@ -233,7 +246,27 @@ ...@@ -233,7 +246,27 @@
/***************************************************************************************** /*****************************************************************************************
******************************* Auto bed levelling ************************************** ******************************* Mesh bed leveling ***************************************
*****************************************************************************************/
//#define MESH_BED_LEVELING
#define MESH_INSET 10 // Mesh inset margin on print area
#define MESH_NUM_X_POINTS 3 // Don't use more than 7 points per axis, implementation limited.
#define MESH_NUM_Y_POINTS 3
#define MESH_HOME_SEARCH_Z 5 // Z after Home, bed somewhere below but above 0.0.
// After homing all axes ('G28' or 'G28 XYZ') rest at origin [0,0,0]
//#define MESH_G28_REST_ORIGIN
// Add display menu option for bed leveling.
//#define MANUAL_BED_LEVELING
// Step size while manually probing Z axis.
#define MBL_Z_STEP 0.025
/*****************************************************************************************/
/*****************************************************************************************
******************************* Auto bed leveling ***************************************
***************************************************************************************** *****************************************************************************************
* * * *
* There are 2 different ways to specify probing locations * * There are 2 different ways to specify probing locations *
...@@ -292,9 +325,6 @@ ...@@ -292,9 +325,6 @@
#define Y_PROBE_OFFSET_FROM_EXTRUDER 0 // Y offset: -front [of the nozzle] +behind #define Y_PROBE_OFFSET_FROM_EXTRUDER 0 // Y offset: -front [of the nozzle] +behind
#define Z_PROBE_OFFSET_FROM_EXTRUDER -1 // Z offset: -below [of the nozzle] (always negative!) #define Z_PROBE_OFFSET_FROM_EXTRUDER -1 // Z offset: -below [of the nozzle] (always negative!)
#define Z_RAISE_BEFORE_HOMING 10 // (in mm) Raise Z before homing (G28) for Probe Clearance.
// Be sure you have this distance over your Z_MAX_POS in case
#define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point. #define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point.
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points #define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points
#define Z_RAISE_AFTER_PROBING 5 //How much the extruder will be raised after the last probing point. #define Z_RAISE_AFTER_PROBING 5 //How much the extruder will be raised after the last probing point.
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* - Endstop pullup resistors * - Endstop pullup resistors
* - Endstops logic * - Endstops logic
* - Endstops min or max * - Endstops min or max
* - Min Z height for homing
* - Stepper enable logic * - Stepper enable logic
* - Stepper step logic * - Stepper step logic
* - Stepper direction * - Stepper direction
...@@ -126,6 +127,18 @@ ...@@ -126,6 +127,18 @@
/*****************************************************************************************/ /*****************************************************************************************/
/*****************************************************************************************
***************************** MIN Z HEIGHT FOR HOMING **********************************
*****************************************************************************************
* *
* (in mm) Minimal z height before homing (G28) for Z clearance above the bed, clamps, *
* Be sure you have this distance over your Z_MAX_POS in case. *
* *
*****************************************************************************************/
#define MIN_Z_HEIGHT_FOR_HOMING 0
/*****************************************************************************************/
/***************************************************************************************** /*****************************************************************************************
********************************* Stepper enable logic ********************************** ********************************* Stepper enable logic **********************************
***************************************************************************************** *****************************************************************************************
...@@ -255,7 +268,27 @@ ...@@ -255,7 +268,27 @@
/***************************************************************************************** /*****************************************************************************************
******************************* Auto bed levelling ************************************** ******************************* Mesh bed leveling ***************************************
*****************************************************************************************/
//#define MESH_BED_LEVELING
#define MESH_INSET 10 // Mesh inset margin on print area
#define MESH_NUM_X_POINTS 3 // Don't use more than 7 points per axis, implementation limited.
#define MESH_NUM_Y_POINTS 3
#define MESH_HOME_SEARCH_Z 5 // Z after Home, bed somewhere below but above 0.0.
// After homing all axes ('G28' or 'G28 XYZ') rest at origin [0,0,0]
//#define MESH_G28_REST_ORIGIN
// Add display menu option for bed leveling.
//#define MANUAL_BED_LEVELING
// Step size while manually probing Z axis.
#define MBL_Z_STEP 0.025
/*****************************************************************************************/
/*****************************************************************************************
******************************* Auto bed leveling ***************************************
***************************************************************************************** *****************************************************************************************
* * * *
* There are 2 different ways to specify probing locations * * There are 2 different ways to specify probing locations *
...@@ -293,9 +326,9 @@ ...@@ -293,9 +326,9 @@
#define ABL_PROBE_PT_1_X 15 #define ABL_PROBE_PT_1_X 15
#define ABL_PROBE_PT_1_Y 180 #define ABL_PROBE_PT_1_Y 180
#define ABL_PROBE_PT_2_X 15 #define ABL_PROBE_PT_2_X 15
#define ABL_PROBE_PT_2_Y 20 #define ABL_PROBE_PT_2_Y 15
#define ABL_PROBE_PT_3_X 170 #define ABL_PROBE_PT_3_X 180
#define ABL_PROBE_PT_3_Y 20 #define ABL_PROBE_PT_3_Y 15
// no AUTO_BED_LEVELING_GRID // no AUTO_BED_LEVELING_GRID
// Offsets to the probe relative to the extruder tip (Hotend - Probe) // Offsets to the probe relative to the extruder tip (Hotend - Probe)
...@@ -314,9 +347,6 @@ ...@@ -314,9 +347,6 @@
#define Y_PROBE_OFFSET_FROM_EXTRUDER 0 // Y offset: -front [of the nozzle] +behind #define Y_PROBE_OFFSET_FROM_EXTRUDER 0 // Y offset: -front [of the nozzle] +behind
#define Z_PROBE_OFFSET_FROM_EXTRUDER -1 // Z offset: -below [of the nozzle] (always negative!) #define Z_PROBE_OFFSET_FROM_EXTRUDER -1 // Z offset: -below [of the nozzle] (always negative!)
#define Z_RAISE_BEFORE_HOMING 10 // (in mm) Raise Z before homing (G28) for Probe Clearance.
// Be sure you have this distance over your Z_MAX_POS in case
#define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point. #define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point.
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points #define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points
#define Z_RAISE_AFTER_PROBING 5 //How much the extruder will be raised after the last probing point. #define Z_RAISE_AFTER_PROBING 5 //How much the extruder will be raised after the last probing point.
...@@ -325,7 +355,7 @@ ...@@ -325,7 +355,7 @@
// Useful to retract a deployable Z probe. // Useful to retract a deployable Z probe.
//#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell //#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell
//#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pick up the sled. 0 should be fine but you can push it further if you'd like. #define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pick up the sled. 0 should be fine but you can push it further if you'd like.
/*****************************************************************************************/ /*****************************************************************************************/
...@@ -336,26 +366,26 @@ ...@@ -336,26 +366,26 @@
* If you have enabled the Auto bed levelling this add the Support for * * If you have enabled the Auto bed levelling this add the Support for *
* a dedicated Z PROBE endstop separate from the Z MIN endstop. * * a dedicated Z PROBE endstop separate from the Z MIN endstop. *
* If you would like to use both a Z PROBE and a Z MIN endstop together * * If you would like to use both a Z PROBE and a Z MIN endstop together *
* or just a Z PROBE with a custom pin, uncomment #define Z_PROBE_ENDSTOP * * or just a Z PROBE with a custom pin, uncomment #define Z PROBE ENDSTOP *
* and read the instructions below. * * and read the instructions below. *
* * * *
* If you want to still use the Z min endstop for homing, * * If you want to still use the Z min endstop for homing, *
* disable Z_SAFE_HOMING. * * disable Z SAFE HOMING. *
* Eg: to park the head outside the bed area when homing with G28. * * Eg: to park the head outside the bed area when homing with G28. *
* * * *
* WARNING: The Z MIN endstop will need to set properly as it would * * WARNING: The Z MIN endstop will need to set properly as it would *
* without a Z PROBE to prevent head crashes and premature stopping * * without a Z PROBE to prevent head crashes and premature stopping *
* during a print. * * during a print. *
* To use a separte Z PROBE endstop, you must have a Z_PROBE_PIN * * To use a separte Z PROBE endstop, you must have a Z PROBE PIN *
* defined in the pins.h file for your control board. * * defined in the pins.h file for your control board. *
* If you are using a servo based Z PROBE, you will need to enable * * If you are using a servo based Z PROBE, you will need to enable *
* NUM_SERVOS, SERVO_ENDSTOPS and SERVO_ENDSTOPS_ANGLES in * * NUM SERVOS, SERVO ENDSTOPS and SERVO ENDSTOPS ANGLES in *
* Configuration_Feature R/C Servo section. * * Configuration_Feature R/C Servo section. *
* * * *
* WARNING: Setting the wrong pin may have unexpected and potentially * * WARNING: Setting the wrong pin may have unexpected and potentially *
* disastrous outcomes. Use with caution and do your homework. * * disastrous outcomes. Use with caution and do your homework. *
* * * *
* Uncomment Z_PROBE_ENDSTOP to enable. * * Uncomment Z PROBE ENDSTOP to enable. *
* * * *
*****************************************************************************************/ *****************************************************************************************/
//#define Z_PROBE_ENDSTOP //#define Z_PROBE_ENDSTOP
...@@ -364,7 +394,7 @@ ...@@ -364,7 +394,7 @@
/***************************************************************************************** /*****************************************************************************************
******************************** Manual home positions ********************************** ******************************** Manual home positions **********************************
/*****************************************************************************************/ *****************************************************************************************/
// The position of the homing switches // The position of the homing switches
//#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used //#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used
//#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0) //#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* - Software endstops * - Software endstops
* - Endstops only for homing * - Endstops only for homing
* - Abort on endstop hit feature * - Abort on endstop hit feature
* - Mesh Level Area
* - R/C Servo * - R/C Servo
* - Late Z axis * - Late Z axis
* - Ahead slowdown * - Ahead slowdown
...@@ -437,6 +438,23 @@ ...@@ -437,6 +438,23 @@
**************************************************************************/ **************************************************************************/
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED //#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
#define ABORT_ON_ENDSTOP_HIT_INIT true #define ABORT_ON_ENDSTOP_HIT_INIT true
/**************************************************************************/
/**************************************************************************
*************************** Mesh Level Area ******************************
**************************************************************************
* *
* Default mesh area is an area with an inset margin on the print area. *
* Below are the macros that are used to define the borders for the mesh *
* area, made available here for specialized needs. *
* *
**************************************************************************/
#define MESH_MIN_X (X_MIN_POS + MESH_INSET)
#define MESH_MAX_X (X_MAX_POS - (MESH_INSET))
#define MESH_MIN_Y (Y_MIN_POS + MESH_INSET)
#define MESH_MAX_Y (Y_MAX_POS - (MESH_INSET))
/**************************************************************************/
/************************************************************************** /**************************************************************************
......
...@@ -178,6 +178,14 @@ void Config_StoreSettings() { ...@@ -178,6 +178,14 @@ void Config_StoreSettings() {
EEPROM_WRITE_VAR(i, home_offset); EEPROM_WRITE_VAR(i, home_offset);
EEPROM_WRITE_VAR(i, hotend_offset); EEPROM_WRITE_VAR(i, hotend_offset);
#if ENABLED(MESH_BED_LEVELING)
// Compile time test that sizeof(mbl.z_values) is as expected
typedef char c_assert[(sizeof(mbl.z_values) == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS) * sizeof(dummy)) ? 1 : -1];
EEPROM_WRITE_VAR(i, mbl.active);
EEPROM_WRITE_VAR(i, mbl.z_offset);
EEPROM_WRITE_VAR(i, mbl.z_values);
#endif
#if !MECH(DELTA) #if !MECH(DELTA)
EEPROM_WRITE_VAR(i, zprobe_zoffset); EEPROM_WRITE_VAR(i, zprobe_zoffset);
#endif #endif
...@@ -337,6 +345,12 @@ void Config_RetrieveSettings() { ...@@ -337,6 +345,12 @@ void Config_RetrieveSettings() {
EEPROM_READ_VAR(i, home_offset); EEPROM_READ_VAR(i, home_offset);
EEPROM_READ_VAR(i, hotend_offset); EEPROM_READ_VAR(i, hotend_offset);
#if ENABLED(MESH_BED_LEVELING)
EPROM_READ_VAR(i, mbl.active);
EEPROM_READ_VAR(i, mbl.z_offset);
EEPROM_READ_VAR(i, mbl.z_values);
#endif
#if !MECH(DELTA) #if !MECH(DELTA)
EEPROM_READ_VAR(i, zprobe_zoffset); EEPROM_READ_VAR(i, zprobe_zoffset);
#endif #endif
...@@ -539,6 +553,10 @@ void Config_ResetDefault() { ...@@ -539,6 +553,10 @@ void Config_ResetDefault() {
max_z_jerk = DEFAULT_ZJERK; max_z_jerk = DEFAULT_ZJERK;
home_offset[X_AXIS] = home_offset[Y_AXIS] = home_offset[Z_AXIS] = 0; home_offset[X_AXIS] = home_offset[Y_AXIS] = home_offset[Z_AXIS] = 0;
#if ENABLED(MESH_BED_LEVELING)
mbl.active = false;
#endif
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER; zprobe_zoffset = Z_PROBE_OFFSET_FROM_EXTRUDER;
#elif !MECH(DELTA) #elif !MECH(DELTA)
...@@ -744,6 +762,23 @@ void Config_ResetDefault() { ...@@ -744,6 +762,23 @@ void Config_ResetDefault() {
ECHO_EMV(" Z", hotend_offset[Z_AXIS][h]); ECHO_EMV(" Z", hotend_offset[Z_AXIS][h]);
} }
#if ENABLED(MESH_BED_LEVELING)
if (!forReplay) {
ECHO_LM(CFG, "Mesh bed leveling:");
}
ECHO_SMV(CFG, " M420 S", mbl.active);
ECHO_MV(" X", MESH_NUM_X_POINTS);
ECHO_EMV(" Y", MESH_NUM_Y_POINTS);
for (int py = 1; py <= MESH_NUM_Y_POINTS; py++) {
for (int px = 1; px <= MESH_NUM_X_POINTS; px++) {
ECHO_SMV(CFG, " G29 S3 X", px);
ECHO_MV(" Y", py);
ECHO_EMV(" Z", mbl.z_values[py-1][px-1], 5);
}
}
#endif
#if HEATER_USES_AD595 #if HEATER_USES_AD595
if (!forReplay) { if (!forReplay) {
ECHO_LM(CFG, "AD595 Offset and Gain:"); ECHO_LM(CFG, "AD595 Offset and Gain:");
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#define CONFIGURATION_VERSION_H #define CONFIGURATION_VERSION_H
#define FIRMWARE_NAME "MK" #define FIRMWARE_NAME "MK"
#define SHORT_BUILD_VERSION "4.2.83_dev" #define SHORT_BUILD_VERSION "4.2.84_dev"
#define BUILD_VERSION FIRMWARE_NAME "_" SHORT_BUILD_VERSION #define BUILD_VERSION FIRMWARE_NAME "_" SHORT_BUILD_VERSION
#define STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time #define STRING_DISTRIBUTION_DATE __DATE__ " " __TIME__ // build date and time
// It might also be appropriate to define a location where additional information can be found // It might also be appropriate to define a location where additional information can be found
......
...@@ -171,6 +171,8 @@ ...@@ -171,6 +171,8 @@
* M407 - Display measured filament diameter * M407 - Display measured filament diameter
* M408 - Report JSON-style response * M408 - Report JSON-style response
* M410 - Quickstop. Abort all the planned moves * M410 - Quickstop. Abort all the planned moves
* M420 - Enable/Disable Mesh Bed Leveling
* M421 - Set a single Mesh Bed Leveling Z coordinate. M421 X<mm> Y<mm> Z<mm>' or 'M421 I<xindex> J<yindex> Z<mm>
* M428 - Set the home_offset logically based on the current_position * M428 - Set the home_offset logically based on the current_position
* M500 - Store parameters in EEPROM * M500 - Store parameters in EEPROM
* M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily). * M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
......
...@@ -52,6 +52,10 @@ ...@@ -52,6 +52,10 @@
#include "module/HAL/HAL.h" #include "module/HAL/HAL.h"
#include "module/communication/communication.h" #include "module/communication/communication.h"
#if ENABLED(MESH_BED_LEVELING)
#include "module/mbl/mesh_bed_leveling.h"
#endif
#include "Configuration_Store.h" #include "Configuration_Store.h"
#include "module/language/language.h" #include "module/language/language.h"
......
...@@ -1411,7 +1411,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio ...@@ -1411,7 +1411,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio
static void set_bed_level_equation_lsq(double *plane_equation_coefficients) { static void set_bed_level_equation_lsq(double *plane_equation_coefficients) {
if (DEBUGGING(INFO)) { if (DEBUGGING(INFO)) {
plan_bed_level_matrix.set_to_identity(); plan_bed_level_matrix.set_to_identity();
vector_3 uncorrected_position = plan_get_position(); vector_3 uncorrected_position = plan_adjusted_position();
DEBUG_POS(">>> set_bed_level_equation_lsq", uncorrected_position); DEBUG_POS(">>> set_bed_level_equation_lsq", uncorrected_position);
DEBUG_POS(">>> set_bed_level_equation_lsq", current_position); DEBUG_POS(">>> set_bed_level_equation_lsq", current_position);
} }
...@@ -1424,7 +1424,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio ...@@ -1424,7 +1424,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio
//vector_3 uncorrected_position = plan_get_position_mm(); //vector_3 uncorrected_position = plan_get_position_mm();
//uncorrected_position.debug("position before"); //uncorrected_position.debug("position before");
vector_3 corrected_position = plan_get_position(); vector_3 corrected_position = plan_adjusted_position();
//corrected_position.debug("position after"); //corrected_position.debug("position after");
current_position[X_AXIS] = corrected_position.x; current_position[X_AXIS] = corrected_position.x;
current_position[Y_AXIS] = corrected_position.y; current_position[Y_AXIS] = corrected_position.y;
...@@ -1453,7 +1453,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio ...@@ -1453,7 +1453,7 @@ inline void do_blocking_move_to_z(float z) { do_blocking_move_to(current_positio
plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal); plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
vector_3 corrected_position = plan_get_position(); vector_3 corrected_position = plan_adjusted_position();
current_position[X_AXIS] = corrected_position.x; current_position[X_AXIS] = corrected_position.x;
current_position[Y_AXIS] = corrected_position.y; current_position[Y_AXIS] = corrected_position.y;
current_position[Z_AXIS] = corrected_position.z; current_position[Z_AXIS] = corrected_position.z;
...@@ -3008,7 +3008,7 @@ inline void wait_heater(bool no_wait_for_cooling = true) { ...@@ -3008,7 +3008,7 @@ inline void wait_heater(bool no_wait_for_cooling = true) {
now = millis(); now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting
next_temp_ms = now + 1000UL; next_temp_ms = now + 1000UL;
#if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675) #if HAS(TEMP_HOTEND) || HAS(TEMP_BED)
print_heaterstates(); print_heaterstates();
#endif #endif
#if TEMP_RESIDENCY_TIME > 0 #if TEMP_RESIDENCY_TIME > 0
...@@ -3083,9 +3083,7 @@ inline void wait_bed(bool no_wait_for_cooling = true) { ...@@ -3083,9 +3083,7 @@ inline void wait_bed(bool no_wait_for_cooling = true) {
now = millis(); now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up. if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up.
next_temp_ms = now + 1000UL; next_temp_ms = now + 1000UL;
#if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675)
print_heaterstates(); print_heaterstates();
#endif
#if TEMP_BED_RESIDENCY_TIME > 0 #if TEMP_BED_RESIDENCY_TIME > 0
ECHO_M(SERIAL_W); ECHO_M(SERIAL_W);
if (residency_start_ms) { if (residency_start_ms) {
...@@ -3297,26 +3295,12 @@ void gcode_get_destination() { ...@@ -3297,26 +3295,12 @@ void gcode_get_destination() {
if(code_seen(axis_codes[E_AXIS])) IDLE_OOZING_retract(false); if(code_seen(axis_codes[E_AXIS])) IDLE_OOZING_retract(false);
#endif #endif
#if HOTENDS == 1 for (int i = X_AXIS; i <= E_AXIS; i++) {
for (int i = 0; i < 3; i++) {
if (code_seen(axis_codes[i])) if (code_seen(axis_codes[i]))
destination[i] = code_value() + (axis_relative_modes[i] || relative_mode ? current_position[i] : 0); destination[i] = code_value() + (axis_relative_modes[i] || relative_mode ? current_position[i] : 0);
else else
destination[i] = current_position[i]; destination[i] = current_position[i];
} }
#else
for (int i = 0; i < 3; i++) {
if (code_seen(axis_codes[i]))
destination[i] = code_value() + (axis_relative_modes[i] || relative_mode ? current_position[i] : -hotend_offset[i][active_extruder]);
else
destination[i] = current_position[i];
}
#endif
if(code_seen(axis_codes[E_AXIS]))
destination[E_AXIS] = code_value() + (axis_relative_modes[E_AXIS] || relative_mode ? current_position[E_AXIS] : 0);
else
destination[E_AXIS] = current_position[E_AXIS];
if (code_seen('F')) { if (code_seen('F')) {
float next_feedrate = code_value(); float next_feedrate = code_value();
...@@ -3676,6 +3660,10 @@ inline void gcode_G28() { ...@@ -3676,6 +3660,10 @@ inline void gcode_G28() {
// Wait for planner moves to finish! // Wait for planner moves to finish!
st_synchronize(); st_synchronize();
#if EXTRUDERS > 1
active_extruder = active_driver = 0;
#endif
// For auto bed leveling, clear the level matrix // For auto bed leveling, clear the level matrix
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
plan_bed_level_matrix.set_to_identity(); plan_bed_level_matrix.set_to_identity();
...@@ -3683,6 +3671,15 @@ inline void gcode_G28() { ...@@ -3683,6 +3671,15 @@ inline void gcode_G28() {
reset_bed_level(); reset_bed_level();
#endif #endif
/**
* For mesh bed leveling deactivate the mesh calculations, will be turned
* on again when homing all axis
*/
#if ENABLED(MESH_BED_LEVELING)
uint8_t mbl_was_active = mbl.active;
mbl.active = false;
#endif
setup_for_endstop_move(); setup_for_endstop_move();
/** /**
...@@ -3731,30 +3728,38 @@ inline void gcode_G28() { ...@@ -3731,30 +3728,38 @@ inline void gcode_G28() {
#else // NOT DELTA #else // NOT DELTA
if (home_all_axis || homeZ) {
#if Z_HOME_DIR > 0 // If homing away from BED do Z first #if Z_HOME_DIR > 0 // If homing away from BED do Z first
if (home_all_axis || homeZ) {
HOMEAXIS(Z); HOMEAXIS(Z);
if (DEBUGGING(INFO)) if (DEBUGGING(INFO))
DEBUG_POS(" > HOMEAXIS(Z)", current_position); DEBUG_POS(" > HOMEAXIS(Z)", current_position);
}
#elif DISABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE) && Z_RAISE_BEFORE_HOMING > 0 #elif ENABLED(MIN_Z_HEIGHT_FOR_HOMING) && MIN_Z_HEIGHT_FOR_HOMING > 0
// Raise Z before homing any other axes // Raise Z before homing any other axes and z is not already high enough (never lower z)
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed if (current_position[Z_AXIS] <= MIN_Z_HEIGHT_FOR_HOMING) {
destination[Z_AXIS] = MIN_Z_HEIGHT_FOR_HOMING;
feedrate = max_feedrate[Z_AXIS] * 60; // feedrate (mm/m) = max_feedrate (mm/s)
if (DEBUGGING(INFO)) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_EMV("Raise Z (before homing) to ", (MIN_Z_HEIGHT_FOR_HOMING));
DEBUG_POS(" > (home_all_axis || homeZ)", destination); DEBUG_POS("> (home_all_axis || homeZ)", current_position);
DEBUG_POS("> (home_all_axis || homeZ)", destination);
} }
feedrate = max_feedrate[Z_AXIS] * 60;
line_to_destination(); line_to_destination();
st_synchronize(); st_synchronize();
/**
* Update the current Z position even if it currently not real from
* Z-home otherwise each call to line_to_destination() will want to
* move Z-axis by MIN_Z_HEIGHT_FOR_HOMING.
*/
current_position[Z_AXIS] = destination[Z_AXIS];
}
#endif #endif
} // home_all_axis || homeZ
#if ENABLED(QUICK_HOME) #if ENABLED(QUICK_HOME)
if (home_all_axis || (homeX && homeY)) { // First diagonal move if (home_all_axis || (homeX && homeY)) { // First diagonal move
...@@ -3849,116 +3854,27 @@ inline void gcode_G28() { ...@@ -3849,116 +3854,27 @@ inline void gcode_G28() {
// Home Z last if homing towards the bed // Home Z last if homing towards the bed
#if Z_HOME_DIR < 0 #if Z_HOME_DIR < 0
#if DISABLED(Z_SAFE_HOMING)
if (code_seen('M') && !(homeX || homeY)) {
// Manual G28 bed level
#if ENABLED(ULTIPANEL)
ECHO_LM(DB, "--LEVEL PLATE SCRIPT--");
while(!lcd_clicked()) {
idle();
}
saved_feedrate = feedrate;
saved_feedrate_multiplier = feedrate_multiplier;
feedrate_multiplier = 100;
refresh_cmd_timeout();
endstops.enable(); if (home_all_axis || homeZ) {
for(uint8_t i = 0; i < NUM_AXIS; i++) {
destination[i] = current_position[i];
}
feedrate = 0.0;
#if Z_HOME_DIR > 0 // If homing away from BED do Z first
HOMEAXIS(Z);
#endif
HOMEAXIS(X);
HOMEAXIS(Y);
#if Z_HOME_DIR < 0
HOMEAXIS(Z);
#endif
sync_plan_position();
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
endstops.enable(false);
#endif
feedrate = saved_feedrate;
feedrate_multiplier = saved_feedrate_multiplier;
refresh_cmd_timeout();
endstops.hit_on_purpose(); // clear endstop hit flags
sync_plan_position();
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
// PROBE FIRST POINT
set_pageShowInfo(1);
do_blocking_move_to(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) {
idle();
}
// PROBE SECOND POINT
set_pageShowInfo(2);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
do_blocking_move_to(RIGHT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) {
idle();
}
// PROBE THIRD POINT
set_pageShowInfo(3);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
do_blocking_move_to(RIGHT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) {
idle();
}
// PROBE FOURTH POINT
set_pageShowInfo(4);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
do_blocking_move_to(LEFT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) {
idle();
}
// PROBE CENTER
set_pageShowInfo(5);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
do_blocking_move_to(((X_MAX_POS) - (X_MIN_POS)) / 2, ((Y_MAX_POS) - (Y_MIN_POS)) / 2, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) {
idle();
}
// FINISH MANUAL BED LEVEL #if ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated.
set_pageShowInfo(6);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
enqueue_and_echo_commands_P(PSTR("G28"));
#endif // ULTIPANEL
}
else if (home_all_axis || homeZ) {
HOMEAXIS(Z);
if (DEBUGGING(INFO))
DEBUG_POS(" > (home_all_axis || homeZ) > final", current_position);
}
#elif ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated.
if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
if (home_all_axis) { if (home_all_axis) {
current_position[Z_AXIS] = 0; /**
* At this point we already have Z at MIN_Z_HEIGHT_FOR_HOMING height
* No need to move Z any more as this height should already be safe
* enough to reach Z_SAFE_HOMING XY positions.
* Just make sure the planner is in sync.
*/
sync_plan_position(); sync_plan_position();
// /**
// Set the probe (or just the nozzle) destination to the safe homing point * Set the Z probe (or just the nozzle) destination to the safe
// * homing point
// NOTE: If current_position[X_AXIS] or current_position[Y_AXIS] were set above */
// then this may not work as expected.
destination[X_AXIS] = round(Z_SAFE_HOMING_X_POINT - (X_PROBE_OFFSET_FROM_EXTRUDER)); destination[X_AXIS] = round(Z_SAFE_HOMING_X_POINT - (X_PROBE_OFFSET_FROM_EXTRUDER));
destination[Y_AXIS] = round(Z_SAFE_HOMING_Y_POINT - (Y_PROBE_OFFSET_FROM_EXTRUDER)); destination[Y_AXIS] = round(Z_SAFE_HOMING_Y_POINT - (Y_PROBE_OFFSET_FROM_EXTRUDER));
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
...@@ -3966,18 +3882,21 @@ inline void gcode_G28() { ...@@ -3966,18 +3882,21 @@ inline void gcode_G28() {
if (DEBUGGING(INFO)) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_LMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
DEBUG_POS(" > home_all_axis", current_position); DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
DEBUG_POS(" > home_all_axis", destination); DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
} }
// This could potentially move X, Y, Z all together // Move in the XY plane
line_to_destination(); line_to_destination();
st_synchronize(); st_synchronize();
// Set current X, Y is the Z_SAFE_HOMING_POINT minus PROBE_OFFSET_FROM_EXTRUDER /**
* Update the current positions for XY
*/
current_position[X_AXIS] = destination[X_AXIS]; current_position[X_AXIS] = destination[X_AXIS];
current_position[Y_AXIS] = destination[Y_AXIS]; current_position[Y_AXIS] = destination[Y_AXIS];
// Home the Z axis
HOMEAXIS(Z); HOMEAXIS(Z);
} }
else if (homeZ) { // Don't need to Home Z twice else if (homeZ) { // Don't need to Home Z twice
...@@ -3985,29 +3904,16 @@ inline void gcode_G28() { ...@@ -3985,29 +3904,16 @@ inline void gcode_G28() {
// Let's see if X and Y are homed // Let's see if X and Y are homed
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) { if (axis_homed[X_AXIS] && axis_homed[Y_AXIS]) {
// Make sure the probe is within the physical limits /**
// NOTE: This doesn't necessarily ensure the probe is also within the bed! * Make sure the Z probe is within the physical limits
* NOTE: This doesn't necessarily ensure the Z probe is also
* within the bed!
*/
float cpx = current_position[X_AXIS], cpy = current_position[Y_AXIS]; float cpx = current_position[X_AXIS], cpy = current_position[Y_AXIS];
if ( cpx >= X_MIN_POS - (X_PROBE_OFFSET_FROM_EXTRUDER) if ( cpx >= X_MIN_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
&& cpx <= X_MAX_POS - (X_PROBE_OFFSET_FROM_EXTRUDER) && cpx <= X_MAX_POS - (X_PROBE_OFFSET_FROM_EXTRUDER)
&& cpy >= Y_MIN_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER) && cpy >= Y_MIN_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)
&& cpy <= Y_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) { && cpy <= Y_MAX_POS - (Y_PROBE_OFFSET_FROM_EXTRUDER)) {
// Set the plan current position to X, Y, 0
current_position[Z_AXIS] = 0;
plan_set_position(cpx, cpy, 0, current_position[E_AXIS]);
// Set Z destination away from bed and raise the axis
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
feedrate = max_feedrate[Z_AXIS] * 60;
if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
DEBUG_POS(" > homeZ", current_position);
DEBUG_POS(" > homeZ", destination);
}
line_to_destination();
st_synchronize();
// Home the Z axis // Home the Z axis
HOMEAXIS(Z); HOMEAXIS(Z);
...@@ -4020,9 +3926,12 @@ inline void gcode_G28() { ...@@ -4020,9 +3926,12 @@ inline void gcode_G28() {
else { else {
axis_unhomed_error(); axis_unhomed_error();
} }
} } // !home_all_axes && homeZ
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#elif ENABLED(Z_SAFE_HOMING) #elif ENABLED(Z_SAFE_HOMING)
if (home_all_axis || homeZ) { if (home_all_axis || homeZ) {
if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
...@@ -4038,8 +3947,8 @@ inline void gcode_G28() { ...@@ -4038,8 +3947,8 @@ inline void gcode_G28() {
feedrate = xy_travel_speed; feedrate = xy_travel_speed;
if (DEBUGGING(INFO)) { if (DEBUGGING(INFO)) {
DEBUG_POS(" > home_all_axis", current_position); DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
DEBUG_POS(" > home_all_axis", destination); DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
} }
// This could potentially move X, Y, Z all together // This could potentially move X, Y, Z all together
...@@ -4056,8 +3965,19 @@ inline void gcode_G28() { ...@@ -4056,8 +3965,19 @@ inline void gcode_G28() {
ECHO_LM(ER, MSG_POSITION_UNKNOWN); ECHO_LM(ER, MSG_POSITION_UNKNOWN);
} }
} }
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#endif // Z_SAFE_HOMING
#else // !Z_SAFE_HOMING
HOMEAXIS(Z);
#endif // !Z_SAFE_HOMING
if (DEBUGGING(INFO)) DEBUG_POS("> (home_all_axis || homeZ) > final", current_position);
}
#endif // Z_HOME_DIR < 0 #endif // Z_HOME_DIR < 0
sync_plan_position(); sync_plan_position();
...@@ -4068,7 +3988,30 @@ inline void gcode_G28() { ...@@ -4068,7 +3988,30 @@ inline void gcode_G28() {
sync_plan_position_delta(); sync_plan_position_delta();
#endif #endif
clean_up_after_endstop_move(); #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
endstops.enable(false);
if (DEBUGGING(INFO))
ECHO_LM(INFO, "ENDSTOPS_ONLY_FOR_HOMING endstops.enable(false)");
#endif
// Enable mesh leveling again
#if ENABLED(MESH_BED_LEVELING)
if (mbl_was_active && home_all_axis) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
sync_plan_position();
mbl.active = 1;
#if ENABLED(MESH_G28_REST_ORIGIN)
current_position[Z_AXIS] = 0.0;
set_destination_to_current();
feedrate = homing_feedrate[Z_AXIS];
line_to_destination();
st_synchronize();
#endif
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(INFO)) DEBUG_POS("mbl_was_active", current_position);
#endif
}
#endif
if(come_back) { if(come_back) {
#if MECH(DELTA) #if MECH(DELTA)
...@@ -4106,11 +4049,189 @@ inline void gcode_G28() { ...@@ -4106,11 +4049,189 @@ inline void gcode_G28() {
#endif #endif
#endif #endif
feedrate = saved_feedrate;
feedrate_multiplier = saved_feedrate_multiplier;
refresh_cmd_timeout();
endstops.hit_on_purpose(); // clear endstop hit flags
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G28"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G28");
report_current_position(); report_current_position();
} }
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(MESH_BED_LEVELING)
enum MeshLevelingState { MeshReport, MeshStart, MeshNext, MeshSet, MeshSetZOffset };
inline void _mbl_goto_xy(float x, float y) {
saved_feedrate = feedrate;
feedrate = homing_feedrate[X_AXIS];
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
#if MIN_Z_HEIGHT_FOR_HOMING > 0
+ MIN_Z_HEIGHT_FOR_HOMING
#endif
;
line_to_current_position();
current_position[X_AXIS] = x + home_offset[X_AXIS];
current_position[Y_AXIS] = y + home_offset[Y_AXIS];
line_to_current_position();
#if MIN_Z_HEIGHT_FOR_HOMING > 0
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
line_to_current_position();
#endif
feedrate = saved_feedrate;
st_synchronize();
}
/**
* G29: Mesh-based Z probe, probes a grid and produces a
* mesh to compensate for variable bed height
*
* Parameters With MESH_BED_LEVELING:
*
* S0 Produce a mesh report
* S1 Start probing mesh points
* S2 Probe the next mesh point
* S3 Xn Yn Zn.nn Manually modify a single point
* S4 Zn.nn Set z offset. Positive away from bed, negative closer to bed.
*
* The S0 report the points as below
*
* +----> X-axis 1-n
* |
* |
* v Y-axis 1-n
*
*/
inline void gcode_G29() {
static int probe_point = -1;
MeshLevelingState state = code_seen('S') ? (MeshLevelingState)code_value_short() : MeshReport;
if (state < 0 || state > 4) {
ECHO_M("S out of range (0-4).");
return;
}
int8_t px, py;
float z;
switch (state) {
case MeshReport:
if (mbl.active) {
ECHO_MV("Num X,Y: ", MESH_NUM_X_POINTS);
ECHO_C(',');
ECHO_V(MESH_NUM_Y_POINTS);
ECHO_MV("\nZ search height: ", MESH_HOME_SEARCH_Z);
ECHO_MV("\nZ offset: ", mbl.z_offset, 5);
ECHO_EM("\nMeasured points:");
for (py = 0; py < MESH_NUM_Y_POINTS; py++) {
for (px = 0; px < MESH_NUM_X_POINTS; px++) {
ECHO_MV(" ", mbl.z_values[py][px], 5);
}
ECHO_E;
}
}
else
ECHO_EM("Mesh bed leveling not active.");
break;
case MeshStart:
mbl.reset();
probe_point = 0;
enqueue_and_echo_commands_P(PSTR("G28\nG29 S2"));
break;
case MeshNext:
if (probe_point < 0) {
ECHO_EM("Start mesh probing with \"G29 S1\" first.");
return;
}
// For each G29 S2...
if (probe_point == 0) {
// For the intial G29 S2 make Z a positive value (e.g., 4.0)
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
sync_plan_position();
}
else {
// For G29 S2 after adjusting Z.
mbl.set_zigzag_z(probe_point - 1, current_position[Z_AXIS]);
}
// If there's another point to sample, move there with optional lift.
if (probe_point < (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
mbl.zigzag(probe_point, px, py);
_mbl_goto_xy(mbl.get_probe_x(px), mbl.get_probe_y(py));
probe_point++;
}
else {
// One last "return to the bed" (as originally coded) at completion
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
#if MIN_Z_HEIGHT_FOR_HOMING > 0
+ MIN_Z_HEIGHT_FOR_HOMING
#endif
;
line_to_current_position();
st_synchronize();
// After recording the last point, activate the mbl and home
ECHO_EM("Mesh probing done.");
probe_point = -1;
mbl.active = true;
enqueue_and_echo_commands_P(PSTR("G28"));
}
break;
case MeshSet:
if (code_seen('X')) {
px = code_value_long() - 1;
if (px < 0 || px >= MESH_NUM_X_POINTS) {
ECHO_M("X out of range (1-" STRINGIFY(MESH_NUM_X_POINTS) ").\n");
return;
}
}
else {
ECHO_M("X not entered.\n");
return;
}
if (code_seen('Y')) {
py = code_value_long() - 1;
if (py < 0 || py >= MESH_NUM_Y_POINTS) {
ECHO_M("Y out of range (1-" STRINGIFY(MESH_NUM_Y_POINTS) ").\n");
return;
}
}
else {
ECHO_M("Y not entered.\n");
return;
}
if (code_seen('Z')) {
z = code_value();
}
else {
ECHO_M("Z not entered.\n");
return;
}
mbl.z_values[py][px] = z;
break;
case MeshSetZOffset:
if (code_seen('Z')) {
z = code_value();
}
else {
ECHO_M("Z not entered.\n");
return;
}
mbl.z_offset = z;
} // switch(state)
report_current_position();
}
#elif ENABLED(AUTO_BED_LEVELING_FEATURE)
void out_of_range_error(const char* p_edge) { void out_of_range_error(const char* p_edge) {
ECHO_M("?Probe "); ECHO_M("?Probe ");
...@@ -4237,7 +4358,7 @@ inline void gcode_G28() { ...@@ -4237,7 +4358,7 @@ inline void gcode_G28() {
// vector_3 corrected_position = plan_get_position_mm(); // vector_3 corrected_position = plan_get_position_mm();
// corrected_position.debug("position before G29"); // corrected_position.debug("position before G29");
vector_3 uncorrected_position = plan_get_position(); vector_3 uncorrected_position = plan_adjusted_position();
// uncorrected_position.debug("position during G29"); // uncorrected_position.debug("position during G29");
current_position[X_AXIS] = uncorrected_position.x; current_position[X_AXIS] = uncorrected_position.x;
current_position[Y_AXIS] = uncorrected_position.y; current_position[Y_AXIS] = uncorrected_position.y;
...@@ -4442,7 +4563,7 @@ inline void gcode_G28() { ...@@ -4442,7 +4563,7 @@ inline void gcode_G28() {
float x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER, float x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER,
y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER, y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER,
z_tmp = current_position[Z_AXIS], z_tmp = current_position[Z_AXIS],
real_z = st_get_axis_position_mm(Z_AXIS); //get the real Z (since plan_get_position is now correcting the plane) real_z = st_get_axis_position_mm(Z_AXIS); //get the real Z (since plan_adjusted_position is now correcting the plane)
if (DEBUGGING(INFO)) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp); ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp);
...@@ -4867,7 +4988,9 @@ inline void gcode_G92() { ...@@ -4867,7 +4988,9 @@ inline void gcode_G92() {
current_position[i] = v; current_position[i] = v;
if (i == E_AXIS) { if (i == E_AXIS) {
#if DISABLED(MUVE_Z_PEEL)
plan_set_e_position(v); plan_set_e_position(v);
#endif
} }
else { else {
position_shift[i] += v - p; // Offset the coordinate space position_shift[i] += v - p; // Offset the coordinate space
...@@ -7294,6 +7417,47 @@ inline void gcode_M400() { st_synchronize(); } ...@@ -7294,6 +7417,47 @@ inline void gcode_M400() { st_synchronize(); }
*/ */
inline void gcode_M410() { quickStop(); } inline void gcode_M410() { quickStop(); }
#if ENABLED(MESH_BED_LEVELING)
/**
* M420: Enable/Disable Mesh Bed Leveling
*/
inline void gcode_M420() { if (code_seen('S') && code_has_value()) mbl.active = !!code_value_short(); }
/**
* M421: Set a single Mesh Bed Leveling Z coordinate
* Use either 'M421 X<mm> Y<mm> Z<mm>' or 'M421 I<xindex> J<yindex> Z<mm>'
*/
inline void gcode_M421() {
int8_t px, py;
float z = 0;
bool hasX, hasY, hasZ, hasI, hasJ;
if ((hasX = code_seen('X'))) px = mbl.probe_index_x(code_value());
if ((hasY = code_seen('Y'))) py = mbl.probe_index_y(code_value());
if ((hasI = code_seen('I'))) px = code_value();
if ((hasJ = code_seen('J'))) py = code_value();
if ((hasZ = code_seen('Z'))) z = code_value();
if (hasX && hasY && hasZ) {
if (px >= 0 && py >= 0)
mbl.set_z(px, py, z);
else {
ECHO_LM(ER, SERIAL_ERR_MESH_XY);
}
}
else if (hasI && hasJ && hasZ) {
if (px >= 0 && px < MESH_NUM_X_POINTS && py >= 0 && py < MESH_NUM_Y_POINTS)
mbl.set_z(px, py, z);
else {
ECHO_LM(ER, SERIAL_ERR_MESH_XY);
}
}
else {
ECHO_LM(ER, SERIAL_ERR_M421_PARAMETERS);
}
}
#endif
/** /**
* M428: Set home_offset based on the distance between the * M428: Set home_offset based on the distance between the
* current_position and the nearest "reference point." * current_position and the nearest "reference point."
...@@ -7959,6 +8123,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -7959,6 +8123,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
{ {
// Save current position to return to after applying extruder offset // Save current position to return to after applying extruder offset
set_destination_to_current(); set_destination_to_current();
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() && if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() &&
(delayed_move_time != 0 || current_position[X_AXIS] != x_home_pos(active_extruder))) { (delayed_move_time != 0 || current_position[X_AXIS] != x_home_pos(active_extruder))) {
...@@ -7983,10 +8148,12 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -7983,10 +8148,12 @@ inline void gcode_T(uint8_t tmp_extruder) {
} }
else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) { else if (dual_x_carriage_mode == DXC_DUPLICATION_MODE) {
active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
if (active_extruder == 0 || active_extruder_parked) if (active_extruder == 0 || active_extruder_parked)
current_position[X_AXIS] = inactive_extruder_x_pos; current_position[X_AXIS] = inactive_extruder_x_pos;
else else
current_position[X_AXIS] = destination[X_AXIS] + duplicate_hotend_x_offset; current_position[X_AXIS] = destination[X_AXIS] + duplicate_hotend_x_offset;
inactive_extruder_x_pos = destination[X_AXIS]; inactive_extruder_x_pos = destination[X_AXIS];
extruder_duplication_enabled = false; extruder_duplication_enabled = false;
} }
...@@ -7997,14 +8164,12 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -7997,14 +8164,12 @@ inline void gcode_T(uint8_t tmp_extruder) {
active_extruder_parked = true; active_extruder_parked = true;
delayed_move_time = 0; delayed_move_time = 0;
} }
#else // !DUAL_X_CARRIAGE
#if ENABLED(MKR4) #elif ENABLED(MKR4)
#if (EXTRUDERS == 4) && HAS(E0E2) && HAS(E1E3) && (DRIVER_EXTRUDERS == 2) #if (EXTRUDERS == 4) && HAS(E0E2) && HAS(E1E3) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
disable_e(); disable_e();
switch(target_extruder) switch(target_extruder) {
{
case 0: case 0:
WRITE_RELE(E0E2_CHOICE_PIN, LOW); WRITE_RELE(E0E2_CHOICE_PIN, LOW);
WRITE_RELE(E1E3_CHOICE_PIN, LOW); WRITE_RELE(E1E3_CHOICE_PIN, LOW);
...@@ -8037,8 +8202,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -8037,8 +8202,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
#elif (EXTRUDERS == 4) && HAS(E0E1) && HAS(E0E2) && HAS(E0E3) && (DRIVER_EXTRUDERS == 1) #elif (EXTRUDERS == 4) && HAS(E0E1) && HAS(E0E2) && HAS(E0E3) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
disable_e(); disable_e();
switch(target_extruder) switch(target_extruder) {
{
case 0: case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW); WRITE_RELE(E0E1_CHOICE_PIN, LOW);
WRITE_RELE(E0E2_CHOICE_PIN, LOW); WRITE_RELE(E0E2_CHOICE_PIN, LOW);
...@@ -8075,8 +8239,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -8075,8 +8239,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
#elif (EXTRUDERS == 3) && HAS(E0E2) && (DRIVER_EXTRUDERS == 2) #elif (EXTRUDERS == 3) && HAS(E0E2) && (DRIVER_EXTRUDERS == 2)
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
disable_e(); disable_e();
switch(target_extruder) switch(target_extruder) {
{
case 0: case 0:
WRITE_RELE(E0E2_CHOICE_PIN, LOW); WRITE_RELE(E0E2_CHOICE_PIN, LOW);
active_driver = 0; active_driver = 0;
...@@ -8099,8 +8262,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -8099,8 +8262,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
#elif (EXTRUDERS == 3) && HAS(E0E1) && HAS(E0E2) && (DRIVER_EXTRUDERS == 1) #elif (EXTRUDERS == 3) && HAS(E0E1) && HAS(E0E2) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
disable_e(); disable_e();
switch(target_extruder) switch(target_extruder) {
{
case 0: case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW); WRITE_RELE(E0E1_CHOICE_PIN, LOW);
WRITE_RELE(E0E2_CHOICE_PIN, LOW); WRITE_RELE(E0E2_CHOICE_PIN, LOW);
...@@ -8126,8 +8288,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -8126,8 +8288,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
#elif (EXTRUDERS == 2) && HAS(E0E1) && (DRIVER_EXTRUDERS == 1) #elif (EXTRUDERS == 2) && HAS(E0E1) && (DRIVER_EXTRUDERS == 1)
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
disable_e(); disable_e();
switch(target_extruder) switch(target_extruder) {
{
case 0: case 0:
WRITE_RELE(E0E1_CHOICE_PIN, LOW); WRITE_RELE(E0E1_CHOICE_PIN, LOW);
active_driver = 0; active_driver = 0;
...@@ -8142,62 +8303,111 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -8142,62 +8303,111 @@ inline void gcode_T(uint8_t tmp_extruder) {
break; break;
} }
#endif // E0E1_CHOICE_PIN E0E2_CHOICE_PIN E1E3_CHOICE_PIN #endif // E0E1_CHOICE_PIN E0E2_CHOICE_PIN E1E3_CHOICE_PIN
previous_extruder = active_extruder; previous_extruder = active_extruder;
active_extruder = target_extruder; active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver); ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder); ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#elif ENABLED(NPR2) #elif ENABLED(NPR2)
long csteps; long csteps;
st_synchronize(); // Finish all movement st_synchronize(); // Finish all movement
if (old_color == 99) {
if (old_color == 99)
csteps = (color_position[target_extruder]) * color_step_moltiplicator; csteps = (color_position[target_extruder]) * color_step_moltiplicator;
} else
else {
csteps = (color_position[target_extruder] - color_position[old_color]) * color_step_moltiplicator; csteps = (color_position[target_extruder] - color_position[old_color]) * color_step_moltiplicator;
}
if (csteps < 0) colorstep(-csteps, false); if (csteps < 0) colorstep(-csteps, false);
if (csteps > 0) colorstep(csteps, true); if (csteps > 0) colorstep(csteps, true);
previous_extruder = active_extruder; previous_extruder = active_extruder;
old_color = active_extruder = target_extruder; old_color = active_extruder = target_extruder;
active_driver = 0; active_driver = 0;
ECHO_LMV(DB, SERIAL_ACTIVE_COLOR, (int)active_extruder); ECHO_LMV(DB, SERIAL_ACTIVE_COLOR, (int)active_extruder);
#elif HAS(DONDOLO) #elif HAS(DONDOLO)
float diff;
st_synchronize(); st_synchronize();
servo[DONDOLO_SERVO_INDEX].attach(0); servo[DONDOLO_SERVO_INDEX].attach(0);
if (target_extruder == 0) {
servo[DONDOLO_SERVO_INDEX].write(DONDOLO_SERVOPOS_E0); for (int i = X_AXIS; i <= Z_AXIS; i++) {
diff = hotend_offset[i][target_extruder] - hotend_offset[i][active_extruder];
current_position[i] += diff;
position_shift[i] += diff; // Offset the coordinate space
update_software_endstops((AxisEnum)i);
} }
else if (target_extruder == 1) {
servo[DONDOLO_SERVO_INDEX].write(DONDOLO_SERVOPOS_E1); // Raise Z before switch servo
if (diff < 0) {
#if MECH(DELTA)
sync_plan_position_delta();
#else
sync_plan_position();
#endif
// Move to the "old position" (move the extruder into place)
if (IsRunning()) prepare_move();
} }
if (target_extruder == 0)
servo[DONDOLO_SERVO_INDEX].write(DONDOLO_SERVOPOS_E0);
else if (target_extruder == 1)
servo[DONDOLO_SERVO_INDEX].write(DONDOLO_SERVOPOS_E1);
#if (DONDOLO_SERVO_DELAY > 0) #if (DONDOLO_SERVO_DELAY > 0)
delay_ms(DONDOLO_SERVO_DELAY); delay_ms(DONDOLO_SERVO_DELAY);
servo[DONDOLO_SERVO_INDEX].detach(); servo[DONDOLO_SERVO_INDEX].detach();
#endif #endif
if (diff >= 0) {
#if MECH(DELTA)
sync_plan_position_delta();
#else
sync_plan_position();
#endif
// Move to the "old position" (move the extruder into place)
if (IsRunning()) prepare_move();
}
previous_extruder = active_extruder; previous_extruder = active_extruder;
#if ENABLED(DONDOLO_SINGLE_MOTOR) #if ENABLED(DONDOLO_SINGLE_MOTOR)
active_extruder = target_extruder; active_extruder = target_extruder;
active_driver = 0; active_driver = 0;
#elif ENABLED(DONDOLO_DUAL_MOTOR) #elif ENABLED(DONDOLO_DUAL_MOTOR)
active_driver = active_extruder = target_extruder; active_driver = active_extruder = target_extruder;
#endif #endif
set_stepper_direction(true); set_stepper_direction(true);
ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver); ECHO_LMV(DB, SERIAL_ACTIVE_DRIVER, (int)active_driver);
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder); ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#else #else
// The newly-selected extruder is actually at...
for (int i = X_AXIS; i <= Z_AXIS; i++) {
float diff = hotend_offset[i][target_extruder] - hotend_offset[i][active_extruder];
current_position[i] += diff;
position_shift[i] += diff; // Offset the coordinate space
update_software_endstops((AxisEnum)i);
}
previous_extruder = active_extruder; previous_extruder = active_extruder;
active_driver = active_extruder = target_extruder; active_driver = active_extruder = target_extruder;
ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder); ECHO_LMV(DB, SERIAL_ACTIVE_EXTRUDER, (int)active_extruder);
#endif // end MKR4 || NPR2 || DONDOLO #endif
#endif // end no DUAL_X_CARRIAGE
#if MECH(DELTA) || MECH(SCARA) // Tell the planner the new "current position"
#if MECH(DELTA)
sync_plan_position_delta(); sync_plan_position_delta();
#else // NO DELTA // Move to the "old position" (move the extruder into place)
if (IsRunning()) prepare_move();
#elif HASNT(DONDOLO) // NO DONDOLO
sync_plan_position(); sync_plan_position();
#endif // !DELTA // Move to the "old position" (move the extruder into place)
// Move to the old position if 'F' was in the parameters
if (IsRunning()) prepare_move(); if (IsRunning()) prepare_move();
#endif // !DELTA
} }
#if ENABLED(EXT_SOLENOID) #if ENABLED(EXT_SOLENOID)
...@@ -8274,7 +8484,7 @@ void process_next_command() { ...@@ -8274,7 +8484,7 @@ void process_next_command() {
switch(command_code) { switch(command_code) {
case 'G': switch (codenum) { case 'G': switch (codenum) {
// G0 -> G1 // G0, G1
case 0: case 0:
case 1: case 1:
gcode_G0_G1(codenum == 1); break; gcode_G0_G1(codenum == 1); break;
...@@ -8306,14 +8516,17 @@ void process_next_command() { ...@@ -8306,14 +8516,17 @@ void process_next_command() {
case 10: // G10: retract case 10: // G10: retract
case 11: // G11: retract_recover case 11: // G11: retract_recover
gcode_G10_G11(codenum == 10); break; gcode_G10_G11(codenum == 10); break;
#endif //FWRETRACT #endif // FWRETRACT
case 28: //G28: Home all axes, one at a time case 28: //G28: Home all axes, one at a time
gcode_G28(); break; gcode_G28(); break;
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(MESH_BED_LEVELING)
case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points. case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points.
gcode_G29(); break; gcode_G29(); break;
#endif
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#if HASNT(Z_PROBE_SLED) #if HASNT(Z_PROBE_SLED)
case 30: // G30 Single Z Probe case 30: // G30 Single Z Probe
gcode_G30(); break; gcode_G30(); break;
...@@ -8715,6 +8928,13 @@ void process_next_command() { ...@@ -8715,6 +8928,13 @@ void process_next_command() {
case 410: // M410 quickstop - Abort all the planned moves. case 410: // M410 quickstop - Abort all the planned moves.
gcode_M410(); break; gcode_M410(); break;
#if ENABLED(MESH_BED_LEVELING)
case 420: // M420 Enable/Disable Mesh Bed Leveling
gcode_M420(); break;
case 421: // M421 Set a Mesh Bed Leveling Z coordinate
gcode_M421(); break;
#endif
case 428: // M428 Apply current_position to home_offset case 428: // M428 Apply current_position to home_offset
gcode_M428(); break; gcode_M428(); break;
...@@ -8837,16 +9057,7 @@ void clamp_to_software_endstops(float target[3]) { ...@@ -8837,16 +9057,7 @@ void clamp_to_software_endstops(float target[3]) {
NOLESS(target[X_AXIS], sw_endstop_min[X_AXIS]); NOLESS(target[X_AXIS], sw_endstop_min[X_AXIS]);
NOLESS(target[Y_AXIS], sw_endstop_min[Y_AXIS]); NOLESS(target[Y_AXIS], sw_endstop_min[Y_AXIS]);
#if !ENABLED(LASERBEAM) #if !ENABLED(LASERBEAM)
float negative_z_offset = 0; NOLESS(target[Z_AXIS], sw_endstop_min[Z_AXIS]);
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
if (zprobe_zoffset < 0) negative_z_offset += zprobe_zoffset;
if (home_offset[Z_AXIS] < 0) {
if (DEBUGGING(INFO))
ECHO_LMV(INFO, "> clamp_to_software_endstops > Add home_offset[Z_AXIS]:", home_offset[Z_AXIS]);
negative_z_offset += home_offset[Z_AXIS];
}
#endif
NOLESS(target[Z_AXIS], sw_endstop_min[Z_AXIS] + negative_z_offset);
#endif #endif
} }
...@@ -8884,6 +9095,87 @@ static void report_current_position() { ...@@ -8884,6 +9095,87 @@ static void report_current_position() {
#endif #endif
} }
#if ENABLED(MESH_BED_LEVELING)
// This function is used to split lines on mesh borders so each segment is only part of one mesh area
void mesh_buffer_line(float x, float y, float z, const float e, float feed_rate, const uint8_t& extruder, const uint8_t& driver, uint8_t x_splits = 0xff, uint8_t y_splits = 0xff) {
if (!mbl.active) {
plan_buffer_line(x, y, z, e, feed_rate, extruder, driver);
set_current_to_destination();
return;
}
int pcx = mbl.cel_index_x(current_position[X_AXIS] - home_offset[X_AXIS]);
int pcy = mbl.cel_index_y(current_position[Y_AXIS] - home_offset[Y_AXIS]);
int cx = mbl.cel_index_x(x - home_offset[X_AXIS]);
int cy = mbl.cel_index_y(y - home_offset[Y_AXIS]);
NOMORE(pcx, MESH_NUM_X_POINTS - 2);
NOMORE(pcy, MESH_NUM_Y_POINTS - 2);
NOMORE(cx, MESH_NUM_X_POINTS - 2);
NOMORE(cy, MESH_NUM_Y_POINTS - 2);
if (pcx == cx && pcy == cy) {
// Start and end on same mesh square
plan_buffer_line(x, y, z, e, feed_rate, extruder, driver);
set_current_to_destination();
return;
}
float nx, ny, nz, ne, normalized_dist;
if (cx > pcx && TEST(x_splits, cx)) {
nx = mbl.get_probe_x(cx) + home_offset[X_AXIS];
normalized_dist = (nx - current_position[X_AXIS]) / (x - current_position[X_AXIS]);
ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
nz = current_position[Z_AXIS] + (z - current_position[Z_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
CBI(x_splits, cx);
}
else if (cx < pcx && TEST(x_splits, pcx)) {
nx = mbl.get_probe_x(pcx) + home_offset[X_AXIS];
normalized_dist = (nx - current_position[X_AXIS]) / (x - current_position[X_AXIS]);
ny = current_position[Y_AXIS] + (y - current_position[Y_AXIS]) * normalized_dist;
nz = current_position[Z_AXIS] + (z - current_position[Z_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
CBI(x_splits, pcx);
}
else if (cy > pcy && TEST(y_splits, cy)) {
ny = mbl.get_probe_y(cy) + home_offset[Y_AXIS];
normalized_dist = (ny - current_position[Y_AXIS]) / (y - current_position[Y_AXIS]);
nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
nz = current_position[Z_AXIS] + (z - current_position[Z_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
CBI(y_splits, cy);
}
else if (cy < pcy && TEST(y_splits, pcy)) {
ny = mbl.get_probe_y(pcy) + home_offset[Y_AXIS];
normalized_dist = (ny - current_position[Y_AXIS]) / (y - current_position[Y_AXIS]);
nx = current_position[X_AXIS] + (x - current_position[X_AXIS]) * normalized_dist;
nz = current_position[Z_AXIS] + (z - current_position[Z_AXIS]) * normalized_dist;
ne = current_position[E_AXIS] + (e - current_position[E_AXIS]) * normalized_dist;
CBI(y_splits, pcy);
}
else {
// Already split on a border
plan_buffer_line(x, y, z, e, feed_rate, extruder, driver);
set_current_to_destination();
return;
}
// Do the split and look for more borders
destination[X_AXIS] = nx;
destination[Y_AXIS] = ny;
destination[Z_AXIS] = nz;
destination[E_AXIS] = ne;
mesh_buffer_line(nx, ny, nz, ne, feed_rate, extruder, driver, x_splits, y_splits);
destination[X_AXIS] = x;
destination[Y_AXIS] = y;
destination[Z_AXIS] = z;
destination[E_AXIS] = e;
mesh_buffer_line(x, y, z, e, feed_rate, extruder, driver, x_splits, y_splits);
}
#endif // MESH_BED_LEVELING
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE) #if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
FORCE_INLINE void prevent_dangerous_extrude(float &curr_e, float &dest_e) { FORCE_INLINE void prevent_dangerous_extrude(float &curr_e, float &dest_e) {
...@@ -9034,9 +9326,14 @@ static void report_current_position() { ...@@ -9034,9 +9326,14 @@ static void report_current_position() {
// Do not use feedrate_multiplier for E or Z only moves // Do not use feedrate_multiplier for E or Z only moves
if (current_position[X_AXIS] == destination[X_AXIS] && current_position[Y_AXIS] == destination[Y_AXIS]) if (current_position[X_AXIS] == destination[X_AXIS] && current_position[Y_AXIS] == destination[Y_AXIS])
line_to_destination(); line_to_destination();
else else {
#if ENABLED(MESH_BED_LEVELING)
mesh_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], (feedrate / 60) * (feedrate_multiplier / 100.0), active_extruder, active_driver);
return false;
#else
line_to_destination(feedrate * feedrate_multiplier / 100.0); line_to_destination(feedrate * feedrate_multiplier / 100.0);
#endif
}
return true; return true;
} }
......
...@@ -376,11 +376,13 @@ ...@@ -376,11 +376,13 @@
* CoreXY or CoreYX or CoreXZ or CoreZX * CoreXY or CoreYX or CoreXZ or CoreZX
*/ */
#if MECH(COREXY) || MECH(COREYX) #if MECH(COREXY) || MECH(COREYX)
#define CORE_AXIS_1 A_AXIS
#define CORE_AXIS_2 B_AXIS #define CORE_AXIS_2 B_AXIS
#define CORE_AXIS_3 Z_AXIS #define NORMAL_AXIS Z_AXIS
#elif MECH(COREXZ) || MECH(COREZX) #elif MECH(COREXZ) || MECH(COREZX)
#define CORE_AXIS_1 A_AXIS
#define CORE_AXIS_2 C_AXIS #define CORE_AXIS_2 C_AXIS
#define CORE_AXIS_3 Y_AXIS #define NORMAL_AXIS Y_AXIS
#endif #endif
/** /**
......
...@@ -116,6 +116,8 @@ ...@@ -116,6 +116,8 @@
#define SERIAL_Z_PROBE "z_probe: " #define SERIAL_Z_PROBE "z_probe: "
#define SERIAL_E_MIN "e_min: " #define SERIAL_E_MIN "e_min: "
#define SERIAL_ERR_MATERIAL_INDEX "M145 S<index> out of range (0-2)" #define SERIAL_ERR_MATERIAL_INDEX "M145 S<index> out of range (0-2)"
#define SERIAL_ERR_M421_PARAMETERS "M421 requires XYZ or IJZ parameters"
#define SERIAL_ERR_MESH_XY "Mesh XY or IJ cannot be resolved"
#define SERIAL_ERR_M428_TOO_FAR "Too far from reference point" #define SERIAL_ERR_M428_TOO_FAR "Too far from reference point"
#define SERIAL_M119_REPORT "Reporting endstop status" #define SERIAL_M119_REPORT "Reporting endstop status"
#define SERIAL_ENDSTOP_HIT "TRIGGERED" #define SERIAL_ENDSTOP_HIT "TRIGGERED"
......
...@@ -45,15 +45,11 @@ ...@@ -45,15 +45,11 @@
#define MSG_AUTO_HOME_X "Home X" #define MSG_AUTO_HOME_X "Home X"
#define MSG_AUTO_HOME_Y "Home Y" #define MSG_AUTO_HOME_Y "Home Y"
#define MSG_AUTO_HOME_Z "Home Z" #define MSG_AUTO_HOME_Z "Home Z"
#define MSG_MBL_SETTING "Manual Bed Leveling" #define MSG_LEVEL_BED_HOMING "Homing XYZ"
#define MSG_MBL_BUTTON " Press the button " #define MSG_LEVEL_BED_WAITING "Click to Begin"
#define MSG_MBL_INTRO " Leveling bed... " #define MSG_LEVEL_BED_NEXT_POINT "Next Point"
#define MSG_MBL_1 " Adjust first point " #define MSG_LEVEL_BED_DONE "Leveling Done!"
#define MSG_MBL_2 " Adjust second point" #define MSG_LEVEL_BED_CANCEL "Cancel"
#define MSG_MBL_3 " Adjust third point "
#define MSG_MBL_4 " Adjust fourth point"
#define MSG_MBL_5 " Is it ok? "
#define MSG_MBL_6 " BED leveled! "
#define MSG_SET_HOME_OFFSETS "Set home offsets" #define MSG_SET_HOME_OFFSETS "Set home offsets"
#define MSG_SET_ORIGIN "Set origin" #define MSG_SET_ORIGIN "Set origin"
#define MSG_ONFOR "On x:" #define MSG_ONFOR "On x:"
...@@ -83,6 +79,7 @@ ...@@ -83,6 +79,7 @@
#define MSG_SPEED "Speed" #define MSG_SPEED "Speed"
#define MSG_NOZZLE "Nozzle" #define MSG_NOZZLE "Nozzle"
#define MSG_BED "Bed" #define MSG_BED "Bed"
#define MSG_BED_Z "Bed Z"
#define MSG_FAN_SPEED "Fan speed" #define MSG_FAN_SPEED "Fan speed"
#define MSG_FLOW "Flow" #define MSG_FLOW "Flow"
#define MSG_CONTROL "Control" #define MSG_CONTROL "Control"
......
...@@ -42,15 +42,10 @@ ...@@ -42,15 +42,10 @@
#define MSG_AUTOSTART "Autostart" #define MSG_AUTOSTART "Autostart"
#define MSG_DISABLE_STEPPERS "Disabilita Motori" #define MSG_DISABLE_STEPPERS "Disabilita Motori"
#define MSG_AUTO_HOME "Auto Home" #define MSG_AUTO_HOME "Auto Home"
#define MSG_MBL_SETTING "Liv. piatto manuale " #define MSG_LEVEL_BED_HOMING "Home assi XYZ"
#define MSG_MBL_BUTTON " Premi il tasto " #define MSG_LEVEL_BED_WAITING "Premi per iniziare"
#define MSG_MBL_INTRO " Liv. piatto... " #define MSG_LEVEL_BED_DONE "Livel. terminato!"
#define MSG_MBL_1 " Calibra il primo punto" #define MSG_LEVEL_BED_CANCEL "Annulla"
#define MSG_MBL_2 " Calibra il secondo punto"
#define MSG_MBL_3 " Calibra il terzo punto"
#define MSG_MBL_4 " Calibra il quarto punto"
#define MSG_MBL_5 " Va bene? "
#define MSG_MBL_6 " Piatto livellato! "
#define MSG_SET_HOME_OFFSETS "Setta offset home" #define MSG_SET_HOME_OFFSETS "Setta offset home"
#define MSG_SET_ORIGIN "Imposta Origine" #define MSG_SET_ORIGIN "Imposta Origine"
#define MSG_ONFOR "On x:" #define MSG_ONFOR "On x:"
...@@ -76,10 +71,11 @@ ...@@ -76,10 +71,11 @@
#define MSG_EXTRUDE "Estrudi" #define MSG_EXTRUDE "Estrudi"
#define MSG_RETRACT "Ritrai" #define MSG_RETRACT "Ritrai"
#define MSG_PURGE "Purge" #define MSG_PURGE "Purge"
#define MSG_LEVEL_BED "Liv. piatto" #define MSG_LEVEL_BED "Livella piano"
#define MSG_SPEED "Velocita" #define MSG_SPEED "Velocita"
#define MSG_NOZZLE "Ugello" #define MSG_NOZZLE "Ugello"
#define MSG_BED "Piatto" #define MSG_BED "Piatto"
#define MSG_BED_Z "piatto Z"
#define MSG_FAN_SPEED "Ventola" #define MSG_FAN_SPEED "Ventola"
#define MSG_FLOW "Flusso" #define MSG_FLOW "Flusso"
#define MSG_CONTROL "Controllo" #define MSG_CONTROL "Controllo"
......
/** /**
* MK & MK4due 3D Printer Firmware * MK & MK4due 3D Printer Firmware
* *
...@@ -23,7 +24,6 @@ ...@@ -23,7 +24,6 @@
/** /**
* laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1 * laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1
* Copyright (c) 2013 Timothy Schmidt. All right reserved. * Copyright (c) 2013 Timothy Schmidt. All right reserved.
* Copyright (c) 2016 Franco (nextime) Lanza
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -335,6 +335,7 @@ ...@@ -335,6 +335,7 @@
} }
} }
} }
#endif // LASER_PERIPHERALS #endif // LASER_PERIPHERALS
#endif // LASERBEAM #endif // LASERBEAM
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
/** /**
* laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1 * laser.cpp - Laser control library for Arduino using 16 bit timers- Version 1
* Copyright (c) 2013 Timothy Schmidt. All right reserved. * Copyright (c) 2013 Timothy Schmidt. All right reserved.
* Copyright (c) 2016 Franco (nextime) Lanza
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
......
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
#define LCD_WIDTH_EDIT 22 #define LCD_WIDTH_EDIT 22
#endif #endif
#if DISABLED(TALL_FONT_CORRECTION) #ifndef TALL_FONT_CORRECTION
#define TALL_FONT_CORRECTION 0 #define TALL_FONT_CORRECTION 0
#endif #endif
...@@ -158,7 +158,10 @@ ...@@ -158,7 +158,10 @@
U8GLIB_LM6059 u8g(DOGLCD_CS, DOGLCD_A0); U8GLIB_LM6059 u8g(DOGLCD_CS, DOGLCD_A0);
#elif ENABLED(U8GLIB_SSD1306) #elif ENABLED(U8GLIB_SSD1306)
// Generic support for SSD1306 OLED I2C LCDs // Generic support for SSD1306 OLED I2C LCDs
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST);
#elif ENABLED(U8GLIB_SH1106)
// Generic support for SH1106 OLED I2C LCDs
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST);
#elif ENABLED(MINIPANEL) #elif ENABLED(MINIPANEL)
// The MINIPanel display // The MINIPanel display
U8GLIB_MINI12864 u8g(DOGLCD_CS, DOGLCD_A0); U8GLIB_MINI12864 u8g(DOGLCD_CS, DOGLCD_A0);
...@@ -167,10 +170,10 @@ ...@@ -167,10 +170,10 @@
U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0 U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0
#endif #endif
#if DISABLED(LCD_PIXEL_WIDTH) #ifndef LCD_PIXEL_WIDTH
#define LCD_PIXEL_WIDTH 128 #define LCD_PIXEL_WIDTH 128
#endif #endif
#if DISABLED(LCD_PIXEL_HEIGHT) #ifndef LCD_PIXEL_HEIGHT
#define LCD_PIXEL_HEIGHT 64 #define LCD_PIXEL_HEIGHT 64
#endif #endif
...@@ -269,7 +272,7 @@ static void lcd_implementation_init() { ...@@ -269,7 +272,7 @@ static void lcd_implementation_init() {
if (show_bootscreen) { if (show_bootscreen) {
u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp); u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp);
lcd_setFont(FONT_MENU); lcd_setFont(FONT_MENU);
#if DISABLED(STRING_SPLASH_LINE2) #ifndef STRING_SPLASH_LINE2
u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT), STRING_SPLASH_LINE1); u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT), STRING_SPLASH_LINE1);
#else #else
int txt2X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE2) - 1) * (DOG_CHAR_WIDTH)) / 2; int txt2X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE2) - 1) * (DOG_CHAR_WIDTH)) / 2;
......
...@@ -49,11 +49,6 @@ int8_t encoderDiff; // updated from interrupt context and added to encoderPositi ...@@ -49,11 +49,6 @@ int8_t encoderDiff; // updated from interrupt context and added to encoderPositi
bool encoderRateMultiplierEnabled; bool encoderRateMultiplierEnabled;
int32_t lastEncoderMovementMillis; int32_t lastEncoderMovementMillis;
#if !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
int pageShowInfo = 0;
void set_pageShowInfo(int value){ pageShowInfo = value; }
#endif
int plaPreheatHotendTemp; int plaPreheatHotendTemp;
int plaPreheatHPBTemp; int plaPreheatHPBTemp;
int plaPreheatFanSpeed; int plaPreheatFanSpeed;
...@@ -158,10 +153,7 @@ static void lcd_status_screen(); ...@@ -158,10 +153,7 @@ static void lcd_status_screen();
#if MECH(DELTA) #if MECH(DELTA)
static void lcd_delta_calibrate_menu(); static void lcd_delta_calibrate_menu();
#elif !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0 #endif
static void lcd_level_bed();
static void config_lcd_level_bed();
#endif // !DELTA
/* Different types of actions that can be used in menu items. */ /* Different types of actions that can be used in menu items. */
static void menu_action_back(); static void menu_action_back();
...@@ -350,7 +342,6 @@ menuPosition menu_history[10]; ...@@ -350,7 +342,6 @@ menuPosition menu_history[10];
uint8_t menu_history_depth = 0; uint8_t menu_history_depth = 0;
millis_t next_lcd_update_ms; millis_t next_lcd_update_ms;
uint8_t lcd_status_update_delay;
bool ignore_click = false; bool ignore_click = false;
bool wait_for_unclick; bool wait_for_unclick;
bool defer_return_to_status = false; bool defer_return_to_status = false;
...@@ -631,12 +622,6 @@ static void lcd_main_menu() { ...@@ -631,12 +622,6 @@ static void lcd_main_menu() {
END_MENU(); END_MENU();
} }
#if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
static void lcd_autostart_sd() {
card.checkautostart(true);
}
#endif
/** /**
* *
* "Tune" submenu items * "Tune" submenu items
...@@ -665,21 +650,21 @@ void lcd_set_home_offsets() { ...@@ -665,21 +650,21 @@ void lcd_set_home_offsets() {
#if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX) #if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX)
#if ENABLED(BABYSTEP_XY) #if ENABLED(BABYSTEP_XY)
switch(axis) { switch(axis) {
case X_AXIS: // X on CoreXY, Core YX, CoreXZ and CoreZZ case CORE_AXIS_1: // X on CoreXY, Core YX, CoreXZ and CoreZZ
babystepsTodo[A_AXIS] += distance * 2; babystepsTodo[CORE_AXIS_1] += distance * 2;
babystepsTodo[CORE_AXIS_2] += distance * 2; babystepsTodo[CORE_AXIS_2] += distance * 2;
break; break;
case CORE_AXIS_2: // Y on CoreXY and CoreYX, Z on CoreXZ and CoreZX case CORE_AXIS_2: // Y on CoreXY and CoreYX, Z on CoreXZ and CoreZX
babystepsTodo[A_AXIS] += distance * 2; babystepsTodo[CORE_AXIS_1] += distance * 2;
babystepsTodo[CORE_AXIS_2] -= distance * 2; babystepsTodo[CORE_AXIS_2] -= distance * 2;
break; break;
case CORE_AXIS_3: // Z on CoreXY and CoreYX, Y on CoreXZ and CoreZX case NORMAL_AXIS: // Z on CoreXY and CoreYX, Y on CoreXZ and CoreZX
babystepsTodo[CORE_AXIS_3] += distance; babystepsTodo[NORMAL_AXIS] += distance;
break; break;
} }
#elif MECH(COREXZ) || MECH(COREZX) #elif MECH(COREXZ) || MECH(COREZX)
babystepsTodo[A_AXIS] += distance * 2; babystepsTodo[CORE_AXIS_1] += distance * 2;
babystepsTodo[C_AXIS] -= distance * 2; babystepsTodo[CORE_AXIS_2] -= distance * 2;
#else #else
babystepsTodo[Z_AXIS] += distance; babystepsTodo[Z_AXIS] += distance;
#endif #endif
...@@ -771,6 +756,11 @@ static void lcd_tune_menu() { ...@@ -771,6 +756,11 @@ static void lcd_tune_menu() {
// //
MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_multiplier, 10, 999); MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_multiplier, 10, 999);
// Manual bed leveling, Bed Z:
#if ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM_EDIT(float43, MSG_BED_Z, &mbl.z_offset, -1, 1);
#endif
// //
// Nozzle: // Nozzle:
// //
...@@ -1027,6 +1017,210 @@ void lcd_cooldown() { ...@@ -1027,6 +1017,210 @@ void lcd_cooldown() {
lcd_return_to_status(); lcd_return_to_status();
} }
#if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
static void lcd_autostart_sd() {
card.checkautostart(true);
}
#endif
#if ENABLED(MANUAL_BED_LEVELING)
/**
*
* "Prepare" > "Bed Leveling" handlers
*
*/
static uint8_t _lcd_level_bed_position;
// Utility to go to the next mesh point
// A raise is added between points if MIN_Z_HEIGHT_FOR_HOMING is in use
// Note: During Manual Bed Leveling the homed Z position is MESH_HOME_SEARCH_Z
// Z position will be restored with the final action, a G28
inline void _mbl_goto_xy(float x, float y) {
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
#if MIN_Z_HEIGHT_FOR_HOMING > 0
+ MIN_Z_HEIGHT_FOR_HOMING
#endif
;
line_to_current(Z_AXIS);
current_position[X_AXIS] = x + home_offset[X_AXIS];
current_position[Y_AXIS] = y + home_offset[Y_AXIS];
line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS);
#if MIN_Z_HEIGHT_FOR_HOMING > 0
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
line_to_current(Z_AXIS);
#endif
st_synchronize();
}
static void _lcd_level_goto_next_point();
static void _lcd_level_bed_done() {
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_DONE));
lcdDrawUpdate =
#if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
#else
LCDVIEW_CALL_NO_REDRAW
#endif
;
}
/**
* Step 7: Get the Z coordinate, then goto next point or exit
*/
static void _lcd_level_bed_get_z() {
ENCODER_DIRECTION_NORMAL();
// Encoder wheel adjusts the Z position
if (encoderPosition && movesplanned() <= 3) {
refresh_cmd_timeout();
current_position[Z_AXIS] += float((int32_t)encoderPosition) * (MBL_Z_STEP);
NOLESS(current_position[Z_AXIS], 0);
NOMORE(current_position[Z_AXIS], MESH_HOME_SEARCH_Z * 2);
line_to_current(Z_AXIS);
lcdDrawUpdate =
#if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
#else
LCDVIEW_REDRAW_NOW
#endif
;
}
encoderPosition = 0;
static bool debounce_click = false;
if (LCD_CLICKED) {
if (!debounce_click) {
debounce_click = true; // ignore multiple "clicks" in a row
mbl.set_zigzag_z(_lcd_level_bed_position++, current_position[Z_AXIS]);
if (_lcd_level_bed_position == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
lcd_goto_menu(_lcd_level_bed_done, true);
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z
#if MIN_Z_HEIGHT_FOR_HOMING > 0
+ MIN_Z_HEIGHT_FOR_HOMING
#endif
;
line_to_current(Z_AXIS);
st_synchronize();
mbl.active = true;
enqueue_and_echo_commands_P(PSTR("G28"));
lcd_return_to_status();
//LCD_MESSAGEPGM(MSG_LEVEL_BED_DONE);
#if HAS(BUZZER)
buzz(200, 659);
buzz(200, 698);
#endif
}
else {
lcd_goto_menu(_lcd_level_goto_next_point, true);
}
}
}
else {
debounce_click = false;
}
// Update on first display, then only on updates to Z position
// Show message above on clicks instead
if (lcdDrawUpdate) {
float v = current_position[Z_AXIS] - MESH_HOME_SEARCH_Z;
lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43(v + (v < 0 ? -0.0001 : 0.0001), '+'));
}
}
/**
* Step 6: Display "Next point: 1 / 9" while waiting for move to finish
*/
static void _lcd_level_bed_moving() {
if (lcdDrawUpdate) {
char msg[10];
sprintf_P(msg, PSTR("%i / %u"), (int)(_lcd_level_bed_position + 1), (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS));
lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_NEXT_POINT), msg);
}
lcdDrawUpdate =
#if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
#else
LCDVIEW_CALL_NO_REDRAW
#endif
;
}
/**
* Step 5: Initiate a move to the next point
*/
static void _lcd_level_goto_next_point() {
// Set the menu to display ahead of blocking call
lcd_goto_menu(_lcd_level_bed_moving);
// _mbl_goto_xy runs the menu loop until the move is done
int8_t px, py;
mbl.zigzag(_lcd_level_bed_position, px, py);
_mbl_goto_xy(mbl.get_probe_x(px), mbl.get_probe_y(py));
// After the blocking function returns, change menus
lcd_goto_menu(_lcd_level_bed_get_z);
}
/**
* Step 4: Display "Click to Begin", wait for click
* Move to the first probe position
*/
static void _lcd_level_bed_homing_done() {
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING));
if (LCD_CLICKED) {
_lcd_level_bed_position = 0;
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]);
lcd_goto_menu(_lcd_level_goto_next_point, true);
}
}
/**
* Step 3: Display "Homing XYZ" - Wait for homing to finish
*/
static void _lcd_level_bed_homing() {
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL);
lcdDrawUpdate =
#if ENABLED(DOGLCD)
LCDVIEW_CALL_REDRAW_NEXT
#else
LCDVIEW_CALL_NO_REDRAW
#endif
;
if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
lcd_goto_menu(_lcd_level_bed_homing_done);
}
/**
* Step 2: Continue Bed Leveling...
*/
static void _lcd_level_bed_continue() {
defer_return_to_status = true;
axis_homed[X_AXIS] = axis_homed[Y_AXIS] = axis_homed[Z_AXIS] = false;
mbl.reset();
enqueue_and_echo_commands_P(PSTR("G28"));
lcd_goto_menu(_lcd_level_bed_homing);
}
/**
* Step 1: MBL entry-point: "Cancel" or "Level Bed"
*/
static void lcd_level_bed() {
START_MENU();
MENU_ITEM(back, MSG_LEVEL_BED_CANCEL);
MENU_ITEM(submenu, MSG_LEVEL_BED, _lcd_level_bed_continue);
END_MENU();
}
#endif // MANUAL_BED_LEVELING
/** /**
* *
* "Prepare" submenu * "Prepare" submenu
...@@ -1068,8 +1262,8 @@ static void lcd_prepare_menu() { ...@@ -1068,8 +1262,8 @@ static void lcd_prepare_menu() {
MENU_ITEM(gcode, MSG_LEVEL_BED, MENU_ITEM(gcode, MSG_LEVEL_BED,
axis_homed[X_AXIS] && axis_homed[Y_AXIS] ? PSTR("G29") : PSTR("G28\nG29") axis_homed[X_AXIS] && axis_homed[Y_AXIS] ? PSTR("G29") : PSTR("G28\nG29")
); );
#elif !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0 #elif ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM(submenu, MSG_MBL_SETTING, config_lcd_level_bed); MENU_ITEM(submenu, MSG_LEVEL_BED, lcd_level_bed);
#endif #endif
// //
...@@ -1157,14 +1351,13 @@ static void lcd_prepare_menu() { ...@@ -1157,14 +1351,13 @@ static void lcd_prepare_menu() {
float move_menu_scale; float move_menu_scale;
static void _lcd_move(const char* name, AxisEnum axis, int min, int max) { static void _lcd_move(const char* name, AxisEnum axis, float min, float max) {
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition != 0) { if (encoderPosition && movesplanned() <= 3) {
refresh_cmd_timeout(); refresh_cmd_timeout();
current_position[axis] += float((int)encoderPosition) * move_menu_scale; current_position[axis] += float((int32_t)encoderPosition) * move_menu_scale;
if (SOFTWARE_MIN_ENDSTOPS) NOLESS(current_position[axis], min); if (SOFTWARE_MIN_ENDSTOPS) NOLESS(current_position[axis], min);
if (SOFTWARE_MAX_ENDSTOPS) NOMORE(current_position[axis], max); if (SOFTWARE_MAX_ENDSTOPS) NOMORE(current_position[axis], max);
encoderPosition = 0;
line_to_current(axis); line_to_current(axis);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW; lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
} }
...@@ -1174,15 +1367,15 @@ static void _lcd_move(const char* name, AxisEnum axis, int min, int max) { ...@@ -1174,15 +1367,15 @@ static void _lcd_move(const char* name, AxisEnum axis, int min, int max) {
} }
#if MECH(DELTA) #if MECH(DELTA)
static float delta_clip_radius_2 = DELTA_PRINTABLE_RADIUS * DELTA_PRINTABLE_RADIUS; static float delta_clip_radius_2 = (DELTA_PRINTABLE_RADIUS) * (DELTA_PRINTABLE_RADIUS);
static int delta_clip( float a ) { return sqrt(delta_clip_radius_2 - a * a); } static int delta_clip( float a ) { return sqrt(delta_clip_radius_2 - a * a); }
static void lcd_move_x() { int clip = delta_clip(current_position[Y_AXIS]); _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, max(X_MIN_POS, -clip), min(X_MAX_POS, clip)); } static void lcd_move_x() { int clip = delta_clip(current_position[Y_AXIS]); _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, max(sw_endstop_min[X_AXIS], -clip), min(sw_endstop_max[X_AXIS], clip)); }
static void lcd_move_y() { int clip = delta_clip(current_position[X_AXIS]); _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, max(X_MIN_POS, -clip), min(X_MAX_POS, clip)); } static void lcd_move_y() { int clip = delta_clip(current_position[X_AXIS]); _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, max(sw_endstop_min[Y_AXIS], -clip), min(sw_endstop_max[Y_AXIS], clip)); }
#else #else
static void lcd_move_x() { _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, X_MIN_POS, X_MAX_POS); } static void lcd_move_x() { _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, sw_endstop_min[X_AXIS], sw_endstop_max[X_AXIS]); }
static void lcd_move_y() { _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, Y_MIN_POS, Y_MAX_POS); } static void lcd_move_y() { _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, sw_endstop_min[Y_AXIS], sw_endstop_max[Y_AXIS]); }
#endif #endif
static void lcd_move_z() { _lcd_move(PSTR(MSG_MOVE_Z), Z_AXIS, Z_MIN_POS, Z_MAX_POS); } static void lcd_move_z() { _lcd_move(PSTR(MSG_MOVE_Z), Z_AXIS, sw_endstop_min[Z_AXIS], sw_endstop_max[Z_AXIS]); }
static void lcd_move_e( static void lcd_move_e(
#if EXTRUDERS > 1 #if EXTRUDERS > 1
uint8_t e uint8_t e
...@@ -1193,11 +1386,11 @@ static void lcd_move_e( ...@@ -1193,11 +1386,11 @@ static void lcd_move_e(
unsigned short original_active_extruder = active_extruder; unsigned short original_active_extruder = active_extruder;
active_extruder = e; active_extruder = e;
#endif #endif
if (encoderPosition != 0) { if (encoderPosition && movesplanned() <= 3) {
#if ENABLED(IDLE_OOZING_PREVENT) #if ENABLED(IDLE_OOZING_PREVENT)
IDLE_OOZING_retract(false); IDLE_OOZING_retract(false);
#endif #endif
current_position[E_AXIS] += float((int)encoderPosition) * move_menu_scale; current_position[E_AXIS] += float((int32_t)encoderPosition) * move_menu_scale;
line_to_current(E_AXIS); line_to_current(E_AXIS);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW; lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
} }
...@@ -1249,7 +1442,7 @@ static void lcd_move_e( ...@@ -1249,7 +1442,7 @@ static void lcd_move_e(
#define _MOVE_XYZ_ALLOWED true #define _MOVE_XYZ_ALLOWED true
#endif #endif
static void lcd_move_menu_axis() { static void _lcd_move_menu_axis() {
START_MENU(); START_MENU();
MENU_ITEM(back, MSG_MOVE_AXIS); MENU_ITEM(back, MSG_MOVE_AXIS);
...@@ -1277,15 +1470,15 @@ static void lcd_move_menu_axis() { ...@@ -1277,15 +1470,15 @@ static void lcd_move_menu_axis() {
static void lcd_move_menu_10mm() { static void lcd_move_menu_10mm() {
move_menu_scale = 10.0; move_menu_scale = 10.0;
lcd_move_menu_axis(); _lcd_move_menu_axis();
} }
static void lcd_move_menu_1mm() { static void lcd_move_menu_1mm() {
move_menu_scale = 1.0; move_menu_scale = 1.0;
lcd_move_menu_axis(); _lcd_move_menu_axis();
} }
static void lcd_move_menu_01mm() { static void lcd_move_menu_01mm() {
move_menu_scale = 0.1; move_menu_scale = 0.1;
lcd_move_menu_axis(); _lcd_move_menu_axis();
} }
/** /**
...@@ -1640,6 +1833,10 @@ static void lcd_control_motion_menu() { ...@@ -1640,6 +1833,10 @@ static void lcd_control_motion_menu() {
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, -50, 50); MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, -50, 50);
#endif #endif
// Manual bed leveling, Bed Z:
#if ENABLED(MANUAL_BED_LEVELING)
MENU_ITEM_EDIT(float43, MSG_BED_Z, &mbl.z_offset, -1, 1);
#endif
MENU_ITEM_EDIT(float5, MSG_ACC, &acceleration, 10, 99000); MENU_ITEM_EDIT(float5, MSG_ACC, &acceleration, 10, 99000);
MENU_ITEM_EDIT(float3, MSG_VXY_JERK, &max_xy_jerk, 1, 990); MENU_ITEM_EDIT(float3, MSG_VXY_JERK, &max_xy_jerk, 1, 990);
MENU_ITEM_EDIT(float52, MSG_VZ_JERK, &max_z_jerk, 0.1, 990); MENU_ITEM_EDIT(float52, MSG_VZ_JERK, &max_z_jerk, 0.1, 990);
...@@ -1733,7 +1930,7 @@ static void lcd_control_motion_menu() { ...@@ -1733,7 +1930,7 @@ static void lcd_control_motion_menu() {
#if HAS(LCD_CONTRAST) #if HAS(LCD_CONTRAST)
static void lcd_set_contrast() { static void lcd_set_contrast() {
ENCODER_DIRECTION_NORMAL(); ENCODER_DIRECTION_NORMAL();
if (encoderPosition != 0) { if (encoderPosition) {
#if ENABLED(U8GLIB_LM6059_AF) #if ENABLED(U8GLIB_LM6059_AF)
lcd_contrast += encoderPosition; lcd_contrast += encoderPosition;
lcd_contrast &= 0xFF; lcd_contrast &= 0xFF;
...@@ -1883,6 +2080,7 @@ static void lcd_control_motion_menu() { ...@@ -1883,6 +2080,7 @@ static void lcd_control_motion_menu() {
* *
*/ */
void lcd_sdcard_menu() { void lcd_sdcard_menu() {
ENCODER_DIRECTION_MENUS();
if (lcdDrawUpdate == 0 && LCD_CLICKED == 0) return; // nothing to do (so don't thrash the SD card) if (lcdDrawUpdate == 0 && LCD_CLICKED == 0) return; // nothing to do (so don't thrash the SD card)
uint16_t fileCnt = card.getnrfilenames(); uint16_t fileCnt = card.getnrfilenames();
START_MENU(); START_MENU();
...@@ -2092,14 +2290,14 @@ static void lcd_control_motion_menu() { ...@@ -2092,14 +2290,14 @@ static void lcd_control_motion_menu() {
currentMenu = menu_edit_callback_ ## _name; \ currentMenu = menu_edit_callback_ ## _name; \
callbackFunc = callback; \ callbackFunc = callback; \
} }
menu_edit_type(int, int3, itostr3, 1) menu_edit_type(int, int3, itostr3, 1);
menu_edit_type(float, float3, ftostr3, 1) menu_edit_type(float, float3, ftostr3, 1);
menu_edit_type(float, float32, ftostr32, 100) menu_edit_type(float, float32, ftostr32, 100);
menu_edit_type(float, float43, ftostr43, 1000) menu_edit_type(float, float43, ftostr43, 1000);
menu_edit_type(float, float5, ftostr5, 0.01) menu_edit_type(float, float5, ftostr5, 0.01);
menu_edit_type(float, float51, ftostr51, 10) menu_edit_type(float, float51, ftostr51, 10);
menu_edit_type(float, float52, ftostr52, 100) menu_edit_type(float, float52, ftostr52, 100);
menu_edit_type(unsigned long, long5, ftostr5, 0.01) menu_edit_type(unsigned long, long5, ftostr5, 0.01);
/** /**
* *
...@@ -2138,7 +2336,7 @@ menu_edit_type(unsigned long, long5, ftostr5, 0.01) ...@@ -2138,7 +2336,7 @@ menu_edit_type(unsigned long, long5, ftostr5, 0.01)
lcd_move_y(); lcd_move_y();
} }
static void reprapworld_keypad_move_home() { static void reprapworld_keypad_move_home() {
enqueue_and_echo_commands_P((PSTR("G28"))); // move all axis home enqueue_and_echo_commands_P(PSTR("G28")); // move all axis home
} }
#endif // REPRAPWORLD_KEYPAD #endif // REPRAPWORLD_KEYPAD
...@@ -2212,7 +2410,7 @@ static void menu_action_function(menuFunc_t func) { (*func)(); } ...@@ -2212,7 +2410,7 @@ static void menu_action_function(menuFunc_t func) { (*func)(); }
#endif // SDSUPPORT #endif // SDSUPPORT
static void menu_action_setting_edit_bool(const char* pstr, bool* ptr) { *ptr = !(*ptr); } static void menu_action_setting_edit_bool(const char* pstr, bool* ptr) {UNUSED(pstr); *ptr = !(*ptr); }
static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callback) { static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callback) {
menu_action_setting_edit_bool(pstr, ptr); menu_action_setting_edit_bool(pstr, ptr);
(*callback)(); (*callback)();
...@@ -2249,10 +2447,16 @@ void lcd_init() { ...@@ -2249,10 +2447,16 @@ void lcd_init() {
WRITE(SHIFT_LD, HIGH); WRITE(SHIFT_LD, HIGH);
#endif #endif
#ifdef RIGIDBOT_PANEL #if BUTTON_EXISTS(UP)
SET_INPUT(BTN_UP); SET_INPUT(BTN_UP);
#endif
#if BUTTON_EXISTS(DWN)
SET_INPUT(BTN_DWN); SET_INPUT(BTN_DWN);
#endif
#if BUTTON_EXISTS(LFT)
SET_INPUT(BTN_LFT); SET_INPUT(BTN_LFT);
#endif
#if BUTTON_EXISTS(RT)
SET_INPUT(BTN_RT); SET_INPUT(BTN_RT);
#endif #endif
...@@ -2274,7 +2478,7 @@ void lcd_init() { ...@@ -2274,7 +2478,7 @@ void lcd_init() {
#endif // !NEWPANEL #endif // !NEWPANEL
#if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT) #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
pinMode(SD_DETECT_PIN, INPUT); SET_INPUT(SD_DETECT_PIN);
PULLUP(SD_DETECT_PIN, HIGH); PULLUP(SD_DETECT_PIN, HIGH);
lcd_sd_status = 2; // UNKNOWN lcd_sd_status = 2; // UNKNOWN
#endif #endif
...@@ -2455,11 +2659,16 @@ void lcd_update() { ...@@ -2455,11 +2659,16 @@ void lcd_update() {
} }
#endif // ULTIPANEL #endif // ULTIPANEL
// Simply redraw the Info Screen 10 times a second // We arrive here every ~100ms when idling often enough.
if (currentMenu == lcd_status_screen && !(++lcd_status_update_delay % 10)) // Instead of tracking the changes simply redraw the Info Screen ~1 time a second.
static int8_t lcd_status_update_delay = 1; // first update one loop delayed
if (currentMenu == lcd_status_screen && !lcd_status_update_delay--) {
lcd_status_update_delay = 9;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW; lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
}
if (lcdDrawUpdate) { if (lcdDrawUpdate) {
switch (lcdDrawUpdate) { switch (lcdDrawUpdate) {
case LCDVIEW_CALL_NO_REDRAW: case LCDVIEW_CALL_NO_REDRAW:
lcdDrawUpdate = LCDVIEW_NONE; lcdDrawUpdate = LCDVIEW_NONE;
...@@ -2492,11 +2701,7 @@ void lcd_update() { ...@@ -2492,11 +2701,7 @@ void lcd_update() {
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
// Return to Status Screen after a timeout // Return to Status Screen after a timeout
if (currentMenu == lcd_status_screen || defer_return_to_status if (currentMenu == lcd_status_screen || defer_return_to_status)
#if !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
|| currentMenu == lcd_level_bed
#endif
)
return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS; return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
else if (ELAPSED(ms, return_to_status_ms)) else if (ELAPSED(ms, return_to_status_ms))
lcd_return_to_status(); lcd_return_to_status();
...@@ -2559,14 +2764,14 @@ bool lcd_hasstatus() { return (lcd_status_message[0] != '\0'); } ...@@ -2559,14 +2764,14 @@ bool lcd_hasstatus() { return (lcd_status_message[0] != '\0'); }
void lcd_setstatus(const char* message, bool persist) { void lcd_setstatus(const char* message, bool persist) {
if (lcd_status_message_level > 0) return; if (lcd_status_message_level > 0) return;
strncpy(lcd_status_message, message, 3 * LCD_WIDTH); strncpy(lcd_status_message, message, 3 * (LCD_WIDTH));
set_utf_strlen(lcd_status_message, LCD_WIDTH); set_utf_strlen(lcd_status_message, LCD_WIDTH);
lcd_finishstatus(persist); lcd_finishstatus(persist);
} }
void lcd_setstatuspgm(const char* message, uint8_t level) { void lcd_setstatuspgm(const char* message, uint8_t level) {
if (level >= lcd_status_message_level) { if (level >= lcd_status_message_level) {
strncpy_P(lcd_status_message, message, 3 * LCD_WIDTH); strncpy_P(lcd_status_message, message, 3 * (LCD_WIDTH));
set_utf_strlen(lcd_status_message, LCD_WIDTH); set_utf_strlen(lcd_status_message, LCD_WIDTH);
lcd_status_message_level = level; lcd_status_message_level = level;
lcd_finishstatus(level > 0); lcd_finishstatus(level > 0);
...@@ -2629,32 +2834,46 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } ...@@ -2629,32 +2834,46 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#if BUTTON_EXISTS(EN2) #if BUTTON_EXISTS(EN2)
if (BUTTON_PRESSED(EN2)) newbutton |= EN_B; if (BUTTON_PRESSED(EN2)) newbutton |= EN_B;
#endif #endif
#if ENABLED(RIGIDBOT_PANEL) || BUTTON_EXISTS(ENC) #if LCD_HAS_DIRECTIONAL_BUTTONS || BUTTON_EXISTS(ENC)
millis_t now = millis(); millis_t now = millis();
#endif #endif
#if ENABLED(RIGIDBOT_PANEL)
#if LCD_HAS_DIRECTIONAL_BUTTONS
if (ELAPSED(now, next_button_update_ms)) { if (ELAPSED(now, next_button_update_ms)) {
if (BUTTON_PRESSED(UP)) { if (false) {
// for the else-ifs below
}
#if BUTTON_EXISTS(UP)
else if (BUTTON_PRESSED(UP)) {
encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM); encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM);
next_button_update_ms = now + 300; next_button_update_ms = now + 300;
} }
#endif
#if BUTTON_EXISTS(DWN)
else if (BUTTON_PRESSED(DWN)) { else if (BUTTON_PRESSED(DWN)) {
encoderDiff = ENCODER_STEPS_PER_MENU_ITEM; encoderDiff = ENCODER_STEPS_PER_MENU_ITEM;
next_button_update_ms = now + 300; next_button_update_ms = now + 300;
} }
#endif
#if BUTTON_EXISTS(LFT)
else if (BUTTON_PRESSED(LFT)) { else if (BUTTON_PRESSED(LFT)) {
encoderDiff = -(ENCODER_PULSES_PER_STEP); encoderDiff = -(ENCODER_PULSES_PER_STEP);
next_button_update_ms = now + 300; next_button_update_ms = now + 300;
} }
#endif
#if BUTTON_EXISTS(RT)
else if (BUTTON_PRESSED(RT)) { else if (BUTTON_PRESSED(RT)) {
encoderDiff = ENCODER_PULSES_PER_STEP; encoderDiff = ENCODER_PULSES_PER_STEP;
next_button_update_ms = now + 300; next_button_update_ms = now + 300;
} }
#endif
} }
#endif #endif
#if BUTTON_EXISTS(ENC) #if BUTTON_EXISTS(ENC)
if (ELAPSED(now, next_button_update_ms) && BUTTON_PRESSED(ENC)) newbutton |= EN_C; if (ELAPSED(now, next_button_update_ms) && BUTTON_PRESSED(ENC)) newbutton |= EN_C;
#endif #endif
buttons = newbutton; buttons = newbutton;
#if ENABLED(LCD_HAS_SLOW_BUTTONS) #if ENABLED(LCD_HAS_SLOW_BUTTONS)
buttons |= slow_buttons; buttons |= slow_buttons;
...@@ -2662,7 +2881,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } ...@@ -2662,7 +2881,7 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
#if ENABLED(REPRAPWORLD_KEYPAD) #if ENABLED(REPRAPWORLD_KEYPAD)
GET_BUTTON_STATES(buttons_reprapworld_keypad); GET_BUTTON_STATES(buttons_reprapworld_keypad);
#endif #endif
#else //read it from the shift register #else
GET_BUTTON_STATES(buttons); GET_BUTTON_STATES(buttons);
#endif //!NEWPANEL #endif //!NEWPANEL
...@@ -2714,7 +2933,7 @@ char *ftostr3(const float& x) { return itostr3((int)x); } ...@@ -2714,7 +2933,7 @@ char *ftostr3(const float& x) { return itostr3((int)x); }
// Convert float to rj string with _123, -123, _-12, or __-1 format // Convert float to rj string with _123, -123, _-12, or __-1 format
char *ftostr4sign(const float& x) { return itostr4sign((int)x); } char *ftostr4sign(const float& x) { return itostr4sign((int)x); }
// Convert int to string with 12 format // Convert unsigned int to string with 12 format
char* itostr2(const uint8_t& x) { char* itostr2(const uint8_t& x) {
//sprintf(conv,"%5.1f",x); //sprintf(conv,"%5.1f",x);
int xx = x; int xx = x;
...@@ -2724,7 +2943,7 @@ char* itostr2(const uint8_t& x) { ...@@ -2724,7 +2943,7 @@ char* itostr2(const uint8_t& x) {
return conv; return conv;
} }
// Convert float to string with +123.4 format // Convert float to string with +123.4 / -123.4 format
char* ftostr31(const float& x) { char* ftostr31(const float& x) {
int xx = abs(x * 10); int xx = abs(x * 10);
conv[0] = (x >= 0) ? '+' : '-'; conv[0] = (x >= 0) ? '+' : '-';
...@@ -2737,7 +2956,7 @@ char* ftostr31(const float& x) { ...@@ -2737,7 +2956,7 @@ char* ftostr31(const float& x) {
return conv; return conv;
} }
// Convert float to string with 123.4 format, dropping sign // Convert unsigned float to string with 123.4 format, dropping sign
char* ftostr31ns(const float& x) { char* ftostr31ns(const float& x) {
int xx = abs(x * 10); int xx = abs(x * 10);
conv[0] = (xx / 1000) % 10 + '0'; conv[0] = (xx / 1000) % 10 + '0';
...@@ -2749,8 +2968,8 @@ char* ftostr31ns(const float& x) { ...@@ -2749,8 +2968,8 @@ char* ftostr31ns(const float& x) {
return conv; return conv;
} }
// Convert float to string with 123.45 format // Convert signed float to string with 023.45 / -23.45 format
char* ftostr32(const float& x) { char *ftostr32(const float& x) {
long xx = abs(x * 100); long xx = abs(x * 100);
conv[0] = x >= 0 ? (xx / 10000) % 10 + '0' : '-'; conv[0] = x >= 0 ? (xx / 10000) % 10 + '0' : '-';
conv[1] = (xx / 1000) % 10 + '0'; conv[1] = (xx / 1000) % 10 + '0';
...@@ -2762,23 +2981,27 @@ char* ftostr32(const float& x) { ...@@ -2762,23 +2981,27 @@ char* ftostr32(const float& x) {
return conv; return conv;
} }
// Convert float to string with 1.234 format // Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
char* ftostr43(const float& x) { char* ftostr43(const float& x, char plus/*=' '*/) {
long xx = x * 1000; long xx = x * 1000;
if (xx >= 0) if (xx == 0)
conv[0] = (xx / 1000) % 10 + '0'; conv[0] = ' ';
else else if (xx > 0)
conv[0] = plus;
else {
xx = -xx;
conv[0] = '-'; conv[0] = '-';
xx = abs(xx); }
conv[1] = '.'; conv[1] = (xx / 1000) % 10 + '0';
conv[2] = (xx / 100) % 10 + '0'; conv[2] = '.';
conv[3] = (xx / 10) % 10 + '0'; conv[3] = (xx / 100) % 10 + '0';
conv[4] = (xx) % 10 + '0'; conv[4] = (xx / 10) % 10 + '0';
conv[5] = 0; conv[5] = (xx) % 10 + '0';
conv[6] = 0;
return conv; return conv;
} }
// Convert float to string with 1.23 format // Convert unsigned float to string with 1.23 format
char* ftostr12ns(const float& x) { char* ftostr12ns(const float& x) {
long xx = x * 100; long xx = x * 100;
xx = abs(xx); xx = abs(xx);
...@@ -2790,11 +3013,12 @@ char* ftostr12ns(const float& x) { ...@@ -2790,11 +3013,12 @@ char* ftostr12ns(const float& x) {
return conv; return conv;
} }
// Convert float to space-padded string with -_23.4_ format // Convert signed float to space-padded string with -_23.4_ format
char* ftostr32sp(const float& x) { char* ftostr32sp(const float& x) {
long xx = abs(x * 100); long xx = x * 100;
uint8_t dig; uint8_t dig;
if (x < 0) { // negative val = -_0 if (xx < 0) { // negative val = -_0
xx = -xx;
conv[0] = '-'; conv[0] = '-';
dig = (xx / 1000) % 10; dig = (xx / 1000) % 10;
conv[1] = dig ? '0' + dig : ' '; conv[1] = dig ? '0' + dig : ' ';
...@@ -2855,7 +3079,7 @@ char* itostr3sign(const int& x) { ...@@ -2855,7 +3079,7 @@ char* itostr3sign(const int& x) {
return conv; return conv;
} }
// Convert int to rj string with 123 or -12 format // Convert signed int to rj string with 123 or -12 format
char* itostr3(const int& x) { char* itostr3(const int& x) {
int xx = x; int xx = x;
if (xx < 0) { if (xx < 0) {
...@@ -2871,38 +3095,38 @@ char* itostr3(const int& x) { ...@@ -2871,38 +3095,38 @@ char* itostr3(const int& x) {
return conv; return conv;
} }
// Convert int to lj string with 123 format // Convert unsigned int to lj string with 123 format
char* itostr3left(const int& xx) { char* itostr3left(const int& x) {
if (xx >= 100) { if (x >= 100) {
conv[0] = (xx / 100) % 10 + '0'; conv[0] = (x / 100) % 10 + '0';
conv[1] = (xx / 10) % 10 + '0'; conv[1] = (x / 10) % 10 + '0';
conv[2] = xx % 10 + '0'; conv[2] = x % 10 + '0';
conv[3] = 0; conv[3] = 0;
} }
else if (xx >= 10) { else if (x >= 10) {
conv[0] = (xx / 10) % 10 + '0'; conv[0] = (x / 10) % 10 + '0';
conv[1] = xx % 10 + '0'; conv[1] = x % 10 + '0';
conv[2] = 0; conv[2] = 0;
} }
else { else {
conv[0] = xx % 10 + '0'; conv[0] = x % 10 + '0';
conv[1] = 0; conv[1] = 0;
} }
return conv; return conv;
} }
// Convert int to rj string with 1234 format // Convert unsigned int to rj string with 1234 format
char* itostr4(const int& xx) { char* itostr4(const int& x) {
conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' '; conv[0] = x >= 1000 ? (x / 1000) % 10 + '0' : ' ';
conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' '; conv[1] = x >= 100 ? (x / 100) % 10 + '0' : ' ';
conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' '; conv[2] = x >= 10 ? (x / 10) % 10 + '0' : ' ';
conv[3] = xx % 10 + '0'; conv[3] = x % 10 + '0';
conv[4] = 0; conv[4] = 0;
return conv; return conv;
} }
// Convert int to rj string with _123, -123, _-12, or __-1 format // Convert signed int to rj string with _123, -123, _-12, or __-1 format
char* itostr4sign(const int& x) { char *itostr4sign(const int& x) {
int xx = abs(x); int xx = abs(x);
int sign = 0; int sign = 0;
if (xx >= 100) { if (xx >= 100) {
...@@ -2925,49 +3149,7 @@ char* itostr4sign(const int& x) { ...@@ -2925,49 +3149,7 @@ char* itostr4sign(const int& x) {
return conv; return conv;
} }
char* ltostr7(const long& xx) { // Convert unsigned float to rj string with 12345 format
if (xx >= 1000000)
conv[0]=(xx/1000000)%10+'0';
else
conv[0]=' ';
if (xx >= 100000)
conv[1]=(xx/100000)%10+'0';
else
conv[1]=' ';
if (xx >= 10000)
conv[2]=(xx/10000)%10+'0';
else
conv[2]=' ';
if (xx >= 1000)
conv[3]=(xx/1000)%10+'0';
else
conv[3]=' ';
if (xx >= 100)
conv[4]=(xx/100)%10+'0';
else
conv[4]=' ';
if (xx >= 10)
conv[5]=(xx/10)%10+'0';
else
conv[5]=' ';
conv[6]=(xx)%10+'0';
conv[7]=0;
return conv;
}
// convert float to string with +123 format
char* ftostr30(const float& x) {
int xx=x;
conv[0]=(xx>=0)?'+':'-';
xx=abs(xx);
conv[1]=(xx/100)%10+'0';
conv[2]=(xx/10)%10+'0';
conv[3]=(xx)%10+'0';
conv[4]=0;
return conv;
}
// Convert float to rj string with 12345 format
char* ftostr5(const float& x) { char* ftostr5(const float& x) {
long xx = abs(x); long xx = abs(x);
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' '; conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
...@@ -2979,7 +3161,7 @@ char* ftostr5(const float& x) { ...@@ -2979,7 +3161,7 @@ char* ftostr5(const float& x) {
return conv; return conv;
} }
// Convert float to string with +1234.5 format // Convert signed float to string with +1234.5 format
char* ftostr51(const float& x) { char* ftostr51(const float& x) {
long xx = abs(x * 10); long xx = abs(x * 10);
conv[0] = (x >= 0) ? '+' : '-'; conv[0] = (x >= 0) ? '+' : '-';
...@@ -2993,7 +3175,7 @@ char* ftostr51(const float& x) { ...@@ -2993,7 +3175,7 @@ char* ftostr51(const float& x) {
return conv; return conv;
} }
// Convert float to string with +123.45 format // Convert signed float to string with +123.45 format
char* ftostr52(const float& x) { char* ftostr52(const float& x) {
conv[0] = (x >= 0) ? '+' : '-'; conv[0] = (x >= 0) ? '+' : '-';
long xx = abs(x * 100); long xx = abs(x * 100);
...@@ -3007,67 +3189,37 @@ char* ftostr52(const float& x) { ...@@ -3007,67 +3189,37 @@ char* ftostr52(const float& x) {
return conv; return conv;
} }
#if !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0 char* ltostr7(const long& x) {
if (x >= 1000000)
static void lcd_level_bed() { conv[0]=(x/1000000)%10+'0';
switch(pageShowInfo) { else
case 0: conv[0]=' ';
{ if (x >= 100000)
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_INTRO)); conv[1]=(x/100000)%10+'0';
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON)); else
} conv[1]=' ';
break; if (x >= 10000)
case 1: conv[2]=(x/10000)%10+'0';
{ else
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_1)); conv[2]=' ';
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON)); if (x >= 1000)
} conv[3]=(x/1000)%10+'0';
break; else
case 2: conv[3]=' ';
{ if (x >= 100)
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_2)); conv[4]=(x/100)%10+'0';
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON)); else
} conv[4]=' ';
break; if (x >= 10)
case 3: conv[5]=(x/10)%10+'0';
{ else
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_3)); conv[5]=' ';
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON)); conv[6]=(x)%10+'0';
} conv[7]=0;
break; return conv;
case 4: }
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_4));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
case 5:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_5));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(MSG_MBL_BUTTON));
}
break;
case 6:
{
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_6));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(" "));
HAL::delayMilliseconds(5000);
enqueue_and_echo_commands_P(PSTR("G28"));
lcd_goto_menu(lcd_prepare_menu);
}
break;
}
}
static void config_lcd_level_bed() {
ECHO_EM(MSG_MBL_SETTING);
enqueue_and_echo_commands_P(PSTR("G28 M"));
pageShowInfo = 0;
lcd_goto_menu(lcd_level_bed);
}
#endif
#endif //ULTRA_LCD #endif // ULTRA_LCD
#if ENABLED(SDSUPPORT) && ENABLED(SD_SETTINGS) #if ENABLED(SDSUPPORT) && ENABLED(SD_SETTINGS)
void set_sd_dot() { void set_sd_dot() {
......
...@@ -55,10 +55,6 @@ ...@@ -55,10 +55,6 @@
void lcd_setcontrast(uint8_t value); void lcd_setcontrast(uint8_t value);
#endif #endif
#if !MECH(DELTA) && DISABLED(Z_SAFE_HOMING) && Z_HOME_DIR < 0
void set_pageShowInfo(int value);
#endif
#define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x)) #define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x))
#define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x)) #define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x))
...@@ -102,7 +98,7 @@ ...@@ -102,7 +98,7 @@
#endif #endif
void lcd_quick_feedback(); // Audible feedback for a button click - could also be visual void lcd_quick_feedback(); // Audible feedback for a button click - could also be visual
bool lcd_clicked(); bool lcd_clicked();
void lcd_ignore_click(bool b = true); void lcd_ignore_click(bool b=true);
bool lcd_blink(); bool lcd_blink();
#if ENABLED(ULTIPANEL) && ENABLED(REPRAPWORLD_KEYPAD) #if ENABLED(ULTIPANEL) && ENABLED(REPRAPWORLD_KEYPAD)
...@@ -138,6 +134,7 @@ ...@@ -138,6 +134,7 @@
#endif // ULTIPANEL && REPRAPWORLD_KEYPAD #endif // ULTIPANEL && REPRAPWORLD_KEYPAD
#if ENABLED(NEWPANEL) #if ENABLED(NEWPANEL)
#define EN_C (_BV(BLEN_C)) #define EN_C (_BV(BLEN_C))
#define EN_B (_BV(BLEN_B)) #define EN_B (_BV(BLEN_B))
#define EN_A (_BV(BLEN_A)) #define EN_A (_BV(BLEN_A))
...@@ -179,25 +176,23 @@ ...@@ -179,25 +176,23 @@
char* itostr2(const uint8_t& x); char* itostr2(const uint8_t& x);
char* itostr3sign(const int& x); char* itostr3sign(const int& x);
char* itostr3(const int& xx); char* itostr3(const int& x);
char* itostr3left(const int& xx); char* itostr3left(const int& x);
char* itostr4(const int& xx); char* itostr4(const int& x);
char* itostr4sign(const int& x); char* itostr4sign(const int& x);
char* ltostr7(const long& xx);
char* ftostr3(const float& x); char* ftostr3(const float& x);
char* ftostr4sign(const float& x); char* ftostr4sign(const float& x);
char* ftostr30(const float& x);
char* ftostr31ns(const float& x); // float to string without sign character char* ftostr31ns(const float& x); // float to string without sign character
char* ftostr31(const float& x); char* ftostr31(const float& x);
char* ftostr32(const float& x); char* ftostr32(const float& x);
char* ftostr43(const float& x); char* ftostr43(const float& x, char plus=' ');
char* ftostr12ns(const float& x); char* ftostr12ns(const float& x);
char* ftostr32sp(const float& x); // remove zero-padding from ftostr32 char* ftostr32sp(const float& x); // remove zero-padding from ftostr32
char* ftostr5(const float& x); char* ftostr5(const float& x);
char* ftostr51(const float& x); char* ftostr51(const float& x);
char* ftostr52(const float& x); char* ftostr52(const float& x);
char* ltostr7(const long& x);
#elif DISABLED(NEXTION) #elif DISABLED(NEXTION)
......
...@@ -416,7 +416,7 @@ static void lcd_implementation_init( ...@@ -416,7 +416,7 @@ static void lcd_implementation_init(
#elif ENABLED(LCD_I2C_TYPE_MCP23017) #elif ENABLED(LCD_I2C_TYPE_MCP23017)
lcd.setMCPType(LTI_TYPE_MCP23017); lcd.setMCPType(LTI_TYPE_MCP23017);
lcd.begin(LCD_WIDTH, LCD_HEIGHT); lcd.begin(LCD_WIDTH, LCD_HEIGHT);
lcd.setBacklight(0); //set all the LEDs off to begin with lcd_implementation_update_indicators();
#elif ENABLED(LCD_I2C_TYPE_MCP23008) #elif ENABLED(LCD_I2C_TYPE_MCP23008)
lcd.setMCPType(LTI_TYPE_MCP23008); lcd.setMCPType(LTI_TYPE_MCP23008);
...@@ -990,14 +990,14 @@ void lcd_implementation_drawedit(const char* pstr, const char* value = NULL) { ...@@ -990,14 +990,14 @@ void lcd_implementation_drawedit(const char* pstr, const char* value = NULL) {
static uint8_t ledsprev = 0; static uint8_t ledsprev = 0;
uint8_t leds = 0; uint8_t leds = 0;
if (target_temperature_bed > 0) leds |= LED_A; if (degTargetBed() > 0) leds |= LED_A;
if (target_temperature[0] > 0) leds |= LED_B; if (degTargetHotend(0) > 0) leds |= LED_B;
if (fanSpeed) leds |= LED_C; if (fanSpeed) leds |= LED_C;
#if HOTENDS > 1 #if HOTENDS > 1
if (target_temperature[1] > 0) leds |= LED_C; if (degTargetHotend(1) > 0) leds |= LED_C;
#endif #endif
if (leds != ledsprev) { if (leds != ledsprev) {
......
...@@ -97,11 +97,11 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo ...@@ -97,11 +97,11 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo
ST7920_WRITE_BYTE(0x01); //clear CGRAM ram ST7920_WRITE_BYTE(0x01); //clear CGRAM ram
u8g_Delay(15); //delay for CGRAM clear u8g_Delay(15); //delay for CGRAM clear
ST7920_WRITE_BYTE(0x3E); //extended mode + GDRAM active ST7920_WRITE_BYTE(0x3E); //extended mode + GDRAM active
for (y = 0; y < LCD_PIXEL_HEIGHT / 2; y++) { //clear GDRAM for (y = 0; y < (LCD_PIXEL_HEIGHT) / 2; y++) { //clear GDRAM
ST7920_WRITE_BYTE(0x80 | y); //set y ST7920_WRITE_BYTE(0x80 | y); //set y
ST7920_WRITE_BYTE(0x80); //set x = 0 ST7920_WRITE_BYTE(0x80); //set x = 0
ST7920_SET_DAT(); ST7920_SET_DAT();
for (i = 0; i < 2 * LCD_PIXEL_WIDTH / 8; i++) //2x width clears both segments for (i = 0; i < 2 * (LCD_PIXEL_WIDTH) / 8; i++) //2x width clears both segments
ST7920_WRITE_BYTE(0); ST7920_WRITE_BYTE(0);
ST7920_SET_CMD(); ST7920_SET_CMD();
} }
...@@ -129,7 +129,7 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo ...@@ -129,7 +129,7 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo
ST7920_WRITE_BYTE(0x80 | 8); //x=64 ST7920_WRITE_BYTE(0x80 | 8); //x=64
} }
ST7920_SET_DAT(); ST7920_SET_DAT();
ST7920_WRITE_BYTES(ptr, LCD_PIXEL_WIDTH / 8); //ptr is incremented inside of macro ST7920_WRITE_BYTES(ptr, (LCD_PIXEL_WIDTH) / 8); //ptr is incremented inside of macro
y++; y++;
} }
ST7920_NCS(); ST7920_NCS();
...@@ -145,7 +145,7 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo ...@@ -145,7 +145,7 @@ uint8_t u8g_dev_rrd_st7920_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo
#endif #endif
} }
uint8_t u8g_dev_st7920_128x64_rrd_buf[LCD_PIXEL_WIDTH * (PAGE_HEIGHT / 8)] U8G_NOCOMMON; uint8_t u8g_dev_st7920_128x64_rrd_buf[(LCD_PIXEL_WIDTH) * (PAGE_HEIGHT) / 8] U8G_NOCOMMON;
u8g_pb_t u8g_dev_st7920_128x64_rrd_pb = {{PAGE_HEIGHT, LCD_PIXEL_HEIGHT, 0, 0, 0}, LCD_PIXEL_WIDTH, u8g_dev_st7920_128x64_rrd_buf}; u8g_pb_t u8g_dev_st7920_128x64_rrd_pb = {{PAGE_HEIGHT, LCD_PIXEL_HEIGHT, 0, 0, 0}, LCD_PIXEL_WIDTH, u8g_dev_st7920_128x64_rrd_buf};
u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = {u8g_dev_rrd_st7920_128x64_fn, &u8g_dev_st7920_128x64_rrd_pb, &u8g_com_null_fn}; u8g_dev_t u8g_dev_st7920_128x64_rrd_sw_spi = {u8g_dev_rrd_st7920_128x64_fn, &u8g_dev_st7920_128x64_rrd_pb, &u8g_com_null_fn};
......
/**
* MK & MK4due 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* 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/>.
*
*/
#ifndef UTF_MAPPER_H #ifndef UTF_MAPPER_H
#define UTF_MAPPER_H #define UTF_MAPPER_H
...@@ -50,7 +72,7 @@ ...@@ -50,7 +72,7 @@
// ヰ ヱ ヲ ン フ ? ? ? ? ? ヲ ・ ー ヽ ヽ ? // ヰ ヱ ヲ ン フ ? ? ? ? ? ヲ ・ ー ヽ ヽ ?
}; };
#elif ENABLED(MAPPER_D0D1) #elif ENABLED(MAPPER_D0D1)
#error( "Cyrillic on a japanese dsplay makes no sense. There are no matching symbols."); #error "Cyrillic on a JAPANESE display makes no sense. There are no matching symbols."
#endif #endif
#elif ENABLED(DISPLAY_CHARSET_HD44780_WESTERN) #elif ENABLED(DISPLAY_CHARSET_HD44780_WESTERN)
...@@ -84,7 +106,7 @@ ...@@ -84,7 +106,7 @@
// p c T y Ф x Ч ч Ш Щ Ъ Ы b Э Ю Я // p c T y Ф x Ч ч Ш Щ Ъ Ы b Э Ю Я
}; };
#elif ENABLED(MAPPER_E382E383) #elif ENABLED(MAPPER_E382E383)
#error( "Katakana on a western display makes no sense. There are no matching symbols." ); #error "Katakana on a WESTERN display makes no sense. There are no matching symbols."
#endif #endif
#elif ENABLED(DISPLAY_CHARSET_HD44780_CYRILLIC) #elif ENABLED(DISPLAY_CHARSET_HD44780_CYRILLIC)
...@@ -111,13 +133,13 @@ ...@@ -111,13 +133,13 @@
// ш щ ъ ы ь э ю я // 7 Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ // ш щ ъ ы ь э ю я // 7 Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ
}; // ѻ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ }; // ѻ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ
#elif ENABLED(MAPPER_C2C3) #elif ENABLED(MAPPER_C2C3)
#error( "Western languages on a cyrillic display makes no sense. There are no matching symbols." ); #error "Western languages on a CYRILLIC display makes no sense. There are no matching symbols."
#elif ENABLED(MAPPER_E382E383) #elif ENABLED(MAPPER_E382E383)
#error( "Katakana on a cyrillic display makes no sense. There are no matching symbols." ); #error "Katakana on a CYRILLIC display makes no sense. There are no matching symbols."
#endif #endif
#else #else
#error("Something went wrong in the selection of DISPLAY_CHARSET_HD44780's"); #error "Something went wrong in the setting of DISPLAY_CHARSET_HD44780"
#endif // DISPLAY_CHARSET_HD44780_CYRILLIC #endif // DISPLAY_CHARSET_HD44780
#endif // SIMULATE_ROMFONT #endif // SIMULATE_ROMFONT
#if ENABLED(MAPPER_NON) #if ENABLED(MAPPER_NON)
...@@ -209,7 +231,7 @@ ...@@ -209,7 +231,7 @@
} }
else if (seen_d5) { else if (seen_d5) {
d &= 0x3fu; d &= 0x3fu;
#if DISABLED(MAPPER_ONE_TO_ONE) #ifndef MAPPER_ONE_TO_ONE
HARDWARE_CHAR_OUT((char)pgm_read_byte_near(utf_recode + d + (utf_hi_char << 6) - 0x20)); HARDWARE_CHAR_OUT((char)pgm_read_byte_near(utf_recode + d + (utf_hi_char << 6) - 0x20));
#else #else
HARDWARE_CHAR_OUT((char)(0xa0u + (utf_hi_char << 6) + d)) ; HARDWARE_CHAR_OUT((char)(0xa0u + (utf_hi_char << 6) + d)) ;
...@@ -245,7 +267,7 @@ ...@@ -245,7 +267,7 @@
} }
else if (seen_e3 && seen_82_83) { else if (seen_e3 && seen_82_83) {
d &= 0x3f; d &= 0x3f;
#if DISABLED(MAPPER_ONE_TO_ONE) #ifndef MAPPER_ONE_TO_ONE
HARDWARE_CHAR_OUT((char)pgm_read_byte_near(utf_recode + d + (utf_hi_char << 6) - 0x20)); HARDWARE_CHAR_OUT((char)pgm_read_byte_near(utf_recode + d + (utf_hi_char << 6) - 0x20));
#else #else
HARDWARE_CHAR_OUT((char)(0x80 + (utf_hi_char << 6) + d)) ; HARDWARE_CHAR_OUT((char)(0x80 + (utf_hi_char << 6) + d)) ;
......
/**
* MK & MK4due 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* 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/>.
*
*/
#include "../../base.h"
#if ENABLED(MESH_BED_LEVELING)
mesh_bed_leveling mbl;
mesh_bed_leveling::mesh_bed_leveling() { reset(); }
void mesh_bed_leveling::reset() {
active = 0;
z_offset = 0;
for (int8_t y = MESH_NUM_Y_POINTS; y--;)
for (int8_t x = MESH_NUM_X_POINTS; x--;)
z_values[y][x] = 0;
}
#endif // MESH_BED_LEVELING
/**
* MK & MK4due 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* 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/>.
*
*/
#if ENABLED(MESH_BED_LEVELING)
#define MESH_X_DIST ((MESH_MAX_X - (MESH_MIN_X))/(MESH_NUM_X_POINTS - 1))
#define MESH_Y_DIST ((MESH_MAX_Y - (MESH_MIN_Y))/(MESH_NUM_Y_POINTS - 1))
class mesh_bed_leveling {
public:
bool active;
float z_offset;
float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS];
mesh_bed_leveling();
void reset();
static FORCE_INLINE float get_probe_x(int8_t i) { return MESH_MIN_X + (MESH_X_DIST) * i; }
static FORCE_INLINE float get_probe_y(int8_t i) { return MESH_MIN_Y + (MESH_Y_DIST) * i; }
void set_z(const int8_t px, const int8_t py, const float z) { z_values[py][px] = z; }
inline void zigzag(int8_t index, int8_t &px, int8_t &py) {
px = index % (MESH_NUM_X_POINTS);
py = index / (MESH_NUM_X_POINTS);
if (py & 1) px = (MESH_NUM_X_POINTS - 1) - px; // Zig zag
}
void set_zigzag_z(int8_t index, float z) {
int8_t px, py;
zigzag(index, px, py);
set_z(px, py, z);
}
int8_t cel_index_x(float x) {
int8_t cx = int(x - (MESH_MIN_X)) / (MESH_X_DIST);
return constrain(cx, 0, (MESH_NUM_X_POINTS) - 2);
}
int8_t cel_index_y(float y) {
int8_t cy = int(y - (MESH_MIN_Y)) / (MESH_Y_DIST);
return constrain(cy, 0, (MESH_NUM_Y_POINTS) - 2);
}
int8_t probe_index_x(float x) {
int8_t px = int(x - (MESH_MIN_X) + (MESH_X_DIST) / 2) / (MESH_X_DIST);
return (px >= 0 && px < (MESH_NUM_X_POINTS)) ? px : -1;
}
int8_t probe_index_y(float y) {
int8_t py = int(y - (MESH_MIN_Y) + (MESH_Y_DIST) / 2) / (MESH_Y_DIST);
return (py >= 0 && py < (MESH_NUM_Y_POINTS)) ? py : -1;
}
float calc_z0(float a0, float a1, float z1, float a2, float z2) {
float delta_z = (z2 - z1) / (a2 - a1);
float delta_a = a0 - a1;
return z1 + delta_a * delta_z;
}
float get_z(float x0, float y0) {
int8_t cx = cel_index_x(x0),
cy = cel_index_y(y0);
if (cx < 0 || cy < 0) return z_offset;
float z1 = calc_z0(x0,
get_probe_x(cx), z_values[cy][cx],
get_probe_x(cx + 1), z_values[cy][cx + 1]);
float z2 = calc_z0(x0,
get_probe_x(cx), z_values[cy + 1][cx],
get_probe_x(cx + 1), z_values[cy + 1][cx + 1]);
float z0 = calc_z0(y0,
get_probe_y(cy), z1,
get_probe_y(cy + 1), z2);
return z0 + z_offset;
}
};
extern mesh_bed_leveling mbl;
#endif // MESH_BED_LEVELING
...@@ -32,6 +32,34 @@ ...@@ -32,6 +32,34 @@
Endstops endstops; Endstops endstops;
// public:
bool Endstops::enabled = true,
Endstops::enabled_globally =
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
false
#else
true
#endif
;
volatile char Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
#if ENABLED(Z_DUAL_ENDSTOPS)
uint16_t
#else
byte
#endif
Endstops::current_endstop_bits = 0,
Endstops::old_endstop_bits = 0;
#if HAS(Z_PROBE)
volatile bool Endstops::z_probe_enabled = false;
#endif
/**
* Class and Instance Methods
*/
Endstops::Endstops() { Endstops::Endstops() {
enable_globally( enable_globally(
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING) #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
...@@ -41,7 +69,7 @@ Endstops::Endstops() { ...@@ -41,7 +69,7 @@ Endstops::Endstops() {
#endif #endif
); );
enable(true); enable(true);
#if ENABLED(HAS_Z_PROBE) #if HAS(Z_PROBE)
enable_z_probe(false); enable_z_probe(false);
#endif #endif
} // Endstops::Endstops } // Endstops::Endstops
...@@ -240,8 +268,8 @@ void Endstops::update() { ...@@ -240,8 +268,8 @@ void Endstops::update() {
#if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX) #if MECH(COREXY) || MECH(COREYX)|| MECH(COREXZ) || MECH(COREZX)
// Head direction in -X axis for CoreXY and CoreXZ bots. // Head direction in -X axis for CoreXY and CoreXZ bots.
// If Delta1 == -Delta2, the movement is only in Y or Z axis // If DeltaA == -DeltaB, the movement is only in Y or Z axis
if ((current_block->steps[A_AXIS] != current_block->steps[CORE_AXIS_2]) || (motor_direction(A_AXIS) == motor_direction(CORE_AXIS_2))) { if ((current_block->steps[CORE_AXIS_1] != current_block->steps[CORE_AXIS_2]) || (motor_direction(CORE_AXIS_1) == motor_direction(CORE_AXIS_2))) {
if (motor_direction(X_HEAD)) if (motor_direction(X_HEAD))
#else #else
if (motor_direction(X_AXIS)) // stepping along -X axis (regular Cartesian bot) if (motor_direction(X_AXIS)) // stepping along -X axis (regular Cartesian bot)
...@@ -274,8 +302,8 @@ void Endstops::update() { ...@@ -274,8 +302,8 @@ void Endstops::update() {
#if MECH(COREXY) || MECH(COREYX) #if MECH(COREXY) || MECH(COREYX)
// Head direction in -Y axis for CoreXY bots. // Head direction in -Y axis for CoreXY bots.
// If DeltaX == DeltaY, the movement is only in X axis // If DeltaA == DeltaB, the movement is only in X axis
if ((current_block->steps[A_AXIS] != current_block->steps[B_AXIS]) || (motor_direction(A_AXIS) != motor_direction(B_AXIS))) { if ((current_block->steps[CORE_AXIS_1] != current_block->steps[CORE_AXIS_2]) || (motor_direction(CORE_AXIS_1) != motor_direction(CORE_AXIS_2))) {
if (motor_direction(Y_HEAD)) if (motor_direction(Y_HEAD))
#else #else
if (motor_direction(Y_AXIS)) // -direction if (motor_direction(Y_AXIS)) // -direction
...@@ -296,8 +324,8 @@ void Endstops::update() { ...@@ -296,8 +324,8 @@ void Endstops::update() {
#if MECH(COREXZ) || MECH(COREZX) #if MECH(COREXZ) || MECH(COREZX)
// Head direction in -Z axis for CoreXZ bots. // Head direction in -Z axis for CoreXZ bots.
// If DeltaX == DeltaZ, the movement is only in X axis // If DeltaA == DeltaB, the movement is only in X axis
if ((current_block->steps[A_AXIS] != current_block->steps[C_AXIS]) || (motor_direction(A_AXIS) != motor_direction(C_AXIS))) { if ((current_block->steps[CORE_AXIS_1] != current_block->steps[CORE_AXIS_2]) || (motor_direction(CORE_AXIS_1) !) != motor_direction(CORE_AXIS_2))) {
if (motor_direction(Z_HEAD)) if (motor_direction(Z_HEAD))
#else #else
if (motor_direction(Z_AXIS)) if (motor_direction(Z_AXIS))
......
...@@ -33,25 +33,15 @@ class Endstops { ...@@ -33,25 +33,15 @@ class Endstops {
public: public:
volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_PROBE as BIT value static bool enabled, enabled_globally;
static volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_PROBE as BIT value
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
uint16_t current_endstop_bits = 0, static uint16_t
old_endstop_bits = 0;
#else #else
byte current_endstop_bits = 0, static byte
old_endstop_bits = 0;
#endif #endif
current_endstop_bits, old_endstop_bits;
bool enabled = true;
bool enabled_globally =
#if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
false
#else
true
#endif
;
Endstops(); Endstops();
...@@ -63,40 +53,40 @@ class Endstops { ...@@ -63,40 +53,40 @@ class Endstops {
/** /**
* Update the endstops bits from the pins * Update the endstops bits from the pins
*/ */
void update(); static void update();
/** /**
* Print an error message reporting the position when the endstops were last hit. * Print an error message reporting the position when the endstops were last hit.
*/ */
void report_state(); // call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered static void report_state(); // call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered
/** /**
* Report endstop positions in response to M119 * Report endstop positions in response to M119
*/ */
void M119(); static void M119();
// Enable / disable endstop checking globally // Enable / disable endstop checking globally
FORCE_INLINE void enable_globally(bool onoff = true) { enabled_globally = enabled = onoff; } static void enable_globally(bool onoff = true) { enabled_globally = enabled = onoff; }
// Enable / disable endstop checking // Enable / disable endstop checking
FORCE_INLINE void enable(bool onoff = true) { enabled = onoff; } static void enable(bool onoff = true) { enabled = onoff; }
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable // Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
FORCE_INLINE void not_homing() { enabled = enabled_globally; } static void not_homing() { enabled = enabled_globally; }
// Clear endstops (i.e., they were hit intentionally) to suppress the report // Clear endstops (i.e., they were hit intentionally) to suppress the report
FORCE_INLINE void hit_on_purpose() { endstop_hit_bits = 0; } static void hit_on_purpose() { endstop_hit_bits = 0; }
// Enable / disable endstop z-probe checking // Enable / disable endstop z-probe checking
#if ENABLED(HAS_Z_PROBE) #if HAS(Z_PROBE)
volatile bool z_probe_enabled = false; static volatile bool z_probe_enabled;
FORCE_INLINE void enable_z_probe(bool onoff = true) { z_probe_enabled = onoff; } static void enable_z_probe(bool onoff = true) { z_probe_enabled = onoff; }
#endif #endif
private: private:
#if ENABLED(Z_DUAL_ENDSTOPS) #if ENABLED(Z_DUAL_ENDSTOPS)
void test_dual_z_endstops(EndstopEnum es1, EndstopEnum es2); static void test_dual_z_endstops(EndstopEnum es1, EndstopEnum es2);
#endif #endif
}; };
......
...@@ -170,8 +170,10 @@ FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, f ...@@ -170,8 +170,10 @@ FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, f
return (acceleration * 2 * distance - initial_rate * initial_rate + final_rate * final_rate) / (acceleration * 4); return (acceleration * 2 * distance - initial_rate * initial_rate + final_rate * final_rate) / (acceleration * 4);
} }
// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors. /**
* Calculate trapezoid parameters, multiplying the entry- and exit-speeds
* by the provided factors.
*/
void calculate_trapezoid_for_block(block_t* block, float entry_factor, float exit_factor) { void calculate_trapezoid_for_block(block_t* block, float entry_factor, float exit_factor) {
unsigned long initial_rate = ceil(block->nominal_rate * entry_factor), unsigned long initial_rate = ceil(block->nominal_rate * entry_factor),
final_rate = ceil(block->nominal_rate * exit_factor); // (steps per second) final_rate = ceil(block->nominal_rate * exit_factor); // (steps per second)
...@@ -218,8 +220,11 @@ void calculate_trapezoid_for_block(block_t* block, float entry_factor, float exi ...@@ -218,8 +220,11 @@ void calculate_trapezoid_for_block(block_t* block, float entry_factor, float exi
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
} }
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the /**
// acceleration within the allotted distance. * Calculate the maximum allowable speed at this point, in order
* to reach 'target_velocity' using 'acceleration' within a given
* 'distance'.
*/
FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) { FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) {
return sqrt(target_velocity * target_velocity - 2 * acceleration * distance); return sqrt(target_velocity * target_velocity - 2 * acceleration * distance);
} }
...@@ -259,24 +264,27 @@ void planner_reverse_pass_kernel(block_t* previous, block_t* current, block_t* n ...@@ -259,24 +264,27 @@ void planner_reverse_pass_kernel(block_t* previous, block_t* current, block_t* n
} // Skip last block. Already initialized and set for recalculation. } // Skip last block. Already initialized and set for recalculation.
} }
// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This /**
// implements the reverse pass. * recalculate() needs to go over the current plan twice.
* Once in reverse and once forward. This implements the reverse pass.
*/
void planner_reverse_pass() { void planner_reverse_pass() {
uint8_t block_index = block_buffer_head;
if (movesplanned() > 3) {
block_t* block[3] = { NULL, NULL, NULL };
//Make a local copy of block_buffer_tail, because the interrupt can alter it //Make a local copy of block_buffer_tail, because the interrupt can alter it
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
unsigned char tail = block_buffer_tail; uint8_t tail = block_buffer_tail;
CRITICAL_SECTION_END CRITICAL_SECTION_END
if (BLOCK_MOD(block_buffer_head - tail + BLOCK_BUFFER_SIZE) > 3) { // moves queued uint8_t b = BLOCK_MOD(block_buffer_head - 3);
block_index = BLOCK_MOD(block_buffer_head - 3); while (b != tail) {
block_t* block[3] = { NULL, NULL, NULL }; b = prev_block_index(b);
while (block_index != tail) {
block_index = prev_block_index(block_index);
block[2] = block[1]; block[2] = block[1];
block[1] = block[0]; block[1] = block[0];
block[0] = &block_buffer[block_index]; block[0] = &block_buffer[b];
planner_reverse_pass_kernel(block[0], block[1], block[2]); planner_reverse_pass_kernel(block[0], block[1], block[2]);
} }
} }
...@@ -304,25 +312,27 @@ void planner_forward_pass_kernel(block_t* previous, block_t* current, block_t* n ...@@ -304,25 +312,27 @@ void planner_forward_pass_kernel(block_t* previous, block_t* current, block_t* n
} }
} }
// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This /**
// implements the forward pass. * recalculate() needs to go over the current plan twice.
* Once in reverse and once forward. This implements the forward pass.
*/
void planner_forward_pass() { void planner_forward_pass() {
uint8_t block_index = block_buffer_tail;
block_t* block[3] = { NULL, NULL, NULL }; block_t* block[3] = { NULL, NULL, NULL };
while (block_index != block_buffer_head) { for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block[0] = block[1]; block[0] = block[1];
block[1] = block[2]; block[1] = block[2];
block[2] = &block_buffer[block_index]; block[2] = &block_buffer[b];
planner_forward_pass_kernel(block[0], block[1], block[2]); planner_forward_pass_kernel(block[0], block[1], block[2]);
block_index = next_block_index(block_index);
} }
planner_forward_pass_kernel(block[1], block[2], NULL); planner_forward_pass_kernel(block[1], block[2], NULL);
} }
// Recalculates the trapezoid speed profiles for all blocks in the plan according to the /**
// entry_factor for each junction. Must be called by planner_recalculate() after * Recalculate the trapezoid speed profiles for all blocks in the plan
// updating the blocks. * according to the entry_factor for each junction. Must be called by
* recalculate() after updating the blocks.
*/
void planner_recalculate_trapezoids() { void planner_recalculate_trapezoids() {
int8_t block_index = block_buffer_tail; int8_t block_index = block_buffer_tail;
block_t* current; block_t* current;
...@@ -410,34 +420,42 @@ void plan_init() { ...@@ -410,34 +420,42 @@ void plan_init() {
} }
#endif //AUTOTEMP #endif //AUTOTEMP
/**
* Maintain fans, paste extruder pressure,
*/
void check_axes_activity() { void check_axes_activity() {
unsigned char axis_active[NUM_AXIS] = { 0 }, unsigned char axis_active[NUM_AXIS] = { 0 },
tail_fan_speed = fanSpeed; tail_fan_speed = fanSpeed;
#if ENABLED(BARICUDA) #if ENABLED(BARICUDA)
unsigned char tail_valve_pressure = ValvePressure, unsigned char tail_valve_pressure = ValvePressure,
tail_e_to_p_pressure = EtoPPressure; tail_e_to_p_pressure = EtoPPressure;
#endif #endif
if (blocks_queued()) {
tail_fan_speed = block_buffer[block_buffer_tail].fan_speed;
block_t* block; block_t* block;
if (blocks_queued()) {
uint8_t block_index = block_buffer_tail;
tail_fan_speed = block_buffer[block_index].fan_speed;
#if ENABLED(BARICUDA) #if ENABLED(BARICUDA)
block = &block_buffer[block_index]; block = &block_buffer[block_buffer_tail];
tail_valve_pressure = block->valve_pressure; tail_valve_pressure = block->valve_pressure;
tail_e_to_p_pressure = block->e_to_p_pressure; tail_e_to_p_pressure = block->e_to_p_pressure;
#endif #endif
while (block_index != block_buffer_head) { for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block = &block_buffer[block_index]; block = &block_buffer[b];
for (int i = 0; i < NUM_AXIS; i++) if (block->steps[i]) axis_active[i]++; for (int i = 0; i < NUM_AXIS; i++) if (block->steps[i]) axis_active[i]++;
block_index = next_block_index(block_index);
} }
} }
if (DISABLE_X && !axis_active[X_AXIS]) disable_x(); if (DISABLE_X && !axis_active[X_AXIS]) disable_x();
if (DISABLE_Y && !axis_active[Y_AXIS]) disable_y(); if (DISABLE_Y && !axis_active[Y_AXIS]) disable_y();
#if DISABLED(LASERBEAM)
if (DISABLE_Z && !axis_active[Z_AXIS]) disable_z(); if (DISABLE_Z && !axis_active[Z_AXIS]) disable_z();
#endif
if (DISABLE_E && !axis_active[E_AXIS]) { if (DISABLE_E && !axis_active[E_AXIS]) {
disable_e0(); disable_e0();
disable_e1(); disable_e1();
...@@ -455,19 +473,24 @@ void check_axes_activity() { ...@@ -455,19 +473,24 @@ void check_axes_activity() {
fan_kick_end = ms + FAN_KICKSTART_TIME; fan_kick_end = ms + FAN_KICKSTART_TIME;
tail_fan_speed = 255; tail_fan_speed = 255;
} }
else if (fan_kick_end > ms) else {
if (PENDING(ms, fan_kick_end)) {
// Fan still spinning up. // Fan still spinning up.
tail_fan_speed = 255; tail_fan_speed = 255;
} }
}
}
else { else {
fan_kick_end = 0; fan_kick_end = 0;
} }
#endif //FAN_KICKSTART_TIME #endif //FAN_KICKSTART_TIME
#if ENABLED(FAN_MIN_PWM) #if ENABLED(FAN_MIN_PWM)
#define CALC_FAN_SPEED (tail_fan_speed ? ( FAN_MIN_PWM + (tail_fan_speed * (255 - (FAN_MIN_PWM))) / 255 ) : 0) #define CALC_FAN_SPEED (tail_fan_speed ? ( FAN_MIN_PWM + (tail_fan_speed * (255 - (FAN_MIN_PWM))) / 255 ) : 0)
#else #else
#define CALC_FAN_SPEED tail_fan_speed #define CALC_FAN_SPEED tail_fan_speed
#endif // FAN_MIN_PWM #endif // FAN_MIN_PWM
#if ENABLED(FAN_SOFT_PWM) #if ENABLED(FAN_SOFT_PWM)
fanSpeedSoftPwm = CALC_FAN_SPEED; fanSpeedSoftPwm = CALC_FAN_SPEED;
#else #else
...@@ -487,14 +510,19 @@ void check_axes_activity() { ...@@ -487,14 +510,19 @@ void check_axes_activity() {
analogWrite(HEATER_2_PIN, tail_e_to_p_pressure); analogWrite(HEATER_2_PIN, tail_e_to_p_pressure);
#endif #endif
#endif #endif
} }
float junction_deviation = 0.1; /**
// Add a new linear movement to the buffer. steps[X_AXIS], _y and _z is the absolute position in * Planner::buffer_line
// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration *
// calculation the caller must also provide the physical length of the line in millimeters. * Add a new linear movement to the buffer.
#if ENABLED(AUTO_BED_LEVELING_FEATURE) *
* x,y,z,e - target position in mm
* feed_rate - (target) speed of the move
* extruder - target extruder
*/
#if ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(MESH_BED_LEVELING)
void plan_buffer_line(float x, float y, float z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver) void plan_buffer_line(float x, float y, float z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver)
#else #else
void plan_buffer_line(const float& x, const float& y, const float& z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver) void plan_buffer_line(const float& x, const float& y, const float& z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver)
...@@ -517,14 +545,16 @@ float junction_deviation = 0.1; ...@@ -517,14 +545,16 @@ float junction_deviation = 0.1;
// Rest here until there is room in the buffer. // Rest here until there is room in the buffer.
while (block_buffer_tail == next_buffer_head) idle(); while (block_buffer_tail == next_buffer_head) idle();
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(MESH_BED_LEVELING)
apply_rotation_xyz(plan_bed_level_matrix, x, y, z); if (mbl.active) z += mbl.get_z(x - home_offset[X_AXIS], y - home_offset[Y_AXIS]);
#elif ENABLED(AUTO_BED_LEVELING_FEATURE)
apply_rotation_xyz(bed_level_matrix, x, y, z);
#endif #endif
// The target position of the tool in absolute steps // The target position of the tool in absolute steps
// Calculate target position in absolute steps // Calculate target position in absolute steps
// this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow // this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
int32_t target[NUM_AXIS] = { long target[NUM_AXIS] = {
lround(x * axis_steps_per_unit[X_AXIS]), lround(x * axis_steps_per_unit[X_AXIS]),
lround(y * axis_steps_per_unit[Y_AXIS]), lround(y * axis_steps_per_unit[Y_AXIS]),
lround(z * axis_steps_per_unit[Z_AXIS]), lround(z * axis_steps_per_unit[Z_AXIS]),
...@@ -542,23 +572,10 @@ float junction_deviation = 0.1; ...@@ -542,23 +572,10 @@ float junction_deviation = 0.1;
} }
#endif #endif
int32_t dx = target[X_AXIS] - position[X_AXIS], long dx = target[X_AXIS] - position[X_AXIS],
dy = target[Y_AXIS] - position[Y_AXIS], dy = target[Y_AXIS] - position[Y_AXIS],
dz = target[Z_AXIS] - position[Z_AXIS], dz = target[Z_AXIS] - position[Z_AXIS],
de = target[E_AXIS] - position[E_AXIS]; de = target[E_AXIS] - position[E_AXIS];
#if MECH(COREXY)
int32_t da = dx + COREX_YZ_FACTOR * dy;
int32_t db = dx - COREX_YZ_FACTOR * dy;
#elif MECH(COREYX)
int32_t da = dy + COREX_YZ_FACTOR * dx;
int32_t db = dy - COREX_YZ_FACTOR * dx;
#elif MECH(COREXZ)
int32_t da = dx + COREX_YZ_FACTOR * dz;
int32_t dc = dx - COREX_YZ_FACTOR * dz;
#elif MECH(COREZX)
int32_t da = dz + COREX_YZ_FACTOR * dx;
int32_t dc = dz - COREX_YZ_FACTOR * dx;
#endif
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE) #if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
if (de) { if (de) {
...@@ -596,6 +613,20 @@ float junction_deviation = 0.1; ...@@ -596,6 +613,20 @@ float junction_deviation = 0.1;
// Mark block as not busy (Not executed by the stepper interrupt) // Mark block as not busy (Not executed by the stepper interrupt)
block->busy = false; block->busy = false;
#if MECH(COREXY)
long da = dx + COREX_YZ_FACTOR * dy;
long db = dx - COREX_YZ_FACTOR * dy;
#elif MECH(COREYX)
long da = dy + COREX_YZ_FACTOR * dx;
long db = dy - COREX_YZ_FACTOR * dx;
#elif MECH(COREXZ)
long da = dx + COREX_YZ_FACTOR * dz;
long dc = dx - COREX_YZ_FACTOR * dz;
#elif MECH(COREZX)
long da = dz + COREX_YZ_FACTOR * dx;
long dc = dz - COREX_YZ_FACTOR * dx;
#endif
// Number of steps for each axis // Number of steps for each axis
#if MECH(COREXY) || MECH(COREYX) #if MECH(COREXY) || MECH(COREYX)
// corexy planning // corexy planning
...@@ -873,6 +904,7 @@ float junction_deviation = 0.1; ...@@ -873,6 +904,7 @@ float junction_deviation = 0.1;
block->laser_duration = laser.duration; block->laser_duration = laser.duration;
block->laser_status = laser.status; block->laser_status = laser.status;
block->laser_mode = laser.mode; block->laser_mode = laser.mode;
// When operating in PULSED or RASTER modes, laser pulsing must operate in sync with movement. // When operating in PULSED or RASTER modes, laser pulsing must operate in sync with movement.
// Calculate steps between laser firings (steps_l) and consider that when determining largest // Calculate steps between laser firings (steps_l) and consider that when determining largest
// interval between steps for X, Y, Z, E, L to feed to the motion control code. // interval between steps for X, Y, Z, E, L to feed to the motion control code.
...@@ -971,7 +1003,7 @@ float junction_deviation = 0.1; ...@@ -971,7 +1003,7 @@ float junction_deviation = 0.1;
// Calculate and limit speed in mm/sec for each axis // Calculate and limit speed in mm/sec for each axis
float current_speed[NUM_AXIS]; float current_speed[NUM_AXIS];
float speed_factor = 1.0; //factor <=1 do decrease speed float speed_factor = 1.0; // factor <=1 do decrease speed
for (int i = 0; i < NUM_AXIS; i++) { for (int i = 0; i < NUM_AXIS; i++) {
current_speed[i] = delta_mm[i] * inverse_second; current_speed[i] = delta_mm[i] * inverse_second;
float cs = fabs(current_speed[i]), mf = max_feedrate[i]; float cs = fabs(current_speed[i]), mf = max_feedrate[i];
...@@ -1057,6 +1089,9 @@ float junction_deviation = 0.1; ...@@ -1057,6 +1089,9 @@ float junction_deviation = 0.1;
#endif #endif
#if 0 // Use old jerk for now #if 0 // Use old jerk for now
float junction_deviation = 0.1;
// Compute path unit vector // Compute path unit vector
double unit_vec[3]; double unit_vec[3];
...@@ -1194,13 +1229,15 @@ float junction_deviation = 0.1; ...@@ -1194,13 +1229,15 @@ float junction_deviation = 0.1;
* *
* On CORE machines XYZ is derived from ABC. * On CORE machines XYZ is derived from ABC.
*/ */
vector_3 plan_get_position() { vector_3 plan_adjusted_position() {
vector_3 position = vector_3(st_get_axis_position_mm(X_AXIS), st_get_axis_position_mm(Y_AXIS), st_get_axis_position_mm(Z_AXIS)); vector_3 position = vector_3(st_get_axis_position_mm(X_AXIS), st_get_axis_position_mm(Y_AXIS), st_get_axis_position_mm(Z_AXIS));
//position.debug("in plan_get position"); //position.debug("in plan_get position");
//plan_bed_level_matrix.debug("in plan_get_position"); //plan_bed_level_matrix.debug("in plan_adjusted_position");
matrix_3x3 inverse = matrix_3x3::transpose(plan_bed_level_matrix); matrix_3x3 inverse = matrix_3x3::transpose(plan_bed_level_matrix);
//inverse.debug("in plan_get inverse"); //inverse.debug("in plan_get inverse");
position.apply_rotation(inverse); position.apply_rotation(inverse);
//position.debug("after rotation"); //position.debug("after rotation");
...@@ -1213,13 +1250,15 @@ float junction_deviation = 0.1; ...@@ -1213,13 +1250,15 @@ float junction_deviation = 0.1;
* *
* On CORE machines stepper ABC will be translated from the given XYZ. * On CORE machines stepper ABC will be translated from the given XYZ.
*/ */
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(MESH_BED_LEVELING)
void plan_set_position(float x, float y, float z, const float& e) void plan_set_position(float x, float y, float z, const float& e)
#else #else
void plan_set_position(const float& x, const float& y, const float& z, const float& e) void plan_set_position(const float& x, const float& y, const float& z, const float& e)
#endif // AUTO_BED_LEVELING_FEATURE #endif // AUTO_BED_LEVELING_FEATURE || MESH_BED_LEVELING
{ {
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(MESH_BED_LEVELING)
if (mbl.active) z += mbl.get_z(x - home_offset[X_AXIS], y - home_offset[Y_AXIS]);
#elif ENABLED(AUTO_BED_LEVELING_FEATURE)
apply_rotation_xyz(plan_bed_level_matrix, x, y, z); apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#endif #endif
......
...@@ -127,29 +127,43 @@ void check_axes_activity(); ...@@ -127,29 +127,43 @@ void check_axes_activity();
// Get the number of buffered moves // Get the number of buffered moves
extern volatile unsigned char block_buffer_head; extern volatile unsigned char block_buffer_head;
extern volatile unsigned char block_buffer_tail; extern volatile unsigned char block_buffer_tail;
/**
* Number of moves currently in the planner
*/
FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); } FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE) || ENABLED(MESH_BED_LEVELING)
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#include "vector_3.h" #include "vector_3.h"
// Transform required to compensate for bed level // Transform to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix; extern matrix_3x3 plan_bed_level_matrix;
/** /**
* Get the position applying the bed level matrix * The corrected position, applying the bed level matrix
*/ */
vector_3 plan_get_position(); vector_3 plan_adjusted_position();
#endif
/** /**
* Add a new linear movement to the buffer. x, y, z are the signed, absolute target position in * Add a new linear movement to the buffer.
* millimeters. Feed rate specifies the (target) speed of the motion. *
* x,y,z,e - target position in mm
* feed_rate - (target) speed of the move
* extruder - target extruder
*/ */
void plan_buffer_line(float x, float y, float z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver); void plan_buffer_line(float x, float y, float z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver);
/** /**
* Set the planner positions. Used for G92 instructions. * Set the planner.position and individual stepper positions.
* Multiplies by axis_steps_per_unit[] to set stepper positions. * Used by G92, G28, G29, and other procedures.
*
* Multiplies by axis_steps_per_unit[] and does necessary conversion
* for COREXY / COREXZ to set the corresponding stepper positions.
*
* Clears previous speed values. * Clears previous speed values.
*/ */
void plan_set_position(float x, float y, float z, const float& e); void plan_set_position(float x, float y, float z, const float& e);
...@@ -159,8 +173,11 @@ FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block ...@@ -159,8 +173,11 @@ FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block
void plan_buffer_line(const float& x, const float& y, const float& z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver); void plan_buffer_line(const float& x, const float& y, const float& z, const float& e, float feed_rate, const uint8_t extruder, const uint8_t driver);
void plan_set_position(const float& x, const float& y, const float& z, const float& e); void plan_set_position(const float& x, const float& y, const float& z, const float& e);
#endif // AUTO_BED_LEVELING_FEATURE #endif // AUTO_BED_LEVELING_FEATURE || MESH_BED_LEVELING
/**
* Set the E position (mm) of the planner (and the E stepper)
*/
void plan_set_e_position(const float& e); void plan_set_e_position(const float& e);
//=========================================================================== //===========================================================================
...@@ -193,17 +210,24 @@ extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for ...@@ -193,17 +210,24 @@ extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for
extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed
extern volatile unsigned char block_buffer_tail; extern volatile unsigned char block_buffer_tail;
// Returns true if the buffer has a queued block, false otherwise /**
* Does the buffer have any blocks queued?
*/
FORCE_INLINE bool blocks_queued() { return (block_buffer_head != block_buffer_tail); } FORCE_INLINE bool blocks_queued() { return (block_buffer_head != block_buffer_tail); }
// Called when the current block is no longer needed. Discards /**
// the block and makes the memory available for new blocks. * "Discards" the block and "releases" the memory.
* Called when the current block is no longer needed.
*/
FORCE_INLINE void plan_discard_current_block() { FORCE_INLINE void plan_discard_current_block() {
if (blocks_queued()) if (blocks_queued())
block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1); block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1);
} }
// Gets the current block. Returns NULL if buffer empty /**
* The current block. NULL if the buffer is empty.
* This also marks the block as busy.
*/
FORCE_INLINE block_t* plan_get_current_block() { FORCE_INLINE block_t* plan_get_current_block() {
if (blocks_queued()) { if (blocks_queued()) {
block_t* block = &block_buffer[block_buffer_tail]; block_t* block = &block_buffer[block_buffer_tail];
......
...@@ -1104,14 +1104,14 @@ long st_get_position(uint8_t axis) { ...@@ -1104,14 +1104,14 @@ long st_get_position(uint8_t axis) {
float st_get_axis_position_mm(AxisEnum axis) { float st_get_axis_position_mm(AxisEnum axis) {
float axis_pos; float axis_pos;
#if MECH(COREXY) || MECH(COREYX) || MECH(COREXZ) || MECH(COREZX) #if MECH(COREXY) || MECH(COREYX) || MECH(COREXZ) || MECH(COREZX)
if (axis == X_AXIS || axis == CORE_AXIS_2) { if (axis == CORE_AXIS_1 || axis == CORE_AXIS_2) {
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
long pos1 = count_position[A_AXIS], long pos1 = count_position[CORE_AXIS_1],
pos2 = count_position[CORE_AXIS_2]; pos2 = count_position[CORE_AXIS_2];
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
// ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1 // ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1
// ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2 // ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2
axis_pos = (pos1 + ((axis == X_AXIS) ? pos2 : -pos2)) / 2.0f; axis_pos = (pos1 + ((axis == CORE_AXIS_1) ? pos2 : -pos2)) / 2.0f;
} }
else else
axis_pos = st_get_position(axis); axis_pos = st_get_position(axis);
...@@ -1160,10 +1160,10 @@ void endstop_triggered(AxisEnum axis) { ...@@ -1160,10 +1160,10 @@ void endstop_triggered(AxisEnum axis) {
#if MECH(COREXY) || MECH(COREYX) || MECH(COREXZ) || MECH(COREZX) #if MECH(COREXY) || MECH(COREYX) || MECH(COREXZ) || MECH(COREZX)
float axis_pos = count_position[axis]; float axis_pos = count_position[axis];
if (axis == A_AXIS) if (axis == CORE_AXIS_1)
axis_pos = (axis_pos + count_position[CORE_AXIS_2]) / 2; axis_pos = (axis_pos + count_position[CORE_AXIS_2]) / 2;
else if (axis == CORE_AXIS_2) else if (axis == CORE_AXIS_2)
axis_pos = (count_position[A_AXIS] - axis_pos) / 2; axis_pos = (count_position[CORE_AXIS_1] - axis_pos) / 2;
endstops_trigsteps[axis] = axis_pos; endstops_trigsteps[axis] = axis_pos;
#else // ! COREXY || COREYX || COREXZ || COREZX #else // ! COREXY || COREYX || COREXZ || COREZX
......
...@@ -530,6 +530,27 @@ ...@@ -530,6 +530,27 @@
#if DISABLED(SOFTWARE_MAX_ENDSTOPS) #if DISABLED(SOFTWARE_MAX_ENDSTOPS)
#error DEPENDENCY ERROR: Missing setting SOFTWARE_MAX_ENDSTOPS #error DEPENDENCY ERROR: Missing setting SOFTWARE_MAX_ENDSTOPS
#endif #endif
/**
* Mesh Bed Leveling
*/
#if ENABLED(MESH_BED_LEVELING)
#if MECH(DELTA)
#error "MESH_BED_LEVELING does not yet support DELTA printers."
#endif
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#error "Select AUTO_BED_LEVELING_FEATURE or MESH_BED_LEVELING, not both."
#endif
#if MESH_NUM_X_POINTS > 7 || MESH_NUM_Y_POINTS > 7
#error "MESH_NUM_X_POINTS and MESH_NUM_Y_POINTS need to be less than 8."
#endif
#elif ENABLED(MANUAL_BED_LEVELING)
#error "MESH_BED_LEVELING is required for MANUAL_BED_LEVELING."
#endif
/**
* Auto Bed Leveling
*/
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
#if ENABLED(AUTO_BED_LEVELING_GRID) #if ENABLED(AUTO_BED_LEVELING_GRID)
#if DISABLED(MIN_PROBE_EDGE) #if DISABLED(MIN_PROBE_EDGE)
...@@ -1924,4 +1945,12 @@ ...@@ -1924,4 +1945,12 @@
#error DEPENDENCY ERROR: You have to set SLED_PIN to a valid pin if you enable Z_PROBE_SLED #error DEPENDENCY ERROR: You have to set SLED_PIN to a valid pin if you enable Z_PROBE_SLED
#endif #endif
/**
* Warnings for old configurations
*/
#if WATCH_TEMP_PERIOD > 500
#error "WATCH_TEMP_PERIOD now uses seconds instead of milliseconds."
#elif defined(Z_RAISE_BEFORE_HOMING)
#error "Z_RAISE_BEFORE_HOMING is deprecated. Use MIN_Z_HEIGHT_FOR_HOMING instead."
#endif
#endif //SANITYCHECK_H #endif //SANITYCHECK_H
...@@ -61,6 +61,7 @@ Added Hysteresis and Z-Wobble correction (only cartesian printers). ...@@ -61,6 +61,7 @@ Added Hysteresis and Z-Wobble correction (only cartesian printers).
Added support reader TAG width MFRC522 Added support reader TAG width MFRC522
Added Cooler and Hot Chamber Added Cooler and Hot Chamber
Added Laser beam and raster base64 Added Laser beam and raster base64
Addes Mesh Bed Level (MBL)
## Credits ## Credits
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment